fyne 2.6.1 update, make all gui threadsafe

This commit is contained in:
aynakeya
2025-06-15 00:04:13 +08:00
parent 45e4c15b8d
commit dd71c3b9ba
15 changed files with 108 additions and 76 deletions

37
go.mod
View File

@@ -10,7 +10,7 @@ replace (
)
require (
fyne.io/fyne/v2 v2.5.4
fyne.io/fyne/v2 v2.6.1
github.com/AynaLivePlayer/liveroom-sdk v0.1.0
github.com/AynaLivePlayer/miaosic v0.1.5
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b
@@ -25,12 +25,12 @@ require (
github.com/saltosystems/winrt-go v0.0.0-20240320184339-289d313a74b7
github.com/sirupsen/logrus v1.9.3
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.10.0
github.com/tidwall/gjson v1.17.3
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459
go.uber.org/zap v1.26.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/sys v0.25.0
golang.org/x/sys v0.30.0
gopkg.in/ini.v1 v1.67.0
)
@@ -48,22 +48,24 @@ require (
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 // indirect
github.com/fredbi/uri v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
github.com/fyne-io/glfw-js v0.0.0-20241126112943-313d8a0fe1d0 // indirect
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
github.com/fyne-io/gl-js v0.1.0 // indirect
github.com/fyne-io/glfw-js v0.2.0 // indirect
github.com/fyne-io/image v0.1.1 // indirect
github.com/fyne-io/oksvg v0.1.0 // indirect
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
github.com/go-text/render v0.2.0 // indirect
github.com/go-text/typesetting v0.2.0 // indirect
github.com/go-text/typesetting v0.2.1 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/jeandeaual/go-locale v0.0.0-20240223122105-ce5225dcaa49 // indirect
github.com/hack-pad/go-indexeddb v0.3.2 // indirect
github.com/hack-pad/safejs v0.1.0 // indirect
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.3.0 // indirect
github.com/rymdport/portal v0.4.1 // indirect
github.com/sahilm/fuzzy v0.1.0 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/spf13/cast v1.5.1 // indirect
@@ -71,12 +73,11 @@ require (
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/yuin/goldmark v1.7.1 // indirect
github.com/yuin/goldmark v1.7.8 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -37,7 +37,8 @@ func (b *AsyncButton) SetOnTapped(f func()) {
b.Disable()
go func() {
f()
b.Enable()
//time.Sleep(3 * time.Second)
fyne.Do(b.Enable)
}()
}
}

View File

@@ -5,6 +5,7 @@ import (
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/component"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/config"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
@@ -44,10 +45,10 @@ func (b *bascicConfig) CreatePanel() fyne.CanvasObject {
})
global.EventManager.RegisterA(events.PlaylistModeChangeUpdate(model.PlaylistIDPlayer),
"gui.config.basic.random_playlist.player",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.PlaylistModeChangeUpdateEvent)
playerRandomCheck.SetChecked(data.Mode == model.PlaylistModeRandom)
})
}))
systemRandomCheck := widget.NewCheck(i18n.T("gui.config.basic.random_playlist.system"),
func(b bool) {
@@ -63,10 +64,10 @@ func (b *bascicConfig) CreatePanel() fyne.CanvasObject {
global.EventManager.RegisterA(events.PlaylistModeChangeUpdate(model.PlaylistIDSystem),
"gui.config.basic.random_playlist.system",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.PlaylistModeChangeUpdateEvent)
systemRandomCheck.SetChecked(data.Mode == model.PlaylistModeRandom)
})
}))
randomPlaylist := container.NewHBox(
widget.NewLabel(i18n.T("gui.config.basic.random_playlist")),
@@ -86,7 +87,7 @@ func (b *bascicConfig) CreatePanel() fyne.CanvasObject {
global.EventManager.RegisterA(
events.PlayerAudioDeviceUpdate,
"gui.config.basic.audio_device.update",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.PlayerAudioDeviceUpdateEvent)
devices := make([]string, len(data.Devices))
deviceDesc2Name = make(map[string]string)
@@ -102,7 +103,7 @@ func (b *bascicConfig) CreatePanel() fyne.CanvasObject {
deviceSel.Options = devices
deviceSel.Selected = currentDevice
deviceSel.Refresh()
})
}))
outputDevice := container.NewBorder(nil, nil,
widget.NewLabel(i18n.T("gui.config.basic.audio_device")), nil,

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/config"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
@@ -34,6 +35,7 @@ func Initialize() {
logger = global.Logger.WithPrefix("GUI")
black_magic()
logger.Info("Initializing GUI")
_ = os.Setenv("FYNE_FONT", config.GetAssetPath("msyha.ttc"))
if !config.General.UseSystemFonts {
_ = os.Setenv("FYNE_FONT", config.GetAssetPath("msyh.ttc"))
}
@@ -68,18 +70,19 @@ func Initialize() {
//MainWindow.Resize(fyne.NewSize(1280, 720))
MainWindow.Resize(fyne.NewSize(config.General.Width, config.General.Height))
setupPlayerWindow()
// todo: fix, window were created even if not show. this block gui from closing
// setupPlayerWindow()
// register error
global.EventManager.RegisterA(
events.ErrorUpdate, "gui.show_error", func(e *event.Event) {
events.ErrorUpdate, "gui.show_error", gutil.ThreadSafeHandler(func(e *event.Event) {
err := e.Data.(events.ErrorUpdateEvent).Error
logger.Warnf("gui received error event: %v, %v", err, err == nil)
if err == nil {
return
}
dialog.ShowError(err, MainWindow)
})
}))
checkUpdate()
MainWindow.SetFixedSize(config.General.FixedSize)
@@ -94,6 +97,7 @@ func Initialize() {
})
}
MainWindow.SetOnClosed(func() {
logger.Infof("GUI closing")
if playerWindow != nil {
playerWindow.Close()
}

15
gui/gutil/fyne.go Normal file
View File

@@ -0,0 +1,15 @@
package gutil
import (
"AynaLivePlayer/pkg/event"
"fyne.io/fyne/v2"
)
// since 2.6.1, calls to fyne API from other go routine must be wrapped in fyne.Do
func ThreadSafeHandler(fn func(e *event.Event)) func(e *event.Event) {
return func(e *event.Event) {
fyne.Do(func() {
fn(e)
})
}
}

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fmt"
@@ -76,10 +77,10 @@ func createHistoryList() fyne.CanvasObject {
func registerHistoryHandler() {
global.EventManager.RegisterA(
events.PlaylistDetailUpdate(model.PlaylistIDHistory),
"gui.history.update", func(event *event.Event) {
"gui.history.update", gutil.ThreadSafeHandler(func(event *event.Event) {
History.mux.Lock()
History.Medias = event.Data.(events.PlaylistDetailUpdateEvent).Medias
History.List.Refresh()
History.mux.Unlock()
})
}))
}

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/gui/xfyne"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
@@ -135,14 +136,14 @@ func registerRoomHandlers() {
global.EventManager.RegisterA(
events.LiveRoomProviderUpdate,
"gui.liveroom.provider_update",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
RoomTab.providers = event.Data.(events.LiveRoomProviderUpdateEvent).Providers
RoomTab.Rooms.Refresh()
})
}))
global.EventManager.RegisterA(
events.LiveRoomRoomsUpdate,
"gui.liveroom.rooms_update",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
logger.Infof("Update rooms")
data := event.Data.(events.LiveRoomRoomsUpdateEvent)
RoomTab.lock.Lock()
@@ -150,11 +151,11 @@ func registerRoomHandlers() {
RoomTab.Rooms.Select(0)
RoomTab.Rooms.Refresh()
RoomTab.lock.Unlock()
})
}))
global.EventManager.RegisterA(
events.LiveRoomStatusUpdate,
"gui.liveroom.room_status_update",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
room := event.Data.(events.LiveRoomStatusUpdateEvent).Room
index := -1
for i := 0; i < len(RoomTab.rooms); i++ {
@@ -182,7 +183,7 @@ func registerRoomHandlers() {
}
RoomTab.Status.Refresh()
}
})
}))
}
@@ -216,10 +217,10 @@ func createRoomController() fyne.CanvasObject {
global.EventManager.RegisterA(
events.LiveRoomOperationFinish,
"gui.liveroom.operation_finish",
func(event *event.Event) {
gutil.ThreadSafeHandler(func(event *event.Event) {
RoomTab.ConnectBtn.Enable()
RoomTab.DisConnectBtn.Enable()
})
}))
RoomTab.Status = widget.NewLabel(i18n.T("gui.room.waiting"))
RoomTab.RoomTitle = widget.NewLabel("")
RoomTab.RoomID = widget.NewLabel("")

View File

@@ -59,7 +59,7 @@ func registerPlayControllerHandler() {
PlayController.ButtonLrc.OnTapped = func() {
if !PlayController.LrcWindowOpen {
PlayController.LrcWindowOpen = true
createLyricWindow().Show()
createLyricWindow().Close()
}
}
@@ -67,26 +67,25 @@ func registerPlayControllerHandler() {
showPlayerWindow()
}
global.EventManager.RegisterA(events.PlayerPropertyPauseUpdate, "gui.player.controller.paused", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyPauseUpdate, "gui.player.controller.paused", gutil.ThreadSafeHandler(func(event *event.Event) {
if event.Data.(events.PlayerPropertyPauseUpdateEvent).Paused {
PlayController.ButtonSwitch.Icon = theme.MediaPlayIcon()
} else {
PlayController.ButtonSwitch.Icon = theme.MediaPauseIcon()
}
PlayController.ButtonSwitch.Refresh()
})
}))
global.EventManager.RegisterA(events.PlayerPropertyPercentPosUpdate, "gui.player.controller.percent_pos", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyPercentPosUpdate, "gui.player.controller.percent_pos", gutil.ThreadSafeHandler(func(event *event.Event) {
if PlayController.Progress.Dragging {
return
}
PlayController.Progress.Value = event.Data.(events.PlayerPropertyPercentPosUpdateEvent).PercentPos * 10
PlayController.Progress.Refresh()
})
}))
global.EventManager.RegisterA(events.PlayerPropertyIdleActiveUpdate, "gui.player.controller.idle_active", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyIdleActiveUpdate, "gui.player.controller.idle_active", gutil.ThreadSafeHandler(func(event *event.Event) {
isIdle := event.Data.(events.PlayerPropertyIdleActiveUpdateEvent).IsIdle
// todo: @3
if isIdle {
PlayController.Progress.Value = 0
PlayController.Progress.Max = 0
@@ -97,7 +96,7 @@ func registerPlayControllerHandler() {
} else {
PlayController.Progress.Max = 1000
}
})
}))
PlayController.Progress.Max = 0
PlayController.Progress.OnDragEnd = func(f float64) {
@@ -107,18 +106,18 @@ func registerPlayControllerHandler() {
})
}
global.EventManager.RegisterA(events.PlayerPropertyTimePosUpdate, "gui.player.controller.time_pos", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyTimePosUpdate, "gui.player.controller.time_pos", gutil.ThreadSafeHandler(func(event *event.Event) {
PlayController.CurrentTime.SetText(util.FormatTime(int(event.Data.(events.PlayerPropertyTimePosUpdateEvent).TimePos)))
})
}))
global.EventManager.RegisterA(events.PlayerPropertyDurationUpdate, "gui.player.controller.duration", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyDurationUpdate, "gui.player.controller.duration", gutil.ThreadSafeHandler(func(event *event.Event) {
PlayController.TotalTime.SetText(util.FormatTime(int(event.Data.(events.PlayerPropertyDurationUpdateEvent).Duration)))
})
}))
global.EventManager.RegisterA(events.PlayerPropertyVolumeUpdate, "gui.player.controller.volume", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerPropertyVolumeUpdate, "gui.player.controller.volume", gutil.ThreadSafeHandler(func(event *event.Event) {
PlayController.Volume.Value = event.Data.(events.PlayerPropertyVolumeUpdateEvent).Volume
PlayController.Volume.Refresh()
})
}))
PlayController.Volume.OnChanged = func(f float64) {
global.EventManager.CallA(events.PlayerVolumeChangeCmd, events.PlayerVolumeChangeCmdEvent{
@@ -126,7 +125,8 @@ func registerPlayControllerHandler() {
})
}
global.EventManager.RegisterA(events.PlayerPlayingUpdate, "gui.player.updateinfo", func(event *event.Event) {
// todo: double check cover loading for new thread model
global.EventManager.RegisterA(events.PlayerPlayingUpdate, "gui.player.updateinfo", gutil.ThreadSafeHandler(func(event *event.Event) {
if event.Data.(events.PlayerPlayingUpdateEvent).Removed {
PlayController.Progress.Value = 0
PlayController.Progress.Max = 0
@@ -181,7 +181,7 @@ func registerPlayControllerHandler() {
}()
}
})
}))
}
func createPlayControllerV2() fyne.CanvasObject {

View File

@@ -3,6 +3,7 @@ package gui
import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fyne.io/fyne/v2"
@@ -41,8 +42,9 @@ func createLyricWindow() fyne.Window {
w.CenterOnScreen()
// register handlers
// todo: lyric not update correctly, known bug https://github.com/fyne-io/fyne/pull/5783
global.EventManager.RegisterA(
events.PlayerLyricPosUpdate, "player.lyric.current_lyric", func(event *event.Event) {
events.PlayerLyricPosUpdate, "player.lyric.current_lyric", gutil.ThreadSafeHandler(func(event *event.Event) {
e := event.Data.(events.PlayerLyricPosUpdateEvent)
logger.Debug("lyric update", e)
if prevIndex >= len(fullLrc.Objects) || e.CurrentIndex >= len(fullLrc.Objects) {
@@ -66,13 +68,13 @@ func createLyricWindow() fyne.Window {
},
})
fullLrc.Refresh()
})
}))
global.EventManager.RegisterA(events.PlayerLyricReload, "player.lyric.current_lyric", func(event *event.Event) {
global.EventManager.RegisterA(events.PlayerLyricReload, "player.lyric.current_lyric", gutil.ThreadSafeHandler(func(event *event.Event) {
e := event.Data.(events.PlayerLyricReloadEvent)
fullLrc.Objects = createLyricObj(&e.Lyrics)
lrcWindow.Refresh()
})
}))
global.EventManager.CallA(events.PlayerLyricRequestCmd, events.PlayerLyricRequestCmdEvent{})

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fmt"
@@ -74,12 +75,12 @@ func createPlaylist() fyne.CanvasObject {
object.(*fyne.Container).Objects[1].(*widget.Label).SetText(fmt.Sprintf("%d", id))
object.(*fyne.Container).Objects[2].(*playlistOperationButton).Index = id
})
global.EventManager.RegisterA(events.PlaylistDetailUpdate(model.PlaylistIDPlayer), "gui.player.playlist.update", func(event *event.Event) {
global.EventManager.RegisterA(events.PlaylistDetailUpdate(model.PlaylistIDPlayer), "gui.player.playlist.update", gutil.ThreadSafeHandler(func(event *event.Event) {
UserPlaylist.mux.Lock()
UserPlaylist.Medias = event.Data.(events.PlaylistDetailUpdateEvent).Medias
UserPlaylist.List.Refresh()
UserPlaylist.mux.Unlock()
})
}))
return container.NewBorder(
container.NewBorder(nil, nil,
widget.NewLabel("#"), widget.NewLabel(i18n.T("gui.player.playlist.ops")),

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/gui/xfyne"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
@@ -97,14 +98,14 @@ func createPlaylists() fyne.CanvasObject {
})
}
global.EventManager.RegisterA(events.MediaProviderUpdate,
"gui.playlists.provider.update", func(event *event.Event) {
"gui.playlists.provider.update", gutil.ThreadSafeHandler(func(event *event.Event) {
providers := event.Data.(events.MediaProviderUpdateEvent)
s := make([]string, len(providers.Providers))
copy(s, providers.Providers)
PlaylistManager.providers = s
})
}))
global.EventManager.RegisterA(events.PlaylistManagerInfoUpdate,
"gui.playlists.info.update", func(event *event.Event) {
"gui.playlists.info.update", gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.PlaylistManagerInfoUpdateEvent)
prevLen := len(PlaylistManager.currentPlaylists)
PlaylistManager.currentPlaylists = data.Playlists
@@ -113,12 +114,12 @@ func createPlaylists() fyne.CanvasObject {
if prevLen != len(PlaylistManager.currentPlaylists) {
PlaylistManager.Playlists.Select(0)
}
})
}))
global.EventManager.RegisterA(events.PlaylistManagerSystemUpdate,
"gui.playlists.system.update", func(event *event.Event) {
"gui.playlists.system.update", gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.PlaylistManagerSystemUpdateEvent)
PlaylistManager.CurrentSystemPlaylist.SetText(i18n.T("gui.playlist.current") + data.Info.DisplayName())
})
}))
return container.NewHBox(
container.NewBorder(
nil, container.NewCenter(container.NewHBox(PlaylistManager.AddBtn, PlaylistManager.RemoveBtn)),
@@ -190,12 +191,12 @@ func createPlaylistMedias() fyne.CanvasObject {
}
})
global.EventManager.RegisterA(events.PlaylistManagerCurrentUpdate,
"gui.playlists.current.update", func(event *event.Event) {
"gui.playlists.current.update", gutil.ThreadSafeHandler(func(event *event.Event) {
logger.Infof("receive current playlist update, try to refresh playlist medias")
data := event.Data.(events.PlaylistManagerCurrentUpdateEvent)
PlaylistManager.currentMedias = data.Medias
PlaylistManager.PlaylistMedia.Refresh()
})
}))
return container.NewBorder(
container.NewHBox(PlaylistManager.RefreshBtn, PlaylistManager.SetAsSystemBtn, PlaylistManager.CurrentSystemPlaylist), nil,
nil, nil,

View File

@@ -5,6 +5,7 @@ import (
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/component"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fyne.io/fyne/v2"
@@ -14,7 +15,7 @@ import (
var SearchBar = &struct {
Input *component.Entry
Button *component.AsyncButton
Button *widget.Button
UseSource *widget.Select
}{}
@@ -26,7 +27,7 @@ func createSearchBar() fyne.CanvasObject {
SearchBar.Button.OnTapped()
}
}
SearchBar.Button = component.NewAsyncButton(i18n.T("gui.search.search"), func() {
SearchBar.Button = widget.NewButton(i18n.T("gui.search.search"), func() {
keyword := SearchBar.Input.Text
pr := SearchBar.UseSource.Selected
logger.Debugf("Search keyword: %s, provider: %s", keyword, pr)
@@ -41,7 +42,7 @@ func createSearchBar() fyne.CanvasObject {
})
global.EventManager.RegisterA(events.MediaProviderUpdate,
"gui.search.provider.update", func(event *event.Event) {
"gui.search.provider.update", gutil.ThreadSafeHandler(func(event *event.Event) {
providers := event.Data.(events.MediaProviderUpdateEvent)
s := make([]string, len(providers.Providers))
copy(s, providers.Providers)
@@ -49,7 +50,7 @@ func createSearchBar() fyne.CanvasObject {
if len(s) > 0 {
SearchBar.UseSource.SetSelected(s[0])
}
})
}))
SearchBar.UseSource = widget.NewSelect([]string{}, func(s string) {
})

View File

@@ -4,6 +4,7 @@ import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fmt"
@@ -61,13 +62,13 @@ func createSearchList() fyne.CanvasObject {
})
}
})
global.EventManager.RegisterA(events.SearchResultUpdate, "gui.search.update_result", func(event *event.Event) {
global.EventManager.RegisterA(events.SearchResultUpdate, "gui.search.update_result", gutil.ThreadSafeHandler(func(event *event.Event) {
items := event.Data.(events.SearchResultUpdateEvent).Medias
SearchResult.Items = items
SearchResult.mux.Lock()
SearchResult.List.Refresh()
SearchResult.mux.Unlock()
})
}))
return container.NewBorder(
container.NewBorder(nil, nil,
widget.NewLabel("#"), widget.NewLabel(i18n.T("gui.search.operation")),

View File

@@ -3,6 +3,7 @@ package gui
import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/global"
"AynaLivePlayer/gui/gutil"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fyne.io/fyne/v2/dialog"
@@ -11,7 +12,7 @@ import (
func checkUpdate() {
global.EventManager.RegisterA(
events.CheckUpdateResultUpdate, "gui.updater.check_update", func(event *event.Event) {
events.CheckUpdateResultUpdate, "gui.updater.check_update", gutil.ThreadSafeHandler(func(event *event.Event) {
data := event.Data.(events.CheckUpdateResultUpdateEvent)
msg := data.Info.Version.String() + "\n\n\n" + data.Info.Info
if data.HasUpdate {
@@ -27,5 +28,5 @@ func checkUpdate() {
widget.NewRichTextFromMarkdown(""),
MainWindow)
}
})
}))
}

View File

@@ -11,6 +11,7 @@ import (
// getGlfwWindow returns the glfw.Window pointer from a fyne.Window.
// very unsafe and ugly hacks. but it works.
// todo: replace with LifeCycle https://github.com/fyne-io/fyne/issues/4483
func getGlfwWindow(window fyne.Window) *glfw.Window {
rv := reflect.ValueOf(window)
if rv.Type().String() != "*glfw.window" {