Functions/GenXdev.AI.Queries/Show-FoundImagesInBrowser.ps1
############################################################################### <# .SYNOPSIS Displays image search results in a masonry layout web gallery. .DESCRIPTION Takes image search results and displays them in a browser-based masonry layout. Can operate in interactive mode with edit and delete capabilities, or in simple display mode. Accepts image data objects typically from Find-Image and renders them with hover tooltips showing metadata like face recognition, object detection, and scene classification data. .PARAMETER InputObject Array of image data objects containing path, keywords, description, people, objects, and scenes metadata. .PARAMETER Interactive When specified, connects to browser and adds additional buttons like Edit and Delete for image management. .PARAMETER Title The title to display at the top of the image gallery. .PARAMETER Description The description text to display in the image gallery. .PARAMETER Private Opens in incognito/private browsing mode. .PARAMETER Force Force enable debugging port, stopping existing browsers if needed. .PARAMETER Edge Opens in Microsoft Edge. .PARAMETER Chrome Opens in Google Chrome. .PARAMETER Chromium Opens in Microsoft Edge or Google Chrome, depending on what the default browser is. .PARAMETER Firefox Opens in Firefox. .PARAMETER All Opens in all registered modern browsers. .PARAMETER Monitor The monitor to use, 0 = default, -1 is discard, -2 = Configured secondary monitor, defaults to Global:DefaultSecondaryMonitor or 2 if not found. .PARAMETER FullScreen Opens in fullscreen mode. .PARAMETER Width The initial width of the webbrowser window. .PARAMETER Height The initial height of the webbrowser window. .PARAMETER X The initial X position of the webbrowser window. .PARAMETER Y The initial Y position of the webbrowser window. .PARAMETER Left Place browser window on the left side of the screen. .PARAMETER Right Place browser window on the right side of the screen. .PARAMETER Top Place browser window on the top side of the screen. .PARAMETER Bottom Place browser window on the bottom side of the screen. .PARAMETER Centered Place browser window in the center of the screen. .PARAMETER ApplicationMode Hide the browser controls. .PARAMETER NoBrowserExtensions Prevent loading of browser extensions. .PARAMETER DisablePopupBlocker Disable the popup blocker. .PARAMETER AcceptLang Set the browser accept-lang http header. .PARAMETER KeysToSend Send specified keys to the browser window after opening. .PARAMETER FocusWindow Focus the browser window after opening. .PARAMETER SetForeground Set the browser window to foreground after opening. .PARAMETER Maximize Maximize the browser window after positioning. .PARAMETER RestoreFocus Restore PowerShell window focus. .PARAMETER NewWindow Create a new browser window instead of reusing existing one. .PARAMETER OnlyReturnHtml Only return the generated HTML instead of displaying it in a browser. .PARAMETER EmbedImages Embed images as base64 data URLs instead of file:// URLs for better portability. .PARAMETER ShowOnlyPictures Show only pictures in a rounded rectangle, no text below. .PARAMETER SendKeyEscape Escape control characters and modifiers when sending keys. .PARAMETER SendKeyHoldKeyboardFocus Prevents returning keyboard focus to PowerShell after sending keys. .PARAMETER SendKeyUseShiftEnter Use Shift+Enter instead of Enter when sending keys. .PARAMETER SendKeyDelayMilliSeconds Delay between different input strings in milliseconds when sending keys. .PARAMETER NoBorders Remove window borders and title bar for a cleaner appearance. .PARAMETER PassThru Return the browser window helper object for further manipulation. .PARAMETER SideBySide Place browser window side by side with PowerShell on the same monitor. .PARAMETER SessionOnly Use alternative settings stored in session for AI preferences. .PARAMETER ClearSession Clear alternative settings stored in session for AI preferences. .PARAMETER SkipSession Store settings only in persistent preferences without affecting session. .EXAMPLE Show-FoundImagesInBrowser -InputObject $images Displays the image results in a simple web gallery. .EXAMPLE Show-FoundImagesInBrowser -InputObject $images -Interactive -Title "My Photos" Displays images in interactive mode with edit/delete buttons. .EXAMPLE showfoundimages $images -Private -FullScreen Opens the gallery in private browsing mode in fullscreen. #> ############################################################################### function Show-FoundImagesInBrowser { [CmdletBinding()] # PSScriptAnalyzer rule exception: allow use of $Global:chromeSession for browser session detection [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '')] [Alias('showfoundimages')] param( ############################################################################### [Parameter( Position = 0, Mandatory = $false, ValueFromPipeline = $true, HelpMessage = 'Image data objects to display in the gallery.' )] [System.Object[]] $InputObject = @(), ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Will connect to browser and adds additional buttons ' + 'like Edit and Delete') )] [Alias('i', 'editimages')] [switch] $Interactive, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Title for the gallery' )] [string] $Title = 'Photo Gallery', ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Hover over images to see face recognition and ' + 'object detection data') )] [string] $Description = ('Hover over images to see face recognition ' + 'and object detection data'), ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in incognito/private browsing mode' )] [Alias('incognito', 'inprivate')] [switch] $Private, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Force enable debugging port, stopping existing ' + 'browsers if needed') )] [switch] $Force, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in Microsoft Edge' )] [Alias('e')] [switch] $Edge, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in Google Chrome' )] [Alias('ch')] [switch] $Chrome, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Opens in Microsoft Edge or Google Chrome, ' + 'depending on what the default browser is') )] [Alias('c')] [switch] $Chromium, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in Firefox' )] [Alias('ff')] [switch] $Firefox, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in all registered modern browsers' )] [switch] $All, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('The monitor to use, 0 = default, -1 is discard, ' + '-2 = Configured secondary monitor, defaults to ' + 'Global:DefaultSecondaryMonitor or 2 if not found') )] [Alias('m', 'mon')] [int] $Monitor = -2, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Opens in fullscreen mode' )] [Alias('fs', 'f')] [switch] $FullScreen, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'The initial width of the webbrowser window' )] [int] $Width = -1, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'The initial height of the webbrowser window' )] [int] $Height = -1, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'The initial X position of the webbrowser window' )] [int] $X = -999999, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'The initial Y position of the webbrowser window' )] [int] $Y = -999999, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window on the left side of the screen' )] [switch] $Left, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window on the right side of the screen' )] [switch] $Right, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window on the top side of the screen' )] [switch] $Top, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window on the bottom side of the screen' )] [switch] $Bottom, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window in the center of the screen' )] [switch] $Centered, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Hide the browser controls' )] [Alias('a', 'app', 'appmode')] [switch] $ApplicationMode, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Prevent loading of browser extensions' )] [Alias('de', 'ne', 'NoExtensions')] [switch] $NoBrowserExtensions, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Disable the popup blocker' )] [Alias('allowpopups')] [switch] $DisablePopupBlocker, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Set the browser accept-lang http header' )] [Alias('lang', 'locale')] [string] $AcceptLang = $null, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Keystrokes to send to the Browser window, ' + 'see documentation for cmdlet GenXdev.Windows\Send-Key') )] [string[]] $KeysToSend, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Focus the browser window after opening' )] [Alias('fw','focus')] [switch] $FocusWindow, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Set the browser window to foreground after opening' )] [Alias('fg')] [switch] $SetForeground, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Maximize the window after positioning' )] [switch] $Maximize, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Restore PowerShell window focus' )] [Alias('rf', 'bg')] [switch] $RestoreFocus, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Create a new browser window instead of reusing ' + 'existing one') )] [Alias('nw', 'new')] [switch] $NewWindow, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Only return the generated HTML instead of ' + 'displaying it in a browser.') )] [switch] $OnlyReturnHtml, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = ('Embed images as base64 data URLs instead of ' + 'file:// URLs for better portability.') )] [switch] $EmbedImages, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Show only pictures in a rounded rectangle, no text below.' )] [Alias('NoMetadata', 'OnlyPictures')] [switch] $ShowOnlyPictures, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Escape control characters and modifiers when sending keys' )] [Alias('Escape')] [switch] $SendKeyEscape, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Hold keyboard focus on target window when sending keys' )] [Alias('HoldKeyboardFocus')] [switch] $SendKeyHoldKeyboardFocus, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Use Shift+Enter instead of Enter when sending keys' )] [Alias('UseShiftEnter')] [switch] $SendKeyUseShiftEnter, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Delay between different input strings in milliseconds when sending keys' )] [Alias('DelayMilliSeconds')] [int] $SendKeyDelayMilliSeconds, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Remove window borders and title bar for a cleaner appearance' )] [Alias('nb')] [switch] $NoBorders, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Return the browser window helper object for further manipulation' )] [Alias('pt')] [switch]$PassThru, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Place browser window side by side with PowerShell on the same monitor' )] [Alias('sbs')] [switch]$SideBySide, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Use alternative settings stored in session for AI preferences' )] [switch] $SessionOnly, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Clear alternative settings stored in session for AI preferences' )] [switch] $ClearSession, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Store settings only in persistent preferences without affecting session' )] [Alias('FromPreferences')] [switch] $SkipSession, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Auto-scroll the page by this many pixels per second (null to disable)' )] [int]$AutoScrollPixelsPerSecond = $null, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Animate rectangles (objects/faces) in visible range, cycling every 300ms' )] [switch]$AutoAnimateRectangles, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Force single column layout (centered, 1/3 screen width)' )] [switch]$SingleColumnMode = $false, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = 'Prefix to prepend to each image path (e.g. for remote URLs)' )] [string]$ImageUrlPrefix = '' ) begin { # initialize collection to accumulate all input objects [System.Collections.Generic.List[Object]] $results = @() } process { # Add naturalWidth/naturalHeight to each image object before passing to GenerateMasonryLayoutHtml foreach ($img in $InputObject) { if ($img -and $img.path) { try { $imageObj = [System.Drawing.Image]::FromFile($img.path) $img | Microsoft.PowerShell.Utility\Add-Member -NotePropertyName 'naturalWidth' -NotePropertyValue $imageObj.Width -Force $img | Microsoft.PowerShell.Utility\Add-Member -NotePropertyName 'naturalHeight' -NotePropertyValue $imageObj.Height -Force $null = $imageObj.Dispose() } catch { Microsoft.PowerShell.Utility\Write-Verbose ("Could not get image dimensions for $($img.path): $_") continue } } } # iterate through each input object for processing $InputObject | Microsoft.PowerShell.Core\ForEach-Object ` -ErrorAction SilentlyContinue { # handle enumerable objects without path property if ($_ -is [System.Collections.IEnumerable] -and (-not $_.PSObject.Properties['Path'])) { # process each item in the enumerable collection $_ | Microsoft.PowerShell.Core\ForEach-Object { # convert object to hashtable for processing $hashTable = $_ | GenXdev.Helpers\ConvertTo-HashTable # add object to results if it contains a path property if ($hashTable.ContainsKey('Path')) { $null = $results.Add($_) } } return } # add unique input objects to the results collection $null = $results.Add($_) } } end { # verify that we have images to display before proceeding if ((-not $results) -or ($null -eq $results) -or ($results.Count -eq 0)) { Microsoft.PowerShell.Utility\Write-Host ( 'No images to display in gallery.') return } # log the number of images being processed Microsoft.PowerShell.Utility\Write-Verbose ( "Processing $($results.Count) images for gallery display") # generate unique temp file path for masonry layout html $filePath = GenXdev.FileSystem\Expand-Path ( "$env:TEMP\$([DateTime]::Now.Ticks)_images-masonry.html") # log the temporary file path being used Microsoft.PowerShell.Utility\Write-Verbose ( "Creating temporary HTML file at: $filePath") # set file attributes to temporary and hidden for cleanup try { $null = Microsoft.PowerShell.Management\Set-ItemProperty ` -Path $filePath ` -Name Attributes ` -Value ([System.IO.FileAttributes]::Temporary -bor ` [System.IO.FileAttributes]::Hidden) ` -ErrorAction SilentlyContinue } catch { # silently ignore errors when setting file attributes } # ensure title has a default value if empty if ([String]::IsNullOrWhiteSpace($Title)) { $Title = 'Image Gallery' } # ensure description has a default value if empty if ([String]::IsNullOrWhiteSpace($Description)) { $Description = 'Image gallery results' } # copy parameter values for masonry layout html generation $params = GenXdev.Helpers\Copy-IdenticalParamValues ` -BoundParameters $PSBoundParameters ` -FunctionName 'GenXdev.AI\GenerateMasonryLayoutHtml' ` -DefaultValues (Microsoft.PowerShell.Utility\Get-Variable ` -Scope Local ` -ErrorAction SilentlyContinue) # configure interactive mode capabilities for editing $params.CanEdit = $Interactive # configure interactive mode capabilities for deletion $params.CanDelete = $Interactive # generate masonry layout html with specified parameters $null = GenXdev.AI\GenerateMasonryLayoutHtml @params ` -Images $results # log successful html generation Microsoft.PowerShell.Utility\Write-Verbose ( 'Generated masonry layout HTML successfully') # return html content if only html is requested if ($OnlyReturnHtml) { # read the generated html file content $html = Microsoft.PowerShell.Management\Get-Content ` -Path $filePath ` -Raw # delete the temporary file $null = [io.file]::Delete($filePath) # return the html content to caller return $html } # handle interactive mode with browser connection if ($Interactive) { # log that interactive mode is starting Microsoft.PowerShell.Utility\Write-Verbose ( 'Starting interactive mode with browser connection') # construct file url for browser navigation $filePathUrl = "file:///$($filePath -replace '\\', '/')" # log the file url being used Microsoft.PowerShell.Utility\Write-Verbose ( "Using file URL: $filePathUrl") # attempt to select existing webbrowser tab try { $null = GenXdev.Webbrowser\Select-WebbrowserTab ` -Chrome:$Chrome ` -Edge:$Edge # check if chrome session is available if ($null -eq $Global:chromeSession) { throw 'No active web browser session found.' } } catch { # close browser if selection fails $null = GenXdev.Webbrowser\Close-Webbrowser ` -Force ` -Chromium ` -Chrome:$Chrome ` -Edge:$Edge } # copy parameter values for open-webbrowser function $params = GenXdev.Helpers\Copy-IdenticalParamValues ` -BoundParameters $PSBoundParameters ` -FunctionName 'GenXdev.Webbrowser\Open-Webbrowser' ` -DefaultValues (Microsoft.PowerShell.Utility\Get-Variable ` -Scope Local ` -ErrorAction SilentlyContinue) # configure new window behavior based on parameter $params.NewWindow = $NewWindow # open generated html file in browser window $null = GenXdev.Webbrowser\Open-Webbrowser ` @params ` -Url $filePathUrl # create tab name pattern for selection $name = "*$([IO.Path]::GetFileNameWithoutExtension($filePath))*" # select the specific tab containing our gallery $null = GenXdev.Webbrowser\Select-WebbrowserTab -Name $name # clear the console for interactive mode display $null = Clear-Host # display interactive mode header Microsoft.PowerShell.Utility\Write-Host ( '===================================================================') ` -ForegroundColor Cyan Microsoft.PowerShell.Utility\Write-Host ( ' PowerShell is waiting for instructions from the webpage') ` -ForegroundColor Yellow Microsoft.PowerShell.Utility\Write-Host ( ' (e.g., delete or edit image actions) ENTER to QUIT') ` -ForegroundColor Yellow Microsoft.PowerShell.Utility\Write-Host ( '===================================================================') ` -ForegroundColor Cyan # display exit instruction Microsoft.PowerShell.Utility\Write-Host 'Press any key to quit...' # main interactive loop waiting for user actions while (-not [Console]::KeyAvailable) { try { # get actions from browser javascript $actions = @(GenXdev.Webbrowser\Invoke-WebbrowserEvaluation ( 'return window.getActions()') ` -ErrorAction SilentlyContinue) # log found actions for debugging Microsoft.PowerShell.Utility\Write-Verbose ( "Found $($actions | Microsoft.PowerShell.Utility\ConvertTo-Json)") # process each action received from the browser foreach ($action in $actions) { try { # handle different action types switch ($action.action) { 'edit' { # display edit action message Microsoft.PowerShell.Utility\Write-Host ( 'Editing image metadata for ' + "$($action.path)") # convert file uri to local path if needed $imagePath = $action.path # handle file uri conversion if ($imagePath -like 'file:///*') { # convert file:/// uri to local path $imagePath = $imagePath -replace ( '^file:///', '') # replace forward slashes with backslashes $imagePath = $imagePath -replace '/', '\' # handle windows drive letters if ($imagePath -match '^[A-Za-z]:') { # path already has drive letter, # no changes needed } } # ensure paint.net is available for editing $null = GenXdev.AI\EnsurePaintNet # inform user about paint.net requirement Microsoft.PowerShell.Utility\Write-Verbose ( ('Paint.NET is not installed or not ' + 'found in PATH. Please install it to ' + 'use the edit feature.')) # handle cropping if bounding box is provided if ($null -ne $action.boundingBox) { # initialize variables for image processing $tempFilePath = $null $image = $null try { # use .net to crop the image using the # bounding box $image = [System.Drawing.Image]::FromFile( $imagePath) # validate and clamp bounding box # coordinates $box = $action.boundingBox $x_min = [Math]::Max(0, [Math]::Min( $box.x_min, $image.Width - 1)) $y_min = [Math]::Max(0, [Math]::Min( $box.y_min, $image.Height - 1)) $x_max = [Math]::Max($x_min + 1, [Math]::Min($box.x_max, $image.Width)) $y_max = [Math]::Max($y_min + 1, [Math]::Min($box.y_max, $image.Height)) # calculate validated width and height $width = $x_max - $x_min $height = $y_max - $y_min # log original bounding box information Microsoft.PowerShell.Utility\Write-Verbose ( ("Original box: x_min=$($box.x_min), " + "y_min=$($box.y_min), " + "x_max=$($box.x_max), " + "y_max=$($box.y_max), " + "width=$($box.width), " + "height=$($box.height)")) # log image dimensions Microsoft.PowerShell.Utility\Write-Verbose ( ('Image dimensions: ' + "$($image.Width) x $($image.Height)")) # log validated bounding box information Microsoft.PowerShell.Utility\Write-Verbose ( ("Validated box: x_min=$x_min, " + "y_min=$y_min, x_max=$x_max, " + "y_max=$y_max, width=$width, " + "height=$height")) # ensure minimum dimensions if ($width -le 0 -or $height -le 0) { # warn about invalid dimensions Microsoft.PowerShell.Utility\Write-Verbose ( ('Invalid bounding box ' + "dimensions: width=$width, " + "height=$height")) continue } # create a rectangle for the bounding box $cropRect = [System.Drawing.Rectangle]::new( $x_min, $y_min, $width, $height) # create a new bitmap for the cropped region $croppedBitmap = [System.Drawing.Bitmap]::new( $width, $height) $croppedGraphics = [System.Drawing.Graphics]::FromImage( $croppedBitmap) # draw the cropped portion of the original # image $destRect = [System.Drawing.Rectangle]::new( 0, 0, $width, $height) # perform the image cropping operation $null = $croppedGraphics.DrawImage( $image, $destRect, $cropRect, [System.Drawing.GraphicsUnit]::Pixel) # determine a safe title for the file $title = 'crop' # use face name if available if (-not [String]::IsNullOrWhiteSpace( $action.faceName)) { $title = $action.faceName } # use object name if available elseif (-not [String]::IsNullOrWhiteSpace( $action.objectName)) { $title = $action.objectName } # sanitize the title for use in filename $title = $title -replace '[^\w\-_]', '_' # get a windows temp file path for the # cropped image $tempFilePath = GenXdev.FileSystem\Expand-Path ( ("$env:TEMP\" + "$([DateTime]::Now.Ticks)_$title." + "$([IO.Path]::GetExtension($imagePath).TrimStart('.'))")) # save the cropped image $null = $croppedBitmap.Save($tempFilePath, [System.Drawing.Imaging.ImageFormat]::Png) # clean up graphics object $null = $croppedGraphics.Dispose() $null = $croppedBitmap.Dispose() } finally { # ensure image object is disposed if ($image) { $null = $image.Dispose() } } # open the cropped image in paint.net if ($tempFilePath) { # check if paint.net is already running [bool] $wasRunning = Microsoft.PowerShell.Management\Get-Process paintdotnet ` -ErrorAction SilentlyContinue # launch paint.net with the cropped image $null = paintdotnet.exe $tempFilePath # wait for paint.net to initialize Microsoft.PowerShell.Utility\Start-Sleep 2 # get paint.net window handle $w = GenXdev.Windows\Get-Window ` -ProcessName paintdotnet ` -ErrorAction silentlyContinue # position and maximize paint.net window if ($w) { $null = GenXdev.Windows\Set-WindowPosition ` -WindowHelper $w ` -Monitor 0 ` -Maximize ` -SetForeground ` -FocusWindow } } } else { # open the original image in paint.net if no # bounding boxes provided [bool] $wasRunning = Microsoft.PowerShell.Management\Get-Process paintdotnet ` -ErrorAction SilentlyContinue # launch paint.net with the original image $null = paintdotnet.exe $imagePath # wait for paint.net to initialize Microsoft.PowerShell.Utility\Start-Sleep 2 # get paint.net window handle $w = GenXdev.Windows\Get-Window ` -ProcessName paintdotnet ` -ErrorAction silentlyContinue # position and maximize paint.net window if ($w) { $null = GenXdev.Windows\Set-WindowPosition ` -WindowHelper $w ` -Monitor 0 ` -Maximize ` -SetForeground ` -FocusWindow } } } 'delete' { # display delete action message Microsoft.PowerShell.Utility\Write-Host ( "Deleting image $($action.path)") # convert file uri to local path if needed $imagePath = $action.path # handle file uri conversion if ($imagePath -like 'file:///*') { # convert file:/// uri to local path $imagePath = $imagePath -replace ( '^file:///', '') # replace forward slashes with backslashes $imagePath = $imagePath -replace '/', '\' # handle windows drive letters if ($imagePath -match '^[A-Za-z]:') { # path already has drive letter, # no changes needed } } # handle delete action by moving to recycle bin $null = GenXdev.FileSystem\Move-ToRecycleBin ` -Path $imagePath } } } catch { # warn about failed action processing Microsoft.PowerShell.Utility\Write-Verbose ( ("Failed to process action $($action.action) " + "for $($action.path): $_")) } } } catch { # sleep and continue on general errors Microsoft.PowerShell.Utility\Start-Sleep 1 continue } # sleep to prevent excessive polling Microsoft.PowerShell.Utility\Start-Sleep 1 } # exit interactive mode return } # copy identical parameter values for open-webbrowser $parameters = GenXdev.Helpers\Copy-IdenticalParamValues ` -BoundParameters $PSBoundParameters ` -FunctionName 'GenXdev.Webbrowser\Open-Webbrowser' ` -DefaultValues (Microsoft.PowerShell.Utility\Get-Variable ` -Scope Local ` -ErrorAction SilentlyContinue) # open generated html file in browser window and let it return naturally GenXdev.Webbrowser\Open-Webbrowser ` @parameters -Url $filePath } } ############################################################################### |