Skip to content

Commit 95de708

Browse files
authored
Make customisations (and general file overrides) easier to specify (#21189)
Intended for customisation endpoints - see included docs.
1 parent a2b0cf9 commit 95de708

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed

docs/customisations.md

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,46 +16,53 @@ the React SDK, you can still override it from the Element Web layer:
1616
`element-web/src/customisations/YourNameSecurity.ts`
1717
2. Edit customisations points and make sure export the ones you actually want to
1818
activate
19-
3. Tweak the Element build process to use the customised module instead of the
20-
default by adding this to the `additionalPlugins` array in `webpack.config.js`:
21-
22-
```js
23-
new webpack.NormalModuleReplacementPlugin(
24-
/src[\/\\]customisations[\/\\]Security\.ts/,
25-
path.resolve(__dirname, 'src/customisations/YourNameSecurity.ts'),
26-
),
27-
```
19+
3. Create/add an entry to `customisations.json` next to the webpack config:
2820

29-
If we add more customisation modules in the future, we'll likely improve these
30-
steps to remove the need for build changes like the above.
21+
```json
22+
{
23+
"src/customisations/Security.ts": "src/customisations/YourNameSecurity.ts"
24+
}
25+
```
3126

3227
By isolating customisations to their own module, this approach should remove the
3328
chance of merge conflicts when updating your fork, and thus simplify ongoing
3429
maintenance.
3530

31+
**Note**: The project deliberately does not exclude `customisations.json` from Git.
32+
This is to ensure that in shared projects it's possible to have a common config. By
33+
default, Element Web does *not* ship with this file to prevent conflicts.
34+
35+
### Custom components
36+
37+
Instead of implementing skinning from the react-sdk, maintainers can use the above system to override components
38+
if they wish. Maintenance and API surface compatibility are left as a responsibility for the project - the layering
39+
in Element Web (including the react-sdk) do not make guarantees that properties/state machines won't change.
40+
3641
### Component visibility customisation
42+
3743
UI for some actions can be hidden via the ComponentVisibility customisation:
3844
- inviting users to rooms and spaces,
3945
- creating rooms,
4046
- creating spaces,
4147

4248
To customise visibility create a customisation module from [ComponentVisibility](https://github.com/matrix-org/matrix-react-sdk/blob/master/src/customisations/ComponentVisibility.ts) following the instructions above.
4349

44-
`shouldShowComponent` determines whether or not the active MatrixClient user should be able to use
50+
`shouldShowComponent` determines whether the active MatrixClient user should be able to use
4551
the given UI component. When `shouldShowComponent` returns falsy all UI components for that feature will be hidden.
4652
If shown, the user might still not be able to use the
4753
component depending on their contextual permissions. For example, invite options
48-
might be shown to the user but they won't have permission to invite users to
54+
might be shown to the user, but they won't have permission to invite users to
4955
the current room: the button will appear disabled.
5056

5157
For example, to only allow users who meet a certain condition to create spaces:
52-
```
58+
```typescript
5359
function shouldShowComponent(component: UIComponent): boolean {
54-
if (component === UIComponent.CreateSpaces) {
55-
const userMeetsCondition = <<check your custom condition here>>
56-
return userMeetsCondition;
57-
}
58-
return true;
60+
if (component === UIComponent.CreateSpaces) {
61+
// customConditionCheck() is a function of your own creation
62+
const userMeetsCondition = customConditionCheck(MatrixClientPeg.get().getUserId());
63+
return userMeetsCondition;
64+
}
65+
return true;
5966
}
6067
```
61-
In this example, all UI related to creating a space will be hidden unless the users meets a custom condition.
68+
In this example, all UI related to creating a space will be hidden unless the users meets the custom condition.

webpack.config.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@ function getActiveThemes() {
3939
return themes;
4040
}
4141

42+
// See docs/customisations.md
43+
let fileOverrides = {/* {[file: string]: string} */};
44+
try {
45+
fileOverrides = require('./customisations.json');
46+
47+
// stringify the output so it appears in logs correctly, as large files can sometimes get
48+
// represented as `<Object>` which is less than helpful.
49+
console.log("Using customisations.json : " + JSON.stringify(fileOverrides, null, 4));
50+
} catch (e) {
51+
// ignore - not important
52+
}
53+
const moduleReplacementPlugins = Object.entries(fileOverrides).map(([oldPath, newPath]) => {
54+
return new webpack.NormalModuleReplacementPlugin(
55+
// because the input is effectively defined by the person running the build, we don't
56+
// need to do anything special to protect against regex overrunning, etc.
57+
new RegExp(oldPath.replace(/\//g, '[\\/\\\\]').replace(/\./g, '\\.')),
58+
path.resolve(__dirname, newPath),
59+
);
60+
});
61+
4262
module.exports = (env, argv) => {
4363
// Establish settings based on the environment and args.
4464
//
@@ -475,6 +495,8 @@ module.exports = (env, argv) => {
475495
},
476496

477497
plugins: [
498+
...moduleReplacementPlugins,
499+
478500
// This exports our CSS using the splitChunks and loaders above.
479501
new MiniCssExtractPlugin({
480502
filename: useHMR ? "bundles/[name].css" : "bundles/[hash]/[name].css",

0 commit comments

Comments
 (0)