MobileMkch/ui/optimization.go
2025-08-05 20:08:15 +03:00

180 lines
2.9 KiB
Go

package ui
import (
"sync"
"time"
"fyne.io/fyne/v2"
)
type Debouncer struct {
mu sync.Mutex
timer *time.Timer
duration time.Duration
callback func()
}
func NewDebouncer(duration time.Duration, callback func()) *Debouncer {
return &Debouncer{
duration: duration,
callback: callback,
}
}
func (d *Debouncer) Trigger() {
d.mu.Lock()
defer d.mu.Unlock()
if d.timer != nil {
d.timer.Stop()
}
d.timer = time.AfterFunc(d.duration, func() {
fyne.Do(d.callback)
})
}
type Throttler struct {
mu sync.Mutex
lastCall time.Time
interval time.Duration
callback func()
}
func NewThrottler(interval time.Duration, callback func()) *Throttler {
return &Throttler{
interval: interval,
callback: callback,
}
}
func (t *Throttler) Trigger() {
t.mu.Lock()
defer t.mu.Unlock()
now := time.Now()
if now.Sub(t.lastCall) >= t.interval {
t.lastCall = now
fyne.Do(t.callback)
}
}
type LazyLoader struct {
mu sync.Mutex
loaded bool
loading bool
callback func()
}
func NewLazyLoader(callback func()) *LazyLoader {
return &LazyLoader{
callback: callback,
}
}
func (l *LazyLoader) Load() {
l.mu.Lock()
defer l.mu.Unlock()
if l.loaded || l.loading {
return
}
l.loading = true
go func() {
l.callback()
l.mu.Lock()
l.loaded = true
l.loading = false
l.mu.Unlock()
}()
}
type VirtualList struct {
items []interface{}
renderer func(item interface{}) fyne.CanvasObject
visible int
start int
end int
}
func NewVirtualList(items []interface{}, renderer func(item interface{}) fyne.CanvasObject, visible int) *VirtualList {
return &VirtualList{
items: items,
renderer: renderer,
visible: visible,
end: visible,
}
}
func (vl *VirtualList) GetVisibleItems() []fyne.CanvasObject {
if vl.start >= len(vl.items) {
return []fyne.CanvasObject{}
}
if vl.end > len(vl.items) {
vl.end = len(vl.items)
}
var result []fyne.CanvasObject
for i := vl.start; i < vl.end; i++ {
result = append(result, vl.renderer(vl.items[i]))
}
return result
}
func (vl *VirtualList) ScrollTo(index int) {
if index < 0 {
index = 0
}
if index >= len(vl.items) {
index = len(vl.items) - 1
}
vl.start = index
vl.end = index + vl.visible
if vl.end > len(vl.items) {
vl.end = len(vl.items)
vl.start = vl.end - vl.visible
if vl.start < 0 {
vl.start = 0
}
}
}
type MemoryPool struct {
mu sync.Mutex
items []interface{}
new func() interface{}
reset func(interface{})
}
func NewMemoryPool(new func() interface{}, reset func(interface{})) *MemoryPool {
return &MemoryPool{
new: new,
reset: reset,
}
}
func (mp *MemoryPool) Get() interface{} {
mp.mu.Lock()
defer mp.mu.Unlock()
if len(mp.items) > 0 {
item := mp.items[len(mp.items)-1]
mp.items = mp.items[:len(mp.items)-1]
mp.reset(item)
return item
}
return mp.new()
}
func (mp *MemoryPool) Put(item interface{}) {
mp.mu.Lock()
defer mp.mu.Unlock()
mp.items = append(mp.items, item)
}