Ariver
2026-06-30 ac31349b32d89b2798cd20224fcdede91d6bfe05
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package services
 
import (
    "fmt"
    "os"
    "os/exec"
    "path/filepath"
    "runtime"
    "time"
    "voicesnap/internal/history"
)
 
// HistoryService provides recognition history to the frontend.
type HistoryService struct {
    store *history.Store
}
 
// HistoryStatus summarizes full-history state for paginated views.
type HistoryStatus struct {
    RetentionDays            int    `json:"retentionDays"`
    StoragePath              string `json:"storagePath"`
    StorageSizeBytes         int64  `json:"storageSizeBytes"`
    StorageExists            bool   `json:"storageExists"`
    StorageSizeAvailable     bool   `json:"storageSizeAvailable"`
    TotalCount               int    `json:"totalCount"`
    ExportedCount            int    `json:"exportedCount"`
    UnexportedTodayCount     int    `json:"unexportedTodayCount"`
    UnexportedLast7DaysCount int    `json:"unexportedLast7DaysCount"`
    UnexportedAllCount       int    `json:"unexportedAllCount"`
}
 
func NewHistoryService(store *history.Store) *HistoryService {
    return &HistoryService{store: store}
}
 
// GetAll returns all history entries (newest first).
func (s *HistoryService) GetAll() []history.Entry {
    return s.store.GetAll()
}
 
// GetPage returns one page of history entries (newest first).
func (s *HistoryService) GetPage(page int, pageSize int) history.PageResult {
    return s.store.GetPage(page, pageSize)
}
 
// GetStatus returns full-history metadata used by the paginated UI.
func (s *HistoryService) GetStatus() HistoryStatus {
    path := s.store.Path()
    counts := s.store.Counts(time.Now(), time.Local)
    status := HistoryStatus{
        RetentionDays:            s.store.GetRetentionDays(),
        StoragePath:              path,
        TotalCount:               counts.TotalCount,
        ExportedCount:            counts.ExportedCount,
        UnexportedTodayCount:     counts.UnexportedTodayCount,
        UnexportedLast7DaysCount: counts.UnexportedLast7DaysCount,
        UnexportedAllCount:       counts.UnexportedAllCount,
    }
 
    if info, err := os.Stat(path); err == nil {
        status.StorageExists = true
        status.StorageSizeAvailable = true
        status.StorageSizeBytes = info.Size()
    } else if os.IsPermission(err) {
        status.StorageExists = true
    }
    return status
}
 
// Add adds a new recognition result to history.
func (s *HistoryService) Add(text string) {
    s.store.Add(text)
}
 
// Delete removes a single entry by timestamp.
func (s *HistoryService) Delete(timestamp int64) {
    s.store.Delete(timestamp)
}
 
// ClearAll removes all history entries.
func (s *HistoryService) ClearAll() {
    s.store.ClearAll()
}
 
// ClearExported removes all history entries that have already been exported.
func (s *HistoryService) ClearExported() (history.ClearExportedResult, error) {
    return s.store.ClearExported()
}
 
// GetRetentionDays returns the current retention period in days.
func (s *HistoryService) GetRetentionDays() int {
    return s.store.GetRetentionDays()
}
 
// SetRetentionDays sets how long to keep history (0 = forever).
func (s *HistoryService) SetRetentionDays(days int) error {
    return s.store.SetRetentionDays(days)
}
 
// GetStoragePath returns the full history.json path.
func (s *HistoryService) GetStoragePath() string {
    return s.store.Path()
}
 
// OpenStorageFolder opens the folder containing history.json.
func (s *HistoryService) OpenStorageFolder() error {
    dir := filepath.Dir(s.store.Path())
    info, err := os.Stat(dir)
    if err != nil {
        return fmt.Errorf("history storage folder unavailable: %w", err)
    }
    if !info.IsDir() {
        return fmt.Errorf("history storage path is not a folder: %s", dir)
    }
 
    switch runtime.GOOS {
    case "darwin":
        return exec.Command("open", dir).Start()
    case "windows":
        return exec.Command("rundll32", "url.dll,FileProtocolHandler", dir).Start()
    default:
        return exec.Command("xdg-open", dir).Start()
    }
}