Add option to create room/space

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2022-02-26 21:00:52 +05:30
parent 2eee3736df
commit 79afc7649d
10 changed files with 365 additions and 208 deletions

View file

@ -65,9 +65,11 @@ export function openPublicRooms(searchTerm) {
});
}
export function openCreateRoom() {
export function openCreateRoom(isSpace = false, parentId = null) {
appDispatcher.dispatch({
type: cons.actions.navigation.OPEN_CREATE_ROOM,
isSpace,
parentId,
});
}

View file

@ -1,6 +1,7 @@
import initMatrix from '../initMatrix';
import appDispatcher from '../dispatcher';
import cons from '../state/cons';
import { getIdServer } from '../../util/matrixUtil';
/**
* https://github.com/matrix-org/matrix-react-sdk/blob/1e6c6e9d800890c732d60429449bc280de01a647/src/Rooms.js#L73
@ -125,36 +126,37 @@ function leave(roomId) {
}).catch();
}
/**
* Create a room.
* @param {Object} opts
* @param {string} [opts.name]
* @param {string} [opts.topic]
* @param {boolean} [opts.isPublic=false] Sets room visibility to public
* @param {string} [opts.roomAlias] Sets the room address
* @param {boolean} [opts.isEncrypted=false] Makes room encrypted
* @param {boolean} [opts.isDirect=false] Makes room as direct message
* @param {string[]} [opts.invite=[]] An array of userId's to invite
* @param{number} [opts.powerLevel=100] My power level
*/
async function create(opts) {
async function create(options, isDM = false) {
const mx = initMatrix.matrixClient;
const customPowerLevels = [101];
const options = {
name: opts.name,
topic: opts.topic,
visibility: opts.isPublic === true ? 'public' : 'private',
room_alias_name: opts.roomAlias,
is_direct: opts.isDirect === true,
invite: opts.invite || [],
initial_state: [],
preset: opts.isDirect === true ? 'trusted_private_chat' : undefined,
power_level_content_override: customPowerLevels.indexOf(opts.powerLevel) === -1 ? undefined : {
users: { [initMatrix.matrixClient.getUserId()]: opts.powerLevel },
},
};
try {
const result = await mx.createRoom(options);
if (isDM && typeof options.invite?.[0] === 'string') {
await addRoomToMDirect(result.room_id, options.invite[0]);
}
appDispatcher.dispatch({
type: cons.actions.room.CREATE,
roomId: result.room_id,
isDM,
});
return result;
} catch (e) {
const errcodes = ['M_UNKNOWN', 'M_BAD_JSON', 'M_ROOM_IN_USE', 'M_INVALID_ROOM_STATE', 'M_UNSUPPORTED_ROOM_VERSION'];
if (errcodes.includes(e.errcode)) {
throw new Error(e);
}
throw new Error('Something went wrong!');
}
}
if (opts.isPublic !== true && opts.isEncrypted === true) {
async function createDM(userId, isEncrypted = true) {
const options = {
is_direct: true,
invite: [userId],
visibility: 'private',
preset: 'trusted_private_chat',
initial_state: [],
};
if (isEncrypted) {
options.initial_state.push({
type: 'm.room.encryption',
state_key: '',
@ -164,28 +166,87 @@ async function create(opts) {
});
}
try {
const result = await mx.createRoom(options);
if (opts.isDirect === true && typeof opts.invite[0] !== 'undefined') {
await addRoomToMDirect(result.room_id, opts.invite[0]);
}
appDispatcher.dispatch({
type: cons.actions.room.CREATE,
roomId: result.room_id,
isDM: opts.isDirect === true,
});
return result;
} catch (e) {
const errcodes = ['M_UNKNOWN', 'M_BAD_JSON', 'M_ROOM_IN_USE', 'M_INVALID_ROOM_STATE', 'M_UNSUPPORTED_ROOM_VERSION'];
if (errcodes.find((errcode) => errcode === e.errcode)) {
appDispatcher.dispatch({
type: cons.actions.room.error.CREATE,
error: e,
});
throw new Error(e);
}
throw new Error('Something went wrong!');
const result = await create(options, true);
return result;
}
async function createRoom(opts) {
// joinRule: 'public' | 'invite' | 'restricted'
const { name, topic, joinRule } = opts;
const alias = opts.alias ?? undefined;
const parentId = opts.parentId ?? undefined;
const isSpace = opts.isSpace ?? false;
const isEncrypted = opts.isEncrypted ?? false;
const powerLevel = opts.powerLevel ?? undefined;
const blockFederation = opts.blockFederation ?? false;
const mx = initMatrix.matrixClient;
const visibility = joinRule === 'public' ? 'public' : 'private';
const options = {
creation_content: undefined,
name,
topic,
visibility,
room_alias_name: alias,
initial_state: [],
power_level_content_override: undefined,
};
if (isSpace) {
options.creation_content = { type: 'm.space' };
}
if (blockFederation) {
options.creation_content = { 'm.federate': false };
}
if (isEncrypted) {
options.initial_state.push({
type: 'm.room.encryption',
state_key: '',
content: {
algorithm: 'm.megolm.v1.aes-sha2',
},
});
}
if (powerLevel) {
options.power_level_content_override = {
users: {
[mx.getUserId()]: powerLevel,
},
};
}
if (parentId) {
options.initial_state.push({
type: 'm.space.parent',
state_key: parentId,
content: {
canonical: true,
via: [getIdServer(mx.getUserId())],
},
});
}
if (parentId && joinRule === 'restricted') {
options.initial_state.push({
type: 'm.room.join_rules',
content: {
join_rule: 'restricted',
allow: [{
type: 'm.room_membership',
room_id: parentId,
}],
},
});
}
const result = await create(options);
if (parentId) {
await mx.sendStateEvent(parentId, 'm.space.child', {
auto_join: false,
suggested: false,
via: [getIdServer(mx.getUserId())],
}, result.room_id);
}
return result;
}
async function invite(roomId, userId) {
@ -242,7 +303,8 @@ function deleteSpaceShortcut(roomId) {
export {
join, leave,
create, invite, kick, ban, unban,
createDM, createRoom,
invite, kick, ban, unban,
setPowerLevel,
createSpaceShortcut, deleteSpaceShortcut,
};

View file

@ -53,9 +53,6 @@ const cons = {
CREATE: 'CREATE',
CREATE_SPACE_SHORTCUT: 'CREATE_SPACE_SHORTCUT',
DELETE_SPACE_SHORTCUT: 'DELETE_SPACE_SHORTCUT',
error: {
CREATE: 'ERROR_CREATE',
},
},
settings: {
TOGGLE_SYSTEM_THEME: 'TOGGLE_SYSTEM_THEME',

View file

@ -113,7 +113,11 @@ class Navigation extends EventEmitter {
this.emit(cons.events.navigation.PUBLIC_ROOMS_OPENED, action.searchTerm);
},
[cons.actions.navigation.OPEN_CREATE_ROOM]: () => {
this.emit(cons.events.navigation.CREATE_ROOM_OPENED);
this.emit(
cons.events.navigation.CREATE_ROOM_OPENED,
action.isSpace,
action.parentId,
);
},
[cons.actions.navigation.OPEN_INVITE_USER]: () => {
this.emit(cons.events.navigation.INVITE_USER_OPENED, action.roomId, action.searchTerm);