Skip to content

Commit

Permalink
Added ModuleRunner extension points for user search extension
Browse files Browse the repository at this point in the history
  • Loading branch information
thoraj committed Aug 21, 2024
1 parent 105311a commit e4b4424
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 11 deletions.
27 changes: 21 additions & 6 deletions src/components/views/dialogs/InviteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import { SdkContextClass } from "../../../contexts/SDKContext";
import { UserProfilesStore } from "../../../stores/UserProfilesStore";
import { Key } from "../../../Keyboard";
import SpaceStore from "../../../stores/spaces/SpaceStore";
import { ModuleRunner } from "../../../modules/ModuleRunner";

// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */
Expand Down Expand Up @@ -641,8 +642,12 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial

let foundUser = false;
try {
await MatrixClientPeg.get()
?.searchUserDirectory({ term: this.state.filterText.trim().split(":")[0] ?? this.state.filterText })
var client = await MatrixClientPeg.get();

Check failure on line 645 in src/components/views/dialogs/InviteDialog.tsx

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected var, use let or const instead

const searchContext = await ModuleRunner.instance.extensions.userSearch.getSearchContext(client, SdkContextClass.instance);

client
?.searchUserDirectory({ term: this.state.filterText.trim().split(":")[0] ?? this.state.filterText }, searchContext.extraBodyArgs, searchContext.extraRequestOptions,)
.then(async (r) => {
this.setState({ busy: false });

Expand Down Expand Up @@ -946,9 +951,16 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.props.onFinished(false);
};




private updateSuggestions = async (term: string): Promise<void> => {
MatrixClientPeg.safeGet()
.searchUserDirectory({ term })

var client = MatrixClientPeg.safeGet();

Check failure on line 959 in src/components/views/dialogs/InviteDialog.tsx

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected var, use let or const instead
var searchContext = await ModuleRunner.instance.extensions.userSearch.getSearchContext(client, SdkContextClass.instance);

Check failure on line 960 in src/components/views/dialogs/InviteDialog.tsx

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected var, use let or const instead

client
.searchUserDirectory({ term }, searchContext.extraBodyArgs, searchContext.extraRequestOptions)
.then(async (r): Promise<void> => {
if (term !== this.state.filterText) {
// Discard the results - we were probably too slow on the server-side to make
Expand Down Expand Up @@ -1157,8 +1169,11 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.setState({ busy: true });

let directoryUsers: any[] = [];
await MatrixClientPeg.get()
?.searchUserDirectory({ term: text })

let client = await MatrixClientPeg.get();

Check failure on line 1173 in src/components/views/dialogs/InviteDialog.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'client' is never reassigned. Use 'const' instead
const searchContext = await ModuleRunner.instance.extensions.userSearch.getSearchContext(client, SdkContextClass.instance);
client
?.searchUserDirectory({ term: text }, searchContext.extraBodyArgs, searchContext.extraRequestOptions)
.then(async (r) => {
this.setState({ busy: false });

Expand Down
7 changes: 6 additions & 1 deletion src/hooks/useUserDirectory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { useCallback, useState } from "react";
import { MatrixClientPeg } from "../MatrixClientPeg";
import { DirectoryMember } from "../utils/direct-messages";
import { useLatestResult } from "./useLatestResult";
import { ModuleRunner } from "../modules/ModuleRunner";
import { SdkContextClass } from "../contexts/SDKContext";

export interface IUserDirectoryOpts {
limit: number;
Expand Down Expand Up @@ -49,7 +51,10 @@ export const useUserDirectory = (): {

try {
setLoading(true);
const { results } = await MatrixClientPeg.safeGet().searchUserDirectory(opts);
const client = await MatrixClientPeg.safeGet();
var searchContext = await ModuleRunner.instance.extensions.userSearch.getSearchContext(client, SdkContextClass.instance);

Check failure on line 55 in src/hooks/useUserDirectory.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected var, use let or const instead
const { results } = await client.searchUserDirectory(opts, searchContext.extraBodyArgs, searchContext.extraRequestOptions);

updateResult(
opts,
results.map((user) => new DirectoryMember(user)),
Expand Down
34 changes: 33 additions & 1 deletion src/modules/ModuleRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import {
DefaultExperimentalExtensions,
ProvideExperimentalExtensions,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions";
import {
DefaultUserSearchExtensions,
ProvideUserSearchExtensions,
} from "@matrix-org/react-sdk-module-api/lib/lifecycles/UserSearchExtensions";

import { AppModule } from "./AppModule";
import { ModuleFactory } from "./ModuleFactory";
Expand All @@ -38,20 +42,26 @@ class ExtensionsManager {
// Private backing fields for extensions
private cryptoSetupExtension: ProvideCryptoSetupExtensions;
private experimentalExtension: ProvideExperimentalExtensions;
private userSearchExtension: ProvideUserSearchExtensions;

/** `true` if `cryptoSetupExtension` is the default implementation; `false` if it is implemented by a module. */
private hasDefaultCryptoSetupExtension = true;

/** `true` if `userSearchExtension` is the default implementation; `false` if it is implemented by a module. */
private hasDefaultUserSearchExtension = true;

/** `true` if `experimentalExtension` is the default implementation; `false` if it is implemented by a module. */
private hasDefaultExperimentalExtension = true;


/**
* Create a new instance.
*/
public constructor() {
// Set up defaults
this.cryptoSetupExtension = new DefaultCryptoSetupExtensions();
this.experimentalExtension = new DefaultExperimentalExtensions();
this.userSearchExtension = new DefaultUserSearchExtensions();
}

/**
Expand All @@ -63,6 +73,16 @@ class ExtensionsManager {
return this.cryptoSetupExtension;
}

/**
* Provides a user search extension.
*
* @returns The registered extension. If no module provides this extension, a default implementation is returned.
*/
public get userSearch(): ProvideUserSearchExtensions {
return this.userSearchExtension;
}


/**
* Provides an experimental extension.
*
Expand Down Expand Up @@ -97,6 +117,18 @@ class ExtensionsManager {
}
}

/* Add the userSearch extension if any */
if (runtimeModule.extensions?.userSearch) {
if (this.hasDefaultUserSearchExtension) {
this.userSearchExtension = runtimeModule.extensions?.userSearch;
this.hasDefaultCryptoSetupExtension = false;
} else {
throw new Error(
`adding userSearch extension implementation from module ${runtimeModule.moduleName} but an implementation was already provided.`,
);
}
}

/* Add the experimental extension if any */
if (runtimeModule.extensions?.experimental) {
if (this.hasDefaultExperimentalExtension) {
Expand Down Expand Up @@ -190,4 +222,4 @@ export class ModuleRunner {
module.module.emit(lifecycleEvent, ...args);
}
}
}
}
4 changes: 3 additions & 1 deletion src/stores/widgets/StopGapWidgetDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,9 @@ export class StopGapWidgetDriver extends WidgetDriver {
public async searchUserDirectory(searchTerm: string, limit?: number): Promise<ISearchUserDirectoryResult> {
const client = MatrixClientPeg.safeGet();

const { limited, results } = await client.searchUserDirectory({ term: searchTerm, limit });
var searchContext = await ModuleRunner.instance.extensions.userSearch.getSearchContext(client, SdkContextClass.instance);

Check failure on line 542 in src/stores/widgets/StopGapWidgetDriver.ts

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected var, use let or const instead

const { limited, results } = await client.searchUserDirectory({ term: searchTerm, limit }, searchContext.extraBodyArgs, searchContext.extraRequestOptions);

return {
limited,
Expand Down
4 changes: 2 additions & 2 deletions test/stores/widgets/StopGapWidgetDriver-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ describe("StopGapWidgetDriver", () => {
results: [{ userId: "@user", displayName: "Name", avatarUrl: "mxc://" }],
});

expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: undefined });
expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: undefined }, {});
});

it("searches for users with a custom limit", async () => {
Expand All @@ -444,7 +444,7 @@ describe("StopGapWidgetDriver", () => {
results: [],
});

expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: 25 });
expect(client.searchUserDirectory).toHaveBeenCalledWith({ term: "foo", limit: 25 }, {});
});
});

Expand Down

0 comments on commit e4b4424

Please sign in to comment.