Merge matrix-react-sdk into element-web

Merge remote-tracking branch 'repomerge/t3chguy/repomerge' into t3chguy/repo-merge

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2024-10-15 14:57:26 +01:00
commit f0ee7f7905
No known key found for this signature in database
GPG key ID: A2B008A5F49F5D0D
3265 changed files with 484599 additions and 699 deletions

View file

@ -8,6 +8,18 @@ const ignore: string[] = [];
ignore.push(...Object.values<string>(JSON.parse(fs.readFileSync(`${__dirname}/../components.json`, "utf-8"))));
ignore.push("/index.ts");
ignore.push("/jest-matrix-react.tsx");
ignore.push("/customisations/");
ignore.push("/test-utils/");
// The following ignores are temporary and false-positives which need to be fixed
ignore.push("/useLocalStorageState.ts");
ignore.push("/blurhash.worker.ts");
ignore.push("/OpenSpotlightPayload.ts");
ignore.push("/PinnedMessageBadge.tsx");
ignore.push("/editor/mock.ts");
ignore.push("DeviceIsolationModeController.ts");
// We ignore js-sdk by default as it may export for other non element-web projects
if (!includeJSSDK) ignore.push("matrix-js-sdk");

View file

@ -0,0 +1,32 @@
#!/bin/bash
# This installs other Matrix dependencies that are often
# developed in parallel with react-sdk, using fetchdep.sh
# for branch matching.
# This will set up a working react-sdk environment, so is
# used for running react-sdk standalone tests. To set up a
# build of element-web, use layered.sh
set -ex
scripts/fetchdep.sh matrix-org matrix-js-sdk develop
pushd matrix-js-sdk
[ -n "$JS_SDK_GITHUB_BASE_REF" ] && git fetch --depth 1 origin $JS_SDK_GITHUB_BASE_REF && git checkout $JS_SDK_GITHUB_BASE_REF
yarn link
yarn install --frozen-lockfile $@
popd
scripts/fetchdep.sh matrix-org matrix-analytics-events
# We don't pass a default branch so cloning may fail when we are not in a PR
# This is expected as this project does not share a release cycle but we still branch match it
if [ -d matrix-analytics-events ]; then
pushd matrix-analytics-events
yarn link
yarn install --frozen-lockfile $@
yarn build:ts
popd
fi
yarn link matrix-js-sdk
[ -d matrix-analytics-events ] && yarn link @matrix-org/analytics-events
yarn install --frozen-lockfile $@

43
scripts/ci/layered.sh Executable file
View file

@ -0,0 +1,43 @@
#!/bin/bash
set -ex
# Creates a layered environment with the full repo for the app and SDKs cloned
# and linked. This gives an element-web dev environment ready to build with
# the current react-sdk branch and any matching branches of react-sdk's dependencies
# so that changes can be tested in element-web.
# Note that this style is different from the recommended developer setup: this
# file nests js-sdk inside element-web, while the local
# development setup places them all at the same level. We are nesting them here
# because some CI systems do not allow moving to a directory above the checkout
# for the primary repo (react-sdk in this case).
# Set up the js-sdk first
scripts/fetchdep.sh matrix-org matrix-js-sdk develop
pushd matrix-js-sdk
[ -n "$JS_SDK_GITHUB_BASE_REF" ] && git fetch --depth 1 origin $JS_SDK_GITHUB_BASE_REF && git checkout $JS_SDK_GITHUB_BASE_REF
yarn link
yarn install --frozen-lockfile
popd
# Also set up matrix-analytics-events for branch with matching name
scripts/fetchdep.sh matrix-org matrix-analytics-events
# We don't pass a default branch so cloning may fail when we are not in a PR
# This is expected as this project does not share a release cycle but we still branch match it
if [ -d matrix-analytics-events ]; then
pushd matrix-analytics-events
yarn link
yarn install --frozen-lockfile
yarn build:ts
popd
fi
# Finally, set up element-web
scripts/fetchdep.sh vector-im element-web develop
pushd element-web
[ -n "$ELEMENT_WEB_GITHUB_BASE_REF" ] && git fetch --depth 1 origin $ELEMENT_WEB_GITHUB_BASE_REF && git checkout $ELEMENT_WEB_GITHUB_BASE_REF
yarn link matrix-js-sdk
yarn install --frozen-lockfile
yarn build:res
popd

47
scripts/copy-i18n.py Executable file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env python
import json
import sys
import os
if len(sys.argv) < 3:
print "Usage: %s <source> <dest>" % (sys.argv[0],)
print "eg. %s pt_BR.json pt.json" % (sys.argv[0],)
print
print "Adds any translations to <dest> that exist in <source> but not <dest>"
sys.exit(1)
srcpath = sys.argv[1]
dstpath = sys.argv[2]
tmppath = dstpath + ".tmp"
with open(srcpath) as f:
src = json.load(f)
with open(dstpath) as f:
dst = json.load(f)
toAdd = {}
for k,v in src.iteritems():
if k not in dst:
print "Adding %s" % (k,)
toAdd[k] = v
# don't just json.dumps as we'll probably re-order all the keys (and they're
# not in any given order so we can't just sort_keys). Append them to the end.
with open(dstpath) as ifp:
with open(tmppath, 'w') as ofp:
for line in ifp:
strippedline = line.strip()
if strippedline in ('{', '}'):
ofp.write(line)
elif strippedline.endswith(','):
ofp.write(line)
else:
ofp.write(' '+strippedline+',')
toAddStr = json.dumps(toAdd, indent=4, separators=(',', ': '), ensure_ascii=False, encoding="utf8").strip("{}\n")
ofp.write("\n")
ofp.write(toAddStr.encode('utf8'))
ofp.write("\n")
os.rename(tmppath, dstpath)

View file

@ -9,9 +9,8 @@ import _ from "lodash";
import { util } from "webpack";
import { Translations } from "matrix-web-i18n";
const REACT_I18N_BASE_PATH = "node_modules/matrix-react-sdk/src/i18n/strings/";
const I18N_BASE_PATH = "src/i18n/strings/";
const INCLUDE_LANGS = [...new Set([...fs.readdirSync(I18N_BASE_PATH), ...fs.readdirSync(REACT_I18N_BASE_PATH)])]
const INCLUDE_LANGS = [...new Set([...fs.readdirSync(I18N_BASE_PATH)])]
.filter((fn) => fn.endsWith(".json"))
.map((f) => f.slice(0, -5));
@ -43,11 +42,10 @@ const logWatch = (path: string) => {
};
function prepareLangFile(lang: string, dest: string): [filename: string, json: string] {
const reactSdkFile = REACT_I18N_BASE_PATH + lang + ".json";
const riotWebFile = I18N_BASE_PATH + lang + ".json";
const path = I18N_BASE_PATH + lang + ".json";
let translations: Translations = {};
[reactSdkFile, riotWebFile].forEach(function (f) {
[path].forEach(function (f) {
if (fs.existsSync(f)) {
try {
translations = _.merge(translations, JSON.parse(fs.readFileSync(f).toString()));
@ -101,8 +99,7 @@ function genLangList(langFileMap: Record<string, string>): void {
* and regenerating languages.json with the new filename
*/
function watchLanguage(lang: string, dest: string, langFileMap: Record<string, string>): void {
const reactSdkFile = REACT_I18N_BASE_PATH + lang + ".json";
const riotWebFile = I18N_BASE_PATH + lang + ".json";
const path = I18N_BASE_PATH + lang + ".json";
// XXX: Use a debounce because for some reason if we read the language
// file immediately after the FS event is received, the file contents
@ -120,7 +117,7 @@ function watchLanguage(lang: string, dest: string, langFileMap: Record<string, s
}, 500);
};
[reactSdkFile, riotWebFile].forEach(function (f) {
[path].forEach(function (f) {
chokidar
.watch(f, { ignoreInitial: true })
.on("ready", () => {

View file

@ -10,12 +10,11 @@ then
echo "using develop dependencies for react-sdk and js-sdk"
USE_CUSTOM_SDKS=true
JS_SDK_BRANCH='develop'
REACT_SDK_BRANCH='develop'
fi
if [[ $USE_CUSTOM_SDKS == false ]]
then
echo "skipping react-sdk and js-sdk installs: USE_CUSTOM_SDKS is false"
echo "skipping js-sdk install: USE_CUSTOM_SDKS is false"
exit 0
fi
@ -26,14 +25,5 @@ yarn link
yarn --network-timeout=100000 install
cd ../
echo "Linking react-sdk"
git clone --depth 1 --branch $REACT_SDK_BRANCH "$REACT_SDK_REPO" react-sdk
cd react-sdk
yarn link
echo "Setting up element-web with js-sdk package"
yarn link matrix-js-sdk
yarn --network-timeout=100000 install
cd ../
echo "Setting up element-web with react-sdk and js-sdk packages"
yarn link matrix-js-sdk
yarn link matrix-react-sdk

View file

@ -1,7 +1,6 @@
#!/usr/bin/env bash
# Fetches the js-sdk and matrix-react-sdk dependencies for development
# or testing purposes
# Fetches the js-sdk dependency for development or testing purposes
# If there exists a branch of that dependency with the same name as
# the branch the current checkout is on, use that branch. Otherwise,
# use develop.
@ -83,17 +82,3 @@ popd
yarn link matrix-js-sdk
##############################
echo 'Setting up matrix-react-sdk'
dodep element-hq matrix-react-sdk
pushd matrix-react-sdk
yarn link
yarn link matrix-js-sdk
yarn install --frozen-lockfile
popd
yarn link matrix-react-sdk
##############################

85
scripts/fetchdep.sh Executable file
View file

@ -0,0 +1,85 @@
#!/bin/bash
set -x
deforg="$1"
defrepo="$2"
defbranch="$3"
rm -r "$defrepo" || true
# figure out where to look for pull requests:
# - We may have been told an explicit repo via the PR_ORG/PR_REPO/PR_NUMBER env vars
# - otherwise, check the $GITHUB_ env vars which are set by Github Actions
# - failing that, fall back to the element-hq/element-web repo.
#
# in ether case, the PR_NUMBER variable must be set explicitly.
default_org_repo=${GITHUB_REPOSITORY:-"element-hq/element-web"}
PR_ORG=${PR_ORG:-${default_org_repo%%/*}}
PR_REPO=${PR_REPO:-${default_org_repo##*/}}
# A function that clones a branch of a repo based on the org, repo and branch
clone() {
org=$1
repo=$2
branch=$3
if [ -n "$branch" ]
then
echo "Trying to use $org/$repo#$branch"
# Disable auth prompts: https://serverfault.com/a/665959
GIT_TERMINAL_PROMPT=0 git clone https://github.com/$org/$repo.git $repo --branch "$branch" --depth 1 && exit 0
fi
}
# A function that gets info about a PR from the GitHub API based on its number
getPRInfo() {
number=$1
if [ -n "$number" ]; then
echo "Getting info about a PR with number $number"
apiEndpoint="https://api.github.com/repos/$PR_ORG/$PR_REPO/pulls/$number"
head=$(curl $apiEndpoint | jq -r '.head.label')
fi
}
# Some CIs don't give us enough info, so we just get the PR number and ask the
# GH API for more info - "fork:branch". Some give us this directly.
if [ -n "$BUILDKITE_BRANCH" ]; then
# BuildKite
head=$BUILDKITE_BRANCH
elif [ -n "$PR_NUMBER" ]; then
# GitHub
getPRInfo $PR_NUMBER
elif [ -n "$REVIEW_ID" ]; then
# Netlify
getPRInfo $REVIEW_ID
fi
# for forks, $head will be in the format "fork:branch", so we split it by ":"
# into an array. On non-forks, this has the effect of splitting into a single
# element array given ":" shouldn't appear in the head - it'll just be the
# branch name. Based on the results, we clone.
BRANCH_ARRAY=(${head//:/ })
TRY_ORG=$deforg
TRY_BRANCH=${BRANCH_ARRAY[0]}
if [[ "$head" == *":"* ]]; then
# ... but only match that fork if it's a real fork
if [ "${BRANCH_ARRAY[0]}" != "$PR_ORG" ]; then
TRY_ORG=${BRANCH_ARRAY[0]}
fi
TRY_BRANCH=${BRANCH_ARRAY[1]}
fi
clone ${TRY_ORG} $defrepo ${TRY_BRANCH}
# Try the target branch of the push or PR.
if [ -n "$GITHUB_BASE_REF" ]; then
clone $deforg $defrepo $GITHUB_BASE_REF
elif [ -n "$BUILDKITE_PULL_REQUEST_BASE_BRANCH" ]; then
clone $deforg $defrepo $BUILDKITE_PULL_REQUEST_BASE_BRANCH
fi
# Try HEAD which is the branch name in Netlify (not BRANCH which is pull/xxxx/head for PR builds)
clone $deforg $defrepo $HEAD
# Use the default branch as the last resort.
clone $deforg $defrepo $defbranch

View file

@ -6,7 +6,6 @@
set -e
# Since the deps are fetched from git, we can rev-parse
REACT_SHA=$(git -C node_modules/matrix-react-sdk rev-parse --short=12 HEAD)
JSSDK_SHA=$(git -C node_modules/matrix-js-sdk rev-parse --short=12 HEAD)
VECTOR_SHA=$(git rev-parse --short=12 HEAD) # use the ACTUAL SHA rather than assume develop
echo $VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA
echo $VECTOR_SHA-js-$JSSDK_SHA

View file

@ -8,12 +8,12 @@ set -ex
# in element-web.
# Note that this style is different from the recommended developer setup: this
# file nests js-sdk and matrix-react-sdk inside element-web, while the local
# file nests js-sdk inside element-web, while the local
# development setup places them all at the same level. We are nesting them here
# because some CI systems do not allow moving to a directory above the checkout
# for the primary repo (element-web in this case).
# Install dependencies, as we'll be using fetchdep.sh from matrix-react-sdk
# Install dependencies
yarn install --frozen-lockfile
# Pass appropriate repo to fetchdep.sh
@ -21,14 +21,14 @@ export PR_ORG=element-hq
export PR_REPO=element-web
# Set up the js-sdk first
node_modules/matrix-react-sdk/scripts/fetchdep.sh matrix-org matrix-js-sdk develop
scripts/fetchdep.sh matrix-org matrix-js-sdk develop
pushd matrix-js-sdk
yarn link
yarn install --frozen-lockfile
popd
# Also set up matrix-analytics-events for branch with matching name
node_modules/matrix-react-sdk/scripts/fetchdep.sh matrix-org matrix-analytics-events
scripts/fetchdep.sh matrix-org matrix-analytics-events
# We don't pass a default branch so cloning may fail when we are not in a PR
# This is expected as this project does not share a release cycle but we still branch match it
if [ -d matrix-analytics-events ]; then
@ -39,15 +39,5 @@ if [ -d matrix-analytics-events ]; then
popd
fi
# Now set up the react-sdk
node_modules/matrix-react-sdk/scripts/fetchdep.sh element-hq matrix-react-sdk develop
pushd matrix-react-sdk
yarn link
yarn link matrix-js-sdk
[ -d matrix-analytics-events ] && yarn link @matrix-org/analytics-events
yarn install --frozen-lockfile
popd
# Link the layers into element-web
yarn link matrix-js-sdk
yarn link matrix-react-sdk

152
scripts/make-react-component.js Executable file
View file

@ -0,0 +1,152 @@
#!/usr/bin/env node
const fs = require("fs/promises");
const path = require("path");
/**
* Unsophisticated script to create a styled, unit-tested react component.
* -filePath / -f : path to the component to be created, including new component name, excluding extension, relative to src
* -withStyle / -s : optional, flag to create a style file for the component. Defaults to false.
*
* eg:
* ```
* node srcipts/make-react-component.js -f components/toasts/NewToast -s
* ```
* creates files:
* - src/components/toasts/NewToast.tsx
* - test/components/toasts/NewToast-test.tsx
* - res/css/components/toasts/_NewToast.pcss
*
*/
const TEMPLATES = {
COMPONENT: `
import React from 'react';
interface Props {}
const %%ComponentName%%: React.FC<Props> = () => {
return <div className='mx_%%ComponentName%%' />;
};
export default %%ComponentName%%;
`,
TEST: `
import React from "react";
import { render } from "@testing-library/react";
import %%ComponentName%% from '%%RelativeComponentPath%%';
describe("<%%ComponentName%% />", () => {
const defaultProps = {};
const getComponent = (props = {}) =>
render(<%%ComponentName%% {...defaultProps} {...props} />);
it("matches snapshot", () => {
const { asFragment } = getComponent();
expect(asFragment()).toMatchSnapshot()();
});
});
`,
STYLE: `
.mx_%%ComponentName%% {
}
`,
};
const options = {
alias: {
filePath: "f",
withStyle: "s",
},
};
const args = require("minimist")(process.argv, options);
const ensureDirectoryExists = async (filePath) => {
const dirName = path.parse(filePath).dir;
try {
await fs.access(dirName);
return;
} catch (error) {}
await fs.mkdir(dirName, { recursive: true });
};
const makeFile = async ({ filePath, componentName, extension, base, template, prefix, componentFilePath }) => {
const newFilePath = path.join(
base,
path.dirname(filePath),
`${prefix || ""}${path.basename(filePath)}${extension}`,
);
await ensureDirectoryExists(newFilePath);
const relativePathToComponent = path.parse(path.relative(path.dirname(newFilePath), componentFilePath || ""));
const importComponentPath = path.join(relativePathToComponent.dir, relativePathToComponent.name);
try {
await fs.writeFile(newFilePath, fillTemplate(template, componentName, importComponentPath), { flag: "wx" });
console.log(`Created ${path.relative(process.cwd(), newFilePath)}`);
return newFilePath;
} catch (error) {
if (error.code === "EEXIST") {
console.log(`File already exists ${path.relative(process.cwd(), newFilePath)}`);
return newFilePath;
} else {
throw error;
}
}
};
const fillTemplate = (template, componentName, relativeComponentFilePath, skinnedSdkPath) =>
template
.replace(/%%ComponentName%%/g, componentName)
.replace(/%%RelativeComponentPath%%/g, relativeComponentFilePath);
const makeReactComponent = async () => {
const { filePath, withStyle } = args;
if (!filePath) {
throw new Error("No file path provided, did you forget -f?");
}
const componentName = filePath.split("/").slice(-1).pop();
const componentFilePath = await makeFile({
filePath,
componentName,
base: "src",
extension: ".tsx",
template: TEMPLATES.COMPONENT,
});
await makeFile({
filePath,
componentFilePath,
componentName,
base: "test",
extension: "-test.tsx",
template: TEMPLATES.TEST,
componentName,
});
if (withStyle) {
await makeFile({
filePath,
componentName,
base: "res/css",
prefix: "_",
extension: ".pcss",
template: TEMPLATES.STYLE,
});
}
};
// Wrapper since await at the top level is not well supported yet
function run() {
(async function () {
await makeReactComponent();
})();
}
run();
return;