@ruc-lib/screen-recorder 2.9.2 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ruc-lib-screen-recorder.mjs","sources":["../../../../../libs/ruclib/screen-recorder/src/lib/models/screen-recorder.models.ts","../../../../../libs/ruclib/screen-recorder/src/lib/screen-recorder/screen-recorder-constant.ts","../../../../../libs/ruclib/screen-recorder/src/lib/services/screen-recorder.service.ts","../../../../../libs/ruclib/screen-recorder/src/lib/screen-recorder/screen-recorder.component.ts","../../../../../libs/ruclib/screen-recorder/src/lib/screen-recorder/screen-recorder.component.html","../../../../../libs/ruclib/screen-recorder/src/lib/ruclib-screen-recorder.module.ts","../../../../../libs/ruclib/screen-recorder/src/ruc-lib-screen-recorder.ts"],"sourcesContent":["export enum ScreenRecorderPosition {\r\n Top = 'top',\r\n Bottom = 'bottom',\r\n Left = 'left',\r\n Right = 'right',\r\n }\r\n \r\n export enum DisplayFormat {\r\n Icon = 'icon',\r\n Text = 'text',\r\n }\r\n \r\n export enum RecordingState {\r\n Idle = 'idle',\r\n Recording = 'recording',\r\n Paused = 'paused',\r\n Stopped = 'stopped',\r\n }\r\n \r\n export interface ScreenRecorderIcons {\r\n record?: string; // Default: '●' (filled circle) or a material icon class\r\n recordWithAudio?: string; // Alternative if specific icon for \"record with audio\" is needed\r\n recordWithoutAudio?: string; // Alternative if specific icon for \"record without audio\" is needed\r\n stop?: string; // Default: '■' (filled square) or a material icon class\r\n pause?: string; // Default: '❚❚' (pause symbol) or a material icon class\r\n resume?: string; // Default: '►' (play symbol) or a material icon class\r\n play?: string; // Default: '►' (play symbol) or a material icon class\r\n download?: string; // Default: '💾' (floppy disk) or a material icon class\r\n audioOn?: string; // Default: '🔊' (speaker high volume) or a material icon class\r\n audioOff?: string; // Default: '🔇' (muted speaker) or a material icon class\r\n }\r\n \r\n export interface ScreenRecorderOptions {\r\n position?: ScreenRecorderPosition;\r\n displayFormat?: DisplayFormat;\r\n showAudioToggle?: boolean;\r\n defaultAudioState?: boolean; // true for audio on, false for audio off\r\n downloadFileName?: string;\r\n icons?: ScreenRecorderIcons; // For custom icons (e.g., CSS classes for icon fonts)\r\n showTimer?: boolean;\r\n showPauseResume?: boolean;\r\n showPlaybackControls?: boolean; // To show/hide the video player preview\r\n showDownloadButton?: boolean;\r\n useUTCForTimer?: boolean;\r\n /* For specific area: getDisplayMedia allows user to choose window/tab/screen.\r\n If a more specific crop is needed, it's outside standard Web API scope.\r\n This option implies we ensure the browser's picker is used.\r\n */\r\n allowSpecificAreaSelection?: boolean;\r\n // Accessibility related texts\r\n accessibilityLabels?: {\r\n recordButton?: string;\r\n stopButton?: string;\r\n pauseButton?: string;\r\n resumeButton?: string;\r\n audioToggleButton?: string;\r\n downloadButton?: string;\r\n playbackVideo?: string;\r\n };\r\n }\r\n ","import { Injectable } from \"@angular/core\";\r\nimport {\r\n ScreenRecorderOptions,\r\n ScreenRecorderPosition,\r\n DisplayFormat,\r\n RecordingState,\r\n ScreenRecorderIcons,\r\n} from '../models/screen-recorder.models';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ScreenRecorderConstants{\r\n constructor(){\r\n\r\n }\r\n public DEFAULT_ICONS: ScreenRecorderIcons = {\r\n record: 'fiber_manual_record', // Material Icon name\r\n stop: 'stop',\r\n pause: 'pause',\r\n resume: 'play_arrow',\r\n play: 'play_circle_filled',\r\n download: 'download',\r\n audioOn: 'volume_up',\r\n audioOff: 'volume_off',\r\n };\r\n \r\n public DEFAULT_LABELS = {\r\n recordButton: 'Start Recording',\r\n stopButton: 'Stop Recording',\r\n pauseButton: 'Pause Recording',\r\n resumeButton: 'Resume Recording',\r\n audioToggleButton: 'Toggle Audio',\r\n downloadButton: 'Download Recording',\r\n playbackVideo: 'Screen Recording Playback',\r\n };\r\n\r\n public INACTIVE = 'inactive';\r\n\r\n public AUDIO_ON = 'Audio ON';\r\n public AUDIO_OFF = 'Audio OFF';\r\n\r\n public RECORDING_IN_PROGRESS_ERROR = 'Recording is already in progress.';\r\n public FAILED_TO_GET_DISPLAY_MEDIA_STREAM_ERROR = 'Failed to get display media stream';\r\n public NO_SUPPORT_MIME = 'No supported MIME type found for MediaRecorder.';\r\n public NO_RECORDING_DOWNLOAD = 'No recording available to download.';\r\n public MEDIA_ERROR = 'MediaRecorder error';\r\n public PERMISSION_DENIED = \"Error starting screen recording: NotAllowedError - Permission denied\";\r\n public NO_SUPPORT = 'Screen recording is not supported in this browser.';\r\n\r\n}","import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject, Observable, Subject, timer } from 'rxjs';\r\nimport { takeWhile, tap } from 'rxjs/operators';\r\nimport { RecordingState } from '../models/screen-recorder.models';\r\nimport { ScreenRecorderConstants } from '../screen-recorder/screen-recorder-constant';\r\n@Injectable({\r\n providedIn: 'root', // Or provide in your module if preferred\r\n})\r\nexport class ScreenRecorderService {\r\n private stream: MediaStream | null = null;\r\n private mediaRecorder: MediaRecorder | null = null;\r\n private recordedBlobs: Blob[] = [];\r\n private timerSubscription: any;\r\n private currentRecordedTime: number = 0;\r\n\r\n private readonly recordingStateSubject = new BehaviorSubject<RecordingState>(RecordingState.Idle);\r\n readonly recordingState$: Observable<RecordingState> = this.recordingStateSubject.asObservable();\r\n\r\n private readonly recordedTimeSubject = new BehaviorSubject<number>(0);\r\n readonly recordedTime$: Observable<number> = this.recordedTimeSubject.asObservable();\r\n\r\n private readonly recordedUrlSubject = new BehaviorSubject<string | null>(null);\r\n readonly recordedUrl$: Observable<string | null> = this.recordedUrlSubject.asObservable();\r\n\r\n private readonly recordingTimestampSubject = new BehaviorSubject<string>('');\r\n readonly recordingTimestamp$: Observable<string> = this.recordingTimestampSubject.asObservable();\r\n\r\n private readonly errorSubject = new Subject<string>();\r\n readonly error$: Observable<string> = this.errorSubject.asObservable();\r\n\r\n constructor(public screenRecordingConstant: ScreenRecorderConstants) { }\r\n\r\n /**\r\n * Starts the screen recording with optional audio\r\n * \r\n * @param options - Configuration options for recording\r\n * @param options.audio - Whether to include audio in the recording\r\n * \r\n * @throws Error if recording is already in progress or if media access is denied\r\n * @returns Promise<void>\r\n */\r\n async startRecording(options: { audio: boolean }): Promise<void> {\r\n\r\n if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.handleError(this.screenRecordingConstant.RECORDING_IN_PROGRESS_ERROR);\r\n return;\r\n }\r\n\r\n this.cleanupPreviousRecording();\r\n\r\n try {\r\n // The browser's native picker handles \"specific area\" selection (window, tab, screen).\r\n const displayStream = await navigator.mediaDevices.getDisplayMedia({\r\n video: true\r\n });\r\n\r\n // If audio is enabled, get the audio stream\r\n let audioStream: MediaStream | null = null;\r\n if (options.audio) {\r\n audioStream = await navigator.mediaDevices.getUserMedia({\r\n audio: {\r\n echoCancellation: true,\r\n noiseSuppression: true,\r\n sampleRate: 44100\r\n }\r\n });\r\n }\r\n\r\n // Combine the streams if audio is enabled\r\n if (audioStream) {\r\n this.stream = new MediaStream([...displayStream.getTracks(), ...audioStream.getTracks()]);\r\n } else {\r\n this.stream = displayStream;\r\n }\r\n\r\n // Listen for when the user stops sharing via browser UI\r\n this.stream.getVideoTracks()[0].onended = () => {\r\n if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.stopRecordingInternal();\r\n }\r\n };\r\n\r\n // Handle errors\r\n if (!this.stream) {\r\n this.handleError(this.screenRecordingConstant.FAILED_TO_GET_DISPLAY_MEDIA_STREAM_ERROR);\r\n return;\r\n }\r\n\r\n // Set recording timestamp\r\n const now = new Date();\r\n const timestamp = now.toLocaleString('en-IN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n });\r\n this.recordingTimestampSubject.next(timestamp);\r\n\r\n\r\n this.recordedBlobs = [];\r\n const mimeType = this.getSupportedMimeType();\r\n if (!mimeType) {\r\n this.handleError(this.screenRecordingConstant.NO_SUPPORT_MIME);\r\n this.stream?.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n return;\r\n }\r\n\r\n // Create a canvas for timestamp overlay\r\n const canvas = document.createElement('canvas');\r\n const videoTrack = this.stream?.getVideoTracks()[0];\r\n if (videoTrack) {\r\n const video = document.createElement('video');\r\n video.srcObject = this.stream;\r\n\r\n // Wait for video to load metadata\r\n video.onloadedmetadata = () => {\r\n canvas.width = video.videoWidth;\r\n canvas.height = video.videoHeight;\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n // Draw video frame\r\n ctx.drawImage(video, 0, 0);\r\n\r\n // Draw timestamp\r\n ctx.font = '16px Arial';\r\n ctx.fillStyle = 'white';\r\n ctx.textAlign = 'right';\r\n ctx.textBaseline = 'top';\r\n ctx.fillText(`Recorded on: ${this.recordingTimestampSubject.value}`, canvas.width - 10, 10);\r\n }\r\n };\r\n }\r\n\r\n // Create a new stream with the canvas\r\n const canvasStream = canvas.captureStream();\r\n const combinedStream = new MediaStream([...this.stream?.getTracks() ?? [], canvasStream.getVideoTracks()[0]]);\r\n\r\n this.mediaRecorder = new MediaRecorder(combinedStream, { mimeType });\r\n\r\n this.mediaRecorder.ondataavailable = (event) => {\r\n if (event.data && event.data.size > 0) {\r\n this.recordedBlobs.push(event.data);\r\n }\r\n };\r\n\r\n this.mediaRecorder.onstop = () => {\r\n const superBuffer = new Blob(this.recordedBlobs, { type: mimeType });\r\n const url = window.URL.createObjectURL(superBuffer);\r\n this.recordedUrlSubject.next(url);\r\n this.recordingStateSubject.next(RecordingState.Stopped);\r\n this.stopTimer();\r\n\r\n };\r\n\r\n this.mediaRecorder.onerror = (event: Event) => {\r\n const errorEvent = event as ErrorEvent; // More specific type if available\r\n let message = this.screenRecordingConstant.MEDIA_ERROR;\r\n if (errorEvent.error && errorEvent.error.name) {\r\n message += `: ${errorEvent.error.name}`;\r\n if (errorEvent.error.message) message += ` - ${errorEvent.error.message}`;\r\n }\r\n this.handleError(message);\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n this.stopTimer();\r\n };\r\n\r\n this.mediaRecorder.start(); // Start recording\r\n this.recordingStateSubject.next(RecordingState.Recording);\r\n this.startTimer();\r\n } catch (err: any) {\r\n this.handleError(`Error starting screen recording: ${err.name} - ${err.message}`);\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the first supported MIME type for MediaRecorder\r\n * \r\n * @returns string|null - The supported MIME type or null if none found\r\n */\r\n private getSupportedMimeType(): string | null {\r\n const mimeTypes = [\r\n 'video/webm;codecs=vp9,opus',\r\n 'video/webm;codecs=vp8,opus',\r\n 'video/webm;codecs=h264,opus',\r\n 'video/mp4;codecs=h264,aac', // MP4 might have broader compatibility but less browser support for recording\r\n 'video/webm',\r\n ];\r\n for (const mimeType of mimeTypes) {\r\n if (MediaRecorder.isTypeSupported(mimeType)) {\r\n return mimeType;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Internal method to stop the recording process\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private stopRecordingInternal(): void {\r\n if (this.mediaRecorder && (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused)) {\r\n this.mediaRecorder.stop();\r\n }\r\n this.stream?.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n // State will be updated by onstop handler\r\n }\r\n\r\n /**\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not in progress\r\n */\r\n stopRecording(): void {\r\n this.stopRecordingInternal();\r\n }\r\n\r\n /**\r\n * Pauses the current recording\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not in progress\r\n */\r\n pauseRecording(): void {\r\n if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Recording) {\r\n this.mediaRecorder.pause();\r\n this.recordingStateSubject.next(RecordingState.Paused);\r\n this.stopTimer(); // Pauses the timer display\r\n }\r\n }\r\n\r\n /**\r\n * Resumes a paused recording\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not paused\r\n */\r\n resumeRecording(): void {\r\n if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.mediaRecorder.resume();\r\n this.recordingStateSubject.next(RecordingState.Recording);\r\n this.startTimer(this.currentRecordedTime); // Resumes timer display\r\n }\r\n }\r\n\r\n /**\r\n * \r\n * @param fileName \r\n */\r\n downloadRecording(fileName: string = 'recording.webm'): void {\r\n const url = this.recordedUrlSubject.value;\r\n const timestamp = this.recordingTimestampSubject.value;\r\n\r\n if (url && timestamp) {\r\n // Format the timestamp for filename (remove spaces and special characters)\r\n const formattedTimestamp = timestamp.replace(/[^a-zA-Z0-9]/g, '_');\r\n // Create filename with timestamp\r\n const fileExtension = fileName.split('.').pop() || 'webm';\r\n const newFileName = `screen_recording_${formattedTimestamp}.${fileExtension}`;\r\n\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n a.download = newFileName;\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n // No need to revoke URL here if user might want to play it again.\r\n // Revoke on cleanup or new recording.\r\n } else {\r\n this.handleError(this.screenRecordingConstant.NO_RECORDING_DOWNLOAD);\r\n }\r\n }\r\n\r\n /**\r\n * Starts the recording timer\r\n * \r\n * @param startTime - Optional start time for the timer\r\n * @private\r\n * @returns void\r\n */\r\n private startTimer(startTime: number = 0): void {\r\n this.stopTimer(); // Ensure no multiple timers\r\n this.currentRecordedTime = startTime;\r\n this.recordedTimeSubject.next(this.currentRecordedTime);\r\n\r\n this.timerSubscription = timer(0, 1000)\r\n .pipe(\r\n tap(() => {\r\n if (this.recordingStateSubject.value === RecordingState.Recording) {\r\n this.currentRecordedTime++;\r\n this.recordedTimeSubject.next(this.currentRecordedTime);\r\n }\r\n }),\r\n takeWhile(() => this.recordingStateSubject.value === RecordingState.Recording)\r\n )\r\n .subscribe();\r\n }\r\n\r\n /**\r\n * Stops the recording timer\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private stopTimer(): void {\r\n if (this.timerSubscription) {\r\n this.timerSubscription.unsubscribe();\r\n this.timerSubscription = null;\r\n }\r\n }\r\n\r\n /**\r\n * Cleans up resources from previous recording\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private cleanupPreviousRecording(): void {\r\n if (this.recordedUrlSubject.value) {\r\n window.URL.revokeObjectURL(this.recordedUrlSubject.value);\r\n this.recordedUrlSubject.next(null);\r\n }\r\n this.recordedBlobs = [];\r\n this.currentRecordedTime = 0;\r\n this.recordedTimeSubject.next(0);\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n }\r\n if (this.mediaRecorder && this.mediaRecorder.state !== this.screenRecordingConstant.INACTIVE) {\r\n this.mediaRecorder.stop();\r\n }\r\n this.mediaRecorder = null;\r\n }\r\n\r\n\r\n /**\r\n * Resets the recording state to idle\r\n * \r\n * @returns void\r\n */\r\n resetToIdle(): void {\r\n this.cleanupPreviousRecording();\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n this.errorSubject.next(''); // Clear any previous errors\r\n }\r\n\r\n\r\n /**\r\n * Handles and broadcasts recording errors\r\n * \r\n * @private\r\n * @param error - The error message to handle\r\n * @returns void\r\n */\r\n private handleError(error: string): void {\r\n this.errorSubject.next(error);\r\n }\r\n}\r\n","import { Component, Input, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core';\r\nimport { DomSanitizer, SafeUrl } from '@angular/platform-browser';\r\nimport { Subscription } from 'rxjs';\r\nimport {\r\n ScreenRecorderOptions,\r\n ScreenRecorderPosition,\r\n DisplayFormat,\r\n RecordingState,\r\n ScreenRecorderIcons,\r\n} from '../models/screen-recorder.models';\r\nimport { ScreenRecorderService } from '../services/screen-recorder.service';\r\nimport { ScreenRecorderConstants } from './screen-recorder-constant';\r\n\r\n\r\n\r\n@Component({\r\n selector: 'uxp-screen-recorder',\r\n templateUrl: './screen-recorder.component.html',\r\n styleUrls: ['./screen-recorder.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ScreenRecorderComponent implements OnInit, OnDestroy {\r\n @Input()\r\n customTheme: any;\r\n \r\n @Input()\r\n set rucInputData(value: ScreenRecorderOptions) {\r\n this._options = {\r\n position: ScreenRecorderPosition.Bottom,\r\n displayFormat: DisplayFormat.Icon,\r\n showAudioToggle: true,\r\n defaultAudioState: true,\r\n downloadFileName: 'screen-recording.webm',\r\n icons: { ...this.screenRecordingConstant.DEFAULT_ICONS },\r\n showTimer: true,\r\n showPauseResume: true,\r\n showPlaybackControls: true,\r\n showDownloadButton: true,\r\n useUTCForTimer: false,\r\n allowSpecificAreaSelection: true, // Default to allowing browser's native picker\r\n accessibilityLabels: { ...this.screenRecordingConstant.DEFAULT_LABELS },\r\n ...value,\r\n };\r\n // Deep merge icons and labels\r\n if (value.icons) {\r\n this._options.icons = { ...this.screenRecordingConstant.DEFAULT_ICONS, ...value.icons };\r\n }\r\n if (value.accessibilityLabels) {\r\n this._options.accessibilityLabels = { ...this.screenRecordingConstant.DEFAULT_LABELS, ...value.accessibilityLabels };\r\n }\r\n this.isAudioEnabled = this._options.defaultAudioState ?? true;\r\n }\r\n get rucInputData(): ScreenRecorderOptions {\r\n return this._options;\r\n }\r\n private _options!: ScreenRecorderOptions;\r\n\r\n @ViewChild('videoPlayer') videoPlayer!: ElementRef<HTMLVideoElement>;\r\n\r\n recordingState: RecordingState = RecordingState.Idle;\r\n recordedTime: number = 0;\r\n formattedTime: string = '00:00:00';\r\n safeRecordedUrl: SafeUrl | null = null;\r\n recordingTimestamp: string = '';\r\n /**\r\n * Checks if recording is currently in progress\r\n * \r\n * @returns boolean - True if recording is in progress, false otherwise\r\n */\r\n isRecordingInProgress(): boolean {\r\n return this.recordingState === RecordingState.Recording;\r\n }\r\n errorMessage: string | null = null;\r\n isBrowserSupported: boolean = true;\r\n isAudioEnabled: boolean = true;\r\n\r\n /**\r\n * Gets the appropriate icon for recording based on audio state and settings\r\n * @returns string - The icon name to display\r\n */\r\n getRecordingIcon(): string {\r\n if (this.isAudioEnabled && this.rucInputData.showAudioToggle) {\r\n return this.getIcon('recordWithAudio');\r\n }\r\n return this.getIcon('record');\r\n }\r\n\r\n // Expose enums to template\r\n DisplayFormat = DisplayFormat;\r\n RecordingState = RecordingState;\r\n ScreenRecorderPosition = ScreenRecorderPosition;\r\n\r\n private subscriptions = new Subscription();\r\n\r\n constructor(\r\n public screenRecorderService: ScreenRecorderService,\r\n private sanitizer: DomSanitizer,\r\n private cdr: ChangeDetectorRef,\r\n public screenRecordingConstant: ScreenRecorderConstants\r\n ) {\r\n\r\n // Initialize with default options. The setter will override if an input is provided.\r\n if (!this._options) {\r\n this.rucInputData = {}; // Trigger setter with empty object to apply defaults\r\n }\r\n } \r\n\r\n ngOnInit(): void {\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordingState$.subscribe((state) => {\r\n this.recordingState = state;\r\n if (state === RecordingState.Idle || state === RecordingState.Stopped) {\r\n // Ensure audio toggle is reset to default if needed, or based on user action\r\n }\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordingTimestamp$.subscribe((timestamp) => {\r\n this.recordingTimestamp = timestamp;\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordedTime$.subscribe((time) => {\r\n this.recordedTime = time;\r\n this.formattedTime = this.formatTimeDisplay(time);\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordedUrl$.subscribe((url) => {\r\n this.safeRecordedUrl = url ? this.sanitizer.bypassSecurityTrustUrl(url) : null;\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.error$.subscribe((error) => {\r\n if(error != this.screenRecordingConstant.PERMISSION_DENIED){\r\n this.errorMessage = error;\r\n }\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.subscriptions) {\r\n this.subscriptions.unsubscribe();\r\n }\r\n }\r\n\r\n /**\r\n * Toggles the recording state between start and stop\r\n * \r\n * @returns Promise<void>\r\n */\r\n async toggleRecord(): Promise<void> {\r\n this.errorMessage = null; // Clear previous errors\r\n if (this.recordingState === RecordingState.Idle || this.recordingState === RecordingState.Stopped) {\r\n // Set recording timestamp when starting recording\r\n const now = new Date();\r\n this.recordingTimestamp = now.toLocaleString('en-IN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n });\r\n await this.screenRecorderService.startRecording({ audio: this.isAudioEnabled });\r\n } else {\r\n this.screenRecorderService.stopRecording();\r\n }\r\n }\r\n\r\n /**\r\n * Toggles between pause and resume states during recording\r\n * \r\n * @returns void\r\n */\r\n togglePauseResume(): void {\r\n this.errorMessage = null;\r\n if (this.recordingState === RecordingState.Recording) {\r\n this.screenRecorderService.pauseRecording();\r\n } else if (this.recordingState === RecordingState.Paused) {\r\n this.screenRecorderService.resumeRecording();\r\n }\r\n }\r\n\r\n /**\r\n * Checks if recording can be resumed\r\n * \r\n * @returns boolean - True if recording can be resumed, false otherwise\r\n */\r\n canResume(): boolean {\r\n return this.recordingState === RecordingState.Paused;\r\n }\r\n\r\n /**\r\n * Downloads the recorded video file\r\n * \r\n * @returns void\r\n */\r\n onDownload(): void {\r\n this.errorMessage = null;\r\n this.screenRecorderService.downloadRecording(this.rucInputData.downloadFileName);\r\n }\r\n\r\n /**\r\n * Checks if recording can be downloaded\r\n * \r\n * @returns boolean - True if recording can be downloaded, false otherwise\r\n */\r\n canDownload(): boolean {\r\n return this.recordingState === RecordingState.Stopped;\r\n }\r\n\r\n /**\r\n * Toggles audio recording on/off\r\n * \r\n * @returns void\r\n */\r\n toggleAudio(): void {\r\n this.isAudioEnabled = !this.isAudioEnabled;\r\n this.cdr.detectChanges();\r\n }\r\n\r\n /**\r\n * \r\n * @param iconName \r\n * @returns \r\n */\r\n getIcon(iconName: keyof ScreenRecorderIcons): string {\r\n return this.rucInputData.icons?.[iconName] || (this.screenRecordingConstant.DEFAULT_ICONS as any)[iconName];\r\n }\r\n\r\n /**\r\n * \r\n * @param labelName \r\n * @returns \r\n */\r\n getLabel(labelName: keyof NonNullable<ScreenRecorderOptions['accessibilityLabels']>): string {\r\n return this.rucInputData.accessibilityLabels?.[labelName] || (this.screenRecordingConstant.DEFAULT_LABELS as any)[labelName];\r\n }\r\n\r\n /**\r\n * \r\n * @param time - The time in seconds to format\r\n * @returns string - Formatted time string (HH:MM:SS)\r\n */\r\n formatTimeDisplay(time: number): string {\r\n const hours = Math.floor(time / 3600);\r\n const minutes = Math.floor((time % 3600) / 60);\r\n const seconds = time % 60;\r\n\r\n const pad = (num: number) => num.toString().padStart(2, '0');\r\n\r\n if (this.rucInputData && this.rucInputData.useUTCForTimer) {\r\n // This is a simple duration format, not a specific UTC time.\r\n // For actual UTC time of day, you'd use new Date().toUTCString() or similar.\r\n // Assuming timer should show elapsed time formatted as HH:MM:SS.\r\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\r\n }\r\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\r\n }\r\n\r\n // Method to reset the component and service to initial state\r\n reset(): void {\r\n this.screenRecorderService.resetToIdle();\r\n this.isAudioEnabled = this.rucInputData.defaultAudioState ?? true;\r\n this.cdr.detectChanges();\r\n }\r\n}\r\n\r\n","<div class=\"screen-recorder-controls\" [ngClass]=\"customTheme + ' position-' + (rucInputData.position || ScreenRecorderPosition.Bottom)\"\r\n *ngIf=\"isBrowserSupported\">\r\n\r\n <!-- Error Message -->\r\n <div *ngIf=\"errorMessage\" class=\"recorder-error\">\r\n {{ errorMessage }}\r\n </div>\r\n\r\n <!-- Record/Stop Button -->\r\n <button\r\n *ngIf=\"recordingState === RecordingState.Idle || recordingState === RecordingState.Stopped\" (click)=\"toggleRecord()\"\r\n [attr.aria-label]=\"getLabel('recordButton')\" [attr.aria-pressed]=\"false\" class=\"recorder-button record-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getRecordingIcon() || getIcon('record') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('recordButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <button\r\n *ngIf=\"recordingState === RecordingState.Recording || recordingState === RecordingState.Paused\"\r\n (click)=\"toggleRecord()\" [attr.aria-label]=\"getLabel('stopButton')\" [attr.aria-pressed]=\"true\"\r\n class=\"recorder-button stop-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('stop') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('stopButton') }}</ng-container>\r\n </button>\r\n\r\n <!-- Pause/Resume Button -->\r\n <button *ngIf=\"rucInputData.showPauseResume && recordingState === RecordingState.Recording\"\r\n (click)=\"togglePauseResume()\" [attr.aria-label]=\"getLabel('pauseButton')\" [attr.aria-pressed]=\"false\"\r\n class=\"recorder-button pause-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('pause') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('pauseButton') }}</ng-container>\r\n </button>\r\n <button *ngIf=\"rucInputData.showPauseResume && recordingState === RecordingState.Paused\"\r\n (click)=\"togglePauseResume()\" [attr.aria-label]=\"getLabel('resumeButton')\" [attr.aria-pressed]=\"true\"\r\n class=\"recorder-button resume-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('resume') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('resumeButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <!-- Audio Toggle Button -->\r\n <button\r\n *ngIf=\"rucInputData.showAudioToggle && (recordingState === RecordingState.Idle || recordingState === RecordingState.Stopped)\"\r\n (click)=\"toggleAudio()\" [attr.aria-label]=\"getLabel('audioToggleButton')\" [attr.aria-pressed]=\"isAudioEnabled\"\r\n class=\"recorder-button audio-toggle-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ isAudioEnabled ? getIcon('audioOn') : getIcon('audioOff') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">\r\n {{ isAudioEnabled ? screenRecordingConstant.AUDIO_ON : screenRecordingConstant.AUDIO_OFF }}\r\n </ng-container>\r\n </button>\r\n\r\n <!-- Timer -->\r\n <div\r\n *ngIf=\"rucInputData.showTimer && (recordingState === RecordingState.Recording || recordingState === RecordingState.Paused)\"\r\n class=\"recorder-timer\" aria-live=\"polite\" aria-atomic=\"true\">\r\n {{ formattedTime }}\r\n </div>\r\n\r\n <!-- Download Button -->\r\n <button\r\n *ngIf=\"rucInputData.showDownloadButton && recordingState === RecordingState.Stopped && safeRecordedUrl\"\r\n (click)=\"onDownload()\" [attr.aria-label]=\"getLabel('downloadButton')\" class=\"recorder-button download-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('download') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('downloadButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <!-- Playback Area -->\r\n <div *ngIf=\"rucInputData.showPlaybackControls && recordingState === RecordingState.Stopped && safeRecordedUrl\"\r\n class=\"playback-area\">\r\n <video #videoPlayer [src]=\"safeRecordedUrl\" controls [attr.aria-label]=\"getLabel('playbackVideo')\"></video>\r\n <div class=\"video-timer-overlay\">\r\n <span>Recorded on: {{ recordingTimestamp }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Reset Button (optional, good for testing/clearing state) -->\r\n <button *ngIf=\"recordingState === RecordingState.Stopped && safeRecordedUrl\" (click)=\"reset()\"\r\n aria-label=\"New Recording\" class=\"recorder-button reset-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">refresh</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">New</ng-container>\r\n </button>\r\n\r\n</div>\r\n\r\n<div *ngIf=\"!isBrowserSupported\" class=\"recorder-notsupported\" [ngClass]=\"customTheme\">\r\n {{screenRecordingConstant.NO_SUPPORT}}\r\n</div>","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ScreenRecorderComponent } from './screen-recorder/screen-recorder.component';\r\nimport { ScreenRecorderService } from './services/screen-recorder.service';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [ScreenRecorderComponent],\r\n exports: [ScreenRecorderComponent],\r\n providers: [ScreenRecorderService],\r\n})\r\nexport class RuclibScreenRecorderModule {}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.ScreenRecorderConstants","i1.ScreenRecorderService","i3.ScreenRecorderConstants"],"mappings":"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"}
1
+ {"version":3,"file":"ruc-lib-screen-recorder.mjs","sources":["../../src/lib/models/screen-recorder.models.ts","../../src/lib/screen-recorder/screen-recorder-constant.ts","../../src/lib/services/screen-recorder.service.ts","../../src/lib/screen-recorder/screen-recorder.component.ts","../../src/lib/screen-recorder/screen-recorder.component.html","../../src/lib/ruclib-screen-recorder.module.ts","../../src/ruc-lib-screen-recorder.ts"],"sourcesContent":["export enum ScreenRecorderPosition {\r\n Top = 'top',\r\n Bottom = 'bottom',\r\n Left = 'left',\r\n Right = 'right',\r\n }\r\n \r\n export enum DisplayFormat {\r\n Icon = 'icon',\r\n Text = 'text',\r\n }\r\n \r\n export enum RecordingState {\r\n Idle = 'idle',\r\n Recording = 'recording',\r\n Paused = 'paused',\r\n Stopped = 'stopped',\r\n }\r\n \r\n export interface ScreenRecorderIcons {\r\n record?: string; // Default: '●' (filled circle) or a material icon class\r\n recordWithAudio?: string; // Alternative if specific icon for \"record with audio\" is needed\r\n recordWithoutAudio?: string; // Alternative if specific icon for \"record without audio\" is needed\r\n stop?: string; // Default: '■' (filled square) or a material icon class\r\n pause?: string; // Default: '❚❚' (pause symbol) or a material icon class\r\n resume?: string; // Default: '►' (play symbol) or a material icon class\r\n play?: string; // Default: '►' (play symbol) or a material icon class\r\n download?: string; // Default: '💾' (floppy disk) or a material icon class\r\n audioOn?: string; // Default: '🔊' (speaker high volume) or a material icon class\r\n audioOff?: string; // Default: '🔇' (muted speaker) or a material icon class\r\n }\r\n \r\n export interface ScreenRecorderOptions {\r\n position?: ScreenRecorderPosition;\r\n displayFormat?: DisplayFormat;\r\n showAudioToggle?: boolean;\r\n defaultAudioState?: boolean; // true for audio on, false for audio off\r\n downloadFileName?: string;\r\n icons?: ScreenRecorderIcons; // For custom icons (e.g., CSS classes for icon fonts)\r\n showTimer?: boolean;\r\n showPauseResume?: boolean;\r\n showPlaybackControls?: boolean; // To show/hide the video player preview\r\n showDownloadButton?: boolean;\r\n useUTCForTimer?: boolean;\r\n /* For specific area: getDisplayMedia allows user to choose window/tab/screen.\r\n If a more specific crop is needed, it's outside standard Web API scope.\r\n This option implies we ensure the browser's picker is used.\r\n */\r\n allowSpecificAreaSelection?: boolean;\r\n // Accessibility related texts\r\n accessibilityLabels?: {\r\n recordButton?: string;\r\n stopButton?: string;\r\n pauseButton?: string;\r\n resumeButton?: string;\r\n audioToggleButton?: string;\r\n downloadButton?: string;\r\n playbackVideo?: string;\r\n };\r\n }\r\n ","import { Injectable } from \"@angular/core\";\r\nimport {\r\n ScreenRecorderOptions,\r\n ScreenRecorderPosition,\r\n DisplayFormat,\r\n RecordingState,\r\n ScreenRecorderIcons,\r\n} from '../models/screen-recorder.models';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ScreenRecorderConstants{\r\n constructor(){\r\n\r\n }\r\n public DEFAULT_ICONS: ScreenRecorderIcons = {\r\n record: 'fiber_manual_record', // Material Icon name\r\n stop: 'stop',\r\n pause: 'pause',\r\n resume: 'play_arrow',\r\n play: 'play_circle_filled',\r\n download: 'download',\r\n audioOn: 'volume_up',\r\n audioOff: 'volume_off',\r\n };\r\n \r\n public DEFAULT_LABELS = {\r\n recordButton: 'Start Recording',\r\n stopButton: 'Stop Recording',\r\n pauseButton: 'Pause Recording',\r\n resumeButton: 'Resume Recording',\r\n audioToggleButton: 'Toggle Audio',\r\n downloadButton: 'Download Recording',\r\n playbackVideo: 'Screen Recording Playback',\r\n };\r\n\r\n public INACTIVE = 'inactive';\r\n\r\n public AUDIO_ON = 'Audio ON';\r\n public AUDIO_OFF = 'Audio OFF';\r\n\r\n public RECORDING_IN_PROGRESS_ERROR = 'Recording is already in progress.';\r\n public FAILED_TO_GET_DISPLAY_MEDIA_STREAM_ERROR = 'Failed to get display media stream';\r\n public NO_SUPPORT_MIME = 'No supported MIME type found for MediaRecorder.';\r\n public NO_RECORDING_DOWNLOAD = 'No recording available to download.';\r\n public MEDIA_ERROR = 'MediaRecorder error';\r\n public PERMISSION_DENIED = \"Error starting screen recording: NotAllowedError - Permission denied\";\r\n public NO_SUPPORT = 'Screen recording is not supported in this browser.';\r\n\r\n}","import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject, Observable, Subject, timer } from 'rxjs';\r\nimport { takeWhile, tap } from 'rxjs/operators';\r\nimport { RecordingState } from '../models/screen-recorder.models';\r\nimport { ScreenRecorderConstants } from '../screen-recorder/screen-recorder-constant';\r\n@Injectable({\r\n providedIn: 'root', // Or provide in your module if preferred\r\n})\r\nexport class ScreenRecorderService {\r\n private stream: MediaStream | null = null;\r\n private mediaRecorder: MediaRecorder | null = null;\r\n private recordedBlobs: Blob[] = [];\r\n private timerSubscription: any;\r\n private currentRecordedTime: number = 0;\r\n\r\n private readonly recordingStateSubject = new BehaviorSubject<RecordingState>(RecordingState.Idle);\r\n readonly recordingState$: Observable<RecordingState> = this.recordingStateSubject.asObservable();\r\n\r\n private readonly recordedTimeSubject = new BehaviorSubject<number>(0);\r\n readonly recordedTime$: Observable<number> = this.recordedTimeSubject.asObservable();\r\n\r\n private readonly recordedUrlSubject = new BehaviorSubject<string | null>(null);\r\n readonly recordedUrl$: Observable<string | null> = this.recordedUrlSubject.asObservable();\r\n\r\n private readonly recordingTimestampSubject = new BehaviorSubject<string>('');\r\n readonly recordingTimestamp$: Observable<string> = this.recordingTimestampSubject.asObservable();\r\n\r\n private readonly errorSubject = new Subject<string>();\r\n readonly error$: Observable<string> = this.errorSubject.asObservable();\r\n\r\n constructor(public screenRecordingConstant: ScreenRecorderConstants) { }\r\n\r\n /**\r\n * Starts the screen recording with optional audio\r\n * \r\n * @param options - Configuration options for recording\r\n * @param options.audio - Whether to include audio in the recording\r\n * \r\n * @throws Error if recording is already in progress or if media access is denied\r\n * @returns Promise<void>\r\n */\r\n async startRecording(options: { audio: boolean }): Promise<void> {\r\n\r\n if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.handleError(this.screenRecordingConstant.RECORDING_IN_PROGRESS_ERROR);\r\n return;\r\n }\r\n\r\n this.cleanupPreviousRecording();\r\n\r\n try {\r\n // The browser's native picker handles \"specific area\" selection (window, tab, screen).\r\n const displayStream = await navigator.mediaDevices.getDisplayMedia({\r\n video: true\r\n });\r\n\r\n // If audio is enabled, get the audio stream\r\n let audioStream: MediaStream | null = null;\r\n if (options.audio) {\r\n audioStream = await navigator.mediaDevices.getUserMedia({\r\n audio: {\r\n echoCancellation: true,\r\n noiseSuppression: true,\r\n sampleRate: 44100\r\n }\r\n });\r\n }\r\n\r\n // Combine the streams if audio is enabled\r\n if (audioStream) {\r\n this.stream = new MediaStream([...displayStream.getTracks(), ...audioStream.getTracks()]);\r\n } else {\r\n this.stream = displayStream;\r\n }\r\n\r\n // Listen for when the user stops sharing via browser UI\r\n this.stream.getVideoTracks()[0].onended = () => {\r\n if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.stopRecordingInternal();\r\n }\r\n };\r\n\r\n // Handle errors\r\n if (!this.stream) {\r\n this.handleError(this.screenRecordingConstant.FAILED_TO_GET_DISPLAY_MEDIA_STREAM_ERROR);\r\n return;\r\n }\r\n\r\n // Set recording timestamp\r\n const now = new Date();\r\n const timestamp = now.toLocaleString('en-IN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n });\r\n this.recordingTimestampSubject.next(timestamp);\r\n\r\n\r\n this.recordedBlobs = [];\r\n const mimeType = this.getSupportedMimeType();\r\n if (!mimeType) {\r\n this.handleError(this.screenRecordingConstant.NO_SUPPORT_MIME);\r\n this.stream?.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n return;\r\n }\r\n\r\n // Create a canvas for timestamp overlay\r\n const canvas = document.createElement('canvas');\r\n const videoTrack = this.stream?.getVideoTracks()[0];\r\n if (videoTrack) {\r\n const video = document.createElement('video');\r\n video.srcObject = this.stream;\r\n\r\n // Wait for video to load metadata\r\n video.onloadedmetadata = () => {\r\n canvas.width = video.videoWidth;\r\n canvas.height = video.videoHeight;\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n // Draw video frame\r\n ctx.drawImage(video, 0, 0);\r\n\r\n // Draw timestamp\r\n ctx.font = '16px Arial';\r\n ctx.fillStyle = 'white';\r\n ctx.textAlign = 'right';\r\n ctx.textBaseline = 'top';\r\n ctx.fillText(`Recorded on: ${this.recordingTimestampSubject.value}`, canvas.width - 10, 10);\r\n }\r\n };\r\n }\r\n\r\n // Create a new stream with the canvas\r\n const canvasStream = canvas.captureStream();\r\n const combinedStream = new MediaStream([...this.stream?.getTracks() ?? [], canvasStream.getVideoTracks()[0]]);\r\n\r\n this.mediaRecorder = new MediaRecorder(combinedStream, { mimeType });\r\n\r\n this.mediaRecorder.ondataavailable = (event) => {\r\n if (event.data && event.data.size > 0) {\r\n this.recordedBlobs.push(event.data);\r\n }\r\n };\r\n\r\n this.mediaRecorder.onstop = () => {\r\n const superBuffer = new Blob(this.recordedBlobs, { type: mimeType });\r\n const url = window.URL.createObjectURL(superBuffer);\r\n this.recordedUrlSubject.next(url);\r\n this.recordingStateSubject.next(RecordingState.Stopped);\r\n this.stopTimer();\r\n\r\n };\r\n\r\n this.mediaRecorder.onerror = (event: Event) => {\r\n const errorEvent = event as ErrorEvent; // More specific type if available\r\n let message = this.screenRecordingConstant.MEDIA_ERROR;\r\n if (errorEvent.error && errorEvent.error.name) {\r\n message += `: ${errorEvent.error.name}`;\r\n if (errorEvent.error.message) message += ` - ${errorEvent.error.message}`;\r\n }\r\n this.handleError(message);\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n this.stopTimer();\r\n };\r\n\r\n this.mediaRecorder.start(); // Start recording\r\n this.recordingStateSubject.next(RecordingState.Recording);\r\n this.startTimer();\r\n } catch (err: any) {\r\n this.handleError(`Error starting screen recording: ${err.name} - ${err.message}`);\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the first supported MIME type for MediaRecorder\r\n * \r\n * @returns string|null - The supported MIME type or null if none found\r\n */\r\n private getSupportedMimeType(): string | null {\r\n const mimeTypes = [\r\n 'video/webm;codecs=vp9,opus',\r\n 'video/webm;codecs=vp8,opus',\r\n 'video/webm;codecs=h264,opus',\r\n 'video/mp4;codecs=h264,aac', // MP4 might have broader compatibility but less browser support for recording\r\n 'video/webm',\r\n ];\r\n for (const mimeType of mimeTypes) {\r\n if (MediaRecorder.isTypeSupported(mimeType)) {\r\n return mimeType;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Internal method to stop the recording process\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private stopRecordingInternal(): void {\r\n if (this.mediaRecorder && (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused)) {\r\n this.mediaRecorder.stop();\r\n }\r\n this.stream?.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n // State will be updated by onstop handler\r\n }\r\n\r\n /**\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not in progress\r\n */\r\n stopRecording(): void {\r\n this.stopRecordingInternal();\r\n }\r\n\r\n /**\r\n * Pauses the current recording\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not in progress\r\n */\r\n pauseRecording(): void {\r\n if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Recording) {\r\n this.mediaRecorder.pause();\r\n this.recordingStateSubject.next(RecordingState.Paused);\r\n this.stopTimer(); // Pauses the timer display\r\n }\r\n }\r\n\r\n /**\r\n * Resumes a paused recording\r\n * \r\n * @returns Promise<void>\r\n * @throws Error if recording is not paused\r\n */\r\n resumeRecording(): void {\r\n if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Paused) {\r\n this.mediaRecorder.resume();\r\n this.recordingStateSubject.next(RecordingState.Recording);\r\n this.startTimer(this.currentRecordedTime); // Resumes timer display\r\n }\r\n }\r\n\r\n /**\r\n * \r\n * @param fileName \r\n */\r\n downloadRecording(fileName: string = 'recording.webm'): void {\r\n const url = this.recordedUrlSubject.value;\r\n const timestamp = this.recordingTimestampSubject.value;\r\n\r\n if (url && timestamp) {\r\n // Format the timestamp for filename (remove spaces and special characters)\r\n const formattedTimestamp = timestamp.replace(/[^a-zA-Z0-9]/g, '_');\r\n // Create filename with timestamp\r\n const fileExtension = fileName.split('.').pop() || 'webm';\r\n const newFileName = `screen_recording_${formattedTimestamp}.${fileExtension}`;\r\n\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n a.download = newFileName;\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n // No need to revoke URL here if user might want to play it again.\r\n // Revoke on cleanup or new recording.\r\n } else {\r\n this.handleError(this.screenRecordingConstant.NO_RECORDING_DOWNLOAD);\r\n }\r\n }\r\n\r\n /**\r\n * Starts the recording timer\r\n * \r\n * @param startTime - Optional start time for the timer\r\n * @private\r\n * @returns void\r\n */\r\n private startTimer(startTime: number = 0): void {\r\n this.stopTimer(); // Ensure no multiple timers\r\n this.currentRecordedTime = startTime;\r\n this.recordedTimeSubject.next(this.currentRecordedTime);\r\n\r\n this.timerSubscription = timer(0, 1000)\r\n .pipe(\r\n tap(() => {\r\n if (this.recordingStateSubject.value === RecordingState.Recording) {\r\n this.currentRecordedTime++;\r\n this.recordedTimeSubject.next(this.currentRecordedTime);\r\n }\r\n }),\r\n takeWhile(() => this.recordingStateSubject.value === RecordingState.Recording)\r\n )\r\n .subscribe();\r\n }\r\n\r\n /**\r\n * Stops the recording timer\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private stopTimer(): void {\r\n if (this.timerSubscription) {\r\n this.timerSubscription.unsubscribe();\r\n this.timerSubscription = null;\r\n }\r\n }\r\n\r\n /**\r\n * Cleans up resources from previous recording\r\n * \r\n * @private\r\n * @returns void\r\n */\r\n private cleanupPreviousRecording(): void {\r\n if (this.recordedUrlSubject.value) {\r\n window.URL.revokeObjectURL(this.recordedUrlSubject.value);\r\n this.recordedUrlSubject.next(null);\r\n }\r\n this.recordedBlobs = [];\r\n this.currentRecordedTime = 0;\r\n this.recordedTimeSubject.next(0);\r\n if (this.stream) {\r\n this.stream.getTracks().forEach(track => track.stop());\r\n this.stream = null;\r\n }\r\n if (this.mediaRecorder && this.mediaRecorder.state !== this.screenRecordingConstant.INACTIVE) {\r\n this.mediaRecorder.stop();\r\n }\r\n this.mediaRecorder = null;\r\n }\r\n\r\n\r\n /**\r\n * Resets the recording state to idle\r\n * \r\n * @returns void\r\n */\r\n resetToIdle(): void {\r\n this.cleanupPreviousRecording();\r\n this.recordingStateSubject.next(RecordingState.Idle);\r\n this.errorSubject.next(''); // Clear any previous errors\r\n }\r\n\r\n\r\n /**\r\n * Handles and broadcasts recording errors\r\n * \r\n * @private\r\n * @param error - The error message to handle\r\n * @returns void\r\n */\r\n private handleError(error: string): void {\r\n this.errorSubject.next(error);\r\n }\r\n}\r\n","import { Component, Input, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core';\r\nimport { DomSanitizer, SafeUrl } from '@angular/platform-browser';\r\nimport { Subscription } from 'rxjs';\r\nimport {\r\n ScreenRecorderOptions,\r\n ScreenRecorderPosition,\r\n DisplayFormat,\r\n RecordingState,\r\n ScreenRecorderIcons,\r\n} from '../models/screen-recorder.models';\r\nimport { ScreenRecorderService } from '../services/screen-recorder.service';\r\nimport { ScreenRecorderConstants } from './screen-recorder-constant';\r\n\r\n\r\n\r\n@Component({\r\n selector: 'uxp-ruclib-screen-recorder',\r\n templateUrl: './screen-recorder.component.html',\r\n styleUrls: ['./screen-recorder.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ScreenRecorderComponent implements OnInit, OnDestroy {\r\n @Input()\r\n customTheme: any;\r\n \r\n @Input()\r\n set rucInputData(value: ScreenRecorderOptions) {\r\n this._options = {\r\n position: ScreenRecorderPosition.Bottom,\r\n displayFormat: DisplayFormat.Icon,\r\n showAudioToggle: true,\r\n defaultAudioState: true,\r\n downloadFileName: 'screen-recording.webm',\r\n icons: { ...this.screenRecordingConstant.DEFAULT_ICONS },\r\n showTimer: true,\r\n showPauseResume: true,\r\n showPlaybackControls: true,\r\n showDownloadButton: true,\r\n useUTCForTimer: false,\r\n allowSpecificAreaSelection: true, // Default to allowing browser's native picker\r\n accessibilityLabels: { ...this.screenRecordingConstant.DEFAULT_LABELS },\r\n ...value,\r\n };\r\n // Deep merge icons and labels\r\n if (value.icons) {\r\n this._options.icons = { ...this.screenRecordingConstant.DEFAULT_ICONS, ...value.icons };\r\n }\r\n if (value.accessibilityLabels) {\r\n this._options.accessibilityLabels = { ...this.screenRecordingConstant.DEFAULT_LABELS, ...value.accessibilityLabels };\r\n }\r\n this.isAudioEnabled = this._options.defaultAudioState ?? true;\r\n }\r\n get rucInputData(): ScreenRecorderOptions {\r\n return this._options;\r\n }\r\n private _options!: ScreenRecorderOptions;\r\n\r\n @ViewChild('videoPlayer') videoPlayer!: ElementRef<HTMLVideoElement>;\r\n\r\n recordingState: RecordingState = RecordingState.Idle;\r\n recordedTime: number = 0;\r\n formattedTime: string = '00:00:00';\r\n safeRecordedUrl: SafeUrl | null = null;\r\n recordingTimestamp: string = '';\r\n /**\r\n * Checks if recording is currently in progress\r\n * \r\n * @returns boolean - True if recording is in progress, false otherwise\r\n */\r\n isRecordingInProgress(): boolean {\r\n return this.recordingState === RecordingState.Recording;\r\n }\r\n errorMessage: string | null = null;\r\n isBrowserSupported: boolean = true;\r\n isAudioEnabled: boolean = true;\r\n\r\n /**\r\n * Gets the appropriate icon for recording based on audio state and settings\r\n * @returns string - The icon name to display\r\n */\r\n getRecordingIcon(): string {\r\n if (this.isAudioEnabled && this.rucInputData.showAudioToggle) {\r\n return this.getIcon('recordWithAudio');\r\n }\r\n return this.getIcon('record');\r\n }\r\n\r\n // Expose enums to template\r\n DisplayFormat = DisplayFormat;\r\n RecordingState = RecordingState;\r\n ScreenRecorderPosition = ScreenRecorderPosition;\r\n\r\n private subscriptions = new Subscription();\r\n\r\n constructor(\r\n public screenRecorderService: ScreenRecorderService,\r\n private sanitizer: DomSanitizer,\r\n private cdr: ChangeDetectorRef,\r\n public screenRecordingConstant: ScreenRecorderConstants\r\n ) {\r\n\r\n // Initialize with default options. The setter will override if an input is provided.\r\n if (!this._options) {\r\n this.rucInputData = {}; // Trigger setter with empty object to apply defaults\r\n }\r\n } \r\n\r\n ngOnInit(): void {\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordingState$.subscribe((state) => {\r\n this.recordingState = state;\r\n if (state === RecordingState.Idle || state === RecordingState.Stopped) {\r\n // Ensure audio toggle is reset to default if needed, or based on user action\r\n }\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordingTimestamp$.subscribe((timestamp) => {\r\n this.recordingTimestamp = timestamp;\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordedTime$.subscribe((time) => {\r\n this.recordedTime = time;\r\n this.formattedTime = this.formatTimeDisplay(time);\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.recordedUrl$.subscribe((url) => {\r\n this.safeRecordedUrl = url ? this.sanitizer.bypassSecurityTrustUrl(url) : null;\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n\r\n this.subscriptions.add(\r\n this.screenRecorderService.error$.subscribe((error) => {\r\n if(error != this.screenRecordingConstant.PERMISSION_DENIED){\r\n this.errorMessage = error;\r\n }\r\n this.cdr.detectChanges();\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.subscriptions) {\r\n this.subscriptions.unsubscribe();\r\n }\r\n }\r\n\r\n /**\r\n * Toggles the recording state between start and stop\r\n * \r\n * @returns Promise<void>\r\n */\r\n async toggleRecord(): Promise<void> {\r\n this.errorMessage = null; // Clear previous errors\r\n if (this.recordingState === RecordingState.Idle || this.recordingState === RecordingState.Stopped) {\r\n // Set recording timestamp when starting recording\r\n const now = new Date();\r\n this.recordingTimestamp = now.toLocaleString('en-IN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n });\r\n await this.screenRecorderService.startRecording({ audio: this.isAudioEnabled });\r\n } else {\r\n this.screenRecorderService.stopRecording();\r\n }\r\n }\r\n\r\n /**\r\n * Toggles between pause and resume states during recording\r\n * \r\n * @returns void\r\n */\r\n togglePauseResume(): void {\r\n this.errorMessage = null;\r\n if (this.recordingState === RecordingState.Recording) {\r\n this.screenRecorderService.pauseRecording();\r\n } else if (this.recordingState === RecordingState.Paused) {\r\n this.screenRecorderService.resumeRecording();\r\n }\r\n }\r\n\r\n /**\r\n * Checks if recording can be resumed\r\n * \r\n * @returns boolean - True if recording can be resumed, false otherwise\r\n */\r\n canResume(): boolean {\r\n return this.recordingState === RecordingState.Paused;\r\n }\r\n\r\n /**\r\n * Downloads the recorded video file\r\n * \r\n * @returns void\r\n */\r\n onDownload(): void {\r\n this.errorMessage = null;\r\n this.screenRecorderService.downloadRecording(this.rucInputData.downloadFileName);\r\n }\r\n\r\n /**\r\n * Checks if recording can be downloaded\r\n * \r\n * @returns boolean - True if recording can be downloaded, false otherwise\r\n */\r\n canDownload(): boolean {\r\n return this.recordingState === RecordingState.Stopped;\r\n }\r\n\r\n /**\r\n * Toggles audio recording on/off\r\n * \r\n * @returns void\r\n */\r\n toggleAudio(): void {\r\n this.isAudioEnabled = !this.isAudioEnabled;\r\n this.cdr.detectChanges();\r\n }\r\n\r\n /**\r\n * \r\n * @param iconName \r\n * @returns \r\n */\r\n getIcon(iconName: keyof ScreenRecorderIcons): string {\r\n return this.rucInputData.icons?.[iconName] || (this.screenRecordingConstant.DEFAULT_ICONS as any)[iconName];\r\n }\r\n\r\n /**\r\n * \r\n * @param labelName \r\n * @returns \r\n */\r\n getLabel(labelName: keyof NonNullable<ScreenRecorderOptions['accessibilityLabels']>): string {\r\n return this.rucInputData.accessibilityLabels?.[labelName] || (this.screenRecordingConstant.DEFAULT_LABELS as any)[labelName];\r\n }\r\n\r\n /**\r\n * \r\n * @param time - The time in seconds to format\r\n * @returns string - Formatted time string (HH:MM:SS)\r\n */\r\n formatTimeDisplay(time: number): string {\r\n const hours = Math.floor(time / 3600);\r\n const minutes = Math.floor((time % 3600) / 60);\r\n const seconds = time % 60;\r\n\r\n const pad = (num: number) => num.toString().padStart(2, '0');\r\n\r\n if (this.rucInputData && this.rucInputData.useUTCForTimer) {\r\n // This is a simple duration format, not a specific UTC time.\r\n // For actual UTC time of day, you'd use new Date().toUTCString() or similar.\r\n // Assuming timer should show elapsed time formatted as HH:MM:SS.\r\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\r\n }\r\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\r\n }\r\n\r\n // Method to reset the component and service to initial state\r\n reset(): void {\r\n this.screenRecorderService.resetToIdle();\r\n this.isAudioEnabled = this.rucInputData.defaultAudioState ?? true;\r\n this.cdr.detectChanges();\r\n }\r\n}\r\n\r\n","<div class=\"main\">\r\n <div class=\"screen-recorder-controls\"\r\n [ngClass]=\"customTheme + ' position-' + (rucInputData.position || ScreenRecorderPosition.Bottom)\"\r\n *ngIf=\"isBrowserSupported\">\r\n\r\n <!-- Error Message -->\r\n <div *ngIf=\"errorMessage\" class=\"recorder-error\">\r\n {{ errorMessage }}\r\n </div>\r\n\r\n <!-- Record/Stop Button -->\r\n <button *ngIf=\"recordingState === RecordingState.Idle || recordingState === RecordingState.Stopped\"\r\n (click)=\"toggleRecord()\" [attr.aria-label]=\"getLabel('recordButton')\" [attr.aria-pressed]=\"false\"\r\n class=\"recorder-button record-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getRecordingIcon() || getIcon('record') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('recordButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <button *ngIf=\"recordingState === RecordingState.Recording || recordingState === RecordingState.Paused\"\r\n (click)=\"toggleRecord()\" [attr.aria-label]=\"getLabel('stopButton')\" [attr.aria-pressed]=\"true\"\r\n class=\"recorder-button stop-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('stop') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('stopButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <!-- Pause/Resume Button -->\r\n <button *ngIf=\"rucInputData.showPauseResume && recordingState === RecordingState.Recording\"\r\n (click)=\"togglePauseResume()\" [attr.aria-label]=\"getLabel('pauseButton')\" [attr.aria-pressed]=\"false\"\r\n class=\"recorder-button pause-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('pause') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('pauseButton')\r\n }}</ng-container>\r\n </button>\r\n <button *ngIf=\"rucInputData.showPauseResume && recordingState === RecordingState.Paused\"\r\n (click)=\"togglePauseResume()\" [attr.aria-label]=\"getLabel('resumeButton')\" [attr.aria-pressed]=\"true\"\r\n class=\"recorder-button resume-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('resume') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('resumeButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <!-- Audio Toggle Button -->\r\n <button\r\n *ngIf=\"rucInputData.showAudioToggle && (recordingState === RecordingState.Idle || recordingState === RecordingState.Stopped)\"\r\n (click)=\"toggleAudio()\" [attr.aria-label]=\"getLabel('audioToggleButton')\" [attr.aria-pressed]=\"isAudioEnabled\"\r\n class=\"recorder-button audio-toggle-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ isAudioEnabled ? getIcon('audioOn') : getIcon('audioOff') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">\r\n {{ isAudioEnabled ? screenRecordingConstant.AUDIO_ON : screenRecordingConstant.AUDIO_OFF }}\r\n </ng-container>\r\n </button>\r\n\r\n <!-- Timer -->\r\n <div\r\n *ngIf=\"rucInputData.showTimer && (recordingState === RecordingState.Recording || recordingState === RecordingState.Paused)\"\r\n class=\"recorder-timer\" aria-live=\"polite\" aria-atomic=\"true\">\r\n {{ formattedTime }}\r\n </div>\r\n\r\n <!-- Download Button -->\r\n <button *ngIf=\"rucInputData.showDownloadButton && recordingState === RecordingState.Stopped && safeRecordedUrl\"\r\n (click)=\"onDownload()\" [attr.aria-label]=\"getLabel('downloadButton')\" class=\"recorder-button download-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">{{ getIcon('download') }}</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">{{ getLabel('downloadButton')\r\n }}</ng-container>\r\n </button>\r\n\r\n <!-- Playback Area -->\r\n <div *ngIf=\"rucInputData.showPlaybackControls && recordingState === RecordingState.Stopped && safeRecordedUrl\"\r\n class=\"playback-area\">\r\n <video #videoPlayer [src]=\"safeRecordedUrl\" controls [attr.aria-label]=\"getLabel('playbackVideo')\"></video>\r\n <div class=\"video-timer-overlay\">\r\n <span>Recorded on: {{ recordingTimestamp }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Reset Button (optional, good for testing/clearing state) -->\r\n <button *ngIf=\"recordingState === RecordingState.Stopped && safeRecordedUrl\" (click)=\"reset()\"\r\n aria-label=\"New Recording\" class=\"recorder-button reset-button\">\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Icon\">\r\n <span class=\"material-icons\">refresh</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rucInputData.displayFormat === DisplayFormat.Text\">New</ng-container>\r\n </button>\r\n\r\n </div>\r\n\r\n <div *ngIf=\"!isBrowserSupported\" class=\"recorder-notsupported\" [ngClass]=\"customTheme\">\r\n {{screenRecordingConstant.NO_SUPPORT}}\r\n </div>\r\n</div>","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ScreenRecorderComponent } from './screen-recorder/screen-recorder.component';\r\nimport { ScreenRecorderService } from './services/screen-recorder.service';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [ScreenRecorderComponent],\r\n exports: [ScreenRecorderComponent],\r\n providers: [ScreenRecorderService],\r\n})\r\nexport class RuclibScreenRecorderModule {}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.ScreenRecorderConstants","i1.ScreenRecorderService","i3.ScreenRecorderConstants"],"mappings":"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"}
@@ -96,5 +96,5 @@ export declare class ScreenRecorderComponent implements OnInit, OnDestroy {
96
96
  formatTimeDisplay(time: number): string;
97
97
  reset(): void;
98
98
  static ɵfac: i0.ɵɵFactoryDeclaration<ScreenRecorderComponent, never>;
99
- static ɵcmp: i0.ɵɵComponentDeclaration<ScreenRecorderComponent, "uxp-screen-recorder", never, { "customTheme": "customTheme"; "rucInputData": "rucInputData"; }, {}, never, never, false, never>;
99
+ static ɵcmp: i0.ɵɵComponentDeclaration<ScreenRecorderComponent, "uxp-ruclib-screen-recorder", never, { "customTheme": "customTheme"; "rucInputData": "rucInputData"; }, {}, never, never, false, never>;
100
100
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruc-lib/screen-recorder",
3
- "version": "2.9.2",
3
+ "version": "3.1.1",
4
4
  "license": "MIT",
5
5
  "peerDependencies": {
6
6
  "@angular/material": "^15.2.0",