diff --git a/bin/aarch64/syncshell-core b/bin/aarch64/syncshell-core index 6a2a5913..240785ea 100755 Binary files a/bin/aarch64/syncshell-core and b/bin/aarch64/syncshell-core differ diff --git a/bin/x86_64/syncshell-core b/bin/x86_64/syncshell-core index 91dafdfb..d02b82c4 100755 Binary files a/bin/x86_64/syncshell-core and b/bin/x86_64/syncshell-core differ diff --git a/core/internal/session/profile.go b/core/internal/session/profile.go index ee8ed194..bd826438 100644 --- a/core/internal/session/profile.go +++ b/core/internal/session/profile.go @@ -41,11 +41,12 @@ func (s *Session) removeWebProfile(ctx context.Context) ActionResult { } modern, _ := s.webProfile.Name("modern") themed, _ := s.webProfile.Name("themed") - if current.Theme != "default" && current.Theme != modern && current.Theme != themed { - return rejected("profile_not_selected", "Another Web UI profile is selected; switch to default before removing this adapter's profiles") - } - if result := s.setWebUITheme(ctx, "default"); !result.OK { - return result + // Only a theme this adapter owns would be left pointing at deleted files; + // any other selection is the user's or another adapter's and stays. + if current.Theme == modern || current.Theme == themed { + if result := s.setWebUITheme(ctx, "default"); !result.OK { + return result + } } if err := s.webProfile.Remove(assets); err != nil { return rejected("profile_cleanup", err.Error()) diff --git a/core/internal/session/profile_test.go b/core/internal/session/profile_test.go index 92ba0157..6aeda334 100644 --- a/core/internal/session/profile_test.go +++ b/core/internal/session/profile_test.go @@ -55,6 +55,36 @@ func TestProfileActionVerifiesThemeAndOwnedFileOutcomes(t *testing.T) { } } +func TestProfileCleanupLeavesAThemeItDoesNotOwn(t *testing.T) { + s, api := profileSession(t) + result := s.Act(context.Background(), "webui.apply-profile", ActionArguments{Profile: "modern"}) + if !result.OK { + t.Fatalf("profile was not applied: %#v", result) + } + profile := filepath.Join(api.guiAssets, "syncshell-test-modern") + other := filepath.Join(api.guiAssets, "another-adapter") + if err := os.Mkdir(other, 0700); err != nil { + t.Fatal(err) + } + for _, theme := range []string{"dark", "another-adapter"} { + api.mu.Lock() + api.theme = theme + api.mu.Unlock() + if result := s.Act(context.Background(), "webui.remove-profile", ActionArguments{}); !result.OK { + t.Fatalf("cleanup refused %s: %#v", theme, result) + } + if api.currentTheme() != theme { + t.Fatalf("cleanup changed %s to %s", theme, api.currentTheme()) + } + if _, err := os.Stat(profile); !os.IsNotExist(err) { + t.Fatalf("owned profile remains under %s: %v", theme, err) + } + if _, err := os.Stat(other); err != nil { + t.Fatal("another adapter's directory was changed", err) + } + } +} + func TestProfileActionRejectsChangedAssetDirectory(t *testing.T) { s, api := profileSession(t) changed := t.TempDir() diff --git a/hosts/caelestia/README.md b/hosts/caelestia/README.md index 21cb3c64..d9ba74c9 100644 --- a/hosts/caelestia/README.md +++ b/hosts/caelestia/README.md @@ -126,7 +126,7 @@ Web UI selection is explicit. Palette changes update only the currently selected `syncshell-caelestia-themed` profile; another adapter's selection is left alone. Profiles use the `caelestia` ownership marker. Use Settings, **Restore default UI and clean owned profiles**, before disabling/removing -Syncshell. If another profile is selected, explicitly apply Default first. +Syncshell. Any other selected theme stays selected. For direct removal without a manager hook, run the same core action before deleting the installed package (set `config` to the selected configuration): diff --git a/packaging/bundled/SHA256SUMS b/packaging/bundled/SHA256SUMS index f2b0758d..56575ad9 100644 --- a/packaging/bundled/SHA256SUMS +++ b/packaging/bundled/SHA256SUMS @@ -1,3 +1,3 @@ 314a89c32525c5b746f50a52b65967ed301e11f12bbbf5f3d44e387a10d540fc bin/syncshell-core -13aa21873936b346df54fd3ea4e1827667757516cabf0c27b4823618ca4ad1d5 bin/x86_64/syncshell-core -b568b7582679dec3eb0bf094f1ff89b0e26505086619a8564772c026b4c563a2 bin/aarch64/syncshell-core +bfd889d229704f88160eed43bb0d4b5da1e48921299e8feab4d121373d915142 bin/x86_64/syncshell-core +2bdfb7361a0e8971127949795694248c0747a1b26c7462928f20d11e25652397 bin/aarch64/syncshell-core diff --git a/shared/AdapterService.qml b/shared/AdapterService.qml index 5741bf5d..2d63eaeb 100644 --- a/shared/AdapterService.qml +++ b/shared/AdapterService.qml @@ -403,7 +403,7 @@ QtObject { } function removeWebProfile() { - return runAction("webui.remove-profile", {}, "Default Web UI restored; this adapter's profiles removed", ""); + return runAction("webui.remove-profile", {}, "This adapter's Web UI profiles removed", ""); } function setServiceEnabled(enabled) {