Compare commits
1 commit
dev
...
add-topic-
Author | SHA1 | Date | |
---|---|---|---|
e75fef6ba3 |
13 changed files with 134 additions and 112 deletions
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile"
|
||||
}
|
|
@ -102,6 +102,6 @@
|
|||
<audio id="inviteSound">
|
||||
<source src="./public/sound/invite.ogg" type="audio/ogg" />
|
||||
</audio>
|
||||
<script type="module" src="./src/index.tsx"></script>
|
||||
<script type="module" src="./src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
22
package-lock.json
generated
22
package-lock.json
generated
|
@ -14,7 +14,6 @@
|
|||
"@khanacademy/simple-markdown": "0.8.6",
|
||||
"@matrix-org/olm": "3.2.14",
|
||||
"@tippyjs/react": "4.2.6",
|
||||
"@types/flux": "3.1.11",
|
||||
"blurhash": "2.0.4",
|
||||
"browser-encrypt-attachment": "0.3.0",
|
||||
"dateformat": "5.0.3",
|
||||
|
@ -44,7 +43,6 @@
|
|||
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
||||
"@rollup/plugin-inject": "5.0.3",
|
||||
"@rollup/plugin-wasm": "6.1.1",
|
||||
"@types/dateformat": "5.0.0",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react-dom": "18.0.9",
|
||||
|
@ -1117,12 +1115,6 @@
|
|||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dateformat": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-5.0.0.tgz",
|
||||
"integrity": "sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||
|
@ -1134,20 +1126,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
|
||||
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
|
||||
},
|
||||
"node_modules/@types/fbemitter": {
|
||||
"version": "2.0.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/fbemitter/-/fbemitter-2.0.32.tgz",
|
||||
"integrity": "sha512-Hwq28bBlbmfCgLnNJvjl5ssTrbZCTSblI4vqPpqZrbbEL8vn5l2UivxhlMYfUY7a4SR8UB6RKoLjOZfljqAa6g=="
|
||||
},
|
||||
"node_modules/@types/flux": {
|
||||
"version": "3.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/flux/-/flux-3.1.11.tgz",
|
||||
"integrity": "sha512-Aq4UB1ZqAKcPbhB0GpgMw2sntvOh71he9tjz53TLKrI7rw3Y3LxCW5pTYY9IV455hQapm4pmxFjpqlWOs308Yg==",
|
||||
"dependencies": {
|
||||
"@types/fbemitter": "*",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"scripts": {
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "npm run check:eslint && npm run check:prettier",
|
||||
"lint": "yarn check:eslint && yarn check:prettier",
|
||||
"check:eslint": "eslint src/*",
|
||||
"check:prettier": "prettier --check .",
|
||||
"fix:prettier": "prettier --write .",
|
||||
|
@ -24,7 +24,6 @@
|
|||
"@khanacademy/simple-markdown": "0.8.6",
|
||||
"@matrix-org/olm": "3.2.14",
|
||||
"@tippyjs/react": "4.2.6",
|
||||
"@types/flux": "3.1.11",
|
||||
"blurhash": "2.0.4",
|
||||
"browser-encrypt-attachment": "0.3.0",
|
||||
"dateformat": "5.0.3",
|
||||
|
@ -54,7 +53,6 @@
|
|||
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
||||
"@rollup/plugin-inject": "5.0.3",
|
||||
"@rollup/plugin-wasm": "6.1.1",
|
||||
"@types/dateformat": "5.0.0",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react-dom": "18.0.9",
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import dateFormat from "dateformat";
|
||||
import { isInSameDay } from "../../../util/common";
|
||||
|
||||
export interface TimeProps {
|
||||
timestamp: number;
|
||||
fullTime?: boolean;
|
||||
}
|
||||
|
||||
function Time({ timestamp, fullTime }: TimeProps) {
|
||||
function Time({ timestamp, fullTime }) {
|
||||
const date = new Date(timestamp);
|
||||
|
||||
const formattedFullTime = dateFormat(date, "dd mmmm yyyy, hh:MM TT");
|
||||
let formattedDateTime = formattedFullTime;
|
||||
let formattedDate = formattedFullTime;
|
||||
|
||||
if (!fullTime) {
|
||||
const compareDate = new Date();
|
||||
|
@ -20,21 +16,18 @@ function Time({ timestamp, fullTime }: TimeProps) {
|
|||
compareDate.setDate(compareDate.getDate() - 1);
|
||||
const isYesterday = isInSameDay(date, compareDate);
|
||||
|
||||
const dtf = new Intl.DateTimeFormat();
|
||||
const formattedDate = dtf.format(date);
|
||||
|
||||
formattedDateTime = dateFormat(
|
||||
formattedDate = dateFormat(
|
||||
date,
|
||||
isToday || isYesterday ? "hh:MM TT" : formattedDate
|
||||
isToday || isYesterday ? "hh:MM TT" : "dd/mm/yyyy"
|
||||
);
|
||||
if (isYesterday) {
|
||||
formattedDateTime = `Yesterday, ${formattedDateTime}`;
|
||||
formattedDate = `Yesterday, ${formattedDate}`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<time dateTime={date.toISOString()} title={formattedFullTime}>
|
||||
{formattedDateTime}
|
||||
{formattedDate}
|
||||
</time>
|
||||
);
|
||||
}
|
||||
|
@ -43,4 +36,9 @@ Time.defaultProps = {
|
|||
fullTime: false,
|
||||
};
|
||||
|
||||
Time.propTypes = {
|
||||
timestamp: PropTypes.number.isRequired,
|
||||
fullTime: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Time;
|
|
@ -97,14 +97,6 @@ function Home({ spaceId }) {
|
|||
/>
|
||||
)}
|
||||
|
||||
{roomIds.length !== 0 && (
|
||||
<RoomsCategory
|
||||
name="Rooms"
|
||||
roomIds={roomIds.sort(roomIdByAtoZ)}
|
||||
drawerPostie={drawerPostie}
|
||||
/>
|
||||
)}
|
||||
|
||||
{directIds.length !== 0 && (
|
||||
<RoomsCategory
|
||||
name="People"
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
}
|
||||
|
||||
& .room-selector {
|
||||
width: calc(100% - 2 * var(--sp-extra-tight));
|
||||
@include dir.side(margin, auto, auto);
|
||||
width: calc(100% - var(--sp-extra-tight));
|
||||
@include dir.side(margin, auto, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
@use "../../partials/screen";
|
||||
|
||||
.room-header__btn {
|
||||
min-width: 0;
|
||||
@extend .cp-fx__row--s-c;
|
||||
@include dir.side(margin, 0, auto);
|
||||
@include dir.side(margin, 0, var(--sp-extra-tight));
|
||||
border-radius: var(--bo-radius);
|
||||
cursor: pointer;
|
||||
|
||||
|
@ -27,21 +26,54 @@
|
|||
}
|
||||
}
|
||||
|
||||
.room-header__topic {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include dir.side(margin, 0, auto);
|
||||
|
||||
p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.room-header__drawer-btn {
|
||||
flex: 0;
|
||||
|
||||
@include screen.smallerThan(tabletBreakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.room-header__members-btn {
|
||||
flex: 0;
|
||||
|
||||
@include screen.biggerThan(tabletBreakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.room-header__back-btn {
|
||||
flex: 0;
|
||||
|
||||
@include dir.side(margin, 0, var(--sp-tight));
|
||||
|
||||
@include screen.biggerThan(mobileBreakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.room-header__left {
|
||||
display: flex;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.room-header__right {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import "./RoomViewHeader.scss";
|
||||
|
||||
import { twemojify } from "../../../util/twemojify";
|
||||
|
@ -33,16 +32,26 @@ import BackArrowIC from "../../../../public/res/ic/outlined/chevron-left.svg";
|
|||
|
||||
import { useForceUpdate } from "../../hooks/useForceUpdate";
|
||||
|
||||
function RoomViewHeader({ roomId }) {
|
||||
interface RoomViewHeaderProps {
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
function RoomViewHeader({ roomId }: RoomViewHeaderProps) {
|
||||
const [, forceUpdate] = useForceUpdate();
|
||||
const mx = initMatrix.matrixClient;
|
||||
const isDM = initMatrix.roomList.directs.has(roomId);
|
||||
const room = mx.getRoom(roomId);
|
||||
let avatarSrc = room.getAvatarUrl(mx.baseUrl, 36, 36, "crop");
|
||||
avatarSrc = isDM
|
||||
? room.getAvatarFallbackMember()?.getAvatarUrl(mx.baseUrl, 36, 36, "crop")
|
||||
? room
|
||||
.getAvatarFallbackMember()
|
||||
?.getAvatarUrl(mx.baseUrl, 36, 36, "crop", true, false)
|
||||
: avatarSrc;
|
||||
const roomName = room.name;
|
||||
const { name: roomName, currentState } = room;
|
||||
|
||||
const roomTopic = currentState
|
||||
.getStateEvents("m.room.topic")[0]
|
||||
?.getContent().topic;
|
||||
|
||||
const roomHeaderBtnRef = useRef(null);
|
||||
useEffect(() => {
|
||||
|
@ -89,61 +98,69 @@ function RoomViewHeader({ roomId }) {
|
|||
|
||||
return (
|
||||
<Header>
|
||||
<IconButton
|
||||
src={BackArrowIC}
|
||||
className="room-header__back-btn"
|
||||
tooltip="Return to navigation"
|
||||
onClick={() => openNavigation()}
|
||||
/>
|
||||
<button
|
||||
ref={roomHeaderBtnRef}
|
||||
className="room-header__btn"
|
||||
onClick={() => toggleRoomSettings()}
|
||||
type="button"
|
||||
onMouseUp={(e) => blurOnBubbling(e, ".room-header__btn")}
|
||||
>
|
||||
<Avatar
|
||||
imageSrc={avatarSrc}
|
||||
text={roomName}
|
||||
bgColor={colorMXID(roomId)}
|
||||
size="small"
|
||||
/>
|
||||
<TitleWrapper>
|
||||
<Text variant="h2" weight="medium" primary>
|
||||
{twemojify(roomName)}
|
||||
</Text>
|
||||
</TitleWrapper>
|
||||
<RawIcon src={ChevronBottomIC} />
|
||||
</button>
|
||||
{mx.isRoomEncrypted(roomId) === false && (
|
||||
<div class="room-header__left">
|
||||
<IconButton
|
||||
onClick={() => toggleRoomSettings(tabText.SEARCH)}
|
||||
tooltip="Search"
|
||||
src={SearchIC}
|
||||
src={BackArrowIC}
|
||||
className="room-header__back-btn"
|
||||
tooltip="Return to navigation"
|
||||
onClick={() => openNavigation()}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
className="room-header__drawer-btn"
|
||||
onClick={togglePeopleDrawer}
|
||||
tooltip="People"
|
||||
src={UserIC}
|
||||
/>
|
||||
<IconButton
|
||||
className="room-header__members-btn"
|
||||
onClick={() => toggleRoomSettings(tabText.MEMBERS)}
|
||||
tooltip="Members"
|
||||
src={UserIC}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={openRoomOptions}
|
||||
tooltip="Options"
|
||||
src={VerticalMenuIC}
|
||||
/>
|
||||
<button
|
||||
ref={roomHeaderBtnRef}
|
||||
className="room-header__btn"
|
||||
onClick={() => toggleRoomSettings()}
|
||||
type="button"
|
||||
onMouseUp={(e) => blurOnBubbling(e, ".room-header__btn")}
|
||||
>
|
||||
<Avatar
|
||||
imageSrc={avatarSrc}
|
||||
text={roomName}
|
||||
bgColor={colorMXID(roomId)}
|
||||
size="small"
|
||||
/>
|
||||
<TitleWrapper>
|
||||
<Text variant="h2" weight="medium" primary>
|
||||
{twemojify(roomName)}
|
||||
</Text>
|
||||
</TitleWrapper>
|
||||
<RawIcon src={ChevronBottomIC} />
|
||||
</button>
|
||||
|
||||
<div className="room-header__topic">
|
||||
{roomTopic && (
|
||||
<Text variant="b2">{twemojify(roomTopic, undefined, true)}</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="room-header__right">
|
||||
{mx.isRoomEncrypted(roomId) === false && (
|
||||
<IconButton
|
||||
onClick={() => toggleRoomSettings(tabText.SEARCH)}
|
||||
tooltip="Search"
|
||||
src={SearchIC}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
className="room-header__drawer-btn"
|
||||
onClick={togglePeopleDrawer}
|
||||
tooltip="People"
|
||||
src={UserIC}
|
||||
/>
|
||||
<IconButton
|
||||
className="room-header__members-btn"
|
||||
onClick={() => toggleRoomSettings(tabText.MEMBERS)}
|
||||
tooltip="Members"
|
||||
src={UserIC}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={openRoomOptions}
|
||||
tooltip="Options"
|
||||
src={VerticalMenuIC}
|
||||
/>
|
||||
</div>
|
||||
</Header>
|
||||
);
|
||||
}
|
||||
RoomViewHeader.propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default RoomViewHeader;
|
|
@ -7,7 +7,12 @@
|
|||
"esModuleInterop": true,
|
||||
"moduleResolution": "Node",
|
||||
"outDir": "dist",
|
||||
"skipLibCheck": true
|
||||
"skipLibCheck": true,
|
||||
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"include": ["src"]
|
||||
|
|
|
@ -5,6 +5,7 @@ import { viteStaticCopy } from "vite-plugin-static-copy";
|
|||
import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";
|
||||
import inject from "@rollup/plugin-inject";
|
||||
import { svgLoader } from "./viteSvgLoader";
|
||||
import path from "path";
|
||||
|
||||
const copyFiles = {
|
||||
targets: [
|
||||
|
@ -35,6 +36,11 @@ export default defineConfig({
|
|||
port: 8080,
|
||||
host: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
plugins: [viteStaticCopy(copyFiles), svgLoader(), wasm(), react()],
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
|
|
Loading…
Add table
Reference in a new issue