BurntToast.psm1

function Optimize-BTImageSource {
    param (
        [Parameter(Mandatory)]
        [String] $Source,

        [Switch] $ForceRefresh
    )

    if ([bool]([System.Uri]$Source).IsUnc -or $Source -like 'http?://*') {
        $RemoteFileName = [string]::Join('-', $Source.Split([System.IO.Path]::GetInvalidFileNameChars()))

        $NewFilePath = Join-Path -Path $Env:TEMP -ChildPath $RemoteFileName

        if (!(Test-Path -Path $NewFilePath) -or $ForceRefresh) {
            if ([bool]([System.Uri]$Source).IsUnc) {
                Copy-Item -Path $Source -Destination $NewFilePath -Force
            } else {
                Invoke-WebRequest -Uri $Source -OutFile $NewFilePath
            }
        }

        $NewFilePath
    } else {
        try {
            (Get-Item -Path $Source -ErrorAction Stop).FullName
        } catch {
            Write-Warning -Message "The image source '$Source' doesn't exist, failed back to icon."
        }
    }
}
function Add-BTDataBinding {
    <#
        .SYNOPSIS
        Add Data Binding key value pairs to a toast content builder.
 
        .DESCRIPTION
        The Add-BTDataBinding function adds Data Binding key value pairs to a toast content builder.
 
        You can provide these as individual pairs via the `Key` and `Value` parameters or you can add multiple pairs via a hashtable.
 
        If the key appears in a bindable string, it will be replaced by the value.
 
        .INPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder. You can pipe a toast content builder object to Add-BTDataBinding.
 
        .OUTPUTS
        None. The Add-BTDataBinding function does not provide any output by default.
 
        You can optionally use the PassThru parameter to output the updated toast content builder object, which enables chaining functions together.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTText -ContentBuilder $Builder -Text 'Heading' -Bindable
 
        PS C:\>Add-BTText -ContentBuilder $Builder -Text 'Body' -Bindable
 
        PS C:\>Add-BTDataBinding -ContentBuilder $Builder -Key 'Heading' -Value 'This is the heading'
 
        PS C:\>Add-BTDataBinding -ContentBuilder $Builder -Key 'Body' -Value 'This is the body'
 
        PS C:\>Show-BTNotification -ContentBuilder $Builder
 
        This example adds two text elements to the toast notification, both of which are bindable. It then adds two key value pairs to the toast notification, which will replace the bindable text elements.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTText -ContentBuilder $Builder -Text 'Heading' -Bindable
 
        PS C:\>Add-BTText -ContentBuilder $Builder -Text 'Body' -Bindable
 
        PS C:\>$Binding = @{Heading = 'This is the heading'; Body = 'This is the body'}
 
        PS C:\>Add-BTDataBinding -ContentBuilder $Builder -Hashtable $Binding
 
        PS C:\>Show-BTNotification -ContentBuilder $Builder
 
        This example adds two text elements to the toast notification, both of which are bindable. It then adds two key value pairs to the toast notification, which will replace the bindable text elements.
 
        .LINK
        https://docs.toastit.dev/commands/add-btdatabinding
    #>


    [CmdletBinding(DefaultParameterSetName = 'KeyValue')]
    param (
        # The toast content builder object that represents the toast notification being constructed.
        [Parameter(Mandatory,
                   ValueFromPipeline)]
        [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder] $ContentBuilder,

        # The key which indicates the bindable string to be replaced.
        [Parameter(Mandatory,
                   ParameterSetName = 'KeyValue')]
        [ValidateNotNullOrEmpty()]
        [string] $Key,

        # The value which will replace the key in the toast notification.
        [Parameter(Mandatory,
                   ParameterSetName = 'KeyValue')]
        [ValidateNotNullOrEmpty()]
        [string] $Value,

        # Allows to adding multiple key value pairs at once via a hash table.
        [Parameter(Mandatory,
                   ParameterSetName = 'Bulk')]
        [hashtable] $Hashtable,

        # Returns an object that represents the item with which you're working. By default, this cmdlet doesn't generate any output.
        [switch] $PassThru
    )

    begin {}
    process {
        if ($PSCmdlet.ParameterSetName -eq 'KeyValue') {
            $ContentBuilder.DataBinding[$Key] = $Value
        } else {
            foreach ($HashtableKey in $Hashtable.Keys) {
                $ContentBuilder.DataBinding[$HashtableKey] = $Hashtable[$HashtableKey]
            }
        }

        if ($PassThru) {
            $ContentBuilder
        }
    }
    end {}
}
function Add-BTImage {
    <#
        .SYNOPSIS
        Add an image to a toast notification.
 
        .DESCRIPTION
        The Add-BTImage function adds one of three image types to a toast notification.
 
        Multiple images can be added to the body of a toast notification by calling the function without the AppLogo or HeroImage switches multiple times. These images are displayed in the order in which they are added.
 
        Any images added to the body of a toast notification are displayed after the text of the toast notification.
 
        By using the AppLogo switch, this function specifies an image to be displayed on a toast notification as the app logo
 
        Prior to Windows 10 20H2 this app logo would replace the smaller icon that represents the source of a notification, but from 20H2 it is displayed in addition to the icon.
 
        Finally, using the HeroImage switch, this function specifies an image to be displayed across the top of a toast notification.
 
        .INPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder. You can pipe a toast content builder object to Add-BTImage.
 
        System.Uri. One image reference can be provided, this cannot be piped to Add-BTImage.
 
        .OUTPUTS
        None. The Add-BTImage function does not provide any output by default.
 
        You can optionally use the PassThru parameter to output the updated toast content builder object, which enables chaining functions together.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTImage -ContentBuilder $Builder -Source 'C:\Temp\LocalImage.png'
 
        This example adds a local image to the body of a toast notification using a toast content builder object.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source '\\FS01\Images$\NetworkImage.gif'
 
        This example adds an image from a network share to the body of a toast notification with its toast content builder object coming from the pipeline.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'https://example.com/OnlineImage.jpeg'
 
        This example adds an image from the internet to the body of a toast notification.
 
        Future invocations of this example will used a cached copy of the referenced image rather than going out to the internet again.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'https://example.com/OnlineImage.jpeg' -IgnoreCache
 
        This example adds an image from the internet to the body of a toast notification, it downloads the image from the internet regardless of if it has been previously cached.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'C:\Temp\LocalImage.png' -AlternateText 'Picture of burnt toast, popped out of a toaster'
 
        This example adds a local image to the body of a toast notification with supplied alt text to aid with accessibility e.g. the use of screen readers.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'C:\Temp\LocalImage.png' -Crop Circle
 
        This example adds a local image to the body of a toast notification cropped into the shape of a circle, overriding the default square shape.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'C:\Temp\LocalImageOne.png'
 
        PS C:\>$Builder | Add-BTImage -Source 'C:\Temp\LocalImageTwo.png'
 
        This example adds two images to a toast content notification, which will be displayed in the order in which they are added.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTImage -Source 'C:\Temp\LocalImage.png' -PassThru |
                          Add-BTText -Text 'First Line of Text' -PassThru |
                          Add-BTText -Text 'Second Line of Text'
 
        This example a image alongside three custom text elements to a toast content builder object on the pipeline by passing through a refference to the builder object.
 
        The image is displayed after the text elements, despite being added first.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTImage -ContentBuilder $Builder -Source 'C:\Temp\LocalImage.png' -AppLogo
 
        This example adds a local image as the app logo on the toast notification using a toast content builder object.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTImage -ContentBuilder $Builder -Source 'C:\Temp\LocalImage.png' -HeroImage
 
        This example adds a local image as the hero image on the toast notification using a toast content builder object.
 
        .NOTES
        You can reference an image from your local computer, a network location, or the internet.
 
        Online images will be downloaded and cached in the user's TEMP directory for future use.
 
        Animated GIFs and images with transparent background are supported.
 
        .LINK
        https://docs.toastit.dev/commands/add-btimage
    #>


    [CmdletBinding(DefaultParameterSetName = 'AdaptiveImage')]
    param (
        # The toast content builder object that represents the toast notification being constructed.
        [Parameter(Mandatory,
                   ValueFromPipeline)]
        [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder] $ContentBuilder,

        # The URI of the image. Can be from your local computer, network location, or the internet.
        # Online images will be downloaded and cached in the user's TEMP directory for future use.
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $Source = $Script:DefaultImage,

        # Specify how the image should be cropped.
        [Parameter(ParameterSetName = 'AdaptiveImage')]
        [Parameter(ParameterSetName = 'AppLogo')]
        [Microsoft.Toolkit.Uwp.Notifications.AdaptiveImageCrop] $Crop = 'Default',

        # A description of the image, for users of assistive technologies.
        [string] $AlternateText,

        # Specify that the online images should be downloaded, regardless of if they have been cached to the TEMP directory.
        # Used when the online resource has been updated and you need to ensure that users see the latest version.
        [switch] $IgnoreCache,

        # Specify that the image should be used as the app logo.
        [Parameter(ParameterSetName = 'AppLogo',
                   Mandatory)]
        [switch] $AppLogo,

        # Specify that the image should be used as the hero image.
        [Parameter(ParameterSetName = 'HeroImage',
                   Mandatory)]
        [switch] $HeroImage,

        # Returns an object that represents the item with which you're working. By default, this cmdlet doesn't generate any output.
        [switch] $PassThru
    )

    begin {}
    process {
        $paramSrc = if ($IgnoreCache) {
            Optimize-BTImageSource -Source $Source -ForceRefresh
        } else {
            Optimize-BTImageSource -Source $Source
        }

        if ($AppLogo.IsPresent) {
            if ($AlternateText) {
                $null = $ContentBuilder.AddAppLogoOverride($paramSrc,
                                                           $Crop,
                                                           $AlternateText)
            } else {
                $null = $ContentBuilder.AddAppLogoOverride($paramSrc,
                                                           $Crop)
            }
        } elseif ($HeroImage.IsPresent) {
            if ($AlternateText) {
                $null = $ContentBuilder.AddHeroImage($paramSrc,
                                                     $AlternateText)
            } else {
                $null = $ContentBuilder.AddHeroImage($paramSrc)
            }
        } else {
            $BTImage = [Microsoft.Toolkit.Uwp.Notifications.AdaptiveImage ]::new()
            $BTImage.Source = $paramSrc
            $BTImage.HintCrop = $Crop

            if ($AlternateText) {
                $BTImage.AlternateText = $AlternateText
            }

            $null = $ContentBuilder.AddVisualChild($BTImage)
        }

        if ($PassThru) {
            $ContentBuilder
        }
    }
    end {}
}
function Add-BTInputTextBox {
    <#
        .SYNOPSIS
        Add a text box for input to a toaster notification.
 
        .DESCRIPTION
        The Add-BTInputTextBox function adds a text box for user input to the body of a toast notification.
 
        You can include a title, which is displayed above the text box, and placeholder text which is displayed when the text box is empty.
 
        Up to five text boxes can be added to a toast notification.
 
        .INPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder. You can pipe a toast content builder object to Add-BTInputTextBox.
 
        .OUTPUTS
        None. The Add-BTInputTextBox function does not provide any output by default.
 
        You can optionally use the PassThru parameter to output the updated toast content builder object, which enables chaining functions together.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTAppLogo -ContentBuilder $Builder
 
        PS C:\>Add-BTInputTextBox -ContentBuilder $Builder -Id 'Example 01'
 
        This example adds a text box to a toast notification, specifying the toast content builder object via a parameter on the function.
 
        It also adds an app logo to the toast notification to ensure that the text box is displayed.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTAppLogo
 
        PS C:\>$Builder | Add-BTInputTextBox -Id 'Example 02'
 
        This example adds a text box to a toast notification, specifying the toast content builder object via the pipeline
 
        It also adds an app logo to the toast notification to ensure that the text box is displayed.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTAppLogo
 
        PS C:\>$Builder | Add-BTInputTextBox -Id 'Example 03' -Title "Enter your name" -PlaceholderContent "John Doe"
 
        This example adds a text box to a toast notification, specifying the toast content builder object via the pipeline.
 
        The text box will be displayed with a title above it and placeholder text to help indicate what the user should enter.
 
        It also adds an app logo to the toast notification to ensure that the text box is displayed.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTAppLogo
 
        PS C:\>$Builder | Add-BTInputTextBox -Id 'Example 04' -PlaceholderContent "Enter your name" -DefaultContent "John Doe"
 
        This example adds a text box to a toast notification, specifying the toast content builder object via the pipeline.
 
        The text box will have the default text "John Doe" when the toast is shown, and will have the placeholder text "Enter your name" if the default text is removed by the user.
 
        It also adds an app logo to the toast notification to ensure that the text box is displayed.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTAppLogo
 
        PS C:\>$Builder | Add-BTInputTextBox -Id 'Example 05 - First Name' -Title 'Set your name' -PlaceholderContent "Enter your first name" -DefaultContent "John"
 
        PS C:\>$Builder | Add-BTInputTextBox -Id 'Example 05 - Last Name' -PlaceholderContent "Enter your last name" -DefaultContent "Doe"
 
        This example adds a text box to a toast notification, specifying the toast content builder object via the pipeline.
 
        The text box will have the default text "John Doe" when the toast is shown, and will have the placeholder text "Enter your name" if the default text is removed by the user.
 
        It also adds an app logo to the toast notification to ensure that the text box is displayed.
 
        .NOTES
        You cannot create a toast notification with only text boxes, as they are only displayed when some other element has been added to the toast notification such as an app logo, text, or image.
 
        .LINK
        https://docs.toastit.dev/commands/add-btinputtextbox
    #>


    [CmdletBinding()]
    param (
        # The toast content builder object that represents the toast notification being constructed.
        [Parameter(Mandatory,
                   ValueFromPipeline)]
        [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder] $ContentBuilder,

        # ID used to identify a specific text box.
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string] $Id,

        # Title text to display above the element.
        [string] $Title,

        # Placeholder text to be displayed on the text box when the user hasn't typed any text yet.
        # If this is used with the DefaultContent parameter, this content will only be displayed if the default content is removed.
        [string] $PlaceholderContent,

        # The default text in the text box.
        [string] $DefaultContent,

        # Returns an object that represents the item with which you're working. By default, this cmdlet doesn't generate any output.
        [switch] $PassThru
    )

    begin {}
    process {
        $ToastTextBox = [Microsoft.Toolkit.Uwp.Notifications.ToastTextBox]::new($Id)

        if ($null -ne $Title) {
            $ToastTextBox.Title = $Title
        }

        if ($null -ne $PlaceholderContent) {
            $ToastTextBox.PlaceholderContent = $PlaceholderContent
        }

        if ($null -ne $DefaultContent) {
            $ToastTextBox.DefaultInput = $DefaultContent
        }

        try {
            $null = $ContentBuilder.AddToastInput($ToastTextBox)
        } catch {
            Write-Warning ('The max number of text and selection boxes (5) on the toast notification has been reached. ' +
                'You cannot add any more input boxes.')
        }

        if ($PassThru) {
            $ContentBuilder
        }
    }
    end {}
}
function Add-BTText {
    <#
        .SYNOPSIS
        Add text to the toast.
 
        .DESCRIPTION
        The Add-BTText function adds custom text to a toast notification via a content builder object.
 
        By default this text will be added to the body of the toast. You can also add attribution text using the Attribution switch.
 
        .INPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder. You can pipe a toast content builder object to Add-BTText.
 
        System.String. You can provide multiple strings at once, but they cannot be piped.
 
        .OUTPUTS
        None. The Add-BTText function does not provide any output by default.
 
        You can optionally use the PassThru parameter to output the updated toast content builder object, which enables chaining functions together.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>Add-BTText -ContentBuilder $Builder -Text 'First Line of Text'
 
        This example adds one custom text element to the toast content builder object stored in the $Builder variable using the ContentBuilder parameter explicitly.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text'
 
        This example adds one custom text element to the toast content builder object stored in the $Builder variable by piping it into the Add-BTText function.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text', 'Second Line of Text'
 
        This example adds two custom text elements to a toast content builder object with a single call of the Add-BTText function.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text'
 
        PS C:\>$Builder | Add-BTText -Text 'Second Line of Text'
 
        This example adds two custom text elements to a toast content builder object with two discrete calls of the Add-BTText function.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text' -PassThru |
                          Add-BTText -Text 'Second Line of Text' -PassThru |
                          Add-BTText -Text 'Third Line of Text'
 
        This example adds three custom text elements to a toast content builder object using multiple calls of the Add-BTText function on the pipeline.
 
        The PassThru parameter is used to pass the toast content builder down the pipeline. Note that this is not required at the end of the pipeline as the builder object being added to is already stored in a variable.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text'
 
        PS C:\>$Builder | Add-BTText -Text 'Second Line of Text'
 
        PS C:\>$Builder | Add-BTText -Text 'Third Line of Text'
 
        PS C:\>$Builder | Add-BTText -Text 'Fourth Line of Text'
 
        This example attempts to add four custom text elements to a toast content builder object.
 
        Only the first three of these elements will be added and the fourth will generate a warning stating that the maximum number of lines has been reached.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text' -MaxLines 1
 
        PS C:\>$Builder | Add-BTText -Text 'Second Line of Text',
                                           'Third Line of Text',
                                           'Fourth Line of Text'
 
        This example sets the max lines for the first custom text element to 1, overriding the default value of 2.
 
        This means the toast notification can now accept four custom text elements, each with a max line count of 1, for a total line count of 4.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text' -Language en-NZ
 
        This example specifies that the language included in the text element is New Zealand English using the relevant BCP-47 code, en-NZ.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'Example Toast Source' -Attribution
 
        This example add attribution test to a toast notification.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'Placeholder String' -Bindable
 
        This example adds a bindable string to a toast notification that should map to a key/value pair in the toast's data binding property.
 
        .NOTES
        A toast notification can contain a maximum of four reserved lines of text. By default this means you can include three customer text elements as the first, which acts like a heading, automatically reserves 2 lines.
 
        You can override this behavior using the MaxLines parameter, specifically by setting the first line to a maximum of 1 line.
 
        This function will ignore any text elements that would exceed this limit and output a warning stating this.
 
        Attribution text is displayed underneath other text elements, but above image elements. You can only have one attribution text element per toast notification and adding attribution to a notification will override any existing attribution text.
 
        .LINK
        https://docs.toastit.dev/commands/add-bttext
    #>


    [CmdletBinding(DefaultParameterSetName = 'CustomText')]
    param (
        # The toast content builder object that represents the toast notification being constructed.
        [Parameter(Mandatory,
                   ValueFromPipeline)]
        [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder] $ContentBuilder,

        # Custom text to display on the tile.
        [Parameter(Mandatory,
                   Position = 0)]
        [ValidateNotNull()]
        [ValidateCount(1,4)]
        [string[]] $Text,

        # The maximum number of lines the text element is allowed to display.
        [Parameter(ParameterSetName = 'CustomText')]
        [ValidateRange(1,2)]
        [int] $MaxLines,

        # Specifies that the text should be considered the name of a bindable string to be used when updating information on a toast notification.
        [Parameter(ParameterSetName = 'CustomText')]
        [switch] $Bindable,

        # Specifies that the text should be added as attribution text.
        [Parameter(Mandatory,
                   ParameterSetName = 'AttributionText')]
        [switch] $Attribution,

        # The target locale of the toast notification, specified as a BCP-47 language tags such as "en-US" or "fr-FR".
        # The locale specified here overrides any other specified locale, such as that in binding or visual.
        [string] $Language,

        # Returns an object that represents the item with which you're working. By default, this cmdlet doesn't generate any output.
        [switch] $PassThru
    )

    begin {}
    process {
        if ($Attribution) {
            if ($Text.Count -gt 1) {
                Write-Warning ('Attribution text can only contain a single string and more than one was provided. ' +
                    'Only the first string will be used.')
            }

            if ($null -ne $ContentBuilder.Content.Visual.BindingGeneric.Attribution.Text) {
                Write-Warning ('Attribution text can only be set once per toast notification. ' +
                    'The existing attribution text will be overwritten.')
            }

            if ($Language) {
                $null = $ContentBuilder.AddAttributionText($Text[0], $Language)
            } else {
                $null = $ContentBuilder.AddAttributionText($Text[0])
            }
        } else {
            $paraStyle    = $null
            $paraWrap     = $null
            $paraMaxLines = if ($MaxLines) {$MaxLines} else {$null}
            $paraMinLines = $null
            $paraAlign    = $null

            try {
                foreach ($Line in $Text) {
                    if ($Bindable) {
                        $ExistingLineCount = 0
                        foreach ($ExistingLine in $ContentBuilder.Content.Visual.BindingGeneric.Children) {
                            if ($ExistingLine.GetType().Name -eq 'AdaptiveText') {
                                if ($ExistingLineCount -eq 0 -and $null -eq $ExistingLine.HintMaxLines) {
                                    $ExistingLineCount += if ($ExistingLine.HintMinLines) {
                                        $ExistingLine.HintMinLines
                                    } else {
                                        2
                                    }
                                } else {
                                    $ExistingLineCount += if ($ExistingLine.HintMinLines) {
                                        $ExistingLine.HintMinLines
                                    } else {
                                        1
                                    }
                                }
                            }
                        }

                        if ($ExistingLineCount -ge 4) {
                            throw
                        }

                        $AdaptiveText = [Microsoft.Toolkit.Uwp.Notifications.AdaptiveText]::new()

                        if ($MaxLines) {
                            $AdaptiveText.HintMaxLines = $MaxLines
                        }

                        if ($Language) {
                            $AdaptiveText.Language = $Language
                        }

                        $AdaptiveText.Text = [Microsoft.Toolkit.Uwp.Notifications.BindableString]::new($Line)

                        $null = $ContentBuilder.AddVisualChild($AdaptiveText)
                    } else {
                        if ($Language) {
                            $null = $ContentBuilder.AddText($Line,
                                                            $paraStyle,
                                                            $paraWrap,
                                                            $paraMaxLines,
                                                            $paraMinLines,
                                                            $paraAlign,
                                                            $Language)
                        } else {
                            $null = $ContentBuilder.AddText($Line,
                                                            $paraStyle,
                                                            $paraWrap,
                                                            $paraMaxLines,
                                                            $paraMinLines,
                                                            $paraAlign)
                        }
                    }
                }
            } catch {
                Write-Warning ('The max lines of text (4) on the toast notification has been reached, extra lines have been ignored. ' +
                    'The first text element automatically reserves 2 lines of text, consider using the MaxLines parameter to override this.')
            }
        }

        if ($PassThru) {
            $ContentBuilder
        }
    }
    end {}
}
function New-BTContentBuilder {
    <#
        .SYNOPSIS
        Create a toast builder object.
 
        .DESCRIPTION
        The New-BTContentBuilder function creates a new toast content builder object to construct a complete notification.
 
        .INPUTS
        None. You cannot pipe objects to New-BTContentBuilder.
 
        .OUTPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        This example creates a new toast content builder object and storing it in a variable named $Builder.
 
        .EXAMPLE
        PS C:\>$Builder = Builder
 
        This example creates a new toast content builder object using the Builder alias and storing it in a variable named $Builder.
 
        .LINK
        https://docs.toastit.dev/commands/new-btcontentbuilder
    #>


    [Alias('Builder')]
    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [ValidateNotNullOrEmpty()]
        [ValidateLength(1, 64)]
        [string] $Group = 'BurntToast',

        [ValidateNotNullOrEmpty()]
        [ValidateLength(1, 64)]
        [string] $Tag = [Guid]::NewGuid().ToString()
    )

    if ($PSCmdlet.ShouldProcess( "Creating instance of a ToastContentBuilder object and returning it.", $env:COMPUTERNAME, 'New-BTContentBuilder' )) {
        $Builder = [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder]::new()
        $Builder | Add-Member -MemberType NoteProperty -Name 'Group' -Value $Group
        $Builder | Add-Member -MemberType NoteProperty -Name 'Tag' -Value $Tag
        $Builder | Add-Member -MemberType NoteProperty -Name 'DataBinding' -Value @{}
        $Builder
    }
}
function Show-BTNotification {
    <#
        .SYNOPSIS
        Shows a new toast notification.
 
        .DESCRIPTION
        The Show-BTNotification function shows a new toast notification with its configured content.
 
        .INPUTS
        Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder. You can pipe a toast content builder object to Show-BTNotification.
 
        .OUTPUTS
        None
 
        .EXAMPLE
        PS C:\>Show-BTNotification -ContentBuilder $ToastContentBuilder
 
        This command displays a toast notification with the content of the ToastContentBuilder object.
 
        .EXAMPLE
        PS C:\>$ToastContentBuilder | Show-BTNotification
 
        This command displays a toast notification with the content of the ToastContentBuilder object supplied via the pipeline.
 
        .EXAMPLE
        PS C:\>$Builder = New-BTContentBuilder
 
        PS C:\>$Builder | Add-BTText -Text 'First Line of Text', 'Second Line of Text'
 
        PS C:\>Show-BTNotification -ContentBuilder $Builder
 
        This example demonstrates the full life cycle of a ToastContentBuilder object from creation to display.
 
        .LINK
        https://docs.toastit.dev/commands/show-btnotification
    #>


    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory,
                   Position = 0,
                   ValueFromPipeline = $true)]
        [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder[]] $ContentBuilder
    )

    begin {}
    process {
        foreach ($Builder in $ContentBuilder) {
            if($PSCmdlet.ShouldProcess( "submitting: $($Builder.GetToastContent().GetContent())")) {
                $Toast = [Windows.UI.Notifications.ToastNotification]::new($Builder.GetXml())

                if ($Builder.DataBinding) {
                    $DataDictionary = New-Object 'system.collections.generic.dictionary[string,string]'

                    foreach ($BindingKey in $Builder.DataBinding.Keys) {
                        $DataDictionary.Add($BindingKey, $Builder.DataBinding.$BindingKey)
                    }

                    $Toast.Data = [Windows.UI.Notifications.NotificationData]::new($DataDictionary)
                }

                $Toast.Group = $Builder.Group
                $Toast.Tag = $Builder.Tag

                [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($Script:Config.AppId).Show($Toast)
            }
        }
    }
    end {}
}
$PublicFunctions = 'Add-BTDataBinding', 'Add-BTImage', 'Add-BTInputTextBox', 'Add-BTText', 'New-BTContentBuilder', 'Show-BTNotification'
$WinMajorVersion = (Get-CimInstance -ClassName Win32_OperatingSystem -Property Version).Version.Split('.')[0]

if ($WinMajorVersion -ge 10) {
    [int] $WinBuild = (Get-CimInstance -ClassName Win32_OperatingSystem -Property BuildNumber).BuildNumber

    if ($WinBuild -ge 15063) {
        $Paths = if ($IsWindows) {
            "$PSScriptRoot\lib\Microsoft.Toolkit.Uwp.Notifications\net5.0-windows10.0.17763\*.dll",
            "$PSScriptRoot\lib\Microsoft.Windows.SDK.NET\*.dll"
        } else {
            "$PSScriptRoot\lib\Microsoft.Toolkit.Uwp.Notifications\net461\*.dll"
        }

        $Library = @( Get-ChildItem -Path $Paths -Recurse -ErrorAction SilentlyContinue )

        # Add one class from each expected DLL here:
        $LibraryMap = @{
            'Microsoft.Toolkit.Uwp.Notifications.dll' = 'Microsoft.Toolkit.Uwp.Notifications.ToastContent'
        }

        $Script:Config = Get-Content -Path $PSScriptRoot\config.json -ErrorAction SilentlyContinue | ConvertFrom-Json
        $Script:DefaultImage = if ($Script:Config.AppLogo -match '^[.\\]') {
            "$PSScriptRoot$($Script:Config.AppLogo)"
        } else {
            $Script:Config.AppLogo
        }

        foreach ($Type in $Library) {
            try {
                if (-not ($LibraryMap[$Type.Name]  -as [type])) {
                    Add-Type -Path $Type.FullName -ErrorAction Stop
                }
            } catch {
                Write-Error -Message "Failed to load library $($Type.FullName): $_"
            }
        }

        Export-ModuleMember -Alias 'Builder'
        Export-ModuleMember -Function $PublicFunctions
    } else {
        throw 'This version of BurntToast will only work on Windows 10 Creators Update (15063) and above. ' +
              'If you would like to use BurntToast on earlier Windows 10 builds, please downgrade to a version of the module below 1.0'
    }
} else {
    throw 'This version of BurntToast will only work on Windows 10. ' +
          'If you would like to use BurntToast on Windows 8, please use version 0.4'
}