chore: release v0.27.12
This commit is contained in:
+69
-5
@@ -42,6 +42,62 @@ func (a *App) SetWatchlistContestPattern(p string) {
|
||||
a.setSettingGlobal(keyWatchlistContestPattern, p)
|
||||
}
|
||||
|
||||
// The named contest callsigns: the other half of the auto-add, and the half the
|
||||
// pattern cannot express.
|
||||
//
|
||||
// A special-event fleet is usually a common string in the callsign — WWA in
|
||||
// TM29WWA, HB9WWA, F4WWA/P — and the pattern collects those on sight. But an
|
||||
// entry list is not a naming convention: R7W can be part of the same event and
|
||||
// share nothing with it, and no pattern will ever catch that station without
|
||||
// catching half the band with it. So the two work together: the pattern for the
|
||||
// family, this list for everybody else.
|
||||
//
|
||||
// Stored GLOBALLY, like the pattern and the list itself — an event is worth
|
||||
// hunting whichever station profile is on.
|
||||
func (a *App) GetWatchlistContestCalls() string {
|
||||
return a.settingOr(keyWatchlistContestCalls, "")
|
||||
}
|
||||
|
||||
// SetWatchlistContestCalls stores the list as typed and caches the parsed set.
|
||||
//
|
||||
// The RAW text is what is stored: the operator's line breaks and their order
|
||||
// are how the list is read back a week later, and rewriting it into a
|
||||
// normalised single line loses the only structure it has.
|
||||
func (a *App) SetWatchlistContestCalls(list string) {
|
||||
a.setSettingGlobal(keyWatchlistContestCalls, list)
|
||||
a.watchCalls.Store(parseContestCalls(list))
|
||||
applog.Printf("watchlist: %d named contest callsigns", len(parseContestCalls(list)))
|
||||
}
|
||||
|
||||
// parseContestCalls splits the box into a set. One per line is what is asked
|
||||
// for, and commas, semicolons and spaces are accepted too: a list pasted from
|
||||
// an announcement arrives in whatever shape the announcement used.
|
||||
func parseContestCalls(list string) map[string]struct{} {
|
||||
out := map[string]struct{}{}
|
||||
for _, tok := range strings.FieldsFunc(strings.ToUpper(list), func(r rune) bool {
|
||||
return r == ',' || r == ';' || r == ' ' || r == '\t' || r == '\n' || r == '\r'
|
||||
}) {
|
||||
if tok = strings.TrimSpace(tok); tok != "" {
|
||||
out[tok] = struct{}{}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// isNamedContestCall answers the hot path from the cached set.
|
||||
func (a *App) isNamedContestCall(call string) bool {
|
||||
v := a.watchCalls.Load()
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
set, ok := v.(map[string]struct{})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, found := set[strings.ToUpper(strings.TrimSpace(call))]
|
||||
return found
|
||||
}
|
||||
|
||||
// WatchlistEntries returns the list for the tab.
|
||||
func (a *App) WatchlistEntries() []watchlist.Entry {
|
||||
if a.watchlist == nil {
|
||||
@@ -210,12 +266,20 @@ func (a *App) watchSpot(dxCall, band, mode, country, comment string, freqHz int6
|
||||
}
|
||||
entry, notify, ok := a.watchlist.MarkSeen(dxCall)
|
||||
if !ok {
|
||||
// Not watched yet — the auto-contest pattern may claim it. Contains, not
|
||||
// prefix: the event string sits anywhere in these calls (HB9WWA, F4WWA/P).
|
||||
if p := a.GetWatchlistContestPattern(); p != "" &&
|
||||
strings.Contains(strings.ToUpper(dxCall), p) {
|
||||
// Not watched yet — the contest pattern or the named list may claim it.
|
||||
// Contains, not prefix, for the pattern: the event string sits anywhere
|
||||
// in those calls (HB9WWA, F4WWA/P). The named list is exact, and is what
|
||||
// catches the entries whose callsign says nothing about the event.
|
||||
p := a.GetWatchlistContestPattern()
|
||||
byPattern := p != "" && strings.Contains(strings.ToUpper(dxCall), p)
|
||||
byName := a.isNamedContestCall(dxCall)
|
||||
if byPattern || byName {
|
||||
if err := a.watchlist.Add(dxCall, true); err == nil {
|
||||
applog.Printf("watchlist: auto-added %s (contest pattern %q)", dxCall, p)
|
||||
why := fmt.Sprintf("contest pattern %q", p)
|
||||
if byName {
|
||||
why = "named in the contest list"
|
||||
}
|
||||
applog.Printf("watchlist: auto-added %s (%s)", dxCall, why)
|
||||
entry, notify, ok = a.watchlist.MarkSeen(dxCall)
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "watchlist:changed")
|
||||
|
||||
Reference in New Issue
Block a user