···29293030## Milestone 4 — Indexing & Progress
31313232-- [ ] Implement `IndexService` struct with Wails service binding
3333-- [ ] `Refresh(limit)` — concurrent bookmark + like fetch, batch insert (port `RefreshAndIndex` logic)
3434-- [ ] Populate `facets` column from `FeedPost.Facets` during `convertPostView`
3535-- [ ] `IsIndexing()` — thread-safe boolean guard to prevent concurrent refreshes
3636-- [ ] Emit Wails events: `index:started`, `index:progress`, `index:done`
3737-- [ ] Frontend: "Refresh" button in header, optional limit input
3838-- [ ] Frontend: bottom-pinned progress bar component driven by `index:*` events
3232+- [x] Implement `IndexService` struct with Wails service binding
3333+- [x] `Refresh(limit)` — concurrent bookmark + like fetch, batch insert (port `RefreshAndIndex` logic)
3434+- [x] Populate `facets` column from `FeedPost.Facets` during `convertPostView`
3535+- [x] `IsIndexing()` — thread-safe boolean guard to prevent concurrent refreshes
3636+- [x] Emit Wails events: `index:started`, `index:progress`, `index:done`
3737+- [x] Frontend: "Refresh" button in header, optional limit input
3838+- [x] Frontend: bottom-pinned progress bar component driven by `index:*` events
39394040## Milestone 5 — Search & Data Table
4141
+10-10
app.go
···55 "fmt"
66 "os"
77 "path/filepath"
88-99- "github.com/wailsapp/wails/v2/pkg/runtime"
108)
1191210// App struct
1311type App struct {
1414- ctx context.Context
1515- authService *AuthService
1212+ ctx context.Context
1313+ authService *AuthService
1414+ indexService *IndexService
1615}
17161817// NewApp creates a new App application struct
1918func NewApp() *App {
2019 return &App{
2121- authService: NewAuthService(),
2020+ authService: NewAuthService(),
2121+ indexService: NewIndexService(),
2222 }
2323}
24242525-// startup is called when the app starts.
2626-//
2727-// The context is saved so we can call the runtime methods
2525+// startup is called when the app starts. The context is saved so we can call
2626+// the runtime methods.
2827func (a *App) startup(ctx context.Context) {
2928 a.ctx = ctx
2929+3030+ a.indexService.SetContext(ctx)
30313132 dbPath := getDBPath()
3233 if err := Open(dbPath); err != nil {
···43444445// shutdown is called when the app shuts down
4546func (a *App) shutdown(ctx context.Context) {
4646- runtime.LogInfo(ctx, "Shutting down")
4747 if err := Close(); err != nil {
4848- runtime.LogErrorf(ctx, "failed to close database: %v", err)
4848+ fmt.Printf("failed to close database: %v\n", err)
4949 }
5050}
5151
···11+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
22+// This file is automatically generated. DO NOT EDIT
33+import {context} from '../models';
44+55+export function IsIndexing():Promise<boolean>;
66+77+export function Refresh(arg1:number):Promise<void>;
88+99+export function SetContext(arg1:context.Context):Promise<void>;
+15
frontend/wailsjs/go/main/IndexService.js
···11+// @ts-check
22+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
33+// This file is automatically generated. DO NOT EDIT
44+55+export function IsIndexing() {
66+ return window['go']['main']['IndexService']['IsIndexing']();
77+}
88+99+export function Refresh(arg1) {
1010+ return window['go']['main']['IndexService']['Refresh'](arg1);
1111+}
1212+1313+export function SetContext(arg1) {
1414+ return window['go']['main']['IndexService']['SetContext'](arg1);
1515+}