Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdb94d7145 | ||
|
|
0ebda9d224 | ||
|
|
808fc8dc0d | ||
|
|
aefed73f5a | ||
|
|
ea47750ea4 | ||
|
|
0f02bfd2c3 | ||
|
|
8e5a5baf52 | ||
|
|
3deb8eb488 | ||
|
|
1dd7f0371d | ||
|
|
7d032bb684 | ||
|
|
ecc4a40eea | ||
|
|
83c6914a50 | ||
|
|
0f06d88e18 | ||
|
|
ea5f7b65f3 | ||
|
|
9ce95da8f4 | ||
|
|
abd1fd3efb | ||
|
|
90ab8dac27 | ||
|
|
c96d556094 | ||
|
|
26f68a890e | ||
|
|
cd5b7b17f6 | ||
|
|
14cfa69060 | ||
|
|
d6d1b0eeef |
@@ -14,6 +14,11 @@ Cinny is a [Matrix](https://matrix.org) client focusing primarily on simple, ele
|
|||||||
|
|
||||||
## Building and Running
|
## Building and Running
|
||||||
|
|
||||||
|
### Running pre-compiled
|
||||||
|
|
||||||
|
A tarball of pre-compiled version of the app is provided with each [release](https://github.com/ajbura/cinny/releases).
|
||||||
|
You can serve the application with a webserver of your choosing by simply copying `dist/` directory to the webroot.
|
||||||
|
|
||||||
### Building from source
|
### Building from source
|
||||||
|
|
||||||
Execute the following commands to compile the app from its source code:
|
Execute the following commands to compile the app from its source code:
|
||||||
@@ -44,10 +49,12 @@ docker run -p 8080:80 cinny:latest
|
|||||||
This will forward your `localhost` port 8080 to the container's port 80. You can visit the app in your browser by
|
This will forward your `localhost` port 8080 to the container's port 80. You can visit the app in your browser by
|
||||||
navigating to `http://localhost:8080`.
|
navigating to `http://localhost:8080`.
|
||||||
|
|
||||||
|
Alternatively you can just pull the [DockerHub image](https://hub.docker.com/r/ajbura/cinny) by `docker pull ajbura/cinny`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright (c) 2021 Ajay Bura (ajbura) and other contributors
|
Copyright (c) 2021 Ajay Bura (ajbura) and other contributors
|
||||||
|
|
||||||
Code licensed under the MIT License: <http://opensource.org/licenses/MIT>
|
Code licensed under the MIT License: <http://opensource.org/licenses/MIT>
|
||||||
|
|
||||||
Graphics licensed under CC-BY 4.0: <https://creativecommons.org/licenses/by/4.0/>
|
Graphics licensed under CC-BY 4.0: <https://creativecommons.org/licenses/by/4.0/>
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "1.3.0",
|
"version": "1.3.2",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "1.3.0",
|
"version": "1.3.2",
|
||||||
"description": "Yet another matrix client",
|
"description": "Yet another matrix client",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
&--alert {
|
&--alert {
|
||||||
background-color: var(--bg-positive);
|
background-color: var(--bg-positive);
|
||||||
& .text { color: white }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:empty {
|
&:empty {
|
||||||
|
|||||||
34
src/app/atoms/chip/Chip.jsx
Normal file
34
src/app/atoms/chip/Chip.jsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import './Chip.scss';
|
||||||
|
|
||||||
|
import Text from '../text/Text';
|
||||||
|
import RawIcon from '../system-icons/RawIcon';
|
||||||
|
|
||||||
|
function Chip({
|
||||||
|
iconSrc, iconColor, text, children,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="chip">
|
||||||
|
{iconSrc != null && <RawIcon src={iconSrc} color={iconColor} size="small" />}
|
||||||
|
{(text != null && text !== '') && <Text variant="b2">{text}</Text>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Chip.propTypes = {
|
||||||
|
iconSrc: PropTypes.string,
|
||||||
|
iconColor: PropTypes.string,
|
||||||
|
text: PropTypes.string,
|
||||||
|
children: PropTypes.element,
|
||||||
|
};
|
||||||
|
|
||||||
|
Chip.defaultProps = {
|
||||||
|
iconSrc: null,
|
||||||
|
iconColor: null,
|
||||||
|
text: null,
|
||||||
|
children: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Chip;
|
||||||
19
src/app/atoms/chip/Chip.scss
Normal file
19
src/app/atoms/chip/Chip.scss
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.chip {
|
||||||
|
padding: var(--sp-ultra-tight) var(--sp-extra-tight);
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background: var(--bg-surface-low);
|
||||||
|
border-radius: var(--bo-radius);
|
||||||
|
border: 1px solid var(--bg-surface-border);
|
||||||
|
|
||||||
|
& > .ic-raw {
|
||||||
|
margin-right: var(--sp-extra-tight);
|
||||||
|
[dir=rtl] & {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: var(--sp-extra-tight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ function ContextMenu({
|
|||||||
interactive
|
interactive
|
||||||
arrow={false}
|
arrow={false}
|
||||||
maxWidth={maxWidth}
|
maxWidth={maxWidth}
|
||||||
|
duration={200}
|
||||||
>
|
>
|
||||||
{render(isVisible ? hideMenu : showMenu)}
|
{render(isVisible ? hideMenu : showMenu)}
|
||||||
</Tippy>
|
</Tippy>
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
@extend .room-selector-flexItem;
|
@extend .room-selector-flexItem;
|
||||||
margin: 0 var(--sp-extra-tight);
|
margin: 0 var(--sp-extra-tight);
|
||||||
|
|
||||||
color: var(--tc-surface-normal);
|
color: var(--tc-surface-normal-low);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|||||||
@@ -139,14 +139,20 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
|
|||||||
updateIsViewMore(false);
|
updateIsViewMore(false);
|
||||||
if (totalRooms.length === 0) {
|
if (totalRooms.length === 0) {
|
||||||
updateSearchQuery({
|
updateSearchQuery({
|
||||||
error: `No result found for "${inputRoomName}" on ${inputHs}`,
|
error: inputRoomName === ''
|
||||||
|
? `No public rooms on ${inputHs}`
|
||||||
|
: `No result found for "${inputRoomName}" on ${inputHs}`,
|
||||||
alias: isInputAlias ? inputRoomName : null,
|
alias: isInputAlias ? inputRoomName : null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
updatePublicRooms([]);
|
updatePublicRooms([]);
|
||||||
|
let err = 'Something went wrong!';
|
||||||
|
if (e?.httpStatus >= 400 && e?.httpStatus < 500) {
|
||||||
|
err = e.message;
|
||||||
|
}
|
||||||
updateSearchQuery({
|
updateSearchQuery({
|
||||||
error: 'Something went wrong!',
|
error: err,
|
||||||
alias: isInputAlias ? inputRoomName : null,
|
alias: isInputAlias ? inputRoomName : null,
|
||||||
});
|
});
|
||||||
updateIsSearching(false);
|
updateIsSearching(false);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ function RoomViewFloating({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`room-view__typing${isSomeoneTyping(typingMembers) ? ' room-view__typing--open' : ''}`}>
|
<div className={`room-view__typing${isSomeoneTyping(typingMembers) ? ' room-view__typing--open' : ''}`}>
|
||||||
<div className="bouncingLoader"><div /></div>
|
<div className="bouncing-loader"><div /></div>
|
||||||
<Text variant="b2">{getTypingMessage(typingMembers)}</Text>
|
<Text variant="b2">{getTypingMessage(typingMembers)}</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className={`room-view__STB${reachedBottom ? '' : ' room-view__STB--open'}`}>
|
<div className={`room-view__STB${reachedBottom ? '' : ' room-view__STB--open'}`}>
|
||||||
|
|||||||
@@ -9,10 +9,6 @@
|
|||||||
color: var(--tc-surface-high);
|
color: var(--tc-surface-high);
|
||||||
}
|
}
|
||||||
|
|
||||||
&--open {
|
|
||||||
transform: translateY(-99%);
|
|
||||||
}
|
|
||||||
|
|
||||||
& .text {
|
& .text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@@ -22,37 +18,48 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
margin: 0 var(--sp-tight);
|
margin: 0 var(--sp-tight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--open {
|
||||||
|
transform: translateY(-99%);
|
||||||
|
& .bouncing-loader {
|
||||||
|
& > *,
|
||||||
|
&::after,
|
||||||
|
&::before {
|
||||||
|
animation: bouncing-loader 0.6s infinite alternate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bouncingLoader {
|
.bouncing-loader {
|
||||||
transform: translateY(2px);
|
transform: translateY(2px);
|
||||||
margin: 0 calc(var(--sp-ultra-tight) / 2);
|
margin: 0 calc(var(--sp-ultra-tight) / 2);
|
||||||
}
|
}
|
||||||
.bouncingLoader > div,
|
.bouncing-loader > div,
|
||||||
.bouncingLoader:before,
|
.bouncing-loader::before,
|
||||||
.bouncingLoader:after {
|
.bouncing-loader::after {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background: var(--tc-surface-high);
|
background: var(--tc-surface-high);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: bouncing-loader 0.6s infinite alternate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bouncingLoader:before,
|
|
||||||
.bouncingLoader:after {
|
.bouncing-loader::before,
|
||||||
|
.bouncing-loader::after {
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
.bouncingLoader > div {
|
.bouncing-loader > div {
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bouncingLoader > div {
|
.bouncing-loader > div {
|
||||||
animation-delay: 0.2s;
|
animation-delay: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bouncingLoader:after {
|
.bouncing-loader::after {
|
||||||
animation-delay: 0.4s;
|
animation-delay: 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -327,7 +327,15 @@ function RoomViewInput({
|
|||||||
if (file !== null) roomsInput.setAttachment(roomId, file);
|
if (file !== null) roomsInput.setAttachment(roomId, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const myPowerlevel = roomTimeline.room.getMember(mx.getUserId()).powerLevel;
|
||||||
|
const canISend = roomTimeline.room.currentState.hasSufficientPowerLevelFor('events_default', myPowerlevel);
|
||||||
|
|
||||||
function renderInputs() {
|
function renderInputs() {
|
||||||
|
if (!canISend) {
|
||||||
|
return (
|
||||||
|
<Text className="room-input__disallowed">You do not have permission to post to this room</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`room-input__option-container${attachment === null ? '' : ' room-attachment__option'}`}>
|
<div className={`room-input__option-container${attachment === null ? '' : ' room-attachment__option'}`}>
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
|
|
||||||
|
&__disallowed {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__space {
|
&__space {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ function AboutSection() {
|
|||||||
<div>
|
<div>
|
||||||
<Text variant="h2">
|
<Text variant="h2">
|
||||||
Cinny
|
Cinny
|
||||||
<span className="text text-b3" style={{ margin: '0 var(--sp-extra-tight)' }}>v1.3.0</span>
|
<span className="text text-b3" style={{ margin: '0 var(--sp-extra-tight)' }}>v1.3.2</span>
|
||||||
</Text>
|
</Text>
|
||||||
<Text>Yet another matrix client</Text>
|
<Text>Yet another matrix client</Text>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
BrowserRouter, Switch, Route, Redirect,
|
BrowserRouter, Switch, Route, Redirect,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import { isAuthanticated } from '../../client/state/auth';
|
import { isAuthenticated } from '../../client/state/auth';
|
||||||
|
|
||||||
import Auth from '../templates/auth/Auth';
|
import Auth from '../templates/auth/Auth';
|
||||||
import Client from '../templates/client/Client';
|
import Client from '../templates/client/Client';
|
||||||
@@ -13,13 +13,13 @@ function App() {
|
|||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/">
|
<Route exact path="/">
|
||||||
{ isAuthanticated() ? <Client /> : <Redirect to="/login" />}
|
{ isAuthenticated() ? <Client /> : <Redirect to="/login" />}
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/login">
|
<Route path="/login">
|
||||||
{ isAuthanticated() ? <Redirect to="/" /> : <Auth type="login" />}
|
{ isAuthenticated() ? <Redirect to="/" /> : <Auth type="login" />}
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/register">
|
<Route path="/register">
|
||||||
{ isAuthanticated() ? <Redirect to="/" /> : <Auth type="register" />}
|
{ isAuthenticated() ? <Redirect to="/" /> : <Auth type="register" />}
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const EMAIL_REGEX = /([a-z0-9]+[_a-z0-9.-][a-z0-9]+)@([a-z0-9-]+(?:.[a-z0-9-]+).
|
|||||||
const BAD_EMAIL_ERROR = 'Invalid email address';
|
const BAD_EMAIL_ERROR = 'Invalid email address';
|
||||||
|
|
||||||
function isValidInput(value, regex) {
|
function isValidInput(value, regex) {
|
||||||
|
if (typeof regex === 'string') return regex === value;
|
||||||
return regex.test(value);
|
return regex.test(value);
|
||||||
}
|
}
|
||||||
function renderErrorMessage(error) {
|
function renderErrorMessage(error) {
|
||||||
@@ -39,24 +40,25 @@ function renderErrorMessage(error) {
|
|||||||
$error.textContent = error;
|
$error.textContent = error;
|
||||||
$error.style.display = 'block';
|
$error.style.display = 'block';
|
||||||
}
|
}
|
||||||
function showBadInputError($input, error) {
|
function showBadInputError($input, error, stopAutoFocus) {
|
||||||
renderErrorMessage(error);
|
renderErrorMessage(error);
|
||||||
$input.focus();
|
if (!stopAutoFocus) $input.focus();
|
||||||
const myInput = $input;
|
const myInput = $input;
|
||||||
myInput.style.border = '1px solid var(--bg-danger)';
|
myInput.style.border = '1px solid var(--bg-danger)';
|
||||||
myInput.style.boxShadow = 'none';
|
myInput.style.boxShadow = 'none';
|
||||||
document.getElementById('auth_submit-btn').disabled = true;
|
document.getElementById('auth_submit-btn').disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateOnChange(e, regex, error) {
|
function validateOnChange(targetInput, regex, error, stopAutoFocus) {
|
||||||
if (!isValidInput(e.target.value, regex) && e.target.value) {
|
if (!isValidInput(targetInput.value, regex) && targetInput.value) {
|
||||||
showBadInputError(e.target, error);
|
showBadInputError(targetInput, error, stopAutoFocus);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
document.getElementById('auth_error').style.display = 'none';
|
document.getElementById('auth_error').style.display = 'none';
|
||||||
e.target.style.removeProperty('border');
|
targetInput.style.removeProperty('border');
|
||||||
e.target.style.removeProperty('box-shadow');
|
targetInput.style.removeProperty('box-shadow');
|
||||||
document.getElementById('auth_submit-btn').disabled = false;
|
document.getElementById('auth_submit-btn').disabled = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,8 +197,8 @@ function Auth({ type }) {
|
|||||||
<Input
|
<Input
|
||||||
forwardRef={usernameRef}
|
forwardRef={usernameRef}
|
||||||
onChange={(e) => (type === 'login'
|
onChange={(e) => (type === 'login'
|
||||||
? validateOnChange(e, LOCALPART_LOGIN_REGEX, BAD_LOCALPART_ERROR)
|
? validateOnChange(e.target, LOCALPART_LOGIN_REGEX, BAD_LOCALPART_ERROR)
|
||||||
: validateOnChange(e, LOCALPART_SIGNUP_REGEX, BAD_LOCALPART_ERROR))}
|
: validateOnChange(e.target, LOCALPART_SIGNUP_REGEX, BAD_LOCALPART_ERROR))}
|
||||||
id="auth_username"
|
id="auth_username"
|
||||||
label="Username"
|
label="Username"
|
||||||
required
|
required
|
||||||
@@ -212,7 +214,15 @@ function Auth({ type }) {
|
|||||||
<div className="password__wrapper">
|
<div className="password__wrapper">
|
||||||
<Input
|
<Input
|
||||||
forwardRef={passwordRef}
|
forwardRef={passwordRef}
|
||||||
onChange={(e) => validateOnChange(e, ((type === 'login') ? PASSWORD_REGEX : PASSWORD_STRENGHT_REGEX), BAD_PASSWORD_ERROR)}
|
onChange={(e) => {
|
||||||
|
const isValidPass = validateOnChange(e.target, ((type === 'login') ? PASSWORD_REGEX : PASSWORD_STRENGHT_REGEX), BAD_PASSWORD_ERROR);
|
||||||
|
if (type === 'register' && isValidPass) {
|
||||||
|
validateOnChange(
|
||||||
|
confirmPasswordRef.current, passwordRef.current.value,
|
||||||
|
CONFIRM_PASSWORD_ERROR, true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
id="auth_password"
|
id="auth_password"
|
||||||
type="password"
|
type="password"
|
||||||
label="Password"
|
label="Password"
|
||||||
@@ -233,7 +243,9 @@ function Auth({ type }) {
|
|||||||
<div className="password__wrapper">
|
<div className="password__wrapper">
|
||||||
<Input
|
<Input
|
||||||
forwardRef={confirmPasswordRef}
|
forwardRef={confirmPasswordRef}
|
||||||
onChange={(e) => validateOnChange(e, new RegExp(`^(${passwordRef.current.value})$`), CONFIRM_PASSWORD_ERROR)}
|
onChange={(e) => {
|
||||||
|
validateOnChange(e.target, passwordRef.current.value, CONFIRM_PASSWORD_ERROR);
|
||||||
|
}}
|
||||||
id="auth_confirmPassword"
|
id="auth_confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
label="Confirm password"
|
label="Confirm password"
|
||||||
@@ -251,7 +263,7 @@ function Auth({ type }) {
|
|||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
forwardRef={emailRef}
|
forwardRef={emailRef}
|
||||||
onChange={(e) => validateOnChange(e, EMAIL_REGEX, BAD_EMAIL_ERROR)}
|
onChange={(e) => validateOnChange(e.target, EMAIL_REGEX, BAD_EMAIL_ERROR)}
|
||||||
id="auth_email"
|
id="auth_email"
|
||||||
type="email"
|
type="email"
|
||||||
label="Email"
|
label="Email"
|
||||||
|
|||||||
@@ -76,10 +76,23 @@ class RoomList extends EventEmitter {
|
|||||||
if (parents.size === 0) this.roomIdToParents.delete(roomId);
|
if (parents.size === 0) this.roomIdToParents.delete(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getParentSpaces(roomId) {
|
||||||
|
let parentIds = this.roomIdToParents.get(roomId);
|
||||||
|
if (parentIds) {
|
||||||
|
[...parentIds].forEach((parentId) => {
|
||||||
|
parentIds = new Set([...parentIds, ...this.getParentSpaces(parentId)]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return parentIds || new Set();
|
||||||
|
}
|
||||||
|
|
||||||
addToSpaces(roomId) {
|
addToSpaces(roomId) {
|
||||||
this.spaces.add(roomId);
|
this.spaces.add(roomId);
|
||||||
|
const allParentSpaces = this.getParentSpaces(roomId);
|
||||||
|
|
||||||
const spaceChildren = this.getSpaceChildren(roomId);
|
const spaceChildren = this.getSpaceChildren(roomId);
|
||||||
spaceChildren?.forEach((childRoomId) => {
|
spaceChildren?.forEach((childRoomId) => {
|
||||||
|
if (allParentSpaces.has(childRoomId)) return;
|
||||||
this.addToRoomIdToParents(childRoomId, roomId);
|
this.addToRoomIdToParents(childRoomId, roomId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -268,6 +281,8 @@ class RoomList extends EventEmitter {
|
|||||||
if (mEvent.getType() === 'm.space.child') {
|
if (mEvent.getType() === 'm.space.child') {
|
||||||
const { event } = mEvent;
|
const { event } = mEvent;
|
||||||
if (isMEventSpaceChild(mEvent)) {
|
if (isMEventSpaceChild(mEvent)) {
|
||||||
|
const allParentSpaces = this.getParentSpaces(event.room_id);
|
||||||
|
if (allParentSpaces.has(event.state_key)) return;
|
||||||
this.addToRoomIdToParents(event.state_key, event.room_id);
|
this.addToRoomIdToParents(event.state_key, event.room_id);
|
||||||
} else this.removeFromRoomIdToParents(event.state_key, event.room_id);
|
} else this.removeFromRoomIdToParents(event.state_key, event.room_id);
|
||||||
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
|
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ function getSecret(key) {
|
|||||||
return localStorage.getItem(key);
|
return localStorage.getItem(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAuthanticated = () => getSecret(cons.secretKey.ACCESS_TOKEN) !== null;
|
const isAuthenticated = () => getSecret(cons.secretKey.ACCESS_TOKEN) !== null;
|
||||||
|
|
||||||
const secret = {
|
const secret = {
|
||||||
accessToken: getSecret(cons.secretKey.ACCESS_TOKEN),
|
accessToken: getSecret(cons.secretKey.ACCESS_TOKEN),
|
||||||
@@ -14,6 +14,6 @@ const secret = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isAuthanticated,
|
isAuthenticated,
|
||||||
secret,
|
secret,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
/* text color | --tc-[background type]-[priority]: value */
|
/* text color | --tc-[background type]-[priority]: value */
|
||||||
--tc-surface-high: #000000;
|
--tc-surface-high: #000000;
|
||||||
--tc-surface-normal: rgba(0, 0, 0, 68%);
|
--tc-surface-normal: rgba(0, 0, 0, 68%);
|
||||||
|
--tc-surface-normal-low: rgba(0, 0, 0, 60%);
|
||||||
--tc-surface-low: rgba(0, 0, 0, 38%);
|
--tc-surface-low: rgba(0, 0, 0, 38%);
|
||||||
|
|
||||||
--tc-primary-high: #ffffff;
|
--tc-primary-high: #ffffff;
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
--tc-danger-low: rgba(240, 71, 71, 60%);
|
--tc-danger-low: rgba(240, 71, 71, 60%);
|
||||||
|
|
||||||
--tc-code: #e62498;
|
--tc-code: #e62498;
|
||||||
|
--tc-link: hsl(213deg 76% 56%);
|
||||||
--tc-tooltip: white;
|
--tc-tooltip: white;
|
||||||
--tc-badge: white;
|
--tc-badge: white;
|
||||||
|
|
||||||
@@ -175,24 +176,26 @@
|
|||||||
--bg-surface-active: rgba(255, 255, 255, 5%);
|
--bg-surface-active: rgba(255, 255, 255, 5%);
|
||||||
--bg-surface-border: rgba(0, 0, 0, 20%);
|
--bg-surface-border: rgba(0, 0, 0, 20%);
|
||||||
|
|
||||||
--bg-primary: rgb(59, 119, 191);
|
--bg-primary: rgb(42, 98, 166);
|
||||||
--bg-primary-hover: rgba(59, 119, 191, 80%);
|
--bg-primary-hover: rgba(42, 98, 166, 80%);
|
||||||
--bg-primary-active: rgba(59, 119, 191, 70%);
|
--bg-primary-active: rgba(42, 98, 166, 70%);
|
||||||
--bg-primary-border: rgba(59, 119, 191, 38%);
|
--bg-primary-border: rgba(42, 98, 166, 38%);
|
||||||
|
|
||||||
--bg-tooltip: #000;
|
--bg-tooltip: #000;
|
||||||
--bg-badge: hsl(0, 0%, 75%);
|
--bg-badge: hsl(0, 0%, 75%);
|
||||||
|
|
||||||
/* text color | --tc-[background type]-[priority]: value */
|
/* text color | --tc-[background type]-[priority]: value */
|
||||||
--tc-surface-high: rgba(255, 255, 255, 94%);
|
--tc-surface-high: rgba(255, 255, 255, 98%);
|
||||||
--tc-surface-normal: rgba(255, 255, 255, 74%);
|
--tc-surface-normal: rgba(255, 255, 255, 84%);
|
||||||
--tc-surface-low: rgba(255, 255, 255, 38%);
|
--tc-surface-normal-low: rgba(255, 255, 255, 60%);
|
||||||
|
--tc-surface-low: rgba(255, 255, 255, 48%);
|
||||||
|
|
||||||
--tc-primary-high: #ffffff;
|
--tc-primary-high: #ffffff;
|
||||||
--tc-primary-normal: rgba(255, 255, 255, 0.68);
|
--tc-primary-normal: rgba(255, 255, 255, 0.68);
|
||||||
--tc-primary-low: rgba(255, 255, 255, 0.4);
|
--tc-primary-low: rgba(255, 255, 255, 0.4);
|
||||||
|
|
||||||
--tc-code: #e565b1;
|
--tc-code: #e565b1;
|
||||||
|
--tc-link: hsl(213deg 94% 73%);
|
||||||
--tc-badge: black;
|
--tc-badge: black;
|
||||||
|
|
||||||
/* system icons | --ic-[background type]-[priority]: value */
|
/* system icons | --ic-[background type]-[priority]: value */
|
||||||
@@ -226,6 +229,7 @@
|
|||||||
/* text color | --tc-[background type]-[priority]: value */
|
/* text color | --tc-[background type]-[priority]: value */
|
||||||
--tc-surface-high: rgb(255, 251, 222, 94%);
|
--tc-surface-high: rgb(255, 251, 222, 94%);
|
||||||
--tc-surface-normal: rgba(255, 251, 222, 74%);
|
--tc-surface-normal: rgba(255, 251, 222, 74%);
|
||||||
|
--tc-surface-normal-low: rgba(255, 251, 222, 60%);
|
||||||
--tc-surface-low: rgba(255, 251, 222, 38%);
|
--tc-surface-low: rgba(255, 251, 222, 38%);
|
||||||
|
|
||||||
|
|
||||||
@@ -257,7 +261,7 @@ body {
|
|||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: var(--bg-primary);
|
color: var(--tc-link);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
b {
|
b {
|
||||||
|
|||||||
Reference in New Issue
Block a user