fix(desktop): window lifecycle for instance switch (#5381)
This resolves window accumulation during instance switching by implementing proper window lifecycle management using Tauri's WebviewWindow APIs. Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
a23a2c657d
commit
ba700886b5
3 changed files with 56 additions and 19 deletions
|
|
@ -40,7 +40,7 @@
|
||||||
"@hoppscotch/httpsnippet": "3.0.9",
|
"@hoppscotch/httpsnippet": "3.0.9",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^",
|
"@hoppscotch/js-sandbox": "workspace:^",
|
||||||
"@hoppscotch/kernel": "workspace:^",
|
"@hoppscotch/kernel": "workspace:^",
|
||||||
"@hoppscotch/plugin-appload": "github:CuriousCorrelation/tauri-plugin-appload#e8dbe06eabf947e5efaf07d2e573238ceb11a7b1",
|
"@hoppscotch/plugin-appload": "github:CuriousCorrelation/tauri-plugin-appload#e05861959938b57479a1a81fa796735ebbd08c7c",
|
||||||
"@hoppscotch/ui": "0.2.5",
|
"@hoppscotch/ui": "0.2.5",
|
||||||
"@hoppscotch/vue-toasted": "0.1.0",
|
"@hoppscotch/vue-toasted": "0.1.0",
|
||||||
"@lezer/highlight": "1.2.1",
|
"@lezer/highlight": "1.2.1",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,17 @@ import { Service } from "dioc"
|
||||||
import { BehaviorSubject, Observable } from "rxjs"
|
import { BehaviorSubject, Observable } from "rxjs"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { LazyStore } from "@tauri-apps/plugin-store"
|
import { LazyStore } from "@tauri-apps/plugin-store"
|
||||||
import { download, load, clear, remove } from "@hoppscotch/plugin-appload"
|
import {
|
||||||
|
getCurrentWebviewWindow,
|
||||||
|
getAllWebviewWindows,
|
||||||
|
} from "@tauri-apps/api/webviewWindow"
|
||||||
|
import {
|
||||||
|
download,
|
||||||
|
load,
|
||||||
|
clear,
|
||||||
|
remove,
|
||||||
|
close,
|
||||||
|
} from "@hoppscotch/plugin-appload"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
|
|
@ -156,6 +166,11 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
this.getVendoredInstance().displayName
|
this.getVendoredInstance().displayName
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Close current window AFTER successful load
|
||||||
|
// NOTE: No need to await it.
|
||||||
|
this.closeCurrentWindow()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage =
|
const errorMessage =
|
||||||
|
|
@ -234,6 +249,10 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
throw new Error("Failed to load bundle")
|
throw new Error("Failed to load bundle")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close current window AFTER successful load
|
||||||
|
// NOTE: No need to await it.
|
||||||
|
this.closeCurrentWindow()
|
||||||
|
|
||||||
this.toast.success(`Connected to ${displayName}`)
|
this.toast.success(`Connected to ${displayName}`)
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -251,6 +270,33 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the current window using Tauri's window management
|
||||||
|
*/
|
||||||
|
private async closeCurrentWindow(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const currentWindow = getCurrentWebviewWindow()
|
||||||
|
const currentLabel = currentWindow.label
|
||||||
|
|
||||||
|
// Don't close if we're the main window or if there are no other windows
|
||||||
|
if (currentLabel === "main") {
|
||||||
|
const allWindows = await getAllWebviewWindows()
|
||||||
|
if (allWindows.length <= 1) {
|
||||||
|
// Don't close the last window
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeResponse = await close({ windowLabel: currentLabel })
|
||||||
|
if (!closeResponse.success) {
|
||||||
|
console.warn(`Failed to close window ${currentLabel}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to close current window:", error)
|
||||||
|
// Don't throw - window closing shouldn't block the operation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async removeInstance(serverUrl: string): Promise<boolean> {
|
public async removeInstance(serverUrl: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const normalizedUrl = this.normalizeUrl(serverUrl)
|
const normalizedUrl = this.normalizeUrl(serverUrl)
|
||||||
|
|
@ -285,8 +331,9 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
const displayName = this.getDisplayNameFromUrl(serverUrl)
|
const displayName = this.getDisplayNameFromUrl(serverUrl)
|
||||||
this.toast.success(`Removed ${displayName}`)
|
this.toast.success(`Removed ${displayName}`)
|
||||||
|
|
||||||
// If we're currently connected to this instance, go back to idle state
|
// If we're currently connected to this instance, close the window and go to idle state
|
||||||
if (this.isCurrentlyConnectedTo(serverUrl)) {
|
if (this.isCurrentlyConnectedTo(serverUrl)) {
|
||||||
|
await this.closeCurrentWindow()
|
||||||
this.state$.next({ status: "idle" })
|
this.state$.next({ status: "idle" })
|
||||||
this.emit(this.state$.value)
|
this.emit(this.state$.value)
|
||||||
await this.saveCurrentState()
|
await this.saveCurrentState()
|
||||||
|
|
@ -301,6 +348,7 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
|
|
||||||
public async clearCache(): Promise<boolean> {
|
public async clearCache(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
|
await this.closeCurrentWindow()
|
||||||
await clear()
|
await clear()
|
||||||
this.toast.success("Cache cleared successfully")
|
this.toast.success("Cache cleared successfully")
|
||||||
return true
|
return true
|
||||||
|
|
@ -367,19 +415,16 @@ export class InstanceSwitcherService extends Service<ConnectionState> {
|
||||||
|
|
||||||
// If it fails, fall back to the original URL with default port
|
// If it fails, fall back to the original URL with default port
|
||||||
try {
|
try {
|
||||||
const re = withSubpath.toString().replace(/\/$/, "")
|
return withSubpath.toString().replace(/\/$/, "")
|
||||||
return re
|
|
||||||
} catch {
|
} catch {
|
||||||
if (!urlObj.port) {
|
if (!urlObj.port) {
|
||||||
urlObj.port = "3200"
|
urlObj.port = "3200"
|
||||||
}
|
}
|
||||||
const re = urlObj.toString().replace(/\/$/, "")
|
return urlObj.toString().replace(/\/$/, "")
|
||||||
return re
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const re = urlObj.toString().replace(/\/$/, "")
|
return urlObj.toString().replace(/\/$/, "")
|
||||||
return re
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -508,8 +508,8 @@ importers:
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../hoppscotch-kernel
|
version: link:../hoppscotch-kernel
|
||||||
'@hoppscotch/plugin-appload':
|
'@hoppscotch/plugin-appload':
|
||||||
specifier: github:CuriousCorrelation/tauri-plugin-appload#e8dbe06eabf947e5efaf07d2e573238ceb11a7b1
|
specifier: github:CuriousCorrelation/tauri-plugin-appload#e05861959938b57479a1a81fa796735ebbd08c7c
|
||||||
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e8dbe06eabf947e5efaf07d2e573238ceb11a7b1'
|
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e05861959938b57479a1a81fa796735ebbd08c7c'
|
||||||
'@hoppscotch/ui':
|
'@hoppscotch/ui':
|
||||||
specifier: 0.2.5
|
specifier: 0.2.5
|
||||||
version: 0.2.5(eslint@8.57.0)(terser@5.39.2)(typescript@5.9.2)(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(sass@1.91.0)(terser@5.39.2)(yaml@2.8.1))(vue@3.5.20(typescript@5.9.2))
|
version: 0.2.5(eslint@8.57.0)(terser@5.39.2)(typescript@5.9.2)(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(sass@1.91.0)(terser@5.39.2)(yaml@2.8.1))(vue@3.5.20(typescript@5.9.2))
|
||||||
|
|
@ -1853,10 +1853,6 @@ packages:
|
||||||
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e05861959938b57479a1a81fa796735ebbd08c7c}
|
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e05861959938b57479a1a81fa796735ebbd08c7c}
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
|
|
||||||
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e8dbe06eabf947e5efaf07d2e573238ceb11a7b1':
|
|
||||||
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e8dbe06eabf947e5efaf07d2e573238ceb11a7b1}
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
'@CuriousCorrelation/plugin-relay@https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158':
|
'@CuriousCorrelation/plugin-relay@https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158':
|
||||||
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158}
|
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158}
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
|
|
@ -15542,10 +15538,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.1.1
|
'@tauri-apps/api': 2.1.1
|
||||||
|
|
||||||
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/e8dbe06eabf947e5efaf07d2e573238ceb11a7b1':
|
|
||||||
dependencies:
|
|
||||||
'@tauri-apps/api': 2.1.1
|
|
||||||
|
|
||||||
'@CuriousCorrelation/plugin-relay@https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158':
|
'@CuriousCorrelation/plugin-relay@https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/ff18f776ddeb53dbbdeaf97e1fabc30bdc57c158':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.1.1
|
'@tauri-apps/api': 2.1.1
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue