pass fetch options through TUI
This commit is contained in:
parent
3a1500bfbb
commit
44f940c882
6 changed files with 24 additions and 8 deletions
|
|
@ -501,7 +501,7 @@ fn runCli(init: std.process.Init) !u8 {
|
|||
// loader resolve + union-merge the same way the CLI does.
|
||||
// This is the load-bearing fix for "CLI and TUI report
|
||||
// different totals" - there's exactly one code path now.
|
||||
tui.run(io, gpa_alloc, tui_config, globals.portfolio_patterns, globals.watchlist_path, resolved_theme, cmd_args, today) catch |err| switch (err) {
|
||||
tui.run(io, gpa_alloc, tui_config, globals.portfolio_patterns, globals.watchlist_path, resolved_theme, cmd_args, today, globals.refresh_policy) catch |err| switch (err) {
|
||||
// tui.run already printed an actionable stderr message
|
||||
// for invalid CLI args; surface as exit 1 without a
|
||||
// panic / stack trace.
|
||||
|
|
|
|||
10
src/tui.zig
10
src/tui.zig
|
|
@ -502,6 +502,12 @@ pub const App = struct {
|
|||
local_tz: zfin.market.TimeZone,
|
||||
config: zfin.Config,
|
||||
svc: *zfin.DataService,
|
||||
/// Cache-vs-network policy from the global `--refresh-data` flag,
|
||||
/// mapped once at init. Threaded into every automatic data fetch
|
||||
/// (the initial `portfolio.load` and each tab's `loadData`) so the
|
||||
/// TUI honors `--refresh-data=never` (offline) and `=force` the same
|
||||
/// way the CLI commands do. Default `.{}` is auto (respect TTL).
|
||||
fetch_options: zfin.FetchOptions = .{},
|
||||
keymap: keybinds.KeyMap,
|
||||
theme: theme.Theme,
|
||||
active_tab: Tab = .portfolio,
|
||||
|
|
@ -2510,6 +2516,7 @@ pub fn run(
|
|||
app_theme: theme.Theme,
|
||||
args: []const []const u8,
|
||||
today: zfin.Date,
|
||||
refresh_policy: framework.RefreshPolicy,
|
||||
) !void {
|
||||
const watchlist_path: ?[]const u8 = global_watchlist_path;
|
||||
|
||||
|
|
@ -2593,6 +2600,7 @@ pub fn run(
|
|||
.local_tz = local_tz,
|
||||
.config = config,
|
||||
.svc = svc,
|
||||
.fetch_options = cli.fetchOptionsFromPolicy(refresh_policy),
|
||||
.keymap = keymap,
|
||||
.theme = app_theme,
|
||||
.symbol = symbol,
|
||||
|
|
@ -2684,6 +2692,8 @@ pub fn run(
|
|||
.progress = symbol_progress.callback(),
|
||||
.aggregate_progress = aggregate_progress.callback(),
|
||||
.watchlist_syms = watch_syms.items,
|
||||
.force_refresh = app_inst.fetch_options.force_refresh,
|
||||
.skip_network = app_inst.fetch_options.skip_network,
|
||||
}) catch |err| blk: {
|
||||
std.log.scoped(.tui).warn("portfolio load failed: {t}", .{err});
|
||||
break :blk null;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,10 @@ pub const tab = struct {
|
|||
/// frees current payload, clears flags, and re-runs the
|
||||
/// fetch path.
|
||||
pub fn reload(state: *State, app: *App) !void {
|
||||
if (app.symbol.len > 0) {
|
||||
// Offline mode (--refresh-data=never): skip cache invalidation.
|
||||
// loadData can't re-fetch, so dropping the entry would just blank
|
||||
// the tab; instead re-render from the cached entry.
|
||||
if (app.symbol.len > 0 and !app.fetch_options.skip_network) {
|
||||
app.svc.invalidate(app.symbol, .earnings);
|
||||
}
|
||||
// Clear every flag so loadData has the same starting
|
||||
|
|
@ -135,7 +138,7 @@ fn loadData(state: *State, app: *App) void {
|
|||
state.loaded = true;
|
||||
state.error_msg = null;
|
||||
|
||||
const result = app.svc.getEarnings(app.symbol, .{}) catch |err| {
|
||||
const result = app.svc.getEarnings(app.symbol, app.fetch_options) catch |err| {
|
||||
switch (err) {
|
||||
zfin.DataError.NoApiKey => {
|
||||
state.error_msg = "No API key. Set FMP_API_KEY (free at financialmodelingprep.com)";
|
||||
|
|
|
|||
|
|
@ -143,7 +143,10 @@ pub const tab = struct {
|
|||
pub const deactivate = framework.noopDeactivate(State);
|
||||
|
||||
pub fn reload(state: *State, app: *App) !void {
|
||||
if (app.symbol.len > 0) {
|
||||
// Offline mode (--refresh-data=never): skip cache invalidation.
|
||||
// loadData can't re-fetch, so dropping the entry would just blank
|
||||
// the tab; instead re-render from the cached entry.
|
||||
if (app.symbol.len > 0 and !app.fetch_options.skip_network) {
|
||||
app.svc.invalidate(app.symbol, .options);
|
||||
}
|
||||
// Drop chains first so loadData starts clean.
|
||||
|
|
@ -298,7 +301,7 @@ fn loadData(state: *State, app: *App) void {
|
|||
}
|
||||
state.chains = null;
|
||||
|
||||
const result = app.svc.getOptions(app.symbol, .{}) catch |err| {
|
||||
const result = app.svc.getOptions(app.symbol, app.fetch_options) catch |err| {
|
||||
switch (err) {
|
||||
zfin.DataError.FetchFailed => app.setStatus("CBOE fetch failed (network error)"),
|
||||
else => app.setStatus("Error loading options"),
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ fn loadData(state: *State, app: *App) void {
|
|||
app.symbol_data.trailing_me_price = null;
|
||||
app.symbol_data.trailing_me_total = null;
|
||||
|
||||
const result = app.svc.getTrailingReturns(app.symbol, .{}) catch |err| {
|
||||
const result = app.svc.getTrailingReturns(app.symbol, app.fetch_options) catch |err| {
|
||||
switch (err) {
|
||||
zfin.DataError.NoApiKey => app.setStatus("No API key. Set TIINGO_API_KEY"),
|
||||
zfin.DataError.FetchFailed => app.setStatus("Fetch failed (network error or rate limit)"),
|
||||
|
|
@ -155,7 +155,7 @@ fn loadData(state: *State, app: *App) void {
|
|||
// Try to load ETF profile (non-fatal, won't show for non-ETFs)
|
||||
if (!app.symbol_data.etf_loaded) {
|
||||
app.symbol_data.etf_loaded = true;
|
||||
if (app.svc.getEtfProfile(app.symbol, .{})) |etf_result| {
|
||||
if (app.svc.getEtfProfile(app.symbol, app.fetch_options)) |etf_result| {
|
||||
if (etf_result.data.isEtf()) {
|
||||
// Take ownership of the EtfProfile data. We
|
||||
// deliberately don't call etf_result.deinit
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ fn refreshLiveQuote(state: *State, app: *App, force: bool) void {
|
|||
// "refreshed Xs ago" header timestamp.
|
||||
const now_s = std.Io.Timestamp.now(app.io, .real).toSeconds();
|
||||
if (!force and !shouldFetchLiveQuote(market.marketSession(now_s), state.live != null, now_s - state.timestamp)) return;
|
||||
if (app.svc.getQuote(app.symbol, .{})) |q| {
|
||||
if (app.svc.getQuote(app.symbol, app.fetch_options)) |q| {
|
||||
state.live = q;
|
||||
state.timestamp = now_s;
|
||||
} else |err| std.log.scoped(.quote_tab).debug("{s}: live-quote fetch failed: {t}", .{ app.symbol, err });
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue