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)
|
||||
err = UpdateFile(localPath, fileData)
|
||||
if err != nil {
|
||||
@@ -124,7 +124,7 @@ func (a *Addon) Update(body []byte) (err error) {
|
||||
return nil
|
||||
}
|
||||
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) {
|
||||
url := a.GetRemoteTocURL()
|
||||
|
93
app.go
93
app.go
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
@@ -37,42 +39,89 @@ type StringResponse struct {
|
||||
Data string `json:"data"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (a *App) GetAddons() AddonsResponse {
|
||||
return AddonsResponse{
|
||||
Data: addonService.Addons,
|
||||
Error: "",
|
||||
}
|
||||
type BoolResponse struct {
|
||||
Data bool `json:"data"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
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)
|
||||
return AddonResponse{
|
||||
Data: addon,
|
||||
Error: err.Error(),
|
||||
res.Data = addon
|
||||
if err != nil {
|
||||
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)
|
||||
return StringResponse{
|
||||
Data: version,
|
||||
Error: err.Error(),
|
||||
res.Data = version
|
||||
if err != nil {
|
||||
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)
|
||||
return StringResponse{
|
||||
Data: version,
|
||||
Error: err.Error(),
|
||||
res.Data = version
|
||||
if err != nil {
|
||||
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)
|
||||
return AddonResponse{
|
||||
Data: addon,
|
||||
Error: err.Error(),
|
||||
res.Data = addon
|
||||
if err != nil {
|
||||
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>
|
||||
|
||||
<template>
|
||||
<header
|
||||
class="flex h-22 items-center justify-center bg-base-100 shadow-lg sticky top-0 z-50 border-b
|
||||
border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"
|
||||
>
|
||||
Biiiiiiiig header
|
||||
</header>
|
||||
</template>
|
||||
<header class="bg-gray-900 text-white py-4">
|
||||
<div class="container mx-auto px-4 relative">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex-1"></div>
|
||||
<h1 class="text-3xl font-bold text-center relative flex-1">
|
||||
{name}
|
||||
</h1>
|
||||
<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">
|
||||
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>
|
||||
|
||||
<template>
|
||||
Hello, world
|
||||
</template>
|
||||
{#if gamePathValid}
|
||||
<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"),
|
||||
$router: join(__dirname, "src/lib/router"),
|
||||
$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 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>;
|
||||
|
@@ -22,6 +22,22 @@ export function 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) {
|
||||
return window['go']['main']['App']['UpdateAddon'](arg1);
|
||||
}
|
||||
|
@@ -78,6 +78,20 @@ export namespace main {
|
||||
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 {
|
||||
data: string;
|
||||
error?: string;
|
||||
|
22
main.go
22
main.go
@@ -30,7 +30,7 @@ func init() {
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
var settingsFilePath = "settings.json"
|
||||
var gamePath string
|
||||
var settings *Settings
|
||||
var addonService *AddonService
|
||||
|
||||
type Settings struct {
|
||||
@@ -55,24 +55,34 @@ func main() {
|
||||
Error.Printf("error opening settings file: %s", err)
|
||||
return
|
||||
}
|
||||
settings := Settings{}
|
||||
err = json.NewDecoder(settingsFile).Decode(&settings)
|
||||
if err != nil {
|
||||
Warning.Printf("error decoding settings: %s", err)
|
||||
settings = Settings{}
|
||||
settings = &Settings{}
|
||||
}
|
||||
settingsFile.Close()
|
||||
log.Printf("Loaded settings: %+v", settings)
|
||||
for name, addon := range settings.Addons {
|
||||
addon.Name = name
|
||||
settings.Addons[name] = addon
|
||||
}
|
||||
|
||||
addonService = &AddonService{}
|
||||
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()
|
||||
|
||||
err = wails.Run(&options.App{
|
||||
Title: "wails-template",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Width: 700,
|
||||
Height: 700,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
@@ -86,5 +96,5 @@ func main() {
|
||||
if err != nil {
|
||||
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