generated from dave/wails-template
Compare commits
6 Commits
4a6a2cf057
...
06bf344ea7
Author | SHA1 | Date | |
---|---|---|---|
06bf344ea7 | |||
e0f3361efe | |||
156c5770e8 | |||
c975aee3cb | |||
a45e3a5d87 | |||
10faaf93c8 |
4
addon.go
4
addon.go
@@ -111,7 +111,7 @@ func (a *Addon) Update(body []byte) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localPath := filepath.Join(gamePath, "Interface", "AddOns", file.Name)
|
localPath := filepath.Join(settings.GamePath, "Interface", "AddOns", file.Name)
|
||||||
log.Printf("Updating file %s", localPath)
|
log.Printf("Updating file %s", localPath)
|
||||||
err = UpdateFile(localPath, fileData)
|
err = UpdateFile(localPath, fileData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -124,7 +124,7 @@ func (a *Addon) Update(body []byte) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (a *Addon) GetLocalTocPath() string {
|
func (a *Addon) GetLocalTocPath() string {
|
||||||
return filepath.Join(gamePath, "Interface", "AddOns", a.Name, a.Name+".toc")
|
return filepath.Join(settings.GamePath, "Interface", "AddOns", a.Name, a.Name+".toc")
|
||||||
}
|
}
|
||||||
func (a *Addon) GetRemoteVersion() (version string, err error) {
|
func (a *Addon) GetRemoteVersion() (version string, err error) {
|
||||||
url := a.GetRemoteTocURL()
|
url := a.GetRemoteTocURL()
|
||||||
|
93
app.go
93
app.go
@@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
)
|
)
|
||||||
@@ -37,42 +39,89 @@ type StringResponse struct {
|
|||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
type BoolResponse struct {
|
||||||
func (a *App) GetAddons() AddonsResponse {
|
Data bool `json:"data"`
|
||||||
return AddonsResponse{
|
Error string `json:"error,omitempty"`
|
||||||
Data: addonService.Addons,
|
|
||||||
Error: "",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetAddon(name string) AddonResponse {
|
func (a *App) GetAddons() (res AddonsResponse) {
|
||||||
|
res.Data = addonService.Addons
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) GetAddon(name string) (res AddonResponse) {
|
||||||
addon, err := addonService.GetAddon(name)
|
addon, err := addonService.GetAddon(name)
|
||||||
return AddonResponse{
|
res.Data = addon
|
||||||
Data: addon,
|
if err != nil {
|
||||||
Error: err.Error(),
|
res.Error = err.Error()
|
||||||
}
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetAddonRemoteVersion(name string) StringResponse {
|
func (a *App) GetAddonRemoteVersion(name string) (res StringResponse) {
|
||||||
version, err := addonService.GetRemoteVersion(name)
|
version, err := addonService.GetRemoteVersion(name)
|
||||||
return StringResponse{
|
res.Data = version
|
||||||
Data: version,
|
if err != nil {
|
||||||
Error: err.Error(),
|
res.Error = err.Error()
|
||||||
}
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetAddonLocalVersion(name string) StringResponse {
|
func (a *App) GetAddonLocalVersion(name string) (res StringResponse) {
|
||||||
version, err := addonService.GetLocalVersion(name)
|
version, err := addonService.GetLocalVersion(name)
|
||||||
return StringResponse{
|
res.Data = version
|
||||||
Data: version,
|
if err != nil {
|
||||||
Error: err.Error(),
|
res.Error = err.Error()
|
||||||
}
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateAddon(name string) AddonResponse {
|
func (a *App) UpdateAddon(name string) (res AddonResponse) {
|
||||||
addon, err := addonService.UpdateAddon(name)
|
addon, err := addonService.UpdateAddon(name)
|
||||||
return AddonResponse{
|
res.Data = addon
|
||||||
Data: addon,
|
if err != nil {
|
||||||
Error: err.Error(),
|
res.Error = err.Error()
|
||||||
}
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) GetGamePath() (res StringResponse) {
|
||||||
|
res.Data = settings.GamePath
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) SetGamePath(path string) (res StringResponse) {
|
||||||
|
settings.GamePath = path
|
||||||
|
err := SaveSettings(*settings)
|
||||||
|
if err != nil {
|
||||||
|
res.Error = err.Error()
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) IsGamePathValid() (res BoolResponse) {
|
||||||
|
if settings.GamePath == "" {
|
||||||
|
res.Data = false
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
// Check if the path exists and contains the Interface/AddOns directory
|
||||||
|
addonPath := filepath.Join(settings.GamePath, "Interface", "AddOns")
|
||||||
|
if _, err := os.Stat(addonPath); os.IsNotExist(err) {
|
||||||
|
res.Data = false
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
res.Data = true
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) SelectDirectory() (res StringResponse) {
|
||||||
|
path, err := runtime.OpenDirectoryDialog(a.ctx, runtime.OpenDialogOptions{
|
||||||
|
Title: "Select World of Warcraft Directory",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
res.Error = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.Data = path
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
39
frontend/src/lib/components/AddonCard.svelte
Normal file
39
frontend/src/lib/components/AddonCard.svelte
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { GetAddonLocalVersion, GetAddonRemoteVersion, UpdateAddon } from "$wails/main/App";
|
||||||
|
import { type main } from "$wails/models";
|
||||||
|
export let addon: main.Addon;
|
||||||
|
let localVersion = "0.0.0";
|
||||||
|
let remoteVersion = "0.0.0";
|
||||||
|
let upToDate = true;
|
||||||
|
GetAddonLocalVersion(addon.name).then((res) => {
|
||||||
|
localVersion = res.data;
|
||||||
|
});
|
||||||
|
GetAddonRemoteVersion(addon.name).then((res) => {
|
||||||
|
remoteVersion = res.data;
|
||||||
|
});
|
||||||
|
$: upToDate = localVersion === remoteVersion;
|
||||||
|
|
||||||
|
async function updateAddon() {
|
||||||
|
const res = await UpdateAddon(addon.name);
|
||||||
|
if (res.error) {
|
||||||
|
console.error(res.error);
|
||||||
|
}
|
||||||
|
GetAddonLocalVersion(addon.name).then((res) => {
|
||||||
|
localVersion = res.data;
|
||||||
|
});
|
||||||
|
GetAddonRemoteVersion(addon.name).then((res) => {
|
||||||
|
remoteVersion = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="bg-gray-900 text-white p-4 m-3 mx-2 rounded-lg">
|
||||||
|
<h2 class="text-2xl font-bold">{addon.name}</h2>
|
||||||
|
<p class="text-gray-300">Local Version: {localVersion}</p>
|
||||||
|
<p class="text-gray-300">Remote Version: {remoteVersion}</p>
|
||||||
|
{#if upToDate}
|
||||||
|
<button class="bg-green-500 disabled text-white p-2 my-2 cursor-default rounded-lg">Up to date</button>
|
||||||
|
{:else}
|
||||||
|
<button class="bg-blue-500 text-white p-2 my-2 rounded-lg" on:click={updateAddon}>Update</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
@@ -1,11 +1,62 @@
|
|||||||
<script lang="ts">
|
<script>
|
||||||
|
import { GetGamePath, IsGamePathValid, SelectDirectory, SetGamePath } from "$wails/main/App";
|
||||||
|
|
||||||
|
let name = "Yggdrasil";
|
||||||
|
let description = "The wow addon manager";
|
||||||
|
let gamePathValid = false;
|
||||||
|
|
||||||
|
IsGamePathValid().then((res) => {
|
||||||
|
if (res.error) {
|
||||||
|
console.error(res.error);
|
||||||
|
} else {
|
||||||
|
gamePathValid = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleSelectDirectory() {
|
||||||
|
try {
|
||||||
|
const result = await SelectDirectory();
|
||||||
|
if (result.error) {
|
||||||
|
console.error("Error selecting directory:", result.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result.data) {
|
||||||
|
const response = await SetGamePath(result.data);
|
||||||
|
if (response.error) {
|
||||||
|
console.error("Error setting game path:", response.error);
|
||||||
|
} else {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error selecting directory:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<header class="bg-gray-900 text-white py-4">
|
||||||
<header
|
<div class="container mx-auto px-4 relative">
|
||||||
class="flex h-22 items-center justify-center bg-base-100 shadow-lg sticky top-0 z-50 border-b
|
<div class="flex justify-between items-center">
|
||||||
border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"
|
<div class="flex-1"></div>
|
||||||
>
|
<h1 class="text-3xl font-bold text-center relative flex-1">
|
||||||
Biiiiiiiig header
|
{name}
|
||||||
</header>
|
</h1>
|
||||||
</template>
|
<div class="flex-1 flex justify-end">
|
||||||
|
<button
|
||||||
|
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center gap-2 transition-colors"
|
||||||
|
on:click={handleSelectDirectory}
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M2 6a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1H8a3 3 0 00-3 3v1.5a1.5 1.5 0 01-3 0V6z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
<path d="M6 12a2 2 0 012-2h8a2 2 0 012 2v2a2 2 0 01-2 2H8a2 2 0 01-2-2v-2z" />
|
||||||
|
</svg>
|
||||||
|
{gamePathValid ? "Change Game Path" : "Set Game Path"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
@@ -1,7 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import AddonCard from "$lib/components/AddonCard.svelte";
|
||||||
|
import { GetAddons, IsGamePathValid } from "$wails/main/App";
|
||||||
|
import { type main } from "$wails/models";
|
||||||
|
|
||||||
|
let addons: { [key: string]: main.Addon } = {};
|
||||||
|
GetAddons().then((res) => {
|
||||||
|
if (res.error) {
|
||||||
|
console.error(res.error);
|
||||||
|
} else {
|
||||||
|
addons = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let gamePath = "";
|
||||||
|
let gamePathValid = false;
|
||||||
|
IsGamePathValid().then((res) => {
|
||||||
|
if (res.error) {
|
||||||
|
console.error(res.error);
|
||||||
|
} else {
|
||||||
|
gamePathValid = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
Hello, world
|
{#if gamePathValid}
|
||||||
</template>
|
<div class="grid grid-cols-3 gap-4">
|
||||||
|
{#each Object.values(addons) as addon}
|
||||||
|
<AddonCard {addon} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex flex-col items-center justify-center h-full">
|
||||||
|
<p class="text-gray-300">Game path is not valid</p>
|
||||||
|
<button class="bg-blue-500 text-white p-2 my-2 rounded-lg">Set Game Path</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</template>
|
||||||
|
@@ -12,6 +12,7 @@ export default defineConfig({
|
|||||||
$components: join(__dirname, "src/lib/components"),
|
$components: join(__dirname, "src/lib/components"),
|
||||||
$router: join(__dirname, "src/lib/router"),
|
$router: join(__dirname, "src/lib/router"),
|
||||||
$wails: join(__dirname, "wailsjs/go"),
|
$wails: join(__dirname, "wailsjs/go"),
|
||||||
|
$runtime: join(__dirname, "wailsjs/runtime"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
8
frontend/wailsjs/go/main/App.d.ts
vendored
8
frontend/wailsjs/go/main/App.d.ts
vendored
@@ -12,4 +12,12 @@ export function GetAddonRemoteVersion(arg1:string):Promise<main.StringResponse>;
|
|||||||
|
|
||||||
export function GetAddons():Promise<main.AddonsResponse>;
|
export function GetAddons():Promise<main.AddonsResponse>;
|
||||||
|
|
||||||
|
export function GetGamePath():Promise<main.StringResponse>;
|
||||||
|
|
||||||
|
export function IsGamePathValid():Promise<main.BoolResponse>;
|
||||||
|
|
||||||
|
export function SelectDirectory():Promise<main.StringResponse>;
|
||||||
|
|
||||||
|
export function SetGamePath(arg1:string):Promise<main.StringResponse>;
|
||||||
|
|
||||||
export function UpdateAddon(arg1:string):Promise<main.AddonResponse>;
|
export function UpdateAddon(arg1:string):Promise<main.AddonResponse>;
|
||||||
|
@@ -22,6 +22,22 @@ export function GetAddons() {
|
|||||||
return window['go']['main']['App']['GetAddons']();
|
return window['go']['main']['App']['GetAddons']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetGamePath() {
|
||||||
|
return window['go']['main']['App']['GetGamePath']();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsGamePathValid() {
|
||||||
|
return window['go']['main']['App']['IsGamePathValid']();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SelectDirectory() {
|
||||||
|
return window['go']['main']['App']['SelectDirectory']();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SetGamePath(arg1) {
|
||||||
|
return window['go']['main']['App']['SetGamePath'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function UpdateAddon(arg1) {
|
export function UpdateAddon(arg1) {
|
||||||
return window['go']['main']['App']['UpdateAddon'](arg1);
|
return window['go']['main']['App']['UpdateAddon'](arg1);
|
||||||
}
|
}
|
||||||
|
@@ -78,6 +78,20 @@ export namespace main {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class BoolResponse {
|
||||||
|
data: boolean;
|
||||||
|
error?: string;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new BoolResponse(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.data = source["data"];
|
||||||
|
this.error = source["error"];
|
||||||
|
}
|
||||||
|
}
|
||||||
export class StringResponse {
|
export class StringResponse {
|
||||||
data: string;
|
data: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
|
22
main.go
22
main.go
@@ -30,7 +30,7 @@ func init() {
|
|||||||
//go:embed all:frontend/dist
|
//go:embed all:frontend/dist
|
||||||
var assets embed.FS
|
var assets embed.FS
|
||||||
var settingsFilePath = "settings.json"
|
var settingsFilePath = "settings.json"
|
||||||
var gamePath string
|
var settings *Settings
|
||||||
var addonService *AddonService
|
var addonService *AddonService
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
@@ -55,24 +55,34 @@ func main() {
|
|||||||
Error.Printf("error opening settings file: %s", err)
|
Error.Printf("error opening settings file: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
settings := Settings{}
|
|
||||||
err = json.NewDecoder(settingsFile).Decode(&settings)
|
err = json.NewDecoder(settingsFile).Decode(&settings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Warning.Printf("error decoding settings: %s", err)
|
Warning.Printf("error decoding settings: %s", err)
|
||||||
settings = Settings{}
|
settings = &Settings{}
|
||||||
}
|
}
|
||||||
settingsFile.Close()
|
settingsFile.Close()
|
||||||
log.Printf("Loaded settings: %+v", settings)
|
log.Printf("Loaded settings: %+v", settings)
|
||||||
|
for name, addon := range settings.Addons {
|
||||||
|
addon.Name = name
|
||||||
|
settings.Addons[name] = addon
|
||||||
|
}
|
||||||
|
|
||||||
addonService = &AddonService{}
|
addonService = &AddonService{}
|
||||||
addonService.Addons = settings.Addons
|
addonService.Addons = settings.Addons
|
||||||
|
for _, addon := range addonService.Addons {
|
||||||
|
version, err := addonService.GetLocalVersion(addon.Name)
|
||||||
|
if err != nil {
|
||||||
|
Warning.Printf("error getting local version: %s", err)
|
||||||
|
}
|
||||||
|
log.Printf("%s %#v", addon.Name, version)
|
||||||
|
}
|
||||||
|
|
||||||
app := NewApp()
|
app := NewApp()
|
||||||
|
|
||||||
err = wails.Run(&options.App{
|
err = wails.Run(&options.App{
|
||||||
Title: "wails-template",
|
Title: "wails-template",
|
||||||
Width: 1024,
|
Width: 700,
|
||||||
Height: 768,
|
Height: 700,
|
||||||
AssetServer: &assetserver.Options{
|
AssetServer: &assetserver.Options{
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
},
|
},
|
||||||
@@ -86,5 +96,5 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
println("Error:", err.Error())
|
println("Error:", err.Error())
|
||||||
}
|
}
|
||||||
SaveSettings(settings)
|
SaveSettings(*settings)
|
||||||
}
|
}
|
||||||
|
@@ -1 +1 @@
|
|||||||
{"gamePath":"","addons":{"Channeler":{"name":"","url":"https://git.site.quack-lab.dev/dave/wow_channeler"},"Dechickenator":{"name":"","url":"https://git.site.quack-lab.dev/dave/wow_dechickenator"},"Heimdall":{"name":"","url":"https://git.site.quack-lab.dev/dave/wow-Heimdall"}}}
|
{"gamePath":"C:\\Games\\WoWRuski","addons":{"Channeler":{"name":"Channeler","url":"https://git.site.quack-lab.dev/dave/wow_channeler"},"Dechickenator":{"name":"Dechickenator","url":"https://git.site.quack-lab.dev/dave/wow_dechickenator"},"Heimdall":{"name":"Heimdall","url":"https://git.site.quack-lab.dev/dave/wow-Heimdall"}}}
|
||||||
|
Reference in New Issue
Block a user