fix: preserve tab state when switching between views#98
Open
deacon-mp wants to merge 1 commit into
Open
Conversation
Wraps router-view with Vue's KeepAlive to preserve component state (filters, selections, scroll position) when switching tabs. Adds onActivated hooks to refresh data from stores so changes made in other tabs are immediately visible. Migrates polling intervals to onActivated/onDeactivated to stop background polling on inactive tabs.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to preserve per-tab UI state (filters/selections/scroll) by caching routed views with Vue’s <KeepAlive>, while refreshing data on tab re-entry and stopping background polling when a tab is inactive.
Changes:
- Wraps the main (non-login)
<router-view>in<KeepAlive>to cache routed views across tab switches. - Adds
onActivatedhooks to many views to refresh data when returning to a tab. - Migrates polling teardown from
onBeforeUnmounttoonDeactivatedfor kept-alive views (Agents/Operations).
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 19 comments.
Show a summary per file
| File | Description |
|---|---|
| src/App.vue | Wrapes routed views in <KeepAlive> to preserve per-tab component state |
| src/views/SettingsView.vue | Refreshes main config on activation |
| src/views/SchedulesView.vue | Refreshes schedules/agents on activation |
| src/views/PlannersView.vue | Refreshes planners on activation |
| src/views/PayloadsView.vue | Refreshes payloads on activation |
| src/views/OperationsView.vue | Refreshes operations/agents on activation; clears polling on deactivation |
| src/views/ObjectivesView.vue | Refreshes objectives on activation |
| src/views/ObfuscatorsView.vue | Refreshes obfuscators on activation |
| src/views/HomeView.vue | Refreshes main config on activation |
| src/views/FactSourcesView.vue | Refreshes sources on activation |
| src/views/ExfilledFilesView.vue | Refreshes operations/files on activation |
| src/views/ContactsView.vue | Refreshes contacts on activation |
| src/views/AgentsView.vue | Starts polling on activation; clears polling on deactivation |
| src/views/AdversariesView.vue | Refreshes abilities/adversaries/objectives on activation |
| src/views/AbilitiesView.vue | Refreshes abilities on activation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+22
to
+24
| onActivated(() => { | ||
| sourceStore.getSources($api); | ||
| }); |
Comment on lines
+31
to
+33
| router-view(v-slot="{ Component }") | ||
| KeepAlive | ||
| component(:is="Component") |
Comment on lines
+21
to
+27
| onActivated(async () => { | ||
| try { | ||
| await coreStore.getMainConfig($api); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }); |
Comment on lines
+42
to
+44
| onActivated(async () => { | ||
| await abilityStore.getAbilities($api); | ||
| }); |
Comment on lines
+183
to
+187
| onActivated(async () => { | ||
| await operationStore.getOperations($api); | ||
| await agentStore.getAgents($api); | ||
| agentStore.updateAgentGroups(); | ||
| selectOperation(); |
Comment on lines
+34
to
+38
| onActivated(async () => { | ||
| await abilityStore.getAbilities($api); | ||
| await adversaryStore.getAdversaries($api); | ||
| await objectiveStore.getObjectives($api); | ||
| }); |
Comment on lines
+32
to
+35
| onActivated(async () => { | ||
| await operationStore.getOperations($api); | ||
| exfilStore.loadFiles($api, selectedOperationId.value); | ||
| }); |
Comment on lines
+183
to
+187
| onActivated(async () => { | ||
| await operationStore.getOperations($api); | ||
| await agentStore.getAgents($api); | ||
| agentStore.updateAgentGroups(); | ||
| selectOperation(); |
Comment on lines
+23
to
+25
| onActivated(async () => { | ||
| await coreStore.getMainConfig($api); | ||
| }); |
Comment on lines
+15
to
+17
| onActivated(async () => { | ||
| await coreStore.getPlanners($api); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<router-view>with<KeepAlive>to preserve component state across tab switchesonActivatedhooks to refresh data from API when returning to a tabonActivated/onDeactivatedto stop background polling on inactive tabsTest plan