From b5076a67ca7234a0c6a6d56fdc15e0b8e8bec1d5 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Mon, 27 Jul 2026 21:23:57 +0300 Subject: [PATCH] fix(ui): clear loading on stats/table early exits Match extension_stats: clear _loading when replaceIfChanged is a no-op. Set error + stop spinner when connection is missing after load started. Closes #448 --- lib/features/mysql/mysql_stats_view.dart | 14 +++++++++++-- lib/features/mysql/mysql_table_view.dart | 20 +++++++++++++++++-- .../postgresql/postgres_stats_view.dart | 18 +++++++++++++++-- .../postgresql/postgres_table_view.dart | 20 +++++++++++++++++-- lib/features/sqlite/sqlite_table_view.dart | 10 +++++++++- 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/lib/features/mysql/mysql_stats_view.dart b/lib/features/mysql/mysql_stats_view.dart index a4040d49..d281bb0c 100644 --- a/lib/features/mysql/mysql_stats_view.dart +++ b/lib/features/mysql/mysql_stats_view.dart @@ -94,11 +94,21 @@ class _MysqlStatsViewState extends material.State { Future _fetch() async { final conn = _lease?.connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (!mounted) return; + setState(() { + _error = 'Not connected'; + _loading = false; + }); + return; + } try { final stats = await conn.serverStats(); if (!mounted) return; - if (!replaceIfChanged(_stats, stats, (v) => _stats = v)) return; + if (!replaceIfChanged(_stats, stats, (v) => _stats = v)) { + if (_loading) setState(() => _loading = false); + return; + } setState(() => _loading = false); } catch (e) { if (!mounted) return; diff --git a/lib/features/mysql/mysql_table_view.dart b/lib/features/mysql/mysql_table_view.dart index d365c2fc..ee065872 100644 --- a/lib/features/mysql/mysql_table_view.dart +++ b/lib/features/mysql/mysql_table_view.dart @@ -165,7 +165,15 @@ class _MysqlTableViewState extends material.State { Future _fetch({bool refreshCount = false}) async { final conn = _connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (mounted && _loading) { + setState(() { + _error = 'Not connected'; + _loading = false; + }); + } + return; + } if (_customSqlActive) { await _fetchCustom(); return; @@ -218,7 +226,15 @@ class _MysqlTableViewState extends material.State { Future _fetchCustom() async { final conn = _connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (mounted && _loading) { + setState(() { + _error = 'Not connected'; + _loading = false; + }); + } + return; + } final sql = _customSql; if (sql == null || sql.isEmpty) return; if (!mounted) return; diff --git a/lib/features/postgresql/postgres_stats_view.dart b/lib/features/postgresql/postgres_stats_view.dart index 07c0fe03..48cd1988 100644 --- a/lib/features/postgresql/postgres_stats_view.dart +++ b/lib/features/postgresql/postgres_stats_view.dart @@ -104,11 +104,25 @@ class _PostgresStatsViewState extends material.State { Future _fetch() async { final c = _connection; - if (c == null || !c.isConnected) return; + if (c == null || !c.isConnected) { + if (!mounted) return; + setState(() { + _error = 'Not connected'; + _loading = false; + }); + return; + } try { final stats = await c.serverStats(); if (!mounted) return; - if (!replaceIfChanged(_stats, stats, (v) => _stats = v)) return; + if (!replaceIfChanged(_stats, stats, (v) => _stats = v)) { + if (_loading) { + setState(() { + _loading = false; + }); + } + return; + } setState(() { _loading = false; }); diff --git a/lib/features/postgresql/postgres_table_view.dart b/lib/features/postgresql/postgres_table_view.dart index 05e6ea26..653f39e2 100644 --- a/lib/features/postgresql/postgres_table_view.dart +++ b/lib/features/postgresql/postgres_table_view.dart @@ -156,7 +156,15 @@ class _PostgresTableViewState extends material.State { /// [refreshCount] runs `COUNT(*)` (e.g. first load or Refresh). Pagination only runs SELECT. Future _fetch({bool refreshCount = false}) async { final conn = _connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (mounted && _loading) { + setState(() { + _error = 'Not connected'; + _loading = false; + }); + } + return; + } if (_customSqlActive) { await _fetchCustom(); return; @@ -219,7 +227,15 @@ class _PostgresTableViewState extends material.State { Future _fetchCustom() async { final conn = _connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (mounted && _loading) { + setState(() { + _error = 'Not connected'; + _loading = false; + }); + } + return; + } final sql = _customSql; if (sql == null || sql.isEmpty) return; if (!mounted) return; diff --git a/lib/features/sqlite/sqlite_table_view.dart b/lib/features/sqlite/sqlite_table_view.dart index fd3f4f7d..2e05929f 100644 --- a/lib/features/sqlite/sqlite_table_view.dart +++ b/lib/features/sqlite/sqlite_table_view.dart @@ -113,7 +113,15 @@ class _SqliteTableViewState extends material.State { Future _fetch({bool refreshCount = false}) async { final conn = _connection; - if (conn == null || !conn.isConnected) return; + if (conn == null || !conn.isConnected) { + if (mounted && _loading) { + setState(() { + _error = 'Not connected'; + _loading = false; + }); + } + return; + } setState(() { _loading = true; _error = null;