Fix room membership and routing

This commit is contained in:
Robert Long 2021-07-19 12:55:30 -07:00
parent b85043eee2
commit f9bc409a0e
3 changed files with 421 additions and 91 deletions

231
package-lock.json generated
View file

@ -11,7 +11,8 @@
"events": "^3.3.0", "events": "^3.3.0",
"matrix-js-sdk": "^12.0.1", "matrix-js-sdk": "^12.0.1",
"react": "^17.0.0", "react": "^17.0.0",
"react-dom": "^17.0.0" "react-dom": "^17.0.0",
"react-router-dom": "^5.2.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-react-refresh": "^1.3.1", "@vitejs/plugin-react-refresh": "^1.3.1",
@ -930,6 +931,27 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"dependencies": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/http-signature": { "node_modules/http-signature": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@ -980,6 +1002,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
}, },
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/isstream": { "node_modules/isstream": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@ -1110,6 +1137,19 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/mini-create-react-context": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"tiny-warning": "^1.0.3"
},
"peerDependencies": {
"prop-types": "^15.0.0",
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -1182,6 +1222,14 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true "dev": true
}, },
"node_modules/path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dependencies": {
"isarray": "0.0.1"
}
},
"node_modules/performance-now": { "node_modules/performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -1217,6 +1265,16 @@
"url": "https://opencollective.com/postcss/" "url": "https://opencollective.com/postcss/"
} }
}, },
"node_modules/prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.8.1"
}
},
"node_modules/psl": { "node_modules/psl": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@ -1269,6 +1327,11 @@
"react": "17.0.2" "react": "17.0.2"
} }
}, },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.10.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
@ -1278,6 +1341,43 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-router": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
"integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
"dependencies": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
},
"peerDependencies": {
"react": ">=15"
}
},
"node_modules/react-router-dom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
"integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
"dependencies": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
},
"peerDependencies": {
"react": ">=15"
}
},
"node_modules/regenerator-runtime": { "node_modules/regenerator-runtime": {
"version": "0.13.7", "version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
@ -1335,6 +1435,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"node_modules/retry": { "node_modules/retry": {
"version": "0.13.1", "version": "0.13.1",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
@ -1453,6 +1558,16 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
},
"node_modules/tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"node_modules/to-fast-properties": { "node_modules/to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@ -1512,6 +1627,11 @@
"uuid": "bin/uuid" "uuid": "bin/uuid"
} }
}, },
"node_modules/value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"node_modules/verror": { "node_modules/verror": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@ -2213,6 +2333,27 @@
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
}, },
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"requires": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
}
},
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
}
},
"http-signature": { "http-signature": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@ -2242,6 +2383,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
}, },
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"isstream": { "isstream": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@ -2341,6 +2487,15 @@
"mime-db": "1.48.0" "mime-db": "1.48.0"
} }
}, },
"mini-create-react-context": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
"requires": {
"@babel/runtime": "^7.12.1",
"tiny-warning": "^1.0.3"
}
},
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -2395,6 +2550,14 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true "dev": true
}, },
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
},
"performance-now": { "performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -2417,6 +2580,16 @@
"source-map-js": "^0.6.2" "source-map-js": "^0.6.2"
} }
}, },
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.8.1"
}
},
"psl": { "psl": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@ -2454,12 +2627,48 @@
"scheduler": "^0.20.2" "scheduler": "^0.20.2"
} }
}, },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-refresh": { "react-refresh": {
"version": "0.10.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
"integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==", "integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==",
"dev": true "dev": true
}, },
"react-router": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
"integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
}
},
"react-router-dom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
"integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
}
},
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.7", "version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
@ -2509,6 +2718,11 @@
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
} }
}, },
"resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"retry": { "retry": {
"version": "0.13.1", "version": "0.13.1",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
@ -2595,6 +2809,16 @@
"has-flag": "^3.0.0" "has-flag": "^3.0.0"
} }
}, },
"tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
},
"tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"to-fast-properties": { "to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@ -2641,6 +2865,11 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}, },
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"verror": { "verror": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",

View file

@ -10,7 +10,8 @@
"events": "^3.3.0", "events": "^3.3.0",
"matrix-js-sdk": "^12.0.1", "matrix-js-sdk": "^12.0.1",
"react": "^17.0.0", "react": "^17.0.0",
"react-dom": "^17.0.0" "react-dom": "^17.0.0",
"react-router-dom": "^5.2.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-react-refresh": "^1.3.1", "@vitejs/plugin-react-refresh": "^1.3.1",

View file

@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { import React, { useCallback, useEffect, useRef, useState } from "react";
useCallback,
useEffect,
useRef,
useState,
createContext,
useContext,
} from "react";
import * as sdk from "matrix-js-sdk"; import * as sdk from "matrix-js-sdk";
import "./App.css"; import "./App.css";
import {
const ClientContext = createContext(); BrowserRouter as Router,
Switch,
Route,
useHistory,
useParams,
Link,
Redirect,
} from "react-router-dom";
export default function App() { export default function App() {
const { protocol, host } = window.location; const { protocol, host } = window.location;
@ -33,33 +33,54 @@ export default function App() {
const homeserverUrl = `${protocol}//${host}`; const homeserverUrl = `${protocol}//${host}`;
const { loading, authenticated, error, client, login, register } = const { loading, authenticated, error, client, login, register } =
useClient(homeserverUrl); useClient(homeserverUrl);
const [roomId, setRoomId] = useState();
return ( return (
<ClientContext.Provider value={client}> <Router>
<div className="App"> <div className="App">
{error && <p>{error.message}</p>} {error && <p>{error.message}</p>}
{loading ? ( {loading ? (
<p>Loading...</p> <p>Loading...</p>
) : ( ) : (
<> <Switch>
{!authenticated && <Register onRegister={register} />} <Route exact path="/">
{!authenticated && <Login onLogin={login} />} {authenticated ? (
{authenticated && !roomId && ( <JoinOrCreateRoom client={client} />
<JoinOrCreateRoom onSetRoomId={setRoomId} /> ) : (
)} <>
{authenticated && roomId && <Room roomId={roomId} />} <Register onRegister={register} />
</> <Login onLogin={login} />
</>
)}
</Route>
<Route path="/room/:roomId">
{!authenticated ? <Redirect to="/" /> : <Room client={client} />}
</Route>
</Switch>
)} )}
</div> </div>
</ClientContext.Provider> </Router>
); );
} }
function waitForSync(client) {
return new Promise((resolve, reject) => {
const onSync = (state) => {
if (state === "PREPARED") {
resolve();
client.removeListener("sync", onSync);
}
};
client.on("sync", onSync);
});
}
function useClient(homeserverUrl) { function useClient(homeserverUrl) {
const [authenticated, setAuthenticated] = useState(false); const [{ loading, authenticated, client, error }, setState] = useState({
const [client, setClient] = useState(); loading: true,
const [error, setError] = useState(); authenticated: false,
client: undefined,
error: undefined,
});
useEffect(() => { useEffect(() => {
async function restoreClient() { async function restoreClient() {
@ -78,14 +99,31 @@ function useClient(homeserverUrl) {
await client.startClient(); await client.startClient();
setAuthenticated(true); await waitForSync(client);
setClient(client);
setState({
client,
loading: false,
authenticated: true,
error: undefined,
});
} else {
setState({
client: undefined,
loading: false,
authenticated: false,
error: undefined,
});
} }
} catch (err) { } catch (err) {
console.error(err); console.error(err);
localStorage.removeItem("matrix-auth-store"); localStorage.removeItem("matrix-auth-store");
setAuthenticated(false); setState({
setError(err); client: undefined,
loading: false,
authenticated: false,
error: err,
});
} }
} }
@ -94,7 +132,11 @@ function useClient(homeserverUrl) {
const login = useCallback(async (username, password) => { const login = useCallback(async (username, password) => {
try { try {
setError(undefined); setState((prevState) => ({
...prevState,
authenticated: false,
error: undefined,
}));
const registrationClient = sdk.createClient(homeserverUrl); const registrationClient = sdk.createClient(homeserverUrl);
@ -114,53 +156,70 @@ function useClient(homeserverUrl) {
"matrix-auth-store", "matrix-auth-store",
JSON.stringify({ user_id, device_id, access_token }) JSON.stringify({ user_id, device_id, access_token })
); );
setAuthenticated(true); setState({
setClient(client); client,
loading: false,
authenticated: true,
error: undefined,
});
} catch (err) { } catch (err) {
console.error(err); console.error(err);
localStorage.removeItem("matrix-auth-store"); localStorage.removeItem("matrix-auth-store");
setAuthenticated(false); setState({
setError(err); client: undefined,
loading: false,
authenticated: false,
error: err,
});
} }
}, []); }, []);
const register = useCallback( const register = useCallback(async (username, password) => {
async (username, password) => { try {
try { setState((prevState) => ({
setError(undefined); ...prevState,
authenticated: false,
error: undefined,
}));
const registrationClient = sdk.createClient(homeserverUrl); const registrationClient = sdk.createClient(homeserverUrl);
const { user_id, device_id, access_token } = const { user_id, device_id, access_token } =
await registrationClient.register(username, password, null, { await registrationClient.register(username, password, null, {
type: "m.login.dummy", type: "m.login.dummy",
});
const client = sdk.createClient({
baseUrl: homeserverUrl,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
}); });
await client.startClient(); const client = sdk.createClient({
baseUrl: homeserverUrl,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
});
localStorage.setItem( await client.startClient();
"matrix-auth-store",
JSON.stringify({ user_id, device_id, access_token })
);
setAuthenticated(true);
setClient(client);
} catch (err) {
localStorage.removeItem("matrix-auth-store");
setAuthenticated(false);
setError(err);
}
},
[client, homeserverUrl]
);
return { authenticated, client, error, login, register }; localStorage.setItem(
"matrix-auth-store",
JSON.stringify({ user_id, device_id, access_token })
);
setState({
client,
loading: false,
authenticated: true,
error: undefined,
});
} catch (err) {
localStorage.removeItem("matrix-auth-store");
setState({
client: undefined,
loading: false,
authenticated: false,
error: err,
});
}
}, []);
return { loading, authenticated, client, error, login, register };
} }
function Register({ onRegister }) { function Register({ onRegister }) {
@ -199,12 +258,27 @@ function Login({ onLogin }) {
); );
} }
function JoinOrCreateRoom({ onSetRoomId }) { function JoinOrCreateRoom({ client }) {
const client = useContext(ClientContext); const history = useHistory();
const roomNameRef = useRef(); const roomNameRef = useRef();
const roomIdRef = useRef(); const roomIdRef = useRef();
const [createRoomError, setCreateRoomError] = useState(); const [createRoomError, setCreateRoomError] = useState();
const [joinRoomError, setJoinRoomError] = useState(); const [joinRoomError, setJoinRoomError] = useState();
const [rooms, setRooms] = useState([]);
useEffect(() => {
function updateRooms() {
setRooms(client.getRooms());
}
updateRooms();
client.on("Room", updateRooms);
return () => {
client.removeListener("Room", updateRooms);
};
}, []);
const onCreateRoom = useCallback( const onCreateRoom = useCallback(
(e) => { (e) => {
@ -214,10 +288,11 @@ function JoinOrCreateRoom({ onSetRoomId }) {
client client
.createRoom({ .createRoom({
visibility: "private", visibility: "private",
preset: "public_chat",
name: roomNameRef.current.value, name: roomNameRef.current.value,
}) })
.then(({ room_id }) => { .then(({ room_id }) => {
onSetRoomId(room_id); history.push(`/rooms/${room_id}`);
}) })
.catch(setCreateRoomError); .catch(setCreateRoomError);
}, },
@ -232,7 +307,7 @@ function JoinOrCreateRoom({ onSetRoomId }) {
client client
.joinRoom(roomIdRef.current.value) .joinRoom(roomIdRef.current.value)
.then(({ roomId }) => { .then(({ roomId }) => {
onSetRoomId(roomId); history.push(`/rooms/${roomId}`);
}) })
.catch(setJoinRoomError); .catch(setJoinRoomError);
}, },
@ -242,7 +317,7 @@ function JoinOrCreateRoom({ onSetRoomId }) {
return ( return (
<div> <div>
<form onSubmit={onCreateRoom}> <form onSubmit={onCreateRoom}>
<p>Create New Room</p> <h3>Create New Room</h3>
<input <input
id="roomName" id="roomName"
name="roomName" name="roomName"
@ -256,7 +331,7 @@ function JoinOrCreateRoom({ onSetRoomId }) {
<button type="submit">Create Room</button> <button type="submit">Create Room</button>
</form> </form>
<form onSubmit={onJoinRoom}> <form onSubmit={onJoinRoom}>
<p>Join Existing Room</p> <h3>Join Existing Room</h3>
<input <input
id="roomId" id="roomId"
name="roomId" name="roomId"
@ -269,23 +344,34 @@ function JoinOrCreateRoom({ onSetRoomId }) {
{joinRoomError && <p>{joinRoomError.message}</p>} {joinRoomError && <p>{joinRoomError.message}</p>}
<button type="submit">Join Room</button> <button type="submit">Join Room</button>
</form> </form>
<h3>Rooms:</h3>
<ul>
{rooms.map((room) => (
<li key={room.roomId}>
<Link to={`/room/${room.roomId}`}>{room.name}</Link>
</li>
))}
</ul>
</div> </div>
); );
} }
function useVideoRoom(roomId, timeout = 5000) { function useVideoRoom(client, roomId, timeout = 5000) {
const client = useContext(ClientContext); const [{ loading, room, error }, setState] = useState({
loading: true,
const [room, setRoom] = useState(); room: undefined,
const [error, setError] = useState(); error: undefined,
});
useEffect(() => { useEffect(() => {
setRoom(undefined); setState({ loading: true, room: undefined, error: undefined });
client.joinRoom(roomId).catch(console.error);
let initialRoom = client.getRoom(roomId); let initialRoom = client.getRoom(roomId);
if (initialRoom) { if (initialRoom) {
setRoom(initialRoom); setState({ loading: false, room: initialRoom, error: undefined });
return; return;
} }
@ -295,14 +381,18 @@ function useVideoRoom(roomId, timeout = 5000) {
if (room && room.roomId === roomId) { if (room && room.roomId === roomId) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
client.removeListener("Room", roomCallback); client.removeListener("Room", roomCallback);
setRoom(room); setState({ loading: false, room, error: undefined });
} }
} }
client.on("Room", roomCallback); client.on("Room", roomCallback);
timeoutId = setTimeout(() => { timeoutId = setTimeout(() => {
setError(new Error("Room could not be found.")); setState({
loading: false,
room: undefined,
error: new Error("Room could not be found."),
});
client.removeListener("Room", roomCallback); client.removeListener("Room", roomCallback);
}, timeout); }, timeout);
@ -312,23 +402,33 @@ function useVideoRoom(roomId, timeout = 5000) {
}; };
}, [roomId]); }, [roomId]);
return { room, error }; const joinCall = useCallback(() => {
console.log("join call");
});
return { loading, room, error, joinCall };
} }
function Room({ roomId }) { function Room({ client }) {
const { room, error } = useVideoRoom(roomId); const { roomId } = useParams();
const { loading, room, error, joinCall } = useVideoRoom(client, roomId);
useEffect(() => {
if (room) {
console.log(room);
}
}, [room]);
return ( return (
<div> <div>
<p>{roomId}</p> <p>{roomId}</p>
{!error && !room && <p>Loading room...</p>} {loading && <p>Loading room...</p>}
{error && <p>{error.message}</p>} {error && <p>{error.message}</p>}
{!loading && room && (
<>
<h3>Members:</h3>
<ul>
{room.getMembers().map((member) => (
<li key={member.userId}>{member.name}</li>
))}
</ul>
<button onClick={joinCall}>Join Call</button>
</>
)}
</div> </div>
); );
} }