forked from go/golangs_learn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.4 KiB
144 lines
3.4 KiB
3 years ago
|
package image
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/wailsapp/wails"
|
||
|
"optimus/backend/config"
|
||
|
"optimus/backend/stat"
|
||
|
"runtime/debug"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// FileManager handles collections of Files for conversion.
|
||
|
type FileManager struct {
|
||
|
Files []*File
|
||
|
|
||
|
Runtime *wails.Runtime
|
||
|
Logger *wails.CustomLogger
|
||
|
|
||
|
config *config.Config
|
||
|
stats *stat.Stat
|
||
|
}
|
||
|
|
||
|
// NewFileManager creates a new FileManager.
|
||
|
func NewFileManager(c *config.Config, s *stat.Stat) *FileManager {
|
||
|
return &FileManager{
|
||
|
config: c,
|
||
|
stats: s,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// WailsInit performs setup when Wails is ready.
|
||
|
func (fm *FileManager) WailsInit(runtime *wails.Runtime) error {
|
||
|
fm.Runtime = runtime
|
||
|
fm.Logger = fm.Runtime.Log.New("FileManager")
|
||
|
fm.Logger.Info("FileManager initialized...")
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// HandleFile processes a file from the client.
|
||
|
func (fm *FileManager) HandleFile(fileJson string) (err error) {
|
||
|
file := &File{Runtime: fm.Runtime}
|
||
|
if err = json.Unmarshal([]byte(fileJson), &file); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err = file.Decode(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
fm.Files = append(fm.Files, file)
|
||
|
fm.Logger.Infof("added file to file manager: %s", file.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Clear removes the files in the FileManager.
|
||
|
func (fm *FileManager) Clear() {
|
||
|
fm.Files = nil
|
||
|
debug.FreeOSMemory()
|
||
|
}
|
||
|
|
||
|
// Convert runs the conversion on all files in the FileManager.
|
||
|
func (fm *FileManager) Convert() (errs []error) {
|
||
|
var wg sync.WaitGroup
|
||
|
wg.Add(fm.countUnconverted())
|
||
|
|
||
|
c := 0
|
||
|
var b int64
|
||
|
t := time.Now().UnixNano()
|
||
|
for _, file := range fm.Files {
|
||
|
file := file
|
||
|
if !file.IsConverted {
|
||
|
go func(wg *sync.WaitGroup) {
|
||
|
err := file.Write(fm.config)
|
||
|
if err != nil {
|
||
|
fm.Logger.Errorf("failed to convert file: %s, %v", file.ID, err)
|
||
|
fm.Runtime.Events.Emit("notify", map[string]interface{}{
|
||
|
"msg": fmt.Sprintf("Failed to convert file: %s, %s", file.Name, err.Error()),
|
||
|
"type": "warn",
|
||
|
})
|
||
|
errs = append(errs, fmt.Errorf("failed to convert file: %s", file.Name))
|
||
|
} else {
|
||
|
fm.Logger.Info(fmt.Sprintf("converted file: %s", file.Name))
|
||
|
s, err := file.GetConvertedSize()
|
||
|
if err != nil {
|
||
|
fm.Logger.Errorf("failed to read converted file size: %v", err)
|
||
|
}
|
||
|
fm.Runtime.Events.Emit("conversion:complete", map[string]interface{}{
|
||
|
"id": file.ID,
|
||
|
// TODO: standardize this path conversion
|
||
|
"path": strings.Replace(file.ConvertedFile, "\\", "/", -1),
|
||
|
"size": s,
|
||
|
})
|
||
|
c++
|
||
|
s, err = file.GetSavings()
|
||
|
if err != nil {
|
||
|
fm.Logger.Errorf("failed to get file conversion savings: %v", err)
|
||
|
}
|
||
|
b += s
|
||
|
}
|
||
|
wg.Done()
|
||
|
}(&wg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
nt := (time.Now().UnixNano() - t) / 1000000
|
||
|
fm.stats.SetImageCount(c)
|
||
|
fm.stats.SetByteCount(b)
|
||
|
fm.stats.SetTimeCount(nt)
|
||
|
fm.Runtime.Events.Emit("conversion:stat", map[string]interface{}{
|
||
|
"count": c,
|
||
|
"resizes": c * len(fm.config.App.Sizes),
|
||
|
"savings": b,
|
||
|
"time": nt,
|
||
|
})
|
||
|
fm.Clear()
|
||
|
return errs
|
||
|
}
|
||
|
|
||
|
// OpenFile opens the file at the given filepath using the file's native file
|
||
|
// application.
|
||
|
func (fm *FileManager) OpenFile(p string) error {
|
||
|
if err := fm.Runtime.Browser.OpenFile(p); err != nil {
|
||
|
fm.Logger.Errorf("failed to open file %s: %v", p, err)
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// countUnconverted returns the number of files in the FileManager that haven't
|
||
|
// been converted.
|
||
|
func (fm *FileManager) countUnconverted() int {
|
||
|
c := 0
|
||
|
for _, file := range fm.Files {
|
||
|
if !file.IsConverted {
|
||
|
c++
|
||
|
}
|
||
|
}
|
||
|
return c
|
||
|
}
|