fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
25.02k stars 1.39k forks source link

Windows: App Icon in Notification #2592

Closed luciferchase closed 6 months ago

luciferchase commented 3 years ago

Is your feature request related to a problem? Please describe:

There is no App Icon in the notification sent by Fyne App (At least in windows, haven't checked with other platforms).

fyne-notification

Is it possible to construct a solution with the existing API?

No.

Describe the solution you'd like to see:

Include app icon both in the toast and in the notification centre as well like this?

notification-with-icon

Jacalz commented 3 years ago

Have you packed this with the fyne package command? I think it could be required that you package the application first.

luciferchase commented 3 years ago

Yes, I checked this with the fyne package too, same result.

Jacalz commented 3 years ago

Thanks for verifying. We should get this fixed.

andydotxyz commented 2 years ago

As best as I can tell this metadata comes from the packaged app metadata. This metadata is only added when preparing for release ("fyne release") with the appropriate signing etc. Can you please try packaging a release and install the result to see if it is fixed?

luciferchase commented 2 years ago

I would love to do so, but unfortunately, I don't know how to do certification, signing etc. Sorry!

montovaneli commented 7 months ago

Regarding this issue, I analyzed the app_windows.go file and saw that the toast template used is ToastText02, which does not allow images. We can use ToastImageAndText02, for example.

Moreover, in PowerShell, the Windows Toast notification requires a file path for the icon.

To work around this, I changed the PowerShell script template to:

const notificationTemplate = `$title = "%s"
$content = "%s"
$iconPath = "file:///%s" # The icon path must be a file URI

[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastImageAndText02)
$toastXml = [xml] $template.GetXml()

$toastXml.GetElementsByTagName("text")[0].AppendChild($toastXml.CreateTextNode($title)) > $null
$toastXml.GetElementsByTagName("text")[1].AppendChild($toastXml.CreateTextNode($content)) > $null

$toastXml.GetElementsByTagName("image")[0].SetAttribute("src", $iconPath) # Set Icon

$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
$xml.LoadXml($toastXml.OuterXml)
$toast = [Windows.UI.Notifications.ToastNotification]::new($xml)
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("%s").Show($toast);`

And I also changed the SendNotification function to create a icon temp file:

func (a *fyneApp) SendNotification(n *fyne.Notification) {
    title := escapeNotificationString(n.Title)
    content := escapeNotificationString(n.Content)
    appID := a.UniqueID()
    if appID == "" || strings.Index(appID, "missing-id") == 0 {
        appID = a.Metadata().Name
    }

    // parse iconFileName and iconFilePath
    iconFileName := fmt.Sprintf("fyne-%s-%d.ico", appID, scriptNum)
    iconFilePath := filepath.Join(os.TempDir(), iconFileName)

    // check if the file exists (if so, do not create it for better performance)
    if _, err := os.Stat(iconFilePath); os.IsNotExist(err) {

            // I also removed forbidden characters from the icon file name (fear of appId with forbidden chars?)
            var forbiddenChars = []string{"<", ">", ":", "\"", "/", "\\", "|", "?", "*"}
            for _, char := range forbiddenChars {
                iconFileName = strings.ReplaceAll(iconFileName, char, "")
            }   
        // create the file
        err := os.WriteFile(iconFilePath, a.Icon().Content(), 0600)
        if err != nil {
            fyne.LogError("Could not write script to show notification", err)
            return
        }
    }

    script := fmt.Sprintf(notificationTemplate, title, content, iconFilePath, appID)
    go runScript("notify", script)
}

This way, the icon is correctly displayed on Windows using the default app icon using fyne package.

andydotxyz commented 7 months ago

That sounds like a clever approach, thanks. Can you open a PR to that extent and we can work through getting it included?

Thanks!

montovaneli commented 7 months ago

That sounds like a clever approach, thanks. Can you open a PR to that extent and we can work through getting it included?

Thanks!

Done! #4764

andydotxyz commented 6 months ago

This is now landed on develop branch for v2.5.0 :)