Lowering time between API Refreshs
This commit is contained in:
@@ -81,7 +81,7 @@ Enums (`EAgentType`, `EAgentStatus`, `EReportType`) mirror .NET enums. **The dec
|
|||||||
|
|
||||||
- `MainApp` picks the layout by width: `>= DesktopView.minimumWidth` (900) → `DesktopView` (three columns side by side: Reports | LatestReports | Agents), otherwise `MobileView` (same three pages behind a `NavigationBar`). Both layouts reuse the *same* page widgets, so pages must not assume they own the whole screen.
|
- `MainApp` picks the layout by width: `>= DesktopView.minimumWidth` (900) → `DesktopView` (three columns side by side: Reports | LatestReports | Agents), otherwise `MobileView` (same three pages behind a `NavigationBar`). Both layouts reuse the *same* page widgets, so pages must not assume they own the whole screen.
|
||||||
- **No state management package and no routing package.** Data loading is consistently: `StatefulWidget` → `late Future<T> mXFuture` assigned in `initState` from `AcApi.instance...` → `FutureBuilder` with explicit loading / `snapshot.hasError` / empty-list branches. Reload = reassign the future inside `setState`. Navigation is plain `Navigator.of(context).push(MaterialPageRoute(...))`.
|
- **No state management package and no routing package.** Data loading is consistently: `StatefulWidget` → `late Future<T> mXFuture` assigned in `initState` from `AcApi.instance...` → `FutureBuilder` with explicit loading / `snapshot.hasError` / empty-list branches. Reload = reassign the future inside `setState`. Navigation is plain `Navigator.of(context).push(MaterialPageRoute(...))`.
|
||||||
- **Automatic refresh**: every widget that shows api data polls the backend (it has no push channel) through the `AutoRefreshState` mixin (`lib/Widgets/AutoRefreshState.dart`): mix it into the `State` and implement `RefreshData`, which fetches again and, only on success, assigns the result as an already completed future. The mixin owns the timer, guards against overlapping requests and swallows errors of a tick. The interval (30 s) lives once in `AutoRefreshState.refreshInterval`. Because a refresh must not flash the spinner or drop the list, the `FutureBuilder`s branch on `snapshot.hasData` / `hasError`, **not** on `connectionState`. A refresh the user did not ask for stays silent — no snackbars, no disabled buttons (see `AgentDetails._reloadAgent`).
|
- **Automatic refresh**: every widget that shows api data polls the backend (it has no push channel) through the `AutoRefreshState` mixin (`lib/Widgets/AutoRefreshState.dart`): mix it into the `State` and implement `RefreshData`, which fetches again and, only on success, assigns the result as an already completed future. The mixin owns the timer, guards against overlapping requests and swallows errors of a tick. The interval (15 s) lives once in `AutoRefreshState.refreshInterval`. Because a refresh must not flash the spinner or drop the list, the `FutureBuilder`s branch on `snapshot.hasData` / `hasError`, **not** on `connectionState`. A refresh the user did not ask for stays silent — no snackbars, no disabled buttons (see `AgentDetails._reloadAgent`).
|
||||||
- Icons per enum value live in extensions (`AgentTypeIcons`, `ReportTypeIcons` — `type.icon`) so every page renders a type identically. Human labels come from `displayName` on the enum itself.
|
- Icons per enum value live in extensions (`AgentTypeIcons`, `ReportTypeIcons` — `type.icon`) so every page renders a type identically. Human labels come from `displayName` on the enum itself.
|
||||||
- `MarkdownText` is a hand-written markdown renderer (no `flutter_markdown` dependency) covering the subset the reports use: headings, lists, block quotes, fenced code, rules, and inline bold/italic/strikethrough/code/links. Extend it rather than adding a package.
|
- `MarkdownText` is a hand-written markdown renderer (no `flutter_markdown` dependency) covering the subset the reports use: headings, lists, block quotes, fenced code, rules, and inline bold/italic/strikethrough/code/links. Extend it rather than adding a package.
|
||||||
- Dependencies are intentionally minimal (`http`, `cupertino_icons`). Prefer solving things with Flutter's own widgets before adding a package.
|
- Dependencies are intentionally minimal (`http`, `cupertino_icons`). Prefer solving things with Flutter's own widgets before adding a package.
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ import 'package:flutter/material.dart';
|
|||||||
///
|
///
|
||||||
/// A refresh happens quietly: implementations are expected to keep the data
|
/// A refresh happens quietly: implementations are expected to keep the data
|
||||||
/// that is already on screen while the request runs, so that the user neither
|
/// that is already on screen while the request runs, so that the user neither
|
||||||
/// sees a spinner nor loses the scroll position every half minute. Failures of
|
/// sees a spinner nor loses the scroll position every few seconds. Failures of
|
||||||
/// a refresh are swallowed on purpose - the data on screen simply stays as it
|
/// a refresh are swallowed on purpose - the data on screen simply stays as it
|
||||||
/// is and the next tick tries again.
|
/// is and the next tick tries again.
|
||||||
mixin AutoRefreshState<TWidget extends StatefulWidget> on State<TWidget> {
|
mixin AutoRefreshState<TWidget extends StatefulWidget> on State<TWidget> {
|
||||||
|
|
||||||
/// Interval in which the api data of the whole app is refreshed.
|
/// Interval in which the api data of the whole app is refreshed.
|
||||||
static const Duration refreshInterval = Duration(seconds: 30);
|
static const Duration refreshInterval = Duration(seconds: 15);
|
||||||
|
|
||||||
Timer? _refreshTimer;
|
Timer? _refreshTimer;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user