imnyang/cinny
Watch
1
0
Fork
You've already forked cinny
0

Renamed channels to rooms (#30)

This commit is contained in:
unknown 2021-08-31 18:43:31 +05:30
commit 705910d9e0
6 changed files with 291 additions and 291 deletions

View file

@ -0,0 +1,47 @@
import React from 'react';
import PropTypes from 'prop-types';
import './RoomIntro.scss';
import Linkify from 'linkifyjs/react';
import colorMXID from '../../../util/colorMXID';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
function linkifyContent(content) {
return <Linkify options={{ target: { url: '_blank' } }}>{content}</Linkify>;
}
function RoomIntro({
roomId, avatarSrc, name, heading, desc, time,
}) {
return (
<div className="room-intro">
<Avatar imageSrc={avatarSrc} text={name.slice(0, 1)} bgColor={colorMXID(roomId)} size="large" />
<div className="room-intro__content">
<Text className="room-intro__name" variant="h1">{heading}</Text>
<Text className="room-intro__desc" variant="b1">{linkifyContent(desc)}</Text>
{ time !== null && <Text className="room-intro__time" variant="b3">{time}</Text>}
</div>
</div>
);
}
RoomIntro.defaultProps = {
avatarSrc: false,
time: null,
};
RoomIntro.propTypes = {
roomId: PropTypes.string.isRequired,
avatarSrc: PropTypes.oneOfType([
PropTypes.string,
PropTypes.bool,
]),
name: PropTypes.string.isRequired,
heading: PropTypes.string.isRequired,
desc: PropTypes.string.isRequired,
time: PropTypes.string,
};
export default RoomIntro;

View file

@ -0,0 +1,31 @@
.room-intro {
margin-top: calc(2 * var(--sp-extra-loose));
margin-bottom: var(--sp-extra-loose);
padding-left: calc(var(--sp-normal) + var(--av-small) + var(--sp-tight));
padding-right: var(--sp-extra-tight);
[dir=rtl] & {
padding: {
left: var(--sp-extra-tight);
right: calc(var(--sp-normal) + var(--av-small) + var(--sp-tight));
}
}
.room-intro__content {
margin-top: var(--sp-extra-loose);
max-width: 640px;
}
&__name {
color: var(--tc-surface-high);
}
&__desc {
color: var(--tc-surface-normal);
margin: var(--sp-tight) 0 var(--sp-extra-tight);
& a {
word-break: break-all;
}
}
&__time {
color: var(--tc-surface-low);
}
}

View file

@ -0,0 +1,88 @@
import React from 'react';
import PropTypes from 'prop-types';
import './RoomSelector.scss';
import colorMXID from '../../../util/colorMXID';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import NotificationBadge from '../../atoms/badge/NotificationBadge';
import { blurOnBubbling } from '../../atoms/button/script';
function RoomSelectorWrapper({
isSelected, onClick, content, options,
}) {
return (
<div className={`room-selector${isSelected ? ' room-selector--selected' : ''}`}>
<button
className="room-selector__content"
type="button"
onClick={onClick}
onMouseUp={(e) => blurOnBubbling(e, '.room-selector')}
>
{content}
</button>
<div className="room-selector__options">{options}</div>
</div>
);
}
RoomSelectorWrapper.defaultProps = {
options: null,
};
RoomSelectorWrapper.propTypes = {
isSelected: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
content: PropTypes.node.isRequired,
options: PropTypes.node,
};
function RoomSelector({
name, roomId, imageSrc, iconSrc,
isSelected, isUnread, notificationCount, isAlert,
options, onClick,
}) {
return (
<RoomSelectorWrapper
isSelected={isSelected}
content={(
<>
<Avatar
text={name.slice(0, 1)}
bgColor={colorMXID(roomId)}
imageSrc={imageSrc}
iconSrc={iconSrc}
size="extra-small"
/>
<Text variant="b1">{name}</Text>
{ isUnread && (
<NotificationBadge
alert={isAlert}
content={notificationCount !== 0 ? notificationCount : null}
/>
)}
</>
)}
options={options}
onClick={onClick}
/>
);
}
RoomSelector.defaultProps = {
imageSrc: null,
iconSrc: null,
options: null,
};
RoomSelector.propTypes = {
name: PropTypes.string.isRequired,
roomId: PropTypes.string.isRequired,
imageSrc: PropTypes.string,
iconSrc: PropTypes.string,
isSelected: PropTypes.bool.isRequired,
isUnread: PropTypes.bool.isRequired,
notificationCount: PropTypes.number.isRequired,
isAlert: PropTypes.bool.isRequired,
options: PropTypes.node,
onClick: PropTypes.func.isRequired,
};
export default RoomSelector;

View file

@ -0,0 +1,88 @@
.room-selector-flex {
display: flex;
align-items: center;
}
.room-selector-flexItem {
flex: 1;
min-width: 0;
min-height: 0;
}
.room-selector {
@extend .room-selector-flex;
border: 1px solid transparent;
border-radius: var(--bo-radius);
cursor: pointer;
&--selected {
background-color: var(--bg-surface);
border-color: var(--bg-surface-border);
& .room-selector__options {
display: flex;
}
}
@media (hover: hover) {
&:hover {
background-color: var(--bg-surface-hover);
& .room-selector__options {
display: flex;
}
}
}
&:focus {
outline: none;
background-color: var(--bg-surface-hover);
}
&:active {
background-color: var(--bg-surface-active);
}
&--selected:hover,
&--selected:focus,
&--selected:active {
background-color: var(--bg-surface);
}
}
.room-selector__content {
@extend .room-selector-flexItem;
@extend .room-selector-flex;
padding: 0 var(--sp-extra-tight);
min-height: 40px;
cursor: inherit;
& > .avatar-container .avatar__bordered {
box-shadow: none;
}
& > .text {
@extend .room-selector-flexItem;
margin: 0 var(--sp-extra-tight);
color: var(--tc-surface-normal);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.room-selector__options {
@extend .room-selector-flex;
display: none;
margin-right: var(--sp-ultra-tight);
[dir=rtl] & {
margin-right: 0;
margin-left: var(--sp-ultra-tight);
}
&:empty {
margin: 0 !important;
}
& .ic-btn-surface {
padding: 6px;
border-radius: calc(var(--bo-radius) / 2);
}
}

View file

@ -0,0 +1,72 @@
import React from 'react';
import PropTypes from 'prop-types';
import './RoomTile.scss';
import Linkify from 'linkifyjs/react';
import colorMXID from '../../../util/colorMXID';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
function linkifyContent(content) {
return <Linkify options={{ target: { url: '_blank' } }}>{content}</Linkify>;
}
function RoomTile({
avatarSrc, name, id,
inviterName, memberCount, desc, options,
}) {
return (
<div className="room-tile">
<div className="room-tile__avatar">
<Avatar
imageSrc={avatarSrc}
bgColor={colorMXID(id)}
text={name.slice(0, 1)}
/>
</div>
<div className="room-tile__content">
<Text variant="s1">{name}</Text>
<Text variant="b3">
{
inviterName !== null
? `Invited by ${inviterName} to ${id}${memberCount === null ? '' : ` • ${memberCount} members`}`
: id + (memberCount === null ? '' : ` • ${memberCount} members`)
}
</Text>
{
desc !== null && (typeof desc === 'string')
? <Text className="room-tile__content__desc" variant="b2">{linkifyContent(desc)}</Text>
: desc
}
</div>
{ options !== null && (
<div className="room-tile__options">
{options}
</div>
)}
</div>
);
}
RoomTile.defaultProps = {
avatarSrc: null,
inviterName: null,
options: null,
desc: null,
memberCount: null,
};
RoomTile.propTypes = {
avatarSrc: PropTypes.string,
name: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
inviterName: PropTypes.string,
memberCount: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
desc: PropTypes.node,
options: PropTypes.node,
};
export default RoomTile;

View file

@ -0,0 +1,21 @@
.room-tile {
display: flex;
&__content {
flex: 1;
min-width: 0;
margin: 0 var(--sp-normal);
&__desc {
white-space: pre-wrap;
& a {
white-space: wrap;
}
}
& .text:not(:first-child) {
margin-top: var(--sp-ultra-tight);
}
}
}