Make customisations (and general file overrides) easier to specify (#21189)
Intended for customisation endpoints - see included docs.
This commit is contained in:
parent
a2b0cf9248
commit
95de708f4e
2 changed files with 48 additions and 19 deletions
|
@ -16,24 +16,30 @@ the React SDK, you can still override it from the Element Web layer:
|
||||||
`element-web/src/customisations/YourNameSecurity.ts`
|
`element-web/src/customisations/YourNameSecurity.ts`
|
||||||
2. Edit customisations points and make sure export the ones you actually want to
|
2. Edit customisations points and make sure export the ones you actually want to
|
||||||
activate
|
activate
|
||||||
3. Tweak the Element build process to use the customised module instead of the
|
3. Create/add an entry to `customisations.json` next to the webpack config:
|
||||||
default by adding this to the `additionalPlugins` array in `webpack.config.js`:
|
|
||||||
|
|
||||||
```js
|
```json
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
{
|
||||||
/src[\/\\]customisations[\/\\]Security\.ts/,
|
"src/customisations/Security.ts": "src/customisations/YourNameSecurity.ts"
|
||||||
path.resolve(__dirname, 'src/customisations/YourNameSecurity.ts'),
|
}
|
||||||
),
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If we add more customisation modules in the future, we'll likely improve these
|
|
||||||
steps to remove the need for build changes like the above.
|
|
||||||
|
|
||||||
By isolating customisations to their own module, this approach should remove the
|
By isolating customisations to their own module, this approach should remove the
|
||||||
chance of merge conflicts when updating your fork, and thus simplify ongoing
|
chance of merge conflicts when updating your fork, and thus simplify ongoing
|
||||||
maintenance.
|
maintenance.
|
||||||
|
|
||||||
|
**Note**: The project deliberately does not exclude `customisations.json` from Git.
|
||||||
|
This is to ensure that in shared projects it's possible to have a common config. By
|
||||||
|
default, Element Web does *not* ship with this file to prevent conflicts.
|
||||||
|
|
||||||
|
### Custom components
|
||||||
|
|
||||||
|
Instead of implementing skinning from the react-sdk, maintainers can use the above system to override components
|
||||||
|
if they wish. Maintenance and API surface compatibility are left as a responsibility for the project - the layering
|
||||||
|
in Element Web (including the react-sdk) do not make guarantees that properties/state machines won't change.
|
||||||
|
|
||||||
### Component visibility customisation
|
### Component visibility customisation
|
||||||
|
|
||||||
UI for some actions can be hidden via the ComponentVisibility customisation:
|
UI for some actions can be hidden via the ComponentVisibility customisation:
|
||||||
- inviting users to rooms and spaces,
|
- inviting users to rooms and spaces,
|
||||||
- creating rooms,
|
- creating rooms,
|
||||||
|
@ -41,21 +47,22 @@ UI for some actions can be hidden via the ComponentVisibility customisation:
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
`shouldShowComponent` determines whether or not the active MatrixClient user should be able to use
|
`shouldShowComponent` determines whether the active MatrixClient user should be able to use
|
||||||
the given UI component. When `shouldShowComponent` returns falsy all UI components for that feature will be hidden.
|
the given UI component. When `shouldShowComponent` returns falsy all UI components for that feature will be hidden.
|
||||||
If shown, the user might still not be able to use the
|
If shown, the user might still not be able to use the
|
||||||
component depending on their contextual permissions. For example, invite options
|
component depending on their contextual permissions. For example, invite options
|
||||||
might be shown to the user but they won't have permission to invite users to
|
might be shown to the user, but they won't have permission to invite users to
|
||||||
the current room: the button will appear disabled.
|
the current room: the button will appear disabled.
|
||||||
|
|
||||||
For example, to only allow users who meet a certain condition to create spaces:
|
For example, to only allow users who meet a certain condition to create spaces:
|
||||||
```
|
```typescript
|
||||||
function shouldShowComponent(component: UIComponent): boolean {
|
function shouldShowComponent(component: UIComponent): boolean {
|
||||||
if (component === UIComponent.CreateSpaces) {
|
if (component === UIComponent.CreateSpaces) {
|
||||||
const userMeetsCondition = <<check your custom condition here>>
|
// customConditionCheck() is a function of your own creation
|
||||||
return userMeetsCondition;
|
const userMeetsCondition = customConditionCheck(MatrixClientPeg.get().getUserId());
|
||||||
}
|
return userMeetsCondition;
|
||||||
return true;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
In this example, all UI related to creating a space will be hidden unless the users meets a custom condition.
|
In this example, all UI related to creating a space will be hidden unless the users meets the custom condition.
|
||||||
|
|
|
@ -39,6 +39,26 @@ function getActiveThemes() {
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See docs/customisations.md
|
||||||
|
let fileOverrides = {/* {[file: string]: string} */};
|
||||||
|
try {
|
||||||
|
fileOverrides = require('./customisations.json');
|
||||||
|
|
||||||
|
// stringify the output so it appears in logs correctly, as large files can sometimes get
|
||||||
|
// represented as `<Object>` which is less than helpful.
|
||||||
|
console.log("Using customisations.json : " + JSON.stringify(fileOverrides, null, 4));
|
||||||
|
} catch (e) {
|
||||||
|
// ignore - not important
|
||||||
|
}
|
||||||
|
const moduleReplacementPlugins = Object.entries(fileOverrides).map(([oldPath, newPath]) => {
|
||||||
|
return new webpack.NormalModuleReplacementPlugin(
|
||||||
|
// because the input is effectively defined by the person running the build, we don't
|
||||||
|
// need to do anything special to protect against regex overrunning, etc.
|
||||||
|
new RegExp(oldPath.replace(/\//g, '[\\/\\\\]').replace(/\./g, '\\.')),
|
||||||
|
path.resolve(__dirname, newPath),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = (env, argv) => {
|
module.exports = (env, argv) => {
|
||||||
// Establish settings based on the environment and args.
|
// Establish settings based on the environment and args.
|
||||||
//
|
//
|
||||||
|
@ -475,6 +495,8 @@ module.exports = (env, argv) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
|
...moduleReplacementPlugins,
|
||||||
|
|
||||||
// This exports our CSS using the splitChunks and loaders above.
|
// This exports our CSS using the splitChunks and loaders above.
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: useHMR ? "bundles/[name].css" : "bundles/[hash]/[name].css",
|
filename: useHMR ? "bundles/[name].css" : "bundles/[hash]/[name].css",
|
||||||
|
|
Loading…
Add table
Reference in a new issue