From 385cf96f5b338ef95d0425542a84516c13bd97f1 Mon Sep 17 00:00:00 2001 From: Vladyslav Sitalo Date: Mon, 2 Jan 2023 15:31:06 -0800 Subject: [PATCH] Join and configure arbitrary room. Iteration 1 (works but has issues) #11 --- src/background/client.ts | 46 ++++++++++++++++++++++---- src/common/messages.ts | 7 ++++ src/common/model/matrix.ts | 1 + src/content/App.tsx | 16 +++++---- src/content/ToolsMenu/JoinRoomView.tsx | 23 +++++++++++++ src/content/ToolsMenu/ToolsMenu.tsx | 27 ++++++++------- src/content/slices/toolsMenu.ts | 5 +++ 7 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 src/content/ToolsMenu/JoinRoomView.tsx diff --git a/src/background/client.ts b/src/background/client.ts index 8b3450a..9a55605 100644 --- a/src/background/client.ts +++ b/src/background/client.ts @@ -1,7 +1,19 @@ -import {Room, User, Highlight, Message, HIGHLIGHT_PAGE_KEY, HighlightContent, HIGHLIGHT_EVENT_TYPE, HIGHLIGHT_EDIT_REL_TYPE, HIGHLIGHT_NEW_HIGHLIGHT_KEY, HIGHLIGHT_EDIT_EVENT_TYPE, HIGHLIGHT_HIDDEN_KEY} from "../common/model"; -import {RoomMembership, ToContentMessage, FromContentMessage} from "../common/messages"; -import * as sdk from "matrix-js-sdk"; -import {BackgroundPlatform} from "./backgroundPlatform"; +import { + Highlight, + HIGHLIGHT_EDIT_EVENT_TYPE, + HIGHLIGHT_EDIT_REL_TYPE, + HIGHLIGHT_EVENT_TYPE, + HIGHLIGHT_NEW_HIGHLIGHT_KEY, + HIGHLIGHT_PAGE_KEY, + HIGHLIGHT_STATE_EVENT_TYPE, + HighlightContent, + Message, + Room, + User, +} from '../common/model' +import {FromContentMessage, RoomMembership, ToContentMessage} from '../common/messages' +import * as sdk from 'matrix-js-sdk' +import {BackgroundPlatform} from './backgroundPlatform' function extractTxnId(event: sdk.MatrixEvent): number | undefined { let localId = undefined; @@ -45,8 +57,11 @@ export class Client { private _checkRoom(room: sdk.Room): string | undefined { const state = room.getLiveTimeline().getState(sdk.EventTimeline.FORWARDS); - const event = state.getStateEvents("m.room.create", ""); - return event.getContent()[HIGHLIGHT_PAGE_KEY]; + + const createEvent = state.getStateEvents("m.room.create", ""); + const configEvent = state.getStateEvents(HIGHLIGHT_STATE_EVENT_TYPE, "") + + return configEvent?.getContent()?.url || createEvent.getContent()[HIGHLIGHT_PAGE_KEY]; } private _processRoom(room: sdk.Room): ToContentMessage[] { @@ -181,6 +196,13 @@ export class Client { this._emitEvent(event, false); }); this._sdkClient.on("Room.timeline", (event: sdk.MatrixEvent, room: sdk.Room, toStartOfTimeline: boolean, removed: boolean, data: {liveEvent: boolean}) => { + if (event.getType() === HIGHLIGHT_STATE_EVENT_TYPE) { + this._emitRoom(room); + this._broadcastRoom({ + type: "room-configured", + roomId: room.roomId, + }, room.roomId) + } if (!data.liveEvent) this._emitEvent(event, toStartOfTimeline); }); this._sdkClient.on("RoomMember.membership", (event: sdk.MatrixEvent, member: sdk.RoomMember, oldMembership: RoomMembership | null) => { @@ -251,6 +273,8 @@ export class Client { async handleMessage(message: FromContentMessage): Promise { if (message.type === "join-room") { await this._sdkClient.joinRoom(message.roomId); + } else if (message.type === "join-configure-room") { + await this.joinAndConfigureRoom(message.roomId, message.url) } else if (message.type === "leave-room") { await this._sdkClient.leave(message.roomId); } else if (message.type === "invite-user") { @@ -265,4 +289,14 @@ export class Client { this._loadRoom(message.roomId); } } + private async joinAndConfigureRoom(roomId: string, url: string) { + await this._sdkClient.joinRoom(roomId) + // TODO: this doesn't really work as intended rn. + // The default synapse configuration is to required power level 50 (moderator) to send custom state events + // So what actually needs to happen is that you join the room first, get moderator status and then + // use "join" functionality in the extension to configure the room + // _ + // It works ok, if someone else has already configured the room and you're just joining it though. + await this._sdkClient.sendStateEvent(roomId, HIGHLIGHT_STATE_EVENT_TYPE, {url}, ""); + } } diff --git a/src/common/messages.ts b/src/common/messages.ts index 731db97..b733207 100644 --- a/src/common/messages.ts +++ b/src/common/messages.ts @@ -15,6 +15,9 @@ export type ToContentMessage = { type: "room-membership", roomId: string, membership: RoomMembership, +} | { + type: "room-configured", + roomId: string, } | { type: "room-name", roomId: string, @@ -69,6 +72,10 @@ export type FromContentMessage = { } | { type: "join-room", roomId: string, +} | { + type: "join-configure-room", + roomId: string, + url: string, } | { type: "leave-room", roomId: string, diff --git a/src/common/model/matrix.ts b/src/common/model/matrix.ts index 2ada894..cd82ec7 100644 --- a/src/common/model/matrix.ts +++ b/src/common/model/matrix.ts @@ -1,6 +1,7 @@ export const COLORS = ["yellow", "pink", "green", "blue", "orange" ] as const; export const HIGHLIGHT_EVENT_TYPE = "com.danilafe.highlight"; +export const HIGHLIGHT_STATE_EVENT_TYPE = "com.danilafe.highlight.state"; export const HIGHLIGHT_EDIT_EVENT_TYPE = "com.danilafe.highlight_edit"; export const HIGHLIGHT_EDIT_REL_TYPE = "com.danilafe.highlight_edit"; export const HIGHLIGHT_PAGE_KEY = "com.danilafe.highlight_page"; diff --git a/src/content/App.tsx b/src/content/App.tsx index f8f3ed2..fab48ed 100644 --- a/src/content/App.tsx +++ b/src/content/App.tsx @@ -81,13 +81,17 @@ const App = (props: { platform: ContentPlatform }) => { const createRoom = async (roomName: string) => { const url = window.location.href; highlightDispatch({ type: "create-room" }); - props.platform.sendMessage({ type: "create-room", name: roomName, url }); + props.platform.sendMessage({ type: "create-room", name: roomName, url }); } const joinRoom = async (roomId: string) => { - props.platform.sendMessage({ type: "join-room", roomId }); + // todo (PR): this effectively replaces normal "join room" arguably it's ok to just do this every + // time. Leaving as a discussion point for PR. + // In case we agree - I should remove the original join-room + const url = window.location.href; + props.platform.sendMessage({ type: "join-configure-room", roomId, url }); } - + const leaveRoom = async (roomId: string) => { props.platform.sendMessage({ type: "leave-room", roomId }); } @@ -144,7 +148,7 @@ const App = (props: { platform: ContentPlatform }) => { const sendReply = async (id: string | number, plainBody: string, formattedBody: string) => { if (!auth.userId || !highlight.currentRoomId) return; if (typeof(id) !== "string") return; - + const txnId = await props.platform.freshTxnId(); const localMessage = new Message({ id: txnId, @@ -225,7 +229,7 @@ const App = (props: { platform: ContentPlatform }) => { }; if (!toolsMenu.showMenu && !toolsMenu.showLogin) { - const toolbarComp = + const toolbarComp = ; const tooltipComp = tooltip.visible ? { } else { return wrapInProviders( - : diff --git a/src/content/ToolsMenu/JoinRoomView.tsx b/src/content/ToolsMenu/JoinRoomView.tsx new file mode 100644 index 0000000..15c4c43 --- /dev/null +++ b/src/content/ToolsMenu/JoinRoomView.tsx @@ -0,0 +1,23 @@ +import {useRef} from 'react' +import {NavBar} from './Navbar' + +export const JoinRoomView = (props: { onJoinRoom(id: string): void }) => { + const inputRef = useRef(null) + return ( + <> + +
{ + e.preventDefault() + inputRef?.current?.value && props.onJoinRoom(inputRef?.current?.value) + }} id="CreateRoom"> + + + +
+ + ) +} diff --git a/src/content/ToolsMenu/ToolsMenu.tsx b/src/content/ToolsMenu/ToolsMenu.tsx index 0250a00..05b31cf 100644 --- a/src/content/ToolsMenu/ToolsMenu.tsx +++ b/src/content/ToolsMenu/ToolsMenu.tsx @@ -1,14 +1,15 @@ -import {QuoteList} from "./QuoteList"; -import {UserList} from "./UserList"; -import {InviteList} from "./InviteList"; -import {RoomCreator} from "./RoomCreator"; -import {Plus, FolderPlus, Bell, Icon, Settings, AlignLeft, Users, MessageSquare} from "react-feather"; -import Select from "react-select"; -import "./ToolsMenu.scss"; -import {useContext} from "react"; -import {AppContext} from "../AppContext"; -import {ToolsMenuContext} from "./ToolsMenuContext"; -import {NavBar, RoomNavBar} from "./Navbar"; +import {QuoteList} from './QuoteList' +import {UserList} from './UserList' +import {InviteList} from './InviteList' +import {RoomCreator} from './RoomCreator' +import {AlignLeft, Bell, FolderPlus, Icon, MessageSquare, Plus, Settings, Users} from 'react-feather' +import Select from 'react-select' +import './ToolsMenu.scss' +import {useContext} from 'react' +import {AppContext} from '../AppContext' +import {ToolsMenuContext} from './ToolsMenuContext' +import {NavBar, RoomNavBar} from './Navbar' +import {JoinRoomView} from './JoinRoomView' export type ToolsMenuTab = "create" | "join" | "invites" | "settings" | "users" | "quotes" | "comments" ; @@ -123,6 +124,8 @@ const ToolView = (props: ToolsMenuProps) => { if (tab === "create") { return + } else if (tab === "join") { + return } else if (tab === "invites") { return ; } else if (page.joinedRooms.length === 0) { @@ -130,7 +133,7 @@ const ToolView = (props: ToolsMenuProps) => { } else if (currentRoom && tab === "quotes") { return ; } else if (currentRoom && tab === "users") { - return ; + return ; } return ; } diff --git a/src/content/slices/toolsMenu.ts b/src/content/slices/toolsMenu.ts index f1f7c39..1e081db 100644 --- a/src/content/slices/toolsMenu.ts +++ b/src/content/slices/toolsMenu.ts @@ -30,6 +30,11 @@ export const toolsMenuReducer = (state: ToolsMenuState, event: ToolsMenuEvent) = if (state.tab === "create") { newState.tab = null; } + } else if ( + (event.type === 'room-configured' || + (event.type === 'room-membership' && event.membership === 'join')) + && state.tab === 'join') { + newState.tab = null } return newState; }