chore(wailsv3): migrate Go backend from Wails v2 to v3

Minimal-structure migration to Wails v3.0.0-beta.20 (CLI-matching pin). Single App service preserved; no domain logic touched.

- main.go: wails.Run(options.App) -> application.New + RegisterService + Window.NewWithOptions. Window keeps title-with-version, 1024x768, RGBA background, Linux icon/translucency/GpuPolicyNever, ProgramName. SingleInstanceLock -> SingleInstanceOptions (same UniqueID); callback closes over the service variable set right after New.
- app.go: App holds *application.App instead of a context. startup(ctx) is gone; the version title moves into the window options via appTitle(). onSecondInstanceLaunch takes v3 SecondInstanceData (Args/WorkingDir) and uses Window.Current() Restore+Focus plus Event.Emit for launchArgs. ShowVersion uses Dialog.Info.
- AniList/MAL/Simkl *UserFunctions.go: runtime.BrowserOpenURL -> app.Browser.OpenURL (errors logged), runtime.MessageDialog -> app.Dialog.Info chains. OAuth callback servers, token flows, and key names unchanged.
- Secrets: 99designs/keyring replaced with zalando/go-keyring (what v3 itself depends on) under the same AniTrack service name, so existing stored tokens keep working. Per-file Set helpers kept; Open/Ready boilerplate deleted (zalando needs no handle).
- go.mod: v2 + 99designs dropped (stale v2 replace directive removed), v3 beta.20 + zalando v0.2.8 added.
This commit is contained in:
John O'Keefe
2026-09-13 17:10:09 -04:00
parent 2bf8d3887e
commit 850c1c6aee
13 changed files with 184 additions and 2191 deletions
+37 -73
View File
@@ -13,41 +13,17 @@ import (
"strings"
"sync"
"github.com/99designs/keyring"
"github.com/wailsapp/wails/v2/pkg/runtime"
"github.com/zalando/go-keyring"
)
var aniListJwt AniListJWT
var aniRing keyring.Keyring
func init() {
var err error
aniRing, err = keyring.Open(keyring.Config{
ServiceName: "AniTrack",
KeychainName: "AniTrack",
KeychainSynchronizable: false,
KeychainTrustApplication: true,
KeychainAccessibleWhenUnlocked: true,
})
if err != nil {
log.Printf("anilist: secure storage unavailable: %s", err)
}
}
func aniRingReady() bool {
if aniRing == nil {
log.Println("anilist: secure storage unavailable")
return false
}
return true
}
// aniKeyringService is the OS keyring service name all AniTrack secrets
// live under (same wallet the 99designs/keyring build used).
const aniKeyringService = "AniTrack"
func aniRingSet(key string, data []byte) error {
if !aniRingReady() {
return errors.New("anilist: secure storage unavailable")
}
if err := aniRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
if err := keyring.Set(aniKeyringService, key, string(data)); err != nil {
log.Printf("anilist: save %s failed: %s", key, err)
return err
}
@@ -58,23 +34,20 @@ var aniCtxShutdown, aniCancel = context.WithCancel(context.Background())
func (a *App) CheckIfAniListLoggedIn() bool {
if (AniListJWT{} == aniListJwt) {
if !aniRingReady() {
return false
}
tokenType, tokenErr := aniRing.Get("anilistTokenType")
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
accessToken, accessTokenErr := aniRing.Get("anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
tokenType, tokenErr := keyring.Get(aniKeyringService, "anilistTokenType")
expiresIn, expiresInErr := keyring.Get(aniKeyringService, "anilistTokenExpiresIn")
refreshToken, refreshTokenErr := keyring.Get(aniKeyringService, "anilistRefreshToken")
accessToken, accessTokenErr := keyring.Get(aniKeyringService, "anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken) == 0 {
return false
} else {
var expiresInConvertErr error
aniListJwt.TokenType = string(tokenType.Data)
aniListJwt.AccessToken = string(accessToken.Data)
aniListJwt.RefreshToken = string(refreshToken.Data)
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
aniListJwt.TokenType = tokenType
aniListJwt.AccessToken = accessToken
aniListJwt.RefreshToken = refreshToken
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(expiresIn)
if expiresInConvertErr != nil {
log.Printf("anilist: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
log.Printf("anilist: invalid expiresIn %q: %s", expiresIn, expiresInConvertErr)
return false
}
return true
@@ -86,17 +59,16 @@ func (a *App) CheckIfAniListLoggedIn() bool {
func (a *App) AniListLogin() {
if (AniListJWT{} == aniListJwt) {
if !aniRingReady() {
log.Println("anilist: cannot check login, secure storage unavailable")
tokenType, tokenErr := keyring.Get(aniKeyringService, "anilistTokenType")
expiresIn, expiresInErr := keyring.Get(aniKeyringService, "anilistTokenExpiresIn")
refreshToken, refreshTokenErr := keyring.Get(aniKeyringService, "anilistRefreshToken")
accessToken, accessTokenErr := keyring.Get(aniKeyringService, "anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken) == 0 {
getAniListCodeUrl := "https://anilist.co/api/v2/oauth/authorize?client_id=" + Environment.ANILIST_APP_ID + "&redirect_uri=" + Environment.ANILIST_CALLBACK_URI + "&response_type=code"
if err := a.app.Browser.OpenURL(getAniListCodeUrl); err != nil {
log.Printf("anilist: failed to open browser: %s", err)
return
}
tokenType, tokenErr := aniRing.Get("anilistTokenType")
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
accessToken, accessTokenErr := aniRing.Get("anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
getAniListCodeUrl := "https://anilist.co/api/v2/oauth/authorize?client_id=" + Environment.ANILIST_APP_ID + "&redirect_uri=" + Environment.ANILIST_CALLBACK_URI + "&response_type=code"
runtime.BrowserOpenURL(*wailsContext, getAniListCodeUrl)
serverDone := &sync.WaitGroup{}
serverDone.Add(1)
@@ -104,12 +76,12 @@ func (a *App) AniListLogin() {
serverDone.Wait()
} else {
var expiresInConvertErr error
aniListJwt.TokenType = string(tokenType.Data)
aniListJwt.AccessToken = string(accessToken.Data)
aniListJwt.RefreshToken = string(refreshToken.Data)
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
aniListJwt.TokenType = tokenType
aniListJwt.AccessToken = accessToken
aniListJwt.RefreshToken = refreshToken
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(expiresIn)
if expiresInConvertErr != nil {
log.Printf("anilist: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
log.Printf("anilist: invalid expiresIn %q: %s", expiresIn, expiresInConvertErr)
}
}
}
@@ -132,17 +104,13 @@ func (a *App) handleAniListCallback(wg *sync.WaitGroup) {
_ = aniRingSet("anilistTokenExpiresIn", []byte(strconv.Itoa(aniListJwt.ExpiresIn)))
_ = aniRingSet("anilistAccessToken", []byte(aniListJwt.AccessToken))
_ = aniRingSet("anilistRefreshToken", []byte(aniListJwt.RefreshToken))
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
Title: "AniList Authorization",
Message: "It is now safe to close your browser tab",
})
if err != nil {
log.Println(err)
}
a.app.Dialog.Info().
SetTitle("AniList Authorization").
SetMessage("It is now safe to close your browser tab").
Show()
fmt.Println("Shutting down...")
aniCancel()
err = srv.Shutdown(context.Background())
if err != nil {
if err := srv.Shutdown(context.Background()); err != nil {
log.Println("server.Shutdown:", err)
}
} else {
@@ -239,14 +207,10 @@ func (a *App) GetAniListLoggedInUser() AniListUser {
func (a *App) LogoutAniList() string {
if (AniListJWT{} != aniListJwt) {
if !aniRingReady() {
aniListJwt = AniListJWT{}
return "AniList Logged Out Successfully"
}
typeErr := aniRing.Remove("anilistTokenType")
expiresInErr := aniRing.Remove("anilistTokenExpiresIn")
accessTokenErr := aniRing.Remove("anilistAccessToken")
refreshTokenErr := aniRing.Remove("anilistRefreshToken")
typeErr := keyring.Delete(aniKeyringService, "anilistTokenType")
expiresInErr := keyring.Delete(aniKeyringService, "anilistTokenExpiresIn")
accessTokenErr := keyring.Delete(aniKeyringService, "anilistAccessToken")
refreshTokenErr := keyring.Delete(aniKeyringService, "anilistRefreshToken")
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
log.Printf("anilist: logout cleanup failed (type=%v expires=%v access=%v refresh=%v)", typeErr, expiresInErr, accessTokenErr, refreshTokenErr)
}
+38 -74
View File
@@ -17,41 +17,17 @@ import (
"sync"
"time"
"github.com/99designs/keyring"
"github.com/wailsapp/wails/v2/pkg/runtime"
"github.com/zalando/go-keyring"
)
var myAnimeListJwt MyAnimeListJWT
var myAnimeListRing keyring.Keyring
func init() {
var err error
myAnimeListRing, err = keyring.Open(keyring.Config{
ServiceName: "AniTrack",
KeychainName: "AniTrack",
KeychainSynchronizable: false,
KeychainTrustApplication: true,
KeychainAccessibleWhenUnlocked: true,
})
if err != nil {
log.Printf("mal: secure storage unavailable: %s", err)
}
}
func malRingReady() bool {
if myAnimeListRing == nil {
log.Println("mal: secure storage unavailable")
return false
}
return true
}
// malKeyringService is the OS keyring service name all AniTrack secrets
// live under (same wallet the 99designs/keyring build used).
const malKeyringService = "AniTrack"
func malRingSet(key string, data []byte) error {
if !malRingReady() {
return errors.New("mal: secure storage unavailable")
}
if err := myAnimeListRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
if err := keyring.Set(malKeyringService, key, string(data)); err != nil {
log.Printf("mal: save %s failed: %s", key, err)
return err
}
@@ -99,25 +75,22 @@ func (v *CodeVerifier) CodeChallengeS256() string {
func (a *App) CheckIfMyAnimeListLoggedIn() bool {
if (MyAnimeListJWT{} == myAnimeListJwt) {
if !malRingReady() {
return false
}
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
refreshToken, refreshTokenErr := myAnimeListRing.Get("MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
tokenType, tokenErr := keyring.Get(malKeyringService, "MyAnimeListTokenType")
expiresIn, expiresInErr := keyring.Get(malKeyringService, "MyAnimeListExpiresIn")
accessToken, accessTokenErr := keyring.Get(malKeyringService, "MyAnimeListAccessToken")
refreshToken, refreshTokenErr := keyring.Get(malKeyringService, "MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken) == 0 {
return false
} else {
var expiresInConvertErr error
myAnimeListJwt.TokenType = string(tokenType.Data)
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
myAnimeListJwt.TokenType = tokenType
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(expiresIn)
if expiresInConvertErr != nil {
log.Printf("mal: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
log.Printf("mal: invalid expiresIn %q: %s", expiresIn, expiresInConvertErr)
return false
}
myAnimeListJwt.AccessToken = string(accessToken.Data)
myAnimeListJwt.RefreshToken = string(refreshToken.Data)
myAnimeListJwt.AccessToken = accessToken
myAnimeListJwt.RefreshToken = refreshToken
return true
}
} else {
@@ -128,31 +101,30 @@ func (a *App) CheckIfMyAnimeListLoggedIn() bool {
func (a *App) MyAnimeListLogin() {
if !a.CheckIfMyAnimeListLoggedIn() {
fmt.Println("check logged in function failed")
if !malRingReady() {
log.Println("mal: cannot check login, secure storage unavailable")
return
}
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
refreshToken, refreshTokenErr := myAnimeListRing.Get("MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
tokenType, tokenErr := keyring.Get(malKeyringService, "MyAnimeListTokenType")
expiresIn, expiresInErr := keyring.Get(malKeyringService, "MyAnimeListExpiresIn")
accessToken, accessTokenErr := keyring.Get(malKeyringService, "MyAnimeListAccessToken")
refreshToken, refreshTokenErr := keyring.Get(malKeyringService, "MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken) == 0 {
verifier, _ := verifier()
getMyAnimeListCodeUrl := "https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=" + Environment.MAL_CLIENT_ID + "&redirect_uri=" + Environment.MAL_CALLBACK_URI + "&code_challenge=" + verifier.Value + "&code_challenge_method=plain"
runtime.BrowserOpenURL(*wailsContext, getMyAnimeListCodeUrl)
if err := a.app.Browser.OpenURL(getMyAnimeListCodeUrl); err != nil {
log.Printf("mal: failed to open browser: %s", err)
return
}
serverDone := &sync.WaitGroup{}
serverDone.Add(1)
a.handleMyAnimeListCallback(serverDone, verifier)
serverDone.Wait()
} else {
var expiresInConvertErr error
myAnimeListJwt.TokenType = string(tokenType.Data)
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
myAnimeListJwt.TokenType = tokenType
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(expiresIn)
if expiresInConvertErr != nil {
log.Printf("mal: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
log.Printf("mal: invalid expiresIn %q: %s", expiresIn, expiresInConvertErr)
}
myAnimeListJwt.AccessToken = string(accessToken.Data)
myAnimeListJwt.RefreshToken = string(refreshToken.Data)
myAnimeListJwt.AccessToken = accessToken
myAnimeListJwt.RefreshToken = refreshToken
}
}
}
@@ -175,17 +147,13 @@ func (a *App) handleMyAnimeListCallback(wg *sync.WaitGroup, verifier *CodeVerifi
_ = malRingSet("MyAnimeListExpiresIn", []byte(strconv.Itoa(myAnimeListJwt.ExpiresIn)))
_ = malRingSet("MyAnimeListAccessToken", []byte(myAnimeListJwt.AccessToken))
_ = malRingSet("MyAnimeListRefreshToken", []byte(myAnimeListJwt.RefreshToken))
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
Title: "MyAnimeList Authorization",
Message: "It is now safe to close your browser tab",
})
if err != nil {
log.Println(err)
}
a.app.Dialog.Info().
SetTitle("MyAnimeList Authorization").
SetMessage("It is now safe to close your browser tab").
Show()
fmt.Println("Shutting down...")
myAnimeListCancel()
err = srv.Shutdown(context.Background())
if err != nil {
if err := srv.Shutdown(context.Background()); err != nil {
log.Println("server.Shutdown:", err)
}
} else {
@@ -378,14 +346,10 @@ func createUser() MyAnimeListUser {
func (a *App) LogoutMyAnimeList() string {
if (MyAnimeListJWT{} != myAnimeListJwt) {
if !malRingReady() {
myAnimeListJwt = MyAnimeListJWT{}
return "MAL Logged Out Successfully"
}
typeErr := myAnimeListRing.Remove("MyAnimeListTokenType")
expiresInErr := myAnimeListRing.Remove("MyAnimeListExpiresIn")
accessTokenErr := myAnimeListRing.Remove("MyAnimeListAccessToken")
refreshTokenErr := myAnimeListRing.Remove("MyAnimeListRefreshToken")
typeErr := keyring.Delete(malKeyringService, "MyAnimeListTokenType")
expiresInErr := keyring.Delete(malKeyringService, "MyAnimeListExpiresIn")
accessTokenErr := keyring.Delete(malKeyringService, "MyAnimeListAccessToken")
refreshTokenErr := keyring.Delete(malKeyringService, "MyAnimeListRefreshToken")
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
log.Printf("mal: logout cleanup failed (type=%v expires=%v access=%v refresh=%v)", typeErr, expiresInErr, accessTokenErr, refreshTokenErr)
}
+30 -66
View File
@@ -11,41 +11,17 @@ import (
"net/http"
"sync"
"github.com/99designs/keyring"
"github.com/wailsapp/wails/v2/pkg/runtime"
"github.com/zalando/go-keyring"
)
var simklJwt SimklJWT
var simklRing keyring.Keyring
func init() {
var err error
simklRing, err = keyring.Open(keyring.Config{
ServiceName: "AniTrack",
KeychainName: "AniTrack",
KeychainSynchronizable: false,
KeychainTrustApplication: true,
KeychainAccessibleWhenUnlocked: true,
})
if err != nil {
log.Printf("simkl: secure storage unavailable: %s", err)
}
}
func simklRingReady() bool {
if simklRing == nil {
log.Println("simkl: secure storage unavailable")
return false
}
return true
}
// simklKeyringService is the OS keyring service name all AniTrack secrets
// live under (same wallet the 99designs/keyring build used).
const simklKeyringService = "AniTrack"
func simklRingSet(key string, data []byte) error {
if !simklRingReady() {
return errors.New("simkl: secure storage unavailable")
}
if err := simklRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
if err := keyring.Set(simklKeyringService, key, string(data)); err != nil {
log.Printf("simkl: save %s failed: %s", key, err)
return err
}
@@ -56,18 +32,15 @@ var simklCtxShutdown, simklCancel = context.WithCancel(context.Background())
func (a *App) CheckIfSimklLoggedIn() bool {
if (SimklJWT{} == simklJwt) {
if !simklRingReady() {
return false
}
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
scope, scopeErr := simklRing.Get("SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken.Data) == 0 {
tokenType, tokenTypeErr := keyring.Get(simklKeyringService, "SimklTokenType")
accessToken, accessTokenErr := keyring.Get(simklKeyringService, "SimklAccessToken")
scope, scopeErr := keyring.Get(simklKeyringService, "SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken) == 0 {
return false
} else {
simklJwt.TokenType = string(tokenType.Data)
simklJwt.AccessToken = string(accessToken.Data)
simklJwt.Scope = string(scope.Data)
simklJwt.TokenType = tokenType
simklJwt.AccessToken = accessToken
simklJwt.Scope = scope
return true
}
} else {
@@ -77,25 +50,24 @@ func (a *App) CheckIfSimklLoggedIn() bool {
func (a *App) SimklLogin() {
if !a.CheckIfSimklLoggedIn() {
if !simklRingReady() {
log.Println("simkl: cannot check login, secure storage unavailable")
tokenType, tokenTypeErr := keyring.Get(simklKeyringService, "SimklTokenType")
accessToken, accessTokenErr := keyring.Get(simklKeyringService, "SimklAccessToken")
scope, scopeErr := keyring.Get(simklKeyringService, "SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken) == 0 {
getSimklCodeUrl := "https://simkl.com/oauth/authorize?response_type=code&client_id=" + Environment.SIMKL_CLIENT_ID + "&redirect_uri=" + Environment.SIMKL_CALLBACK_URI
if err := a.app.Browser.OpenURL(getSimklCodeUrl); err != nil {
log.Printf("simkl: failed to open browser: %s", err)
return
}
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
scope, scopeErr := simklRing.Get("SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken.Data) == 0 {
getSimklCodeUrl := "https://simkl.com/oauth/authorize?response_type=code&client_id=" + Environment.SIMKL_CLIENT_ID + "&redirect_uri=" + Environment.SIMKL_CALLBACK_URI
runtime.BrowserOpenURL(*wailsContext, getSimklCodeUrl)
serverDone := &sync.WaitGroup{}
serverDone.Add(1)
a.handleSimklCallback(serverDone)
serverDone.Wait()
} else {
simklJwt.TokenType = string(tokenType.Data)
simklJwt.AccessToken = string(accessToken.Data)
simklJwt.Scope = string(scope.Data)
simklJwt.TokenType = tokenType
simklJwt.AccessToken = accessToken
simklJwt.Scope = scope
}
}
}
@@ -117,17 +89,13 @@ func (a *App) handleSimklCallback(wg *sync.WaitGroup) {
_ = simklRingSet("SimklTokenType", []byte(simklJwt.TokenType))
_ = simklRingSet("SimklAccessToken", []byte(simklJwt.AccessToken))
_ = simklRingSet("SimklScope", []byte(simklJwt.Scope))
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
Title: "Simkl Authorization",
Message: "It is now safe to close your browser tab",
})
if err != nil {
log.Println(err)
}
a.app.Dialog.Info().
SetTitle("Simkl Authorization").
SetMessage("It is now safe to close your browser tab").
Show()
fmt.Println("Shutting down...")
simklCancel()
err = srv.Shutdown(context.Background())
if err != nil {
if err := srv.Shutdown(context.Background()); err != nil {
log.Println("server.Shutdown:", err)
}
} else {
@@ -243,13 +211,9 @@ func (a *App) GetSimklLoggedInUser() SimklUser {
func (a *App) LogoutSimkl() string {
if (SimklJWT{} != simklJwt) {
if !simklRingReady() {
simklJwt = SimklJWT{}
return "Simkl Logged Out Successfully"
}
tokenTypeErr := simklRing.Remove("SimklTokenType")
accessTokenErr := simklRing.Remove("SimklAccessToken")
scopeErr := simklRing.Remove("SimklScope")
tokenTypeErr := keyring.Delete(simklKeyringService, "SimklTokenType")
accessTokenErr := keyring.Delete(simklKeyringService, "SimklAccessToken")
scopeErr := keyring.Delete(simklKeyringService, "SimklScope")
if tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil {
log.Printf("simkl: logout cleanup failed (type=%v access=%v scope=%v)", tokenTypeErr, accessTokenErr, scopeErr)
+23 -32
View File
@@ -1,58 +1,49 @@
package main
import (
"context"
_ "embed"
"log"
"strings"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/runtime"
"github.com/tidwall/gjson"
"github.com/wailsapp/wails/v3/pkg/application"
)
//go:embed wails.json
var wailsJSON string
var wailsContext *context.Context
// App struct
type App struct {
ctx context.Context
app *application.App
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
func NewApp(app *application.App) *App {
return &App{app: app}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
version := gjson.Get(wailsJSON, "info.productVersion")
wailsContext = &ctx
runtime.WindowSetTitle(ctx, "AniTrack "+version.String())
//runtime.WindowMaximise(ctx)
// appVersion reads the product version from wails.json.
func appVersion() string {
return gjson.Get(wailsJSON, "info.productVersion").String()
}
func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
var secondInstanceArgs = secondInstanceData.Args
// appTitle is the window title: "AniTrack <version>".
func appTitle() string {
return "AniTrack " + appVersion()
}
println("user opened second instance", strings.Join(secondInstanceData.Args, ","))
println("user opened second from", secondInstanceData.WorkingDirectory)
runtime.WindowUnminimise(*wailsContext)
runtime.Show(*wailsContext)
go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs)
func (a *App) onSecondInstanceLaunch(data application.SecondInstanceData) {
println("user opened second instance", strings.Join(data.Args, ","))
println("user opened second from", data.WorkingDir)
if w := a.app.Window.Current(); w != nil {
w.Restore()
w.Focus()
}
go a.app.Event.Emit("launchArgs", data.Args)
}
func (a *App) ShowVersion() {
version := gjson.Get(wailsJSON, "info.productVersion")
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
Title: "Version",
Message: "AniTrack Version: " + version.String(),
})
if err != nil {
log.Println(err)
}
a.app.Dialog.Info().
SetTitle("Version").
SetMessage("AniTrack Version: " + appVersion()).
Show()
}
-61
View File
@@ -1,61 +0,0 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {main} from '../models';
export function AniListBrowse(arg1:number,arg2:number,arg3:number,arg4:boolean,arg5:string,arg6:Array<string>,arg7:string,arg8:string,arg9:string,arg10:string,arg11:number,arg12:string,arg13:boolean,arg14:number,arg15:number,arg16:number,arg17:number,arg18:number,arg19:number,arg20:number,arg21:number,arg22:number,arg23:number,arg24:Array<number>,arg25:boolean,arg26:Array<string>,arg27:Array<string>,arg28:Array<string>,arg29:Array<string>,arg30:number,arg31:Array<string>):Promise<main.AniListCurrentUserWatchList>;
export function AniListDeleteEntry(arg1:number):Promise<main.DeleteAniListReturn>;
export function AniListLogin():Promise<void>;
export function AniListSearch(arg1:string):Promise<any>;
export function AniListUpdateEntry(arg1:main.AniListUpdateVariables):Promise<main.AniListGetSingleAnime>;
export function CheckIfAniListLoggedIn():Promise<boolean>;
export function CheckIfMyAnimeListLoggedIn():Promise<boolean>;
export function CheckIfSimklLoggedIn():Promise<boolean>;
export function DeleteMyAnimeListEntry(arg1:number):Promise<boolean>;
export function GetAniListItem(arg1:number,arg2:boolean):Promise<main.AniListGetSingleAnime>;
export function GetAniListLoggedInUser():Promise<main.AniListUser>;
export function GetAniListUserWatchingList(arg1:number,arg2:number,arg3:string):Promise<main.AniListCurrentUserWatchList>;
export function GetMyAnimeList(arg1:number):Promise<main.MALWatchlist>;
export function GetMyAnimeListAnime(arg1:number):Promise<main.MALAnime>;
export function GetMyAnimeListLoggedInUser():Promise<main.MyAnimeListUser>;
export function GetSimklLoggedInUser():Promise<main.SimklUser>;
export function LogoutAniList():Promise<string>;
export function LogoutMyAnimeList():Promise<string>;
export function LogoutSimkl():Promise<string>;
export function MyAnimeListLogin():Promise<void>;
export function MyAnimeListUpdate(arg1:main.MALAnime,arg2:main.MALUploadStatus):Promise<main.MalListStatus>;
export function ShowVersion():Promise<void>;
export function SimklGetUserWatchlist():Promise<main.SimklWatchListType>;
export function SimklLogin():Promise<void>;
export function SimklSearch(arg1:main.MediaList):Promise<main.SimklAnime>;
export function SimklSyncEpisodes(arg1:main.SimklAnime,arg2:number):Promise<main.SimklAnime>;
export function SimklSyncRating(arg1:main.SimklAnime,arg2:number):Promise<main.SimklAnime>;
export function SimklSyncRemove(arg1:main.SimklAnime):Promise<boolean>;
export function SimklSyncStatus(arg1:main.SimklAnime,arg2:string):Promise<main.SimklAnime>;
-119
View File
@@ -1,119 +0,0 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function AniListBrowse(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20, arg21, arg22, arg23, arg24, arg25, arg26, arg27, arg28, arg29, arg30, arg31) {
return window['go']['main']['App']['AniListBrowse'](arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20, arg21, arg22, arg23, arg24, arg25, arg26, arg27, arg28, arg29, arg30, arg31);
}
export function AniListDeleteEntry(arg1) {
return window['go']['main']['App']['AniListDeleteEntry'](arg1);
}
export function AniListLogin() {
return window['go']['main']['App']['AniListLogin']();
}
export function AniListSearch(arg1) {
return window['go']['main']['App']['AniListSearch'](arg1);
}
export function AniListUpdateEntry(arg1) {
return window['go']['main']['App']['AniListUpdateEntry'](arg1);
}
export function CheckIfAniListLoggedIn() {
return window['go']['main']['App']['CheckIfAniListLoggedIn']();
}
export function CheckIfMyAnimeListLoggedIn() {
return window['go']['main']['App']['CheckIfMyAnimeListLoggedIn']();
}
export function CheckIfSimklLoggedIn() {
return window['go']['main']['App']['CheckIfSimklLoggedIn']();
}
export function DeleteMyAnimeListEntry(arg1) {
return window['go']['main']['App']['DeleteMyAnimeListEntry'](arg1);
}
export function GetAniListItem(arg1, arg2) {
return window['go']['main']['App']['GetAniListItem'](arg1, arg2);
}
export function GetAniListLoggedInUser() {
return window['go']['main']['App']['GetAniListLoggedInUser']();
}
export function GetAniListUserWatchingList(arg1, arg2, arg3) {
return window['go']['main']['App']['GetAniListUserWatchingList'](arg1, arg2, arg3);
}
export function GetMyAnimeList(arg1) {
return window['go']['main']['App']['GetMyAnimeList'](arg1);
}
export function GetMyAnimeListAnime(arg1) {
return window['go']['main']['App']['GetMyAnimeListAnime'](arg1);
}
export function GetMyAnimeListLoggedInUser() {
return window['go']['main']['App']['GetMyAnimeListLoggedInUser']();
}
export function GetSimklLoggedInUser() {
return window['go']['main']['App']['GetSimklLoggedInUser']();
}
export function LogoutAniList() {
return window['go']['main']['App']['LogoutAniList']();
}
export function LogoutMyAnimeList() {
return window['go']['main']['App']['LogoutMyAnimeList']();
}
export function LogoutSimkl() {
return window['go']['main']['App']['LogoutSimkl']();
}
export function MyAnimeListLogin() {
return window['go']['main']['App']['MyAnimeListLogin']();
}
export function MyAnimeListUpdate(arg1, arg2) {
return window['go']['main']['App']['MyAnimeListUpdate'](arg1, arg2);
}
export function ShowVersion() {
return window['go']['main']['App']['ShowVersion']();
}
export function SimklGetUserWatchlist() {
return window['go']['main']['App']['SimklGetUserWatchlist']();
}
export function SimklLogin() {
return window['go']['main']['App']['SimklLogin']();
}
export function SimklSearch(arg1) {
return window['go']['main']['App']['SimklSearch'](arg1);
}
export function SimklSyncEpisodes(arg1, arg2) {
return window['go']['main']['App']['SimklSyncEpisodes'](arg1, arg2);
}
export function SimklSyncRating(arg1, arg2) {
return window['go']['main']['App']['SimklSyncRating'](arg1, arg2);
}
export function SimklSyncRemove(arg1) {
return window['go']['main']['App']['SimklSyncRemove'](arg1);
}
export function SimklSyncStatus(arg1, arg2) {
return window['go']['main']['App']['SimklSyncStatus'](arg1, arg2);
}
-974
View File
@@ -1,974 +0,0 @@
export namespace main {
export class AiringScheduleNode {
id: number;
airingAt: number;
timeUntilAiring: number;
episode: number;
mediaId: number;
static createFrom(source: any = {}) {
return new AiringScheduleNode(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.airingAt = source["airingAt"];
this.timeUntilAiring = source["timeUntilAiring"];
this.episode = source["episode"];
this.mediaId = source["mediaId"];
}
}
export class AniListCurrentUserWatchList {
data: struct { Page struct { PageInfo struct { Total int "json:\"total\""; PerPage int "json:\"perPage\""; CurrentPage int "json:\"currentPage\""; LastPage int "json:\"lastPage\""; HasNextPage bool "json:\"hasNextPage\"" } "json:\"pageInfo\""; MediaList []main.;
static createFrom(source: any = {}) {
return new AniListCurrentUserWatchList(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = this.convertValues(source["data"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class AniListGetSingleAnime {
data: struct { MediaList main.;
static createFrom(source: any = {}) {
return new AniListGetSingleAnime(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = this.convertValues(source["data"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class CompletedAt {
year: number;
month: number;
day: number;
static createFrom(source: any = {}) {
return new CompletedAt(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.year = source["year"];
this.month = source["month"];
this.day = source["day"];
}
}
export class StartedAt {
year: number;
month: number;
day: number;
static createFrom(source: any = {}) {
return new StartedAt(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.year = source["year"];
this.month = source["month"];
this.day = source["day"];
}
}
export class AniListUpdateVariables {
mediaId: number;
progress: number;
status: string;
score: number;
repeat: number;
notes: string;
startedAt: StartedAt;
completedAt: CompletedAt;
static createFrom(source: any = {}) {
return new AniListUpdateVariables(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.mediaId = source["mediaId"];
this.progress = source["progress"];
this.status = source["status"];
this.score = source["score"];
this.repeat = source["repeat"];
this.notes = source["notes"];
this.startedAt = this.convertValues(source["startedAt"], StartedAt);
this.completedAt = this.convertValues(source["completedAt"], CompletedAt);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class AniListUser {
// Go type: struct { Viewer struct { ID int "json:\"id\""; Name string "json:\"name\""; Avatar struct { Large string "json:\"large\""; Medium string "json:\"medium\"" } "json:\"avatar\""; BannerImage string "json:\"bannerImage\""; SiteUrl string "json:\"siteUrl\"" } "json:\"Viewer\"" }
data: any;
static createFrom(source: any = {}) {
return new AniListUser(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = this.convertValues(source["data"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class DeleteAniListReturn {
// Go type: struct { DeleteMediaListEntry struct { Deleted bool "json:\"deleted\"" } "json:\"DeleteMediaListEntry\"" }
data: any;
static createFrom(source: any = {}) {
return new DeleteAniListReturn(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = this.convertValues(source["data"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MALAnime {
id: id;
title: title;
main_picture: mainPicture;
alternative_titles: alternativeTitles;
start_date: startDate;
end_date: endDate;
synopsis: synopsis;
mean: mean;
rank: rank;
popularity: popularity;
num_list_users: numListUsers;
num_scoring_users: numScoringUsers;
nsfw: nsfw;
genres: genres;
created_at: createdAt;
updated_at: updatedAt;
media_type: mediaType;
status: status;
my_list_status: MalListStatus;
num_episodes: numEpisodes;
start_season: startSeason;
broadcast: broadcast;
source: source;
average_episode_duration: averageEpisodeDuration;
rating: rating;
studios: studios;
pictures: pictures;
background: background;
related_anime: relatedAnime;
recommendations: recommendations;
Statistics: struct { NumListUsers int "json:\"num_list_users\" ts_type:\"numListUsers\""; Status struct { Watching main.;
static createFrom(source: any = {}) {
return new MALAnime(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.title = source["title"];
this.main_picture = source["main_picture"];
this.alternative_titles = source["alternative_titles"];
this.start_date = source["start_date"];
this.end_date = source["end_date"];
this.synopsis = source["synopsis"];
this.mean = source["mean"];
this.rank = source["rank"];
this.popularity = source["popularity"];
this.num_list_users = source["num_list_users"];
this.num_scoring_users = source["num_scoring_users"];
this.nsfw = source["nsfw"];
this.genres = source["genres"];
this.created_at = source["created_at"];
this.updated_at = source["updated_at"];
this.media_type = source["media_type"];
this.status = source["status"];
this.my_list_status = source["my_list_status"];
this.num_episodes = source["num_episodes"];
this.start_season = source["start_season"];
this.broadcast = source["broadcast"];
this.source = source["source"];
this.average_episode_duration = source["average_episode_duration"];
this.rating = source["rating"];
this.studios = source["studios"];
this.pictures = source["pictures"];
this.background = source["background"];
this.related_anime = source["related_anime"];
this.recommendations = source["recommendations"];
this.Statistics = this.convertValues(source["Statistics"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MALUploadStatus {
status: string;
is_rewatching: boolean;
score: number;
num_watched_episodes: number;
num_times_rewatched: number;
comments: string;
static createFrom(source: any = {}) {
return new MALUploadStatus(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.status = source["status"];
this.is_rewatching = source["is_rewatching"];
this.score = source["score"];
this.num_watched_episodes = source["num_watched_episodes"];
this.num_times_rewatched = source["num_times_rewatched"];
this.comments = source["comments"];
}
}
export class MALWatchlist {
data: data;
paging: paging;
static createFrom(source: any = {}) {
return new MALWatchlist(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = source["data"];
this.paging = source["paging"];
}
}
export class MalListStatus {
status: status;
score: score;
num_episodes_watched: numEpisodesWatched;
is_rewatching: isRewatching;
start_date: startDate;
finish_date: finishDate;
priority: priority;
num_times_rewatched: numTimesRewatched;
rewatch_value: rewatchValue;
tags: tags;
comments: comments;
updated_at: updatedAt;
static createFrom(source: any = {}) {
return new MalListStatus(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.status = source["status"];
this.score = source["score"];
this.num_episodes_watched = source["num_episodes_watched"];
this.is_rewatching = source["is_rewatching"];
this.start_date = source["start_date"];
this.finish_date = source["finish_date"];
this.priority = source["priority"];
this.num_times_rewatched = source["num_times_rewatched"];
this.rewatch_value = source["rewatch_value"];
this.tags = source["tags"];
this.comments = source["comments"];
this.updated_at = source["updated_at"];
}
}
export class {
id: number;
name: string;
description: string;
rank: number;
isMediaSpoiler: boolean;
isAdult: boolean;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.description = source["description"];
this.rank = source["rank"];
this.isMediaSpoiler = source["isMediaSpoiler"];
this.isAdult = source["isAdult"];
}
}
export class MediaAiringSchedule {
nodes: AiringScheduleNode[];
static createFrom(source: any = {}) {
return new MediaAiringSchedule(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.nodes = this.convertValues(source["nodes"], AiringScheduleNode);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MediaFuzzyDate {
year: number;
month: number;
day: number;
static createFrom(source: any = {}) {
return new MediaFuzzyDate(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.year = source["year"];
this.month = source["month"];
this.day = source["day"];
}
}
export class MediaRelation {
id: number;
title: MediaTitle;
static createFrom(source: any = {}) {
return new MediaRelation(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.title = this.convertValues(source["title"], MediaTitle);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MediaRelations {
nodes: MediaRelation[];
static createFrom(source: any = {}) {
return new MediaRelations(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.nodes = this.convertValues(source["nodes"], MediaRelation);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MediaTitle {
userPreferred: string;
romaji: string;
english: string;
native: string;
static createFrom(source: any = {}) {
return new MediaTitle(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.userPreferred = source["userPreferred"];
this.romaji = source["romaji"];
this.english = source["english"];
this.native = source["native"];
}
}
export class Media {
id: number;
idMal: number;
title: MediaTitle;
description: string;
// Go type: struct { ExtraLarge string; Large string "json:\"large\""; Medium string; Color string }
coverImage: any;
BannerImage: string;
Format: string;
season: string;
seasonYear: number;
status: string;
episodes: number;
Duration: number;
CountryOfOrigin: string;
Source: string;
Synonyms: string[];
AverageScore: number;
MeanScore: number;
Popularity: number;
Trending: number;
Favourites: number;
relations: MediaRelations;
startDate: MediaFuzzyDate;
endDate: MediaFuzzyDate;
// Go type: struct { AiringAt int "json:\"airingAt\""; TimeUntilAiring int "json:\"timeUntilAiring\""; Episode int "json:\"episode\"" }
nextAiringEpisode: any;
airingSchedule: MediaAiringSchedule;
genres: string[];
tags: [];
isAdult: boolean;
static createFrom(source: any = {}) {
return new Media(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.idMal = source["idMal"];
this.title = this.convertValues(source["title"], MediaTitle);
this.description = source["description"];
this.coverImage = this.convertValues(source["coverImage"], Object);
this.BannerImage = source["BannerImage"];
this.Format = source["Format"];
this.season = source["season"];
this.seasonYear = source["seasonYear"];
this.status = source["status"];
this.episodes = source["episodes"];
this.Duration = source["Duration"];
this.CountryOfOrigin = source["CountryOfOrigin"];
this.Source = source["Source"];
this.Synonyms = source["Synonyms"];
this.AverageScore = source["AverageScore"];
this.MeanScore = source["MeanScore"];
this.Popularity = source["Popularity"];
this.Trending = source["Trending"];
this.Favourites = source["Favourites"];
this.relations = this.convertValues(source["relations"], MediaRelations);
this.startDate = this.convertValues(source["startDate"], MediaFuzzyDate);
this.endDate = this.convertValues(source["endDate"], MediaFuzzyDate);
this.nextAiringEpisode = this.convertValues(source["nextAiringEpisode"], Object);
this.airingSchedule = this.convertValues(source["airingSchedule"], MediaAiringSchedule);
this.genres = source["genres"];
this.tags = this.convertValues(source["tags"], );
this.isAdult = source["isAdult"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MediaList {
id: number;
mediaId: number;
userId: number;
status: string;
media: Media;
// Go type: struct { Year int "json:\"year\""; Month int "json:\"month\""; Day int "json:\"day\"" }
startedAt: any;
// Go type: struct { Year int "json:\"year\""; Month int "json:\"month\""; Day int "json:\"day\"" }
completedAt: any;
notes: string;
progress: number;
score: number;
repeat: number;
// Go type: struct { ID int "json:\"id\""; Name string "json:\"name\""; Avatar struct { Large string "json:\"large\""; Medium string "json:\"medium\"" } "json:\"avatar\""; Statistics struct { Anime struct { Count int "json:\"count\""; Statuses []struct { Status string "json:\"status\""; Count int "json:\"count\"" } "json:\"statuses\"" } "json:\"anime\"" } "json:\"statistics\"" }
user: any;
static createFrom(source: any = {}) {
return new MediaList(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.mediaId = source["mediaId"];
this.userId = source["userId"];
this.status = source["status"];
this.media = this.convertValues(source["media"], Media);
this.startedAt = this.convertValues(source["startedAt"], Object);
this.completedAt = this.convertValues(source["completedAt"], Object);
this.notes = source["notes"];
this.progress = source["progress"];
this.score = source["score"];
this.repeat = source["repeat"];
this.user = this.convertValues(source["user"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MyAnimeListUser {
id: id;
name: name;
picture: picture;
gender: gender;
birthday: birthday;
location: location;
joined_at: joinedAt;
num_items_watching: numItemsWatching;
num_items_completed: numItemsCompleted;
num_items_on_hold: numItemsOnHold;
num_items_dropped: numItemsDropped;
num_items_plan_to_watch: numItemsPlanToWatch;
num_items: numItems;
num_days_watched: numDaysWatched;
num_days_watching: numDaysWatching;
num_days_completed: numDaysCompleted;
num_days_on_hold: numDaysOnHold;
num_days_dropped: numDaysDropped;
num_days: numDays;
num_episodes: numEpisodes;
num_times_rewatched: numTimesRewatched;
mean_score: meanScore;
time_zone: timeZone;
is_supporter: isSupporter;
static createFrom(source: any = {}) {
return new MyAnimeListUser(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.picture = source["picture"];
this.gender = source["gender"];
this.birthday = source["birthday"];
this.location = source["location"];
this.joined_at = source["joined_at"];
this.num_items_watching = source["num_items_watching"];
this.num_items_completed = source["num_items_completed"];
this.num_items_on_hold = source["num_items_on_hold"];
this.num_items_dropped = source["num_items_dropped"];
this.num_items_plan_to_watch = source["num_items_plan_to_watch"];
this.num_items = source["num_items"];
this.num_days_watched = source["num_days_watched"];
this.num_days_watching = source["num_days_watching"];
this.num_days_completed = source["num_days_completed"];
this.num_days_on_hold = source["num_days_on_hold"];
this.num_days_dropped = source["num_days_dropped"];
this.num_days = source["num_days"];
this.num_episodes = source["num_episodes"];
this.num_times_rewatched = source["num_times_rewatched"];
this.mean_score = source["mean_score"];
this.time_zone = source["time_zone"];
this.is_supporter = source["is_supporter"];
}
}
export class SimklAnime {
last_watched_at: last_watched_at;
status: status;
user_rating: user_rating;
last_watched: last_watched;
next_to_watch: next_to_watch;
watched_episodes_count: watched_episodes_count;
total_episodes_count: total_episodes_count;
not_aired_episodes_count: not_aired_episodes_count;
show: show;
anime_type: anime_type;
static createFrom(source: any = {}) {
return new SimklAnime(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.last_watched_at = source["last_watched_at"];
this.status = source["status"];
this.user_rating = source["user_rating"];
this.last_watched = source["last_watched"];
this.next_to_watch = source["next_to_watch"];
this.watched_episodes_count = source["watched_episodes_count"];
this.total_episodes_count = source["total_episodes_count"];
this.not_aired_episodes_count = source["not_aired_episodes_count"];
this.show = source["show"];
this.anime_type = source["anime_type"];
}
}
export class SimklUser {
user: user;
account: account;
connections: connections;
static createFrom(source: any = {}) {
return new SimklUser(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.user = source["user"];
this.account = source["account"];
this.connections = source["connections"];
}
}
export class SimklWatchListType {
anime: anime;
static createFrom(source: any = {}) {
return new SimklWatchListType(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.anime = source["anime"];
}
}
}
export namespace struct { MediaList main {
export class {
MediaList: main.MediaList;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.MediaList = this.convertValues(source["MediaList"], main.MediaList);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
export namespace struct { Node main {
export class {
node: node;
num_recommendations: numRecommendations;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.node = source["node"];
this.num_recommendations = source["num_recommendations"];
}
}
export class {
node: node;
relation_type: relationType;
relation_type_formatted: relationTypeFormatted;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.node = source["node"];
this.relation_type = source["relation_type"];
this.relation_type_formatted = source["relation_type_formatted"];
}
}
}
export namespace struct { Node struct { Id int "json:\"id\" ts_type:\"id\""; Title string "json:\"title\" ts_type:\"title\""; MainPicture struct { Medium string "json:\"medium\" ts_type:\"medium\""; Large string "json:\"large\" ts_type:\"large\"" } "json:\"main_picture\" ts_type:\"mainPicture\"" } "json:\"node\" ts_type:\"node\""; ListStatus struct { Status string "json:\"status\" ts_type:\"status\""; Score int "json:\"score\" ts_type:\"score\""; NumEpisodesWatched int "json:\"num_episodes_watched\" ts_type:\"numEpisodesWatched\""; IsRewatching bool "json:\"is_rewatching\" ts_type:\"isRewatching\""; UpdatedAt time {
export class {
node: node;
list_status: listStatus;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.node = source["node"];
this.list_status = source["list_status"];
}
}
}
export namespace struct { NumListUsers int "json:\"num_list_users\" ts_type:\"numListUsers\""; Status struct { Watching main {
export class {
num_list_users: numListUsers;
Status: struct { Watching main.;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.num_list_users = source["num_list_users"];
this.Status = this.convertValues(source["Status"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
export namespace struct { Status string "json:\"status\" ts_type:\"status\""; Score int "json:\"score\" ts_type:\"score\""; NumEpisodesWatched int "json:\"num_episodes_watched\" ts_type:\"numEpisodesWatched\""; IsRewatching bool "json:\"is_rewatching\" ts_type:\"isRewatching\""; UpdatedAt time {
export class {
status: status;
score: score;
num_episodes_watched: numEpisodesWatched;
is_rewatching: isRewatching;
updated_at: updatedAt;
start_date: startDate;
finish_date: finishDate;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.status = source["status"];
this.score = source["score"];
this.num_episodes_watched = source["num_episodes_watched"];
this.is_rewatching = source["is_rewatching"];
this.updated_at = source["updated_at"];
this.start_date = source["start_date"];
this.finish_date = source["finish_date"];
}
}
}
export namespace struct { Watching main {
export class {
watching: string;
completed: string;
on_hold: string;
dropped: string;
plan_to_watch: string;
static createFrom(source: any = {}) {
return new (source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.watching = source["watching"];
this.completed = source["completed"];
this.on_hold = source["on_hold"];
this.dropped = source["dropped"];
this.plan_to_watch = source["plan_to_watch"];
}
}
}
-24
View File
@@ -1,24 +0,0 @@
{
"name": "@wailsapp/runtime",
"version": "2.0.0",
"description": "Wails Javascript runtime library",
"main": "runtime.js",
"types": "runtime.d.ts",
"scripts": {
},
"repository": {
"type": "git",
"url": "git+https://github.com/wailsapp/wails.git"
},
"keywords": [
"Wails",
"Javascript",
"Go"
],
"author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/wailsapp/wails/issues"
},
"homepage": "https://github.com/wailsapp/wails#readme"
}
-330
View File
@@ -1,330 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export interface Position {
x: number;
y: number;
}
export interface Size {
w: number;
h: number;
}
export interface Screen {
isCurrent: boolean;
isPrimary: boolean;
width : number
height : number
}
// Environment information such as platform, buildtype, ...
export interface EnvironmentInfo {
buildType: string;
platform: string;
arch: string;
}
// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
// emits the given event. Optional data may be passed with the event.
// This will trigger any event listeners.
export function EventsEmit(eventName: string, ...data: any): void;
// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
// sets up a listener for the given event name, but will only trigger a given number times.
export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
// sets up a listener for the given event name, but will only trigger once.
export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
// unregisters the listener for the given event name.
export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
// unregisters all listeners.
export function EventsOffAll(): void;
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
// logs the given message at the `trace` log level.
export function LogTrace(message: string): void;
// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
// logs the given message at the `debug` log level.
export function LogDebug(message: string): void;
// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
// logs the given message at the `error` log level.
export function LogError(message: string): void;
// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
// logs the given message at the `fatal` log level.
// The application will quit after calling this method.
export function LogFatal(message: string): void;
// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
// logs the given message at the `info` log level.
export function LogInfo(message: string): void;
// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
// logs the given message at the `warning` log level.
export function LogWarning(message: string): void;
// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
// Forces a reload by the main application as well as connected browsers.
export function WindowReload(): void;
// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
// Reloads the application frontend.
export function WindowReloadApp(): void;
// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
// Sets the window AlwaysOnTop or not on top.
export function WindowSetAlwaysOnTop(b: boolean): void;
// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
// *Windows only*
// Sets window theme to system default (dark/light).
export function WindowSetSystemDefaultTheme(): void;
// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
// *Windows only*
// Sets window to light theme.
export function WindowSetLightTheme(): void;
// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
// *Windows only*
// Sets window to dark theme.
export function WindowSetDarkTheme(): void;
// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
// Centers the window on the monitor the window is currently on.
export function WindowCenter(): void;
// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
// Sets the text in the window title bar.
export function WindowSetTitle(title: string): void;
// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
// Makes the window full screen.
export function WindowFullscreen(): void;
// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
// Restores the previous window dimensions and position prior to full screen.
export function WindowUnfullscreen(): void;
// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
// Returns the state of the window, i.e. whether the window is in full screen mode or not.
export function WindowIsFullscreen(): Promise<boolean>;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
export function WindowGetSize(): Promise<Size>;
// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMaxSize(width: number, height: number): void;
// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMinSize(width: number, height: number): void;
// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
// Sets the window position relative to the monitor the window is currently on.
export function WindowSetPosition(x: number, y: number): void;
// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
// Gets the window position relative to the monitor the window is currently on.
export function WindowGetPosition(): Promise<Position>;
// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
// Hides the window.
export function WindowHide(): void;
// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
// Shows the window, if it is currently hidden.
export function WindowShow(): void;
// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
// Maximises the window to fill the screen.
export function WindowMaximise(): void;
// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
// Toggles between Maximised and UnMaximised.
export function WindowToggleMaximise(): void;
// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
// Restores the window to the dimensions and position prior to maximising.
export function WindowUnmaximise(): void;
// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
// Returns the state of the window, i.e. whether the window is maximised or not.
export function WindowIsMaximised(): Promise<boolean>;
// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
// Minimises the window.
export function WindowMinimise(): void;
// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
// Returns the state of the window, i.e. whether the window is minimised or not.
export function WindowIsMinimised(): Promise<boolean>;
// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
// Returns the state of the window, i.e. whether the window is normal or not.
export function WindowIsNormal(): Promise<boolean>;
// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
export function ScreenGetAll(): Promise<Screen[]>;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
export function Environment(): Promise<EnvironmentInfo>;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
export function Quit(): void;
// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
// Hides the application.
export function Hide(): void;
// [Show](https://wails.io/docs/reference/runtime/intro#show)
// Shows the application.
export function Show(): void;
// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
// Returns the current text stored on clipboard
export function ClipboardGetText(): Promise<string>;
// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
// Sets a text on the clipboard
export function ClipboardSetText(text: string): Promise<boolean>;
// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
// OnFileDropOff removes the drag and drop listeners and handlers.
export function OnFileDropOff() :void
// Check if the file path resolver is available
export function CanResolveFilePaths(): boolean;
// Resolves file paths for an array of files
export function ResolveFilePaths(files: File[]): void
// Notification types
export interface NotificationOptions {
id: string;
title: string;
subtitle?: string; // macOS and Linux only
body?: string;
categoryId?: string;
data?: { [key: string]: any };
}
export interface NotificationAction {
id?: string;
title?: string;
destructive?: boolean; // macOS-specific
}
export interface NotificationCategory {
id?: string;
actions?: NotificationAction[];
hasReplyField?: boolean;
replyPlaceholder?: string;
replyButtonTitle?: string;
}
// [InitializeNotifications](https://wails.io/docs/reference/runtime/notification#initializenotifications)
// Initializes the notification service for the application.
// This must be called before sending any notifications.
export function InitializeNotifications(): Promise<void>;
// [CleanupNotifications](https://wails.io/docs/reference/runtime/notification#cleanupnotifications)
// Cleans up notification resources and releases any held connections.
export function CleanupNotifications(): Promise<void>;
// [IsNotificationAvailable](https://wails.io/docs/reference/runtime/notification#isnotificationavailable)
// Checks if notifications are available on the current platform.
export function IsNotificationAvailable(): Promise<boolean>;
// [RequestNotificationAuthorization](https://wails.io/docs/reference/runtime/notification#requestnotificationauthorization)
// Requests notification authorization from the user (macOS only).
export function RequestNotificationAuthorization(): Promise<boolean>;
// [CheckNotificationAuthorization](https://wails.io/docs/reference/runtime/notification#checknotificationauthorization)
// Checks the current notification authorization status (macOS only).
export function CheckNotificationAuthorization(): Promise<boolean>;
// [SendNotification](https://wails.io/docs/reference/runtime/notification#sendnotification)
// Sends a basic notification with the given options.
export function SendNotification(options: NotificationOptions): Promise<void>;
// [SendNotificationWithActions](https://wails.io/docs/reference/runtime/notification#sendnotificationwithactions)
// Sends a notification with action buttons. Requires a registered category.
export function SendNotificationWithActions(options: NotificationOptions): Promise<void>;
// [RegisterNotificationCategory](https://wails.io/docs/reference/runtime/notification#registernotificationcategory)
// Registers a notification category that can be used with SendNotificationWithActions.
export function RegisterNotificationCategory(category: NotificationCategory): Promise<void>;
// [RemoveNotificationCategory](https://wails.io/docs/reference/runtime/notification#removenotificationcategory)
// Removes a previously registered notification category.
export function RemoveNotificationCategory(categoryId: string): Promise<void>;
// [RemoveAllPendingNotifications](https://wails.io/docs/reference/runtime/notification#removeallpendingnotifications)
// Removes all pending notifications from the notification center.
export function RemoveAllPendingNotifications(): Promise<void>;
// [RemovePendingNotification](https://wails.io/docs/reference/runtime/notification#removependingnotification)
// Removes a specific pending notification by its identifier.
export function RemovePendingNotification(identifier: string): Promise<void>;
// [RemoveAllDeliveredNotifications](https://wails.io/docs/reference/runtime/notification#removealldeliverednotifications)
// Removes all delivered notifications from the notification center.
export function RemoveAllDeliveredNotifications(): Promise<void>;
// [RemoveDeliveredNotification](https://wails.io/docs/reference/runtime/notification#removedeliverednotification)
// Removes a specific delivered notification by its identifier.
export function RemoveDeliveredNotification(identifier: string): Promise<void>;
// [RemoveNotification](https://wails.io/docs/reference/runtime/notification#removenotification)
// Removes a notification by its identifier (cross-platform convenience function).
export function RemoveNotification(identifier: string): Promise<void>;
-298
View File
@@ -1,298 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export function LogPrint(message) {
window.runtime.LogPrint(message);
}
export function LogTrace(message) {
window.runtime.LogTrace(message);
}
export function LogDebug(message) {
window.runtime.LogDebug(message);
}
export function LogInfo(message) {
window.runtime.LogInfo(message);
}
export function LogWarning(message) {
window.runtime.LogWarning(message);
}
export function LogError(message) {
window.runtime.LogError(message);
}
export function LogFatal(message) {
window.runtime.LogFatal(message);
}
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
}
export function EventsOn(eventName, callback) {
return EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName, ...additionalEventNames) {
return window.runtime.EventsOff(eventName, ...additionalEventNames);
}
export function EventsOffAll() {
return window.runtime.EventsOffAll();
}
export function EventsOnce(eventName, callback) {
return EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
let args = [eventName].slice.call(arguments);
return window.runtime.EventsEmit.apply(null, args);
}
export function WindowReload() {
window.runtime.WindowReload();
}
export function WindowReloadApp() {
window.runtime.WindowReloadApp();
}
export function WindowSetAlwaysOnTop(b) {
window.runtime.WindowSetAlwaysOnTop(b);
}
export function WindowSetSystemDefaultTheme() {
window.runtime.WindowSetSystemDefaultTheme();
}
export function WindowSetLightTheme() {
window.runtime.WindowSetLightTheme();
}
export function WindowSetDarkTheme() {
window.runtime.WindowSetDarkTheme();
}
export function WindowCenter() {
window.runtime.WindowCenter();
}
export function WindowSetTitle(title) {
window.runtime.WindowSetTitle(title);
}
export function WindowFullscreen() {
window.runtime.WindowFullscreen();
}
export function WindowUnfullscreen() {
window.runtime.WindowUnfullscreen();
}
export function WindowIsFullscreen() {
return window.runtime.WindowIsFullscreen();
}
export function WindowGetSize() {
return window.runtime.WindowGetSize();
}
export function WindowSetSize(width, height) {
window.runtime.WindowSetSize(width, height);
}
export function WindowSetMaxSize(width, height) {
window.runtime.WindowSetMaxSize(width, height);
}
export function WindowSetMinSize(width, height) {
window.runtime.WindowSetMinSize(width, height);
}
export function WindowSetPosition(x, y) {
window.runtime.WindowSetPosition(x, y);
}
export function WindowGetPosition() {
return window.runtime.WindowGetPosition();
}
export function WindowHide() {
window.runtime.WindowHide();
}
export function WindowShow() {
window.runtime.WindowShow();
}
export function WindowMaximise() {
window.runtime.WindowMaximise();
}
export function WindowToggleMaximise() {
window.runtime.WindowToggleMaximise();
}
export function WindowUnmaximise() {
window.runtime.WindowUnmaximise();
}
export function WindowIsMaximised() {
return window.runtime.WindowIsMaximised();
}
export function WindowMinimise() {
window.runtime.WindowMinimise();
}
export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
export function WindowSetBackgroundColour(R, G, B, A) {
window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function ScreenGetAll() {
return window.runtime.ScreenGetAll();
}
export function WindowIsMinimised() {
return window.runtime.WindowIsMinimised();
}
export function WindowIsNormal() {
return window.runtime.WindowIsNormal();
}
export function BrowserOpenURL(url) {
window.runtime.BrowserOpenURL(url);
}
export function Environment() {
return window.runtime.Environment();
}
export function Quit() {
window.runtime.Quit();
}
export function Hide() {
window.runtime.Hide();
}
export function Show() {
window.runtime.Show();
}
export function ClipboardGetText() {
return window.runtime.ClipboardGetText();
}
export function ClipboardSetText(text) {
return window.runtime.ClipboardSetText(text);
}
/**
* Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
*
* @export
* @callback OnFileDropCallback
* @param {number} x - x coordinate of the drop
* @param {number} y - y coordinate of the drop
* @param {string[]} paths - A list of file paths.
*/
/**
* OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
*
* @export
* @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
* @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
*/
export function OnFileDrop(callback, useDropTarget) {
return window.runtime.OnFileDrop(callback, useDropTarget);
}
/**
* OnFileDropOff removes the drag and drop listeners and handlers.
*/
export function OnFileDropOff() {
return window.runtime.OnFileDropOff();
}
export function CanResolveFilePaths() {
return window.runtime.CanResolveFilePaths();
}
export function ResolveFilePaths(files) {
return window.runtime.ResolveFilePaths(files);
}
export function InitializeNotifications() {
return window.runtime.InitializeNotifications();
}
export function CleanupNotifications() {
return window.runtime.CleanupNotifications();
}
export function IsNotificationAvailable() {
return window.runtime.IsNotificationAvailable();
}
export function RequestNotificationAuthorization() {
return window.runtime.RequestNotificationAuthorization();
}
export function CheckNotificationAuthorization() {
return window.runtime.CheckNotificationAuthorization();
}
export function SendNotification(options) {
return window.runtime.SendNotification(options);
}
export function SendNotificationWithActions(options) {
return window.runtime.SendNotificationWithActions(options);
}
export function RegisterNotificationCategory(category) {
return window.runtime.RegisterNotificationCategory(category);
}
export function RemoveNotificationCategory(categoryId) {
return window.runtime.RemoveNotificationCategory(categoryId);
}
export function RemoveAllPendingNotifications() {
return window.runtime.RemoveAllPendingNotifications();
}
export function RemovePendingNotification(identifier) {
return window.runtime.RemovePendingNotification(identifier);
}
export function RemoveAllDeliveredNotifications() {
return window.runtime.RemoveAllDeliveredNotifications();
}
export function RemoveDeliveredNotification(identifier) {
return window.runtime.RemoveDeliveredNotification(identifier);
}
export function RemoveNotification(identifier) {
return window.runtime.RemoveNotification(identifier);
}
+4 -31
View File
@@ -3,49 +3,22 @@ module AniTrack
go 1.25.0
require (
github.com/99designs/keyring v1.2.2
github.com/tidwall/gjson v1.19.0
github.com/wailsapp/wails/v2 v2.15.0
github.com/wailsapp/wails/v3 v3.0.0-beta.20
github.com/zalando/go-keyring v0.2.8
)
require (
git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/bep/debounce v1.2.1 // indirect
github.com/adrg/xdg v0.5.3 // indirect
github.com/coder/websocket v1.8.14 // indirect
github.com/danieljoos/wincred v1.2.3 // indirect
github.com/dvsekhvalnov/jose2go v1.8.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/godbus/dbus/v5 v5.2.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect
github.com/labstack/echo/v4 v4.15.2 // indirect
github.com/labstack/gommon v0.5.0 // indirect
github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
github.com/leaanthony/gosod v1.0.4 // indirect
github.com/leaanthony/slicer v1.6.0 // indirect
github.com/leaanthony/u v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.22 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/samber/lo v1.53.0 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tkrajina/go-reflector v0.5.8 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/wailsapp/go-webview2 v1.0.23 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
golang.org/x/crypto v0.53.0 // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.39.0 // indirect
)
// replace github.com/wailsapp/wails/v2 v2.9.1 => /home/nymusicman/go/pkg/mod
+12 -80
View File
@@ -1,70 +1,27 @@
git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 h1:N3IGoHHp9pb6mj1cbXbuaSXV/UMKwmbKLf53nQmtqMA=
git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3/go.mod h1:QtOLZGz8olr4qH2vWK0QH0w0O4T9fEIjMuWpKUsH7nc=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0=
github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk=
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dvsekhvalnov/jose2go v1.8.0 h1:LqkkVKAlHFfH9LOEl5fe4p/zL02OhWE7pCufMBG2jLA=
github.com/dvsekhvalnov/jose2go v1.8.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU=
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ=
github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo/v4 v4.15.2 h1:nnh2sCzGCVYnU+wCisMPiYapEg/QVo/gcI9ePKg5/T4=
github.com/labstack/echo/v4 v4.15.2/go.mod h1:Xzp1Ns1RA2c9fY7nSgUJkpkUZGNbEIVHZbtbOMPktBI=
github.com/labstack/gommon v0.5.0 h1:6VSQ2NOzsnEJ5W6+84E0RbcaDDmgB6NIAzWCczTEe6c=
github.com/labstack/gommon v0.5.0/go.mod h1:Rzlg7HHy1maLfzBYGg9NZcVuz1sA68HHhLjhcEllYE0=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI=
github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw=
github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
@@ -75,37 +32,12 @@ github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0=
github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wailsapp/wails/v2 v2.15.0 h1:u7cHK+UesZOlYxyJxfYLteaCPhws6UsZoDdqUejuX6Q=
github.com/wailsapp/wails/v2 v2.15.0/go.mod h1:scxrgwfsv6yR6fE6cCF+Flfl+JeU+SR87T9x4kILJ6M=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
github.com/wailsapp/wails/v3 v3.0.0-beta.20 h1:AKKrRGMSqzJET1W0Jt9v+f0oOqM9Amsi7LKMM6XnSOE=
github.com/wailsapp/wails/v3 v3.0.0-beta.20/go.mod h1:/6QR46/nhGCSADHbS++XtDb9dkTnenTHlGskTPRo9S0=
github.com/zalando/go-keyring v0.2.8 h1:6sD/Ucpl7jNq10rM2pgqTs0sZ9V3qMrqfIIy5YPccHs=
github.com/zalando/go-keyring v0.2.8/go.mod h1:tsMo+VpRq5NGyKfxoBVjCuMrG47yj8cmakZDO5QGii0=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+36 -25
View File
@@ -2,45 +2,56 @@ package main
import (
"embed"
"log"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/linux"
"github.com/wailsapp/wails/v3/pkg/application"
)
//go:embed all:frontend/dist
var assets embed.FS
func main() {
// Create an instance of the app structure
app := NewApp()
// The service is created after the application (it needs the app
// reference), so the single-instance callback closes over the variable
// and resolves it at call time. A second instance can only launch once
// this one is running, by which point svc is always set.
var svc *App
// Create application with options
err := wails.Run(&options.App{
Title: "AniTrack",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
app := application.New(application.Options{
Name: "AniTrack",
Description: "Track anime watchlists across AniList, MyAnimeList, and Simkl",
Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets),
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
SingleInstanceLock: &options.SingleInstanceLock{
UniqueId: "49c93b6d-663d-4b7a-9cb0-8a469ea9182b",
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
SingleInstance: &application.SingleInstanceOptions{
UniqueID: "49c93b6d-663d-4b7a-9cb0-8a469ea9182b",
OnSecondInstanceLaunch: func(data application.SecondInstanceData) {
svc.onSecondInstanceLaunch(data)
},
Bind: []interface{}{
app,
},
Linux: &linux.Options{
Icon: []byte("./build/AniTrack.png"),
WindowIsTranslucent: false,
WebviewGpuPolicy: linux.WebviewGpuPolicyNever,
Linux: application.LinuxOptions{
ProgramName: "AniTrack",
},
})
if err != nil {
println("Error:", err.Error())
svc = NewApp(app)
app.RegisterService(application.NewService(svc))
app.Window.NewWithOptions(application.WebviewWindowOptions{
Title: appTitle(),
Width: 1024,
Height: 768,
BackgroundColour: application.NewRGBA(27, 38, 54, 1),
URL: "/",
Linux: application.LinuxWindow{
Icon: []byte("./build/AniTrack.png"),
WindowIsTranslucent: false,
WebviewGpuPolicy: application.WebviewGpuPolicyNever,
},
})
if err := app.Run(); err != nil {
log.Fatal(err)
}
}