diff --git a/README.md b/README.md index c80c790..997af57 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ Full mesh group calls powered by [Matrix](https://matrix.org), implementing [MatrixRTC](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). +![A demo of Element Call with six people](demo.jpg) + To try it out, visit our hosted version at [call.element.io](https://call.element.io). You can also find the latest development version continuously deployed to [element-call.netlify.app](https://element-call.netlify.app). ## Host it yourself diff --git a/demo.jpg b/demo.jpg new file mode 100644 index 0000000..afce1ae Binary files /dev/null and b/demo.jpg differ diff --git a/package.json b/package.json index 58001db..c3a511f 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "i18next-browser-languagedetector": "^6.1.8", "i18next-http-backend": "^1.4.4", "lodash": "^4.17.21", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#7b10fa367df357b51c2e78e220d39e5e7967f9e3", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#64197bf4db6486d77708125d7fb2e8d7fe001f14", "matrix-widget-api": "^1.0.0", "mermaid": "^8.13.8", "normalize.css": "^8.0.1", diff --git a/public/locales/ja/app.json b/public/locales/ja/app.json index 0967ef4..fd876f1 100644 --- a/public/locales/ja/app.json +++ b/public/locales/ja/app.json @@ -1 +1,95 @@ -{} +{ + "{{name}} (Connecting...)": "{{name}}(接続しています…)", + "{{count}} people connected|other": "{{count}}人が接続済", + "{{count}} people connected|one": "{{count}}人が接続済", + "{{name}} (Waiting for video...)": "{{name}}(ビデオを待機しています…)", + "<0>Already have an account?<1><0>Log in Or <2>Access as a guest": "<0>既にアカウントをお持ちですか?<1><0>ログインまたは<2>ゲストとしてアクセス", + "{{roomName}} - Walkie-talkie call": "{{roomName}} - トランシーバー通話", + "<0>Create an account Or <2>Access as a guest": "<0>アカウントを作成または<2>ゲストとしてアクセス", + "<0>Join call now<1>Or<2>Copy call link and join later": "<0>今すぐ通話に参加<1>または<2>通話リンクをコピーし、後で参加", + "Accept camera/microphone permissions to join the call.": "通話に参加するには、カメラ・マイクの許可が必要です。", + "<0>Oops, something's gone wrong.": "<0>何かがうまく行きませんでした。", + "Camera/microphone permissions needed to join the call.": "通話に参加する場合、カメラ・マイクの許可が必要です。", + "Allow analytics": "アナリティクスを許可", + "Camera": "カメラ", + "Call link copied": "通話リンクをコピーしました", + "By clicking \"Join call now\", you agree to our <2>Terms and conditions": "「今すぐ通話に参加」をクリックすると、<2>利用規約に同意したとみなされます", + "By clicking \"Go\", you agree to our <2>Terms and conditions": "「続行」をクリックすると、 <2>利用規約に同意したとみなされます", + "Avatar": "アバター", + "Accept microphone permissions to join the call.": "通話に参加するには、マイクの許可が必要です。", + "Audio": "音声", + "Advanced": "高度", + "Connection lost": "接続が切断されました", + "Confirm password": "パスワードを確認", + "Close": "閉じる", + "Change layout": "レイアウトを変更", + "Copied!": "コピーしました!", + "Copy and share this call link": "通話リンクをコピーし共有", + "Copy": "コピー", + "Description (optional)": "概要(任意)", + "Debug log": "デバッグログ", + "Create account": "アカウントを作成", + "Having trouble? Help us fix it.": "問題が起きましたか?修正にご協力ください。", + "Go": "続行", + "Fetching group call timed out.": "グループ通話の取得がタイムアウトしました。", + "Element Call Home": "Element Call ホーム", + "Download debug logs": "デバッグログをダウンロード", + "Display name": "表示名", + "Developer": "開発者", + "Details": "詳細", + "Full screen": "全画面表示", + "Exit full screen": "全画面表示を終了", + "Include debug logs": "デバッグログを含める", + "Home": "ホーム", + "Incompatible versions!": "互換性のないバージョンです!", + "Incompatible versions": "互換性のないバージョン", + "Join existing call?": "既存の通話に参加しますか?", + "Join call now": "今すぐ通話に参加", + "Join call": "通話に参加", + "Invite": "招待", + "Invite people": "連絡先を招待", + "Not registered yet? <2>Create an account": "アカウントがありませんか? <2>アカウントを作成", + "Mute microphone": "マイクをミュート", + "Microphone permissions needed to join the call.": "通話の参加にはマイクの許可が必要です。", + "Microphone": "マイク", + "Login": "ログイン", + "Logging in…": "ログインしています…", + "Loading…": "読み込んでいます…", + "Loading room…": "ルームを読み込んでいます…", + "Leave": "退出", + "Version: {{version}}": "バージョン:{{version}}", + "Username": "ユーザー名", + "User menu": "ユーザーメニュー", + "User ID": "ユーザーID", + "Unmute microphone": "マイクのミュートを解除", + "Turn on camera": "カメラをつける", + "Turn off camera": "カメラを切る", + "Submitting feedback…": "フィードバックを送信しています…", + "Submit feedback": "フィードバックを送信", + "Stop sharing screen": "画面共有を停止", + "Spotlight": "スポットライト", + "Send debug logs": "デバッグログを送信", + "Sign out": "サインアウト", + "Sign in": "サインイン", + "Share screen": "画面共有", + "Settings": "設定", + "Sending…": "送信しています…", + "Sending debug logs…": "デバッグログを送信しています…", + "Saving…": "保存しています…", + "Save": "保存", + "Return to home screen": "ホーム画面に戻る", + "Registering…": "登録しています…", + "Register": "登録", + "Profile": "プロフィール", + "Press and hold spacebar to talk": "スペースを長押しで会話", + "Passwords must match": "パスワードが一致する必要があります", + "Password": "パスワード", + "Speaker": "スピーカー", + "Video call name": "ビデオ通話の名称", + "Video call": "ビデオ通話", + "Video": "ビデオ", + "Waiting for other participants…": "他の参加者を待機しています…", + "Waiting for network": "ネットワークを待機しています", + "Walkie-talkie call name": "トランシーバー通話の名前", + "Walkie-talkie call": "トランシーバー通話" +} diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index dc55702..0a2ecfe 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -211,6 +211,12 @@ export function fullAliasFromRoomName( return `#${roomAliasLocalpartFromRoomName(roomName)}:${client.getDomain()}`; } +/** + * XXX: What is this trying to do? It looks like it's getting the localpart from + * a room alias, but why is it splitting on hyphens and then putting spaces in?? + * @param roomId + * @returns + */ export function roomNameFromRoomId(roomId: string): string { return roomId .match(/([^:]+):.*$/)[1] diff --git a/src/room/RoomPage.tsx b/src/room/RoomPage.tsx index e8b3fa9..f4e460d 100644 --- a/src/room/RoomPage.tsx +++ b/src/room/RoomPage.tsx @@ -50,9 +50,9 @@ export const RoomPage: FC = () => { const [isRegistering, setIsRegistering] = useState(false); useEffect(() => { - // If we're not already authed and we've been given a display name as + // If we've finished loading, are not already authed and we've been given a display name as // a URL param, automatically register a passwordless user - if (!isAuthenticated && displayName) { + if (!loading && !isAuthenticated && displayName) { setIsRegistering(true); registerPasswordlessUser(displayName).finally(() => { setIsRegistering(false); @@ -63,6 +63,7 @@ export const RoomPage: FC = () => { displayName, setIsRegistering, registerPasswordlessUser, + loading, ]); const groupCallView = useCallback( diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts index 363739a..ae4de80 100644 --- a/src/room/useLoadGroupCall.ts +++ b/src/room/useLoadGroupCall.ts @@ -52,12 +52,22 @@ export const useLoadGroupCall = ( const fetchOrCreateRoom = async (): Promise => { try { - const room = await client.joinRoom(roomIdOrAlias, { viaServers }); + // We lowercase the localpart when we create the room, so we must lowercase + // it here too (we just do the whole alias). We can't do the same to room IDs + // though. + const sanitisedIdOrAlias = + roomIdOrAlias[0] === "#" + ? roomIdOrAlias.toLowerCase() + : roomIdOrAlias; + + const room = await client.joinRoom(sanitisedIdOrAlias, { + viaServers, + }); logger.info( - `Joined ${roomIdOrAlias}, waiting room to be ready for group calls` + `Joined ${sanitisedIdOrAlias}, waiting room to be ready for group calls` ); await client.waitUntilRoomReadyForGroupCalls(room.roomId); - logger.info(`${roomIdOrAlias}, is ready for group calls`); + logger.info(`${sanitisedIdOrAlias}, is ready for group calls`); return room; } catch (error) { if ( diff --git a/src/room/usePTT.ts b/src/room/usePTT.ts index 71d7d4e..a171f0b 100644 --- a/src/room/usePTT.ts +++ b/src/room/usePTT.ts @@ -113,12 +113,14 @@ export const usePTT = ( }, setState, ] = useState(() => { + // slightly concerningly, this can end up null as we seem to sometimes get + // here before the room state contains our own member event const roomMember = groupCall.room.getMember(client.getUserId()); const activeSpeakerFeed = getActiveSpeakerFeed(userMediaFeeds, groupCall); return { - isAdmin: roomMember.powerLevel >= 100, + isAdmin: roomMember ? roomMember.powerLevel >= 100 : false, talkOverEnabled: false, pttButtonHeld: false, activeSpeakerUserId: activeSpeakerFeed ? activeSpeakerFeed.userId : null, diff --git a/yarn.lock b/yarn.lock index cd7b188..f571952 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10362,9 +10362,9 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#7b10fa367df357b51c2e78e220d39e5e7967f9e3": - version "23.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/7b10fa367df357b51c2e78e220d39e5e7967f9e3" +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#64197bf4db6486d77708125d7fb2e8d7fe001f14": + version "23.1.1" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/64197bf4db6486d77708125d7fb2e8d7fe001f14" dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.2"