Skip to content

Commit cf81932

Browse files
authored
Merge pull request #345 from ErikKalkoken/fix-improve-charts
fix: improve charts
2 parents 94667d2 + 2c5ac51 commit cf81932

File tree

10 files changed

+164
-92
lines changed

10 files changed

+164
-92
lines changed

FyneApp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Website = "https://github.com/ErikKalkoken/evebuddy"
44
Icon = "icon.png"
55
Name = "EVE Buddy"
66
ID = "io.github.erikkalkoken.evebuddy"
7-
Version = "0.52.0"
7+
Version = "0.52.1"
88
Build = 0
99

1010
[Release]

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
fyne.io/fyne/v2 v2.7.1
99
github.com/ErikKalkoken/eveauth v0.1.0
1010
github.com/ErikKalkoken/fyne-kx v0.6.4
11-
github.com/ErikKalkoken/go-set v0.2.0
11+
github.com/ErikKalkoken/go-set v0.3.0
1212
github.com/JohannesKaufmann/html-to-markdown v1.6.0
1313
github.com/PuerkitoBio/goquery v1.11.0
1414
github.com/anthonynsimon/bild v0.14.0
@@ -26,7 +26,7 @@ require (
2626
github.com/maniartech/signals v1.3.1
2727
github.com/mattn/go-sqlite3 v1.14.32
2828
github.com/microcosm-cc/bluemonday v1.0.27
29-
github.com/s-daehling/fyne-charts v0.0.0-20251223123406-e9d1bc6e925e
29+
github.com/s-daehling/fyne-charts v0.0.0-20251227165118-196292e3799e
3030
github.com/stretchr/testify v1.11.1
3131
github.com/yuin/goldmark v1.7.13
3232
golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ github.com/ErikKalkoken/fyne-kx v0.6.4 h1:maAd3GEVaT6SeOumhnVkSNGnq/XG5xJc17mClZ
4545
github.com/ErikKalkoken/fyne-kx v0.6.4/go.mod h1:yRxTow1yH6mWQigWVE8HLl++kKHvtgy8PIucH7hOlOc=
4646
github.com/ErikKalkoken/go-set v0.2.0 h1:qbeuoupUMuwnbHzGwXTeFXXC9m/WLAPeoDakyP6rLnw=
4747
github.com/ErikKalkoken/go-set v0.2.0/go.mod h1:8hyYMuo2dqGaCGf32C/CILHMTVRJ9CV2vlcIPGOBe5I=
48+
github.com/ErikKalkoken/go-set v0.3.0 h1:yJxMD/7UfVB4+wEJ9PD0A+pODy0vreyo72szy1UcgZQ=
49+
github.com/ErikKalkoken/go-set v0.3.0/go.mod h1:8hyYMuo2dqGaCGf32C/CILHMTVRJ9CV2vlcIPGOBe5I=
4850
github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5x+rHJnb1ssNmqpLH/k=
4951
github.com/JohannesKaufmann/html-to-markdown v1.6.0/go.mod h1:NUI78lGg/a7vpEJTz/0uOcYMaibytE4BUOQS8k78yPQ=
5052
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
@@ -281,6 +283,10 @@ github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU
281283
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
282284
github.com/s-daehling/fyne-charts v0.0.0-20251223123406-e9d1bc6e925e h1:WEoJbRceextSbiiMQvoN6mkEiJ9GDLNqm6jckPxBzJA=
283285
github.com/s-daehling/fyne-charts v0.0.0-20251223123406-e9d1bc6e925e/go.mod h1:2Rqw/+P+IlFt/+KmHQYTfPK8qqTkvafhXiN8pg5MTIg=
286+
github.com/s-daehling/fyne-charts v0.0.0-20251226130856-a9897318c5b6 h1:dbNhNdu8oauDarC8poWAD+XLbecH7+sHU5ydduFznBg=
287+
github.com/s-daehling/fyne-charts v0.0.0-20251226130856-a9897318c5b6/go.mod h1:2Rqw/+P+IlFt/+KmHQYTfPK8qqTkvafhXiN8pg5MTIg=
288+
github.com/s-daehling/fyne-charts v0.0.0-20251227165118-196292e3799e h1:N6JG18Nfb07YMwpQEseD9JWjx/JUAs79NgPC1pF5izc=
289+
github.com/s-daehling/fyne-charts v0.0.0-20251227165118-196292e3799e/go.mod h1:2Rqw/+P+IlFt/+KmHQYTfPK8qqTkvafhXiN8pg5MTIg=
284290
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
285291
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
286292
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=

internal/app/ui/theme.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ type customTheme struct {
4545

4646
// newCustomTheme returns a new custom theme.
4747
// Must be called after the app has started.
48-
func newCustomTheme(mode settings.ColorTheme) *customTheme {
48+
func newCustomTheme(defaultTheme fyne.Theme, mode settings.ColorTheme) *customTheme {
4949
th := &customTheme{
50-
defaultTheme: fyne.CurrentApp().Settings().Theme(),
50+
defaultTheme: defaultTheme,
5151
mode: mode,
5252
}
5353
return th

internal/app/ui/ui.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,13 @@ type baseUI struct {
187187
concurrencyLimit int
188188
corporation atomic.Pointer[app.Corporation]
189189
dataPaths xmaps.OrderedMap[string, string] // Paths to user data
190-
isDesktop bool // whether the app runs on a desktop. If false we assume it's on mobile.
191-
isFakeMobile bool // Show mobile variant on a desktop (for development)
192-
isForeground atomic.Bool // whether the app is currently shown in the foreground
193-
isOffline bool // Run the app in offline mode
194-
isStartupCompleted atomic.Bool // whether the app has completed startup (for testing)
195-
isUpdateDisabled bool // Whether to disable update tickers (useful for debugging)
190+
defaultTheme fyne.Theme
191+
isDesktop bool // whether the app runs on a desktop. If false we assume it's on mobile.
192+
isFakeMobile bool // Show mobile variant on a desktop (for development)
193+
isForeground atomic.Bool // whether the app is currently shown in the foreground
194+
isOffline bool // Run the app in offline mode
195+
isStartupCompleted atomic.Bool // whether the app has completed startup (for testing)
196+
isUpdateDisabled bool // Whether to disable update tickers (useful for debugging)
196197
sig *singleinstance.Group
197198
wasStarted atomic.Bool // whether the app has already been started at least once
198199
window fyne.Window // main window
@@ -461,6 +462,7 @@ func (u *baseUI) Start() bool {
461462
return false
462463
}
463464
// First app start
465+
u.defaultTheme = theme.Current()
464466
u.setColorTheme(u.settings.ColorTheme())
465467
if u.isOffline {
466468
slog.Info("App started in offline mode")
@@ -912,7 +914,7 @@ func (u *baseUI) updateStatus() {
912914
}
913915

914916
func (u *baseUI) setColorTheme(s settings.ColorTheme) {
915-
u.app.Settings().SetTheme(newCustomTheme(s))
917+
u.app.Settings().SetTheme(newCustomTheme(u.defaultTheme, s))
916918
}
917919

918920
func (u *baseUI) updateMailIndicator() {

internal/app/ui/wealth.go

Lines changed: 88 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ import (
1414
"fyne.io/fyne/v2/theme"
1515
"fyne.io/fyne/v2/widget"
1616
"github.com/s-daehling/fyne-charts/pkg/coord"
17-
chartData "github.com/s-daehling/fyne-charts/pkg/data"
17+
"github.com/s-daehling/fyne-charts/pkg/data"
1818
"github.com/s-daehling/fyne-charts/pkg/prop"
1919

2020
"github.com/ErikKalkoken/evebuddy/internal/app"
2121
"github.com/ErikKalkoken/evebuddy/internal/xslices"
2222
)
2323

2424
const (
25-
wealthMultiplier = 1_000_000_000
26-
wealthMaxCharacters = 7
25+
wealthMultiplier = 1_000_000_000
26+
wealthMaxCharacters = 7
27+
wealthNameTruncationLimit = 16
28+
wealthNameTruncationSuffix = 2
2729
)
2830

2931
type wealth struct {
@@ -104,7 +106,7 @@ func (a *wealth) CreateRenderer() fyne.WidgetRenderer {
104106
}
105107

106108
func (a *wealth) update() {
107-
data, characters, err := a.compileData(a.u.services())
109+
rows, characters, err := a.compileData(a.u.services())
108110
if err != nil {
109111
slog.Error("Failed to fetch data for charts", "err", err)
110112
fyne.Do(func() {
@@ -130,7 +132,7 @@ func (a *wealth) update() {
130132
})
131133

132134
var totalWallet, totalAssets float64
133-
for _, r := range data {
135+
for _, r := range rows {
134136
totalAssets += r.assets
135137
totalWallet += r.wallet
136138
}
@@ -139,19 +141,19 @@ func (a *wealth) update() {
139141
a.onUpdate(totalWallet*wealthMultiplier, totalAssets*wealthMultiplier)
140142
}
141143

142-
a.updateAssetDetail(data, totalAssets)
143-
a.updateAssetSplit(data, totalAssets)
144-
a.updateCharacterSplit(data, totalAssets, totalWallet)
144+
a.updateAssetDetail(rows, totalAssets)
145+
a.updateAssetSplit(rows, totalAssets)
146+
a.updateCharacterSplit(rows, totalAssets, totalWallet)
145147
a.updateTotalSplit(totalAssets, totalWallet)
146-
a.updateWalletDetail(data, totalWallet)
147-
a.updateWalletSplit(data, totalWallet)
148+
a.updateWalletDetail(rows, totalWallet)
149+
a.updateWalletSplit(rows, totalWallet)
148150
}
149151

150-
func (a *wealth) updateAssetDetail(data []dataRow, totalAssets float64) {
152+
func (a *wealth) updateAssetDetail(rows []wealthRow, totalAssets float64) {
151153
colors := newColorWheel()
152-
d := xslices.Map(data, func(r dataRow) chartData.CategoricalPoint {
153-
return chartData.CategoricalPoint{
154-
C: r.label,
154+
d := xslices.Map(rows, func(r wealthRow) data.CategoricalPoint {
155+
return data.CategoricalPoint{
156+
C: r.character,
155157
Val: r.assets,
156158
}
157159
})
@@ -172,11 +174,11 @@ func (a *wealth) updateAssetDetail(data []dataRow, totalAssets float64) {
172174
})
173175
}
174176

175-
func (a *wealth) updateAssetSplit(data []dataRow, totalAssets float64) {
177+
func (a *wealth) updateAssetSplit(rows []wealthRow, totalAssets float64) {
176178
colors := newColorWheel()
177-
d := xslices.Map(data, func(r dataRow) chartData.ProportionalPoint {
178-
return chartData.ProportionalPoint{
179-
C: r.label,
179+
d := xslices.Map(rows, func(r wealthRow) data.ProportionalPoint {
180+
return data.ProportionalPoint{
181+
C: r.character,
180182
Val: r.assets,
181183
Col: colors.next(),
182184
}
@@ -198,11 +200,11 @@ func (a *wealth) updateAssetSplit(data []dataRow, totalAssets float64) {
198200
})
199201
}
200202

201-
func (a *wealth) updateCharacterSplit(data []dataRow, totalAssets float64, totalWallet float64) {
203+
func (a *wealth) updateCharacterSplit(rows []wealthRow, totalAssets float64, totalWallet float64) {
202204
colors := newColorWheel()
203-
d := xslices.Map(data, func(r dataRow) chartData.ProportionalPoint {
204-
return chartData.ProportionalPoint{
205-
C: r.label,
205+
d := xslices.Map(rows, func(r wealthRow) data.ProportionalPoint {
206+
return data.ProportionalPoint{
207+
C: r.character,
206208
Val: r.assets,
207209
Col: colors.next(),
208210
}
@@ -226,7 +228,7 @@ func (a *wealth) updateCharacterSplit(data []dataRow, totalAssets float64, total
226228

227229
func (a *wealth) updateTotalSplit(totalAssets float64, totalWallet float64) {
228230
colors := newColorWheel()
229-
s, err := prop.NewSeries("", []chartData.ProportionalPoint{
231+
s, err := prop.NewSeries("", []data.ProportionalPoint{
230232
{
231233
C: "Assets combined",
232234
Val: totalAssets,
@@ -249,11 +251,11 @@ func (a *wealth) updateTotalSplit(totalAssets float64, totalWallet float64) {
249251
})
250252
}
251253

252-
func (a *wealth) updateWalletDetail(data []dataRow, totalWallet float64) {
254+
func (a *wealth) updateWalletDetail(rows []wealthRow, totalWallet float64) {
253255
colors := newColorWheel()
254-
d := xslices.Map(data, func(r dataRow) chartData.CategoricalPoint {
255-
return chartData.CategoricalPoint{
256-
C: r.label,
256+
d := xslices.Map(rows, func(r wealthRow) data.CategoricalPoint {
257+
return data.CategoricalPoint{
258+
C: r.character,
257259
Val: r.wallet,
258260
}
259261
})
@@ -274,11 +276,11 @@ func (a *wealth) updateWalletDetail(data []dataRow, totalWallet float64) {
274276
})
275277
}
276278

277-
func (a *wealth) updateWalletSplit(data []dataRow, totalWallet float64) {
279+
func (a *wealth) updateWalletSplit(rows []wealthRow, totalWallet float64) {
278280
colors := newColorWheel()
279-
d := xslices.Map(data, func(r dataRow) chartData.ProportionalPoint {
280-
return chartData.ProportionalPoint{
281-
C: r.label,
281+
d := xslices.Map(rows, func(r wealthRow) data.ProportionalPoint {
282+
return data.ProportionalPoint{
283+
C: r.character,
282284
Val: r.wallet,
283285
Col: colors.next(),
284286
}
@@ -300,65 +302,65 @@ func (a *wealth) updateWalletSplit(data []dataRow, totalWallet float64) {
300302
})
301303
}
302304

303-
func reduceProportionalPoints(data []chartData.ProportionalPoint, m int) []chartData.ProportionalPoint {
304-
if len(data) <= m {
305-
return data
305+
func reduceProportionalPoints(rows []data.ProportionalPoint, m int) []data.ProportionalPoint {
306+
if len(rows) <= m {
307+
return rows
306308
}
307-
slices.SortFunc(data, func(a, b chartData.ProportionalPoint) int {
309+
slices.SortFunc(rows, func(a, b data.ProportionalPoint) int {
308310
return cmp.Compare(b.Val, a.Val)
309311
})
310-
others := data[m].Val
311-
if len(data) > m {
312-
for _, x := range data[m+1:] {
312+
others := rows[m].Val
313+
if len(rows) > m {
314+
for _, x := range rows[m+1:] {
313315
others += x.Val
314316
}
315317
}
316-
data = data[:m]
317-
slices.SortFunc(data, func(a, b chartData.ProportionalPoint) int {
318+
rows = rows[:m]
319+
slices.SortFunc(rows, func(a, b data.ProportionalPoint) int {
318320
return strings.Compare(a.C, b.C)
319321
})
320-
data = append(data,
321-
chartData.ProportionalPoint{
322+
rows = append(rows,
323+
data.ProportionalPoint{
322324
C: "Others",
323325
Val: others,
324326
Col: theme.Color(theme.ColorNameDisabled),
325327
})
326-
return data
328+
return rows
327329
}
328330

329-
func reduceCategoricalPoints(data []chartData.CategoricalPoint, m int) []chartData.CategoricalPoint {
330-
if len(data) <= m {
331-
return data
331+
func reduceCategoricalPoints(rows []data.CategoricalPoint, m int) []data.CategoricalPoint {
332+
if len(rows) <= m {
333+
return rows
332334
}
333-
slices.SortFunc(data, func(a, b chartData.CategoricalPoint) int {
335+
slices.SortFunc(rows, func(a, b data.CategoricalPoint) int {
334336
return cmp.Compare(b.Val, a.Val)
335337
})
336-
others := data[m].Val
337-
if len(data) > m {
338-
for _, x := range data[m+1:] {
338+
others := rows[m].Val
339+
if len(rows) > m {
340+
for _, x := range rows[m+1:] {
339341
others += x.Val
340342
}
341343
}
342-
data = data[:m]
343-
slices.SortFunc(data, func(a, b chartData.CategoricalPoint) int {
344+
rows = rows[:m]
345+
slices.SortFunc(rows, func(a, b data.CategoricalPoint) int {
344346
return strings.Compare(a.C, b.C)
345347
})
346-
data = append(data,
347-
chartData.CategoricalPoint{
348+
rows = append(rows,
349+
data.CategoricalPoint{
348350
C: "Others",
349351
Val: others,
350352
})
351-
return data
353+
return rows
352354
}
353355

354-
type dataRow struct {
355-
label string
356-
wallet float64
357-
assets float64
358-
total float64
356+
type wealthRow struct {
357+
character string
358+
wallet float64
359+
assets float64
360+
total float64
359361
}
360362

361-
func (*wealth) compileData(s services) ([]dataRow, int, error) {
363+
func (*wealth) compileData(s services) ([]wealthRow, int, error) {
362364
ctx := context.Background()
363365
cc, err := s.cs.ListCharacters(ctx)
364366
if err != nil {
@@ -372,7 +374,7 @@ func (*wealth) compileData(s services) ([]dataRow, int, error) {
372374
selected = append(selected, c)
373375
}
374376
}
375-
data := make([]dataRow, 0)
377+
rows := make([]wealthRow, 0)
376378
for _, c := range selected {
377379
assetTotal, err := s.cs.AssetTotalValue(ctx, c.ID)
378380
if err != nil {
@@ -381,21 +383,21 @@ func (*wealth) compileData(s services) ([]dataRow, int, error) {
381383
if c.WalletBalance.IsEmpty() && assetTotal.IsEmpty() {
382384
continue
383385
}
386+
character := TruncateWithSuffix(c.EveCharacter.Name, wealthNameTruncationLimit, wealthNameTruncationSuffix)
384387
wallet := c.WalletBalance.ValueOrZero() / wealthMultiplier
385388
assets := assetTotal.ValueOrZero() / wealthMultiplier
386-
label := c.EveCharacter.Name
387-
r := dataRow{
388-
label: label,
389-
assets: assets,
390-
wallet: wallet,
391-
total: assets + wallet,
389+
r := wealthRow{
390+
character: character,
391+
assets: assets,
392+
wallet: wallet,
393+
total: assets + wallet,
392394
}
393-
data = append(data, r)
395+
rows = append(rows, r)
394396
}
395-
slices.SortFunc(data, func(a, b dataRow) int {
396-
return strings.Compare(a.label, b.label)
397+
slices.SortFunc(rows, func(a, b wealthRow) int {
398+
return strings.Compare(a.character, b.character)
397399
})
398-
return data, len(selected), nil
400+
return rows, len(selected), nil
399401
}
400402

401403
type colorWheel struct {
@@ -434,3 +436,17 @@ func (w *colorWheel) next() color.Color {
434436
// func (w *colorWheel) reset() {
435437
// w.n = 0
436438
// }
439+
440+
// TruncateWithSuffix shortens a string to length limit.
441+
// It adds "..." and keeps 'suffixLen' characters at the end.
442+
func TruncateWithSuffix(s string, limit int, suffixLen int) string {
443+
runes := []rune(strings.TrimRight(s, " "))
444+
if len(runes) <= limit {
445+
return string(runes)
446+
}
447+
prefixLen := max(limit-1-suffixLen, 0) // ellipsis counts as 1
448+
prefix := runes[:prefixLen]
449+
suffix := runes[len(runes)-suffixLen:]
450+
strSuffix := strings.TrimRight(string(suffix), " ")
451+
return string(prefix) + "..." + strSuffix
452+
}

0 commit comments

Comments
 (0)