Skip to content

web: add status monitor for background tasks#2909

Merged
dgdavid merged 8 commits intoapi-v2from
api-v2-progress
Nov 25, 2025
Merged

web: add status monitor for background tasks#2909
dgdavid merged 8 commits intoapi-v2from
api-v2-progress

Conversation

@dgdavid
Copy link
Copy Markdown
Contributor

@dgdavid dgdavid commented Nov 25, 2025

This PR introduces a lightweight status monitor for background tasks (aka progresses), allowing users to track ongoing activity in the app. Please, note that the design and placement of this feature are expected to evolve as we gain further insights into optimal UI integration. Proposed one is just an simple starting point.

localhost_8080_ (9)

Additionally, the PR refactors the state logic in App.tsx to reduce unnecessary layout re-renders, which were causing unexpected UI issues such as menus and floating elements closing unexpectedly. This change separates concerns by moving state management and redirect logic to an internal component defined outside the main one, improving the overall stability of the layout.

To make everything work, a new hook for listening to and update progress changes has been added.

Since src/App.tsx wraps the layout for all protected routes, consuming
application state directly from there caused unnecessary layout
re-renders with noticeable side effects, such as menus or other floating
UI elements closing unexpectedly.

The problem happened because the internal guard and flow-control logic
lived inside the component, which was also retrieving the application
data directly. With both concerns mixed together, any state update
forced the entire layout tree to re-render. The fix separates these
responsibilities: the new App component now only sets up the global
listeners, while the new Content component handles state consumption and
redirect logic. This keeps layout updates stable and prevents UI
elements from closing unexpectedly.

This is slightly related to [1], since internal <Content /> was already
a component, but was previously defined inside App, causing React to
treat it as “a different component at the same position” and reset state
unnecessarily.

[1] https://react.dev/learn/preserving-and-resetting-state#different-components-at-the-same-position-reset-state
This adds a simple status monitor to track and display background
activity. The design and placement will evolve as more insights are
gathered on optimal UI integration.
@dgdavid dgdavid requested a review from imobachgs November 25, 2025 11:14
Restore default behavior where the popover is hidden when its trigger
element is hidden, instead of remaining open with irrelevant
information.
@dgdavid dgdavid merged commit 1d7733e into api-v2 Nov 25, 2025
7 of 9 checks passed
@dgdavid dgdavid deleted the api-v2-progress branch November 25, 2025 12:35
dgdavid added a commit that referenced this pull request Dec 17, 2025
A few weeks ago, in #2909, a
small, non-blocking component was introduced to subtly inform users when
actions are in progress . This PR introduces its _blocking counterpart_,
allowing Agama pages to subscribe to specific progress signals and block
user interactions until those progress events are complete.

The changes in this PR ended up being more complex than initially
expected due to an edge case that caused an undesirable flickering
effect: the progress indicator would disappear almost simultaneously, or
even slightly before, certain proposal queries were invalidated and
refetched. This led to a transition from the progress state to an
outdated UI, which was not ideal.

To address this, a new hook has been implemented to subscribe to the
TanStack Query cache, notifying when specific queries are considered
fully refetched after a certain point. This is then used in conjunction
with `useProposalChanges` query invalidation. As a result, it now emits
a custom event once proposal-related queries are fully refetched,
allowing the Page component to subscribe to this event and unmount the
blocking overlay just before React performs the UI redraw.

Please, note that using something like `const { isFetching } =
useProposalChanges()` wasn't suitable for this scenario. For further
details, please refer to the code and commit messages.


### Additional notes

* Using query.state.fetchStatus, query.isStale, or similar properties to directly check in the hook if a query is in a refetching state could end up making things more complex for this scenario. The hook would need to track multiple statuses transitions (e.g., from stale/invalidated to fetching, and then to success), which increases the complexity. Instead, working with the dataUpdatedAt timestamp looks simpler and enough for this use case right now. It can be changed if race conditions or other issues related with timing are found.

* Currently, only the software pages (all of them) and the storage
proposal page are subscribed to their respective progress scopes. The
only pages missing at the moment are the network pages, but since the
progress for network is not yet ready, TypeScript raises an error when
trying to include these pages in this PR, as it doesn't recognize
"network" as a valid scope.

* It would be nice to allow pages to conditionally discard the blocking
state based on the number of progress steps. This idea originated with
the assumption that one-step progress (like for storage proposals) would
be fast, though it might not be for certain users or stacks. It's
difficult to predict since other factors such as connection speed,
whether the page is remote or localhost, etc can have a significant
impact. These factors could be explored further to refine the behavior,
if/when time permits.

* Another possibility, which is fully outside the scope of this PR for
now because there is no current use case, is to allow pages to subscribe
to multiple progress scopes, rather than just one.
imobachgs added a commit that referenced this pull request Jan 10, 2026
Merge the new HTTP API. Each PR has been already reviewed, so it should
be safe to merge it.

* #1829
* #2508
* #2772
* #2826
* #2848
* #2860
* #2863
* #2866
* #2867
* #2869
* #2870
* #2871
* #2872
* #2873
* #2874
* #2875
* #2876
* #2877
* #2880
* #2881
* #2882
* #2884
* #2885
* #2886
* #2891
* #2892
* #2893
* #2894
* #2895
* #2896
* #2897
* #2898
* #2899
* #2900
* #2901
* #2902
* #2903
* #2904
* #2908
* #2909
* #2910
* #2912
* #2913
* #2914
* #2915
* #2916
* #2917
* #2918
* #2920
* #2921
* #2923
* #2924
* #2926
* #2928
* #2929
* #2930
* #2933
* #2934
* #2935
* #2936
* #2938
* #2939
* #2942
* #2943
* #2944
* #2945
* #2946
* #2947
* #2948
* #2950
* #2951
* #2952
* #2954
* #2955
* #2956
* #2957
* #2958
* #2959
* #2960
* #2961
* #2963
* #2964
* #2965
* #2967
* #2968
* #2969
* #2970
* #2971
* #2972
* #2974
* #2975
* #2977
* #2978
* #2980
* #2982
* #2983
* #2984
* #2988
* #2989
* #2991
* #2992
* #2993
* #2994
* #2995
* #2996
* #2997
* #2999
@imobachgs imobachgs mentioned this pull request Mar 17, 2026
imobachgs added a commit that referenced this pull request Mar 17, 2026
Prepare to release version 19.

* #1829
* #2508
* #2772
* #2818
* #2826
* #2848
* #2860
* #2863
* #2864
* #2866
* #2867
* #2869
* #2870
* #2871
* #2872
* #2873
* #2874
* #2875
* #2876
* #2877
* #2880
* #2881
* #2882
* #2884
* #2885
* #2886
* #2891
* #2892
* #2893
* #2894
* #2895
* #2896
* #2897
* #2898
* #2899
* #2900
* #2901
* #2902
* #2903
* #2904
* #2908
* #2909
* #2910
* #2912
* #2913
* #2914
* #2915
* #2916
* #2917
* #2918
* #2920
* #2921
* #2923
* #2924
* #2926
* #2928
* #2929
* #2930
* #2933
* #2934
* #2935
* #2936
* #2937
* #2938
* #2939
* #2942
* #2943
* #2944
* #2945
* #2946
* #2947
* #2948
* #2949
* #2950
* #2951
* #2952
* #2954
* #2955
* #2956
* #2957
* #2958
* #2959
* #2960
* #2961
* #2963
* #2964
* #2965
* #2967
* #2968
* #2969
* #2970
* #2971
* #2972
* #2974
* #2975
* #2977
* #2978
* #2980
* #2981
* #2982
* #2983
* #2984
* #2988
* #2989
* #2990
* #2991
* #2992
* #2993
* #2994
* #2995
* #2996
* #2997
* #2998
* #2999
* #3000
* #3001
* #3002
* #3004
* #3005
* #3006
* #3007
* #3008
* #3009
* #3011
* #3012
* #3013
* #3014
* #3015
* #3016
* #3018
* #3019
* #3020
* #3021
* #3022
* #3023
* #3024
* #3025
* #3026
* #3027
* #3028
* #3029
* #3030
* #3031
* #3033
* #3034
* #3035
* #3036
* #3037
* #3039
* #3040
* #3041
* #3042
* #3043
* #3044
* #3045
* #3046
* #3047
* #3048
* #3049
* #3050
* #3051
* #3052
* #3053
* #3054
* #3055
* #3056
* #3057
* #3058
* #3060
* #3061
* #3062
* #3063
* #3064
* #3065
* #3066
* #3067
* #3068
* #3069
* #3070
* #3071
* #3072
* #3073
* #3074
* #3075
* #3076
* #3077
* #3078
* #3079
* #3086
* #3087
* #3088
* #3089
* #3090
* #3091
* #3092
* #3093
* #3094
* #3095
* #3096
* #3097
* #3098
* #3099
* #3100
* #3101
* #3102
* #3103
* #3104
* #3105
* #3106
* #3107
* #3108
* #3109
* #3110
* #3112
* #3113
* #3114
* #3115
* #3116
* #3117
* #3118
* #3119
* #3120
* #3122
* #3123
* #3124
* #3127
* #3128
* #3129
* #3130
* #3131
* #3133
* #3134
* #3135
* #3136
* #3137
* #3138
* #3139
* #3140
* #3141
* #3142
* #3143
* #3144
* #3145
* #3146
* #3147
* #3148
* #3149
* #3150
* #3151
* #3152
* #3153
* #3154
* #3155
* #3157
* #3158
* #3159
* #3160
* #3161
* #3162
* #3163
* #3164
* #3165
* #3166
* #3167
* #3168
* #3169
* #3170
* #3174
* #3175
* #3176
* #3177
* #3178
* #3179
* #3181
* #3182
* #3184
* #3185
* #3186
* #3188
* #3189
* #3190
* #3191
* #3192
* #3194
* #3195
* #3196
* #3197
* #3198
* #3199
* #3200
* #3201
* #3202
* #3203
* #3205
* #3206
* #3208
* #3209
* #3210
* #3213
* #3214
* #3215
* #3216
* #3217
* #3218
* #3219
* #3220
* #3222
* #3223
* #3224
* #3225
* #3226
* #3227
* #3228
* #3229
* #3230
* #3231
* #3232
* #3233
* #3234
* #3235
* #3236
* #3237
* #3238
* #3239
* #3240
* #3241
* #3242
* #3243
* #3244
* #3246
* #3247
* #3248
* #3250
* #3251
* #3252
* #3253
* #3254
* #3255
* #3256
* #3257
* #3258
* #3259
* #3260
* #3261
* #3262
* #3263
* #3265
* #3266
* #3267
* #3268
* #3269
* #3270
* #3271
* #3272
* #3273
* #3274
* #3275
* #3276
* #3277
* #3278
* #3279
* #3280
* #3281
* #3282
* #3283
* #3284
* #3285
* #3286
* #3287
* #3288
* #3289
* #3290
* #3291
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants