Skip to content

Commit 458e6af

Browse files
committed
Improvement: Moved extension objects to runtime lifecycle.
1 parent 25c7271 commit 458e6af

17 files changed

Lines changed: 370 additions & 168 deletions

gnome-extensions/extension/extension.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@ import * as Gettext from 'gettext';
55
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
66
import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';
77

8+
import { destroyAllRecentItemsManagers } from './shared/utilities/utilityRecents.js';
89
import { initializeMenuRegistry } from './shared/menu/menuRegistry.js';
910
import { IOFile } from './shared/utilities/utilityIO.js';
1011
import { Logger } from './shared/utilities/utilityLogger.js';
1112
import { MenuIndicator } from './shared/menu/menuIndicator.js';
13+
import { resetSearchHub } from './shared/services/serviceSearchHub.js';
1214
import { getAutoPaster, destroyAutoPaster } from './shared/utilities/utilityAutoPaste.js';
1315
import { initStorage, FileItem } from './shared/constants/storagePaths.js';
1416

1517
import { ClipboardManager } from './features/Clipboard/managers/clipboardManager.js';
18+
import { resetClipboardSearchProvider } from './features/Clipboard/integrations/clipboardSearchProvider.js';
19+
import { resetEmojiSearchProvider } from './features/Emoji/integrations/emojiSearchProvider.js';
20+
import { resetGifSearchProvider } from './features/GIF/integrations/gifSearchProvider.js';
21+
import { resetKaomojiSearchProvider } from './features/Kaomoji/integrations/kaomojiSearchProvider.js';
22+
import { resetSymbolsSearchProvider } from './features/Symbols/integrations/symbolsSearchProvider.js';
1623
import { getGifCacheManager, destroyGifCacheManager } from './features/GIF/logic/gifCacheManager.js';
1724
import { getSkinnableCharSet, destroySkinnableCharSetCache } from './features/Emoji/logic/emojiDataCache.js';
1825

@@ -259,6 +266,14 @@ export default class AllInOneClipboardExtension extends Extension {
259266
this._clipboardManager?.destroy();
260267
this._clipboardManager = null;
261268

269+
resetClipboardSearchProvider();
270+
resetEmojiSearchProvider();
271+
resetGifSearchProvider();
272+
resetKaomojiSearchProvider();
273+
resetSymbolsSearchProvider();
274+
resetSearchHub();
275+
destroyAllRecentItemsManagers();
276+
262277
if (this._resource) {
263278
Gio.resources_unregister(this._resource);
264279
this._resource = null;

gnome-extensions/extension/features/Clipboard/integrations/clipboardSearchProvider.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { IOJson } from '../../../shared/utilities/utilityIO.js';
2-
import { registerSearchProvider } from '../../../shared/services/serviceSearchHub.js';
2+
import { registerSearchProvider, unregisterSearchProvider } from '../../../shared/services/serviceSearchHub.js';
33

44
import { ClipboardProvider } from '../constants/clipboardConstants.js';
55
import { ClipboardSearchUtils } from '../utilities/clipboardSearchUtils.js';
@@ -72,15 +72,15 @@ export function ensureClipboardSearchProviderRegistered() {
7272
return items.filter((item) => ClipboardSearchUtils.isMatch(item, query));
7373
},
7474
applyToTab: async ({ tabActor, query }) => {
75-
if (!tabActor || typeof tabActor.applyExternalSearch !== 'function') {
75+
if (!tabActor) {
7676
return false;
7777
}
7878

7979
await tabActor.applyExternalSearch(query);
8080
return true;
8181
},
8282
clearOnTab: async ({ tabActor }) => {
83-
if (!tabActor || typeof tabActor.clearExternalSearch !== 'function') {
83+
if (!tabActor) {
8484
return false;
8585
}
8686

@@ -92,3 +92,13 @@ export function ensureClipboardSearchProviderRegistered() {
9292
_isProviderRegistered = true;
9393
return ClipboardProvider.SEARCH_PROVIDER_ID;
9494
}
95+
96+
/**
97+
* Unregisters the Clipboard provider and clears module state.
98+
*
99+
* @returns {void}
100+
*/
101+
export function resetClipboardSearchProvider() {
102+
unregisterSearchProvider(ClipboardProvider.SEARCH_PROVIDER_ID);
103+
_isProviderRegistered = false;
104+
}

gnome-extensions/extension/features/Emoji/integrations/emojiSearchProvider.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { registerSearchProvider } from '../../../shared/services/serviceSearchHub.js';
21
import { IOResource, ResourceItem } from '../../../shared/constants/storagePaths.js';
2+
import { registerSearchProvider, unregisterSearchProvider } from '../../../shared/services/serviceSearchHub.js';
33

44
import { EmojiJsonParser } from '../parsers/emojiJsonParser.js';
55
import { EmojiProvider } from '../constants/emojiConstants.js';
66
import { EmojiViewRenderer } from '../view/emojiViewRenderer.js';
77

8-
// Private Resources
9-
const _emojiSearchRenderer = new EmojiViewRenderer(null);
10-
118
// ========================================================================
129
// State
1310
// ========================================================================
1411

15-
let _emojiCatalogItems = [];
12+
let _emojiCatalogItems = null;
1613
let _emojiCatalogPromise = null;
1714
let _emojiExtensionUuid = 'EmojiSearchProvider';
1815
let _isProviderRegistered = false;
@@ -27,7 +24,7 @@ let _isProviderRegistered = false;
2724
* @returns {Promise<Array>} A promise that resolves to an array of emoji catalog items.
2825
*/
2926
async function loadEmojiCatalog() {
30-
if (_emojiCatalogItems.length > 0) {
27+
if (Array.isArray(_emojiCatalogItems)) {
3128
return _emojiCatalogItems;
3229
}
3330

@@ -70,6 +67,8 @@ export function ensureEmojiSearchProviderRegistered({ extensionUuid } = {}) {
7067
return EmojiProvider.SEARCH_PROVIDER_ID;
7168
}
7269

70+
let emojiSearchRenderer = null;
71+
7372
registerSearchProvider({
7473
id: EmojiProvider.SEARCH_PROVIDER_ID,
7574
targetTabs: ['Emoji'],
@@ -78,19 +77,23 @@ export function ensureEmojiSearchProviderRegistered({ extensionUuid } = {}) {
7877
return [];
7978
}
8079

80+
if (!emojiSearchRenderer) {
81+
emojiSearchRenderer = new EmojiViewRenderer(null);
82+
}
83+
8184
const catalogItems = await loadEmojiCatalog();
82-
return catalogItems.filter((item) => _emojiSearchRenderer.searchFilter(item || {}, query));
85+
return catalogItems.filter((item) => emojiSearchRenderer.searchFilter(item || {}, query));
8386
},
8487
applyToTab: async ({ tabActor, query }) => {
85-
if (!tabActor || typeof tabActor.applyExternalSearch !== 'function') {
88+
if (!tabActor) {
8689
return false;
8790
}
8891

8992
await tabActor.applyExternalSearch(query);
9093
return true;
9194
},
9295
clearOnTab: async ({ tabActor }) => {
93-
if (!tabActor || typeof tabActor.clearExternalSearch !== 'function') {
96+
if (!tabActor) {
9497
return false;
9598
}
9699

@@ -102,3 +105,16 @@ export function ensureEmojiSearchProviderRegistered({ extensionUuid } = {}) {
102105
_isProviderRegistered = true;
103106
return EmojiProvider.SEARCH_PROVIDER_ID;
104107
}
108+
109+
/**
110+
* Unregisters the Emoji provider and clears cached module state.
111+
*
112+
* @returns {void}
113+
*/
114+
export function resetEmojiSearchProvider() {
115+
unregisterSearchProvider(EmojiProvider.SEARCH_PROVIDER_ID);
116+
_emojiCatalogItems = null;
117+
_emojiCatalogPromise = null;
118+
_emojiExtensionUuid = 'EmojiSearchProvider';
119+
_isProviderRegistered = false;
120+
}

gnome-extensions/extension/features/GIF/integrations/gifSearchProvider.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { registerSearchProvider } from '../../../shared/services/serviceSearchHub.js';
1+
import { registerSearchProvider, unregisterSearchProvider } from '../../../shared/services/serviceSearchHub.js';
22

33
import { GifManager } from '../managers/gifManager.js';
44
import { GifProvider } from '../constants/gifConstants.js';
@@ -9,6 +9,7 @@ import { GifProvider } from '../constants/gifConstants.js';
99

1010
let _isProviderRegistered = false;
1111
let _gifManager = null;
12+
let _ownsGifManager = false;
1213

1314
// ========================================================================
1415
// Internal Helpers
@@ -29,6 +30,7 @@ function ensureGifManager({ settings, extensionUuid, extensionPath } = {}) {
2930
}
3031

3132
_gifManager = new GifManager(settings, extensionUuid, extensionPath);
33+
_ownsGifManager = true;
3234
return _gifManager;
3335
}
3436

@@ -48,7 +50,11 @@ function ensureGifManager({ settings, extensionUuid, extensionPath } = {}) {
4850
*/
4951
export function ensureGifSearchProviderRegistered({ settings, extensionUuid, extensionPath, gifManager } = {}) {
5052
if (gifManager) {
53+
if (_ownsGifManager && _gifManager && _gifManager !== gifManager) {
54+
_gifManager.destroy();
55+
}
5156
_gifManager = gifManager;
57+
_ownsGifManager = false;
5258
} else {
5359
ensureGifManager({ settings, extensionUuid, extensionPath });
5460
}
@@ -82,15 +88,15 @@ export function ensureGifSearchProviderRegistered({ settings, extensionUuid, ext
8288
}
8389
},
8490
applyToTab: async ({ tabActor, query }) => {
85-
if (!tabActor || typeof tabActor.applyExternalSearch !== 'function') {
91+
if (!tabActor) {
8692
return false;
8793
}
8894

8995
await tabActor.applyExternalSearch(query);
9096
return true;
9197
},
9298
clearOnTab: async ({ tabActor }) => {
93-
if (!tabActor || typeof tabActor.clearExternalSearch !== 'function') {
99+
if (!tabActor) {
94100
return false;
95101
}
96102

@@ -102,3 +108,20 @@ export function ensureGifSearchProviderRegistered({ settings, extensionUuid, ext
102108
_isProviderRegistered = true;
103109
return GifProvider.SEARCH_PROVIDER_ID;
104110
}
111+
112+
/**
113+
* Unregisters the GIF provider and destroys any manager owned by this module.
114+
*
115+
* @returns {void}
116+
*/
117+
export function resetGifSearchProvider() {
118+
unregisterSearchProvider(GifProvider.SEARCH_PROVIDER_ID);
119+
120+
if (_ownsGifManager && _gifManager) {
121+
_gifManager.destroy();
122+
}
123+
124+
_gifManager = null;
125+
_ownsGifManager = false;
126+
_isProviderRegistered = false;
127+
}

gnome-extensions/extension/features/Kaomoji/integrations/kaomojiSearchProvider.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { registerSearchProvider } from '../../../shared/services/serviceSearchHub.js';
21
import { IOResource, ResourceItem } from '../../../shared/constants/storagePaths.js';
2+
import { registerSearchProvider, unregisterSearchProvider } from '../../../shared/services/serviceSearchHub.js';
33

44
import { KaomojiJsonParser } from '../parsers/kaomojiJsonParser.js';
55
import { KaomojiProvider } from '../constants/kaomojiConstants.js';
66
import { KaomojiViewRenderer } from '../view/kaomojiViewRenderer.js';
77

8-
// Private Resource
9-
const _kaomojiSearchRenderer = new KaomojiViewRenderer();
10-
118
// ========================================================================
129
// State
1310
// ========================================================================
1411

15-
let _kaomojiCatalogItems = [];
12+
let _kaomojiCatalogItems = null;
1613
let _kaomojiCatalogPromise = null;
1714
let _kaomojiExtensionUuid = 'KaomojiSearchProvider';
1815
let _isProviderRegistered = false;
@@ -27,7 +24,7 @@ let _isProviderRegistered = false;
2724
* @returns {Promise<Array>} A promise that resolves to an array of kaomoji catalog items.
2825
*/
2926
async function loadKaomojiCatalog() {
30-
if (_kaomojiCatalogItems.length > 0) {
27+
if (Array.isArray(_kaomojiCatalogItems)) {
3128
return _kaomojiCatalogItems;
3229
}
3330

@@ -70,6 +67,8 @@ export function ensureKaomojiSearchProviderRegistered({ extensionUuid } = {}) {
7067
return KaomojiProvider.SEARCH_PROVIDER_ID;
7168
}
7269

70+
let kaomojiSearchRenderer = null;
71+
7372
registerSearchProvider({
7473
id: KaomojiProvider.SEARCH_PROVIDER_ID,
7574
targetTabs: ['Kaomoji'],
@@ -78,19 +77,23 @@ export function ensureKaomojiSearchProviderRegistered({ extensionUuid } = {}) {
7877
return [];
7978
}
8079

80+
if (!kaomojiSearchRenderer) {
81+
kaomojiSearchRenderer = new KaomojiViewRenderer();
82+
}
83+
8184
const catalogItems = await loadKaomojiCatalog();
82-
return catalogItems.filter((item) => _kaomojiSearchRenderer.searchFilter(item || {}, query));
85+
return catalogItems.filter((item) => kaomojiSearchRenderer.searchFilter(item || {}, query));
8386
},
8487
applyToTab: async ({ tabActor, query }) => {
85-
if (!tabActor || typeof tabActor.applyExternalSearch !== 'function') {
88+
if (!tabActor) {
8689
return false;
8790
}
8891

8992
await tabActor.applyExternalSearch(query);
9093
return true;
9194
},
9295
clearOnTab: async ({ tabActor }) => {
93-
if (!tabActor || typeof tabActor.clearExternalSearch !== 'function') {
96+
if (!tabActor) {
9497
return false;
9598
}
9699

@@ -102,3 +105,16 @@ export function ensureKaomojiSearchProviderRegistered({ extensionUuid } = {}) {
102105
_isProviderRegistered = true;
103106
return KaomojiProvider.SEARCH_PROVIDER_ID;
104107
}
108+
109+
/**
110+
* Unregisters the Kaomoji provider and clears cached module state.
111+
*
112+
* @returns {void}
113+
*/
114+
export function resetKaomojiSearchProvider() {
115+
unregisterSearchProvider(KaomojiProvider.SEARCH_PROVIDER_ID);
116+
_kaomojiCatalogItems = null;
117+
_kaomojiCatalogPromise = null;
118+
_kaomojiExtensionUuid = 'KaomojiSearchProvider';
119+
_isProviderRegistered = false;
120+
}

gnome-extensions/extension/features/RecentlyUsed/definitions/recentlyUsedDefinitionClipboard.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,8 @@ function createRecentlyUsedDefinitionClipboardInstance() {
140140
return true;
141141
}
142142

143-
try {
144-
return ClipboardSearchUtils.isMatch(item, query);
145-
} catch {
146-
return typeof fallbackMatch === 'function' ? fallbackMatch(item) : false;
147-
}
143+
const fallback = fallbackMatch(item);
144+
return ClipboardSearchUtils.isMatch(item, query) || fallback;
148145
};
149146

150147
/**
@@ -191,4 +188,4 @@ function createRecentlyUsedDefinitionClipboardInstance() {
191188
/**
192189
* Section definition template for clipboard history items.
193190
*/
194-
export const RecentlyUsedDefinitionClipboard = createRecentlyUsedDefinitionClipboardInstance();
191+
export const RecentlyUsedDefinitionClipboard = () => createRecentlyUsedDefinitionClipboardInstance();

gnome-extensions/extension/features/RecentlyUsed/definitions/recentlyUsedDefinitionEmoji.js

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import { EmojiProvider } from '../../Emoji/constants/emojiConstants.js';
99
import { EmojiViewRenderer } from '../../Emoji/view/emojiViewRenderer.js';
1010
import { ensureEmojiSearchProviderRegistered } from '../../Emoji/integrations/emojiSearchProvider.js';
1111

12-
const _emojiSearchRenderer = new EmojiViewRenderer(null);
13-
1412
/**
1513
* Creates a runtime-scoped emoji section definition.
1614
*
1715
* @returns {object} Emoji section definition instance.
1816
*/
1917
function createRecentlyUsedDefinitionEmojiInstance() {
2018
let recentManager = null;
19+
let emojiSearchRenderer = null;
2120

2221
const definition = {
2322
id: 'emoji',
@@ -49,11 +48,7 @@ function createRecentlyUsedDefinitionEmojiInstance() {
4948
ensureEmojiSearchProviderRegistered({ extensionUuid });
5049

5150
if (recentManager) {
52-
try {
53-
recentManager.destroy();
54-
} catch {
55-
// Ignore stale manager teardown errors before re-init.
56-
}
51+
recentManager.destroy();
5752
recentManager = null;
5853
}
5954

@@ -146,11 +141,12 @@ function createRecentlyUsedDefinitionEmojiInstance() {
146141
return true;
147142
}
148143

149-
try {
150-
return _emojiSearchRenderer.searchFilter(item || {}, query);
151-
} catch {
152-
return typeof fallbackMatch === 'function' ? fallbackMatch(item) : false;
144+
if (!emojiSearchRenderer) {
145+
emojiSearchRenderer = new EmojiViewRenderer(null);
153146
}
147+
148+
const fallback = fallbackMatch(item);
149+
return emojiSearchRenderer.searchFilter(item || {}, query) || fallback;
154150
};
155151

156152
/**
@@ -183,4 +179,4 @@ function createRecentlyUsedDefinitionEmojiInstance() {
183179
/**
184180
* Section definition template for recently used emoji items.
185181
*/
186-
export const RecentlyUsedDefinitionEmoji = createRecentlyUsedDefinitionEmojiInstance();
182+
export const RecentlyUsedDefinitionEmoji = () => createRecentlyUsedDefinitionEmojiInstance();

0 commit comments

Comments
 (0)