Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1487dcbadc | ||
|
|
a4b27fdeab | ||
|
|
1137c11c59 | ||
|
|
14cd84dab7 | ||
|
|
b5c5cd9586 | ||
|
|
85cc4cb8f7 | ||
|
|
cf6732fb29 | ||
|
|
1207f5abad | ||
|
|
6e9394ec7a |
32
.github/workflows/build-pull-request.yml
vendored
Normal file
32
.github/workflows/build-pull-request.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: 'Build PR'
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: ['opened', 'synchronize']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
PR_NUMBER: ${{github.event.number}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build
|
||||||
|
run: npm install && npm run build
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: previewbuild
|
||||||
|
path: dist
|
||||||
|
retention-days: 1
|
||||||
|
- uses: actions/github-script@v3.1.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
var fs = require('fs');
|
||||||
|
fs.writeFileSync('${{github.workspace}}/pr.json', JSON.stringify(context.payload.pull_request));
|
||||||
|
- name: Upload PR Info
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: pr.json
|
||||||
|
path: pr.json
|
||||||
|
retention-days: 1
|
||||||
78
.github/workflows/deploy-pull-request.yml
vendored
Normal file
78
.github/workflows/deploy-pull-request.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
name: Upload Preview Build to Netlify
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Build PR"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
|
steps:
|
||||||
|
# There's a 'download artifact' action but it hasn't been updated for the
|
||||||
|
# workflow_run action (https://github.com/actions/download-artifact/issues/60)
|
||||||
|
# so instead we get this mess:
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/github-script@v3.1.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
var artifacts = await github.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
run_id: ${{github.event.workflow_run.id }},
|
||||||
|
});
|
||||||
|
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "previewbuild"
|
||||||
|
})[0];
|
||||||
|
var download = await github.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
var fs = require('fs');
|
||||||
|
fs.writeFileSync('${{github.workspace}}/previewbuild.zip', Buffer.from(download.data));
|
||||||
|
var prInfoArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "pr.json"
|
||||||
|
})[0];
|
||||||
|
var download = await github.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: prInfoArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
var fs = require('fs');
|
||||||
|
fs.writeFileSync('${{github.workspace}}/pr.json.zip', Buffer.from(download.data));
|
||||||
|
- name: Extract Artifacts
|
||||||
|
run: unzip -d dist previewbuild.zip && rm previewbuild.zip && unzip pr.json.zip && rm pr.json.zip
|
||||||
|
- name: 'Read PR Info'
|
||||||
|
id: readctx
|
||||||
|
uses: actions/github-script@v3.1.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
var fs = require('fs');
|
||||||
|
var pr = JSON.parse(fs.readFileSync('${{github.workspace}}/pr.json'));
|
||||||
|
console.log(`::set-output name=prnumber::${pr.number}`);
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: netlify
|
||||||
|
uses: nwtgck/actions-netlify@v1.2
|
||||||
|
with:
|
||||||
|
publish-dir: dist
|
||||||
|
deploy-message: "Deploy from GitHub Actions"
|
||||||
|
# These don't work because we're in workflow_run
|
||||||
|
enable-pull-request-comment: false
|
||||||
|
enable-commit-comment: false
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE3_ID }}
|
||||||
|
timeout-minutes: 1
|
||||||
|
- name: Edit PR Description
|
||||||
|
uses: velas/pr-description@v1.0.1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
pull-request-number: ${{ steps.readctx.outputs.prnumber }}
|
||||||
|
description-message: |
|
||||||
|
Preview: ${{ steps.netlify.outputs.deploy-url }}
|
||||||
|
⚠️ Do you trust the author of this PR? Maybe this build will steal your keys or give you malware. Exercise caution. Use test accounts.
|
||||||
30
.github/workflows/pull-request.yml
vendored
30
.github/workflows/pull-request.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: 'Netlify Preview Deploy'
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: ['opened', 'synchronize']
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
name: "Deploy to Netlify"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
- uses: jsmrcaga/action-netlify-deploy@master
|
|
||||||
with:
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE3_ID }}
|
|
||||||
BUILD_DIRECTORY: "dist"
|
|
||||||
- name: Post on PR
|
|
||||||
uses: nwtgck/actions-netlify@v1.1
|
|
||||||
with:
|
|
||||||
publish-dir: "dist"
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
deploy-message: "Deploy from GitHub Actions"
|
|
||||||
enable-pull-request-comment: true
|
|
||||||
enable-commit-comment: false
|
|
||||||
overwrites-pull-request-comment: true
|
|
||||||
env:
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE3_ID }}
|
|
||||||
@@ -57,7 +57,7 @@ To set default Homeserver on login and register page, place a customized [`confi
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright (c) 2021 Ajay Bura (ajbura) and other contributors
|
Copyright (c) 2021 Ajay Bura (ajbura) and contributors
|
||||||
|
|
||||||
Code licensed under the MIT License: <http://opensource.org/licenses/MIT>
|
Code licensed under the MIT License: <http://opensource.org/licenses/MIT>
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "1.5.0",
|
"version": "1.5.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "1.5.0",
|
"version": "1.5.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.4.tgz",
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.4.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "1.5.0",
|
"version": "1.5.1",
|
||||||
"description": "Yet another matrix client",
|
"description": "Yet another matrix client",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0 maximum-scale=1.0 user-scalable=no">
|
||||||
<link href="https://api.fontshare.com/css?f[]=supreme@300,301,400,401,500,501,700,701&display=swap" rel="stylesheet">
|
<link href="https://api.fontshare.com/css?f[]=supreme@300,301,400,401,500,501,700,701&display=swap" rel="stylesheet">
|
||||||
<title>Cinny</title>
|
<title>Cinny</title>
|
||||||
<meta name="name" content="Cinny">
|
<meta name="name" content="Cinny">
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function Avatar({
|
|||||||
{
|
{
|
||||||
iconSrc !== null
|
iconSrc !== null
|
||||||
? <RawIcon size={size} src={iconSrc} />
|
? <RawIcon size={size} src={iconSrc} />
|
||||||
: text !== null && <Text variant={textSize}>{text}</Text>
|
: text !== null && <Text variant={textSize}>{[...text][0]}</Text>
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function ImageUpload({
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
imageSrc={imageSrc}
|
imageSrc={imageSrc}
|
||||||
text={text.slice(0, 1)}
|
text={text}
|
||||||
bgColor={bgColor}
|
bgColor={bgColor}
|
||||||
size="large"
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -106,10 +106,17 @@ MessageReply.propTypes = {
|
|||||||
content: PropTypes.string.isRequired,
|
content: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function MessageContent({ content, isMarkdown, isEdited }) {
|
function MessageContent({
|
||||||
|
senderName,
|
||||||
|
content,
|
||||||
|
isMarkdown,
|
||||||
|
isEdited,
|
||||||
|
msgType,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="message__content">
|
<div className="message__content">
|
||||||
<div className="text text-b1">
|
<div className="text text-b1">
|
||||||
|
{ msgType === 'm.emote' && `* ${senderName} ` }
|
||||||
{ isMarkdown ? genMarkdown(content) : linkifyContent(content) }
|
{ isMarkdown ? genMarkdown(content) : linkifyContent(content) }
|
||||||
</div>
|
</div>
|
||||||
{ isEdited && <Text className="message__content-edited" variant="b3">(edited)</Text>}
|
{ isEdited && <Text className="message__content-edited" variant="b3">(edited)</Text>}
|
||||||
@@ -121,9 +128,11 @@ MessageContent.defaultProps = {
|
|||||||
isEdited: false,
|
isEdited: false,
|
||||||
};
|
};
|
||||||
MessageContent.propTypes = {
|
MessageContent.propTypes = {
|
||||||
|
senderName: PropTypes.string.isRequired,
|
||||||
content: PropTypes.node.isRequired,
|
content: PropTypes.node.isRequired,
|
||||||
isMarkdown: PropTypes.bool,
|
isMarkdown: PropTypes.bool,
|
||||||
isEdited: PropTypes.bool,
|
isEdited: PropTypes.bool,
|
||||||
|
msgType: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function MessageEdit({ content, onSave, onCancel }) {
|
function MessageEdit({ content, onSave, onCancel }) {
|
||||||
@@ -228,10 +237,27 @@ MessageOptions.propTypes = {
|
|||||||
|
|
||||||
function Message({
|
function Message({
|
||||||
avatar, header, reply, content, editContent, reactions, options,
|
avatar, header, reply, content, editContent, reactions, options,
|
||||||
|
msgType,
|
||||||
}) {
|
}) {
|
||||||
const msgClass = header === null ? ' message--content-only' : ' message--full';
|
const className = [
|
||||||
|
'message',
|
||||||
|
header === null ? ' message--content-only' : ' message--full',
|
||||||
|
];
|
||||||
|
switch (msgType) {
|
||||||
|
case 'm.text':
|
||||||
|
className.push('message--type-text');
|
||||||
|
break;
|
||||||
|
case 'm.emote':
|
||||||
|
className.push('message--type-emote');
|
||||||
|
break;
|
||||||
|
case 'm.notice':
|
||||||
|
className.push('message--type-notice');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`message${msgClass}`}>
|
<div className={className.join(' ')}>
|
||||||
<div className="message__avatar-container">
|
<div className="message__avatar-container">
|
||||||
{avatar !== null && avatar}
|
{avatar !== null && avatar}
|
||||||
</div>
|
</div>
|
||||||
@@ -254,6 +280,7 @@ Message.defaultProps = {
|
|||||||
editContent: null,
|
editContent: null,
|
||||||
reactions: null,
|
reactions: null,
|
||||||
options: null,
|
options: null,
|
||||||
|
msgType: 'm.text',
|
||||||
};
|
};
|
||||||
Message.propTypes = {
|
Message.propTypes = {
|
||||||
avatar: PropTypes.node,
|
avatar: PropTypes.node,
|
||||||
@@ -263,6 +290,7 @@ Message.propTypes = {
|
|||||||
editContent: PropTypes.node,
|
editContent: PropTypes.node,
|
||||||
reactions: PropTypes.node,
|
reactions: PropTypes.node,
|
||||||
options: PropTypes.node,
|
options: PropTypes.node,
|
||||||
|
msgType: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -410,3 +410,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message.message--type-emote {
|
||||||
|
.message__content {
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
// Remove blockness of first `<p>` so that markdown emotes stay on one line.
|
||||||
|
p:first-of-type {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function PeopleSelector({
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<Avatar imageSrc={avatarSrc} text={name.slice(0, 1)} bgColor={color} size="extra-small" />
|
<Avatar imageSrc={avatarSrc} text={name} bgColor={color} size="extra-small" />
|
||||||
<Text className="people-selector__name" variant="b1">{name}</Text>
|
<Text className="people-selector__name" variant="b1">{name}</Text>
|
||||||
{peopleRole !== null && <Text className="people-selector__role" variant="b3">{peopleRole}</Text>}
|
{peopleRole !== null && <Text className="people-selector__role" variant="b3">{peopleRole}</Text>}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function RoomIntro({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="room-intro">
|
<div className="room-intro">
|
||||||
<Avatar imageSrc={avatarSrc} text={name.slice(0, 1)} bgColor={colorMXID(roomId)} size="large" />
|
<Avatar imageSrc={avatarSrc} text={name} bgColor={colorMXID(roomId)} size="large" />
|
||||||
<div className="room-intro__content">
|
<div className="room-intro__content">
|
||||||
<Text className="room-intro__name" variant="h1">{heading}</Text>
|
<Text className="room-intro__name" variant="h1">{heading}</Text>
|
||||||
<Text className="room-intro__desc" variant="b1">{linkifyContent(desc)}</Text>
|
<Text className="room-intro__desc" variant="b1">{linkifyContent(desc)}</Text>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function RoomSelector({
|
|||||||
content={(
|
content={(
|
||||||
<>
|
<>
|
||||||
<Avatar
|
<Avatar
|
||||||
text={name.slice(0, 1)}
|
text={name}
|
||||||
bgColor={colorMXID(roomId)}
|
bgColor={colorMXID(roomId)}
|
||||||
imageSrc={imageSrc}
|
imageSrc={imageSrc}
|
||||||
iconSrc={iconSrc}
|
iconSrc={iconSrc}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function RoomTile({
|
|||||||
<Avatar
|
<Avatar
|
||||||
imageSrc={avatarSrc}
|
imageSrc={avatarSrc}
|
||||||
bgColor={colorMXID(id)}
|
bgColor={colorMXID(id)}
|
||||||
text={name.slice(0, 1)}
|
text={name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="room-tile__content">
|
<div className="room-tile__content">
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function ProfileAvatarMenu() {
|
|||||||
tooltip={profile.displayName}
|
tooltip={profile.displayName}
|
||||||
imageSrc={profile.avatarUrl !== null ? mx.mxcUrlToHttp(profile.avatarUrl, 42, 42, 'crop') : null}
|
imageSrc={profile.avatarUrl !== null ? mx.mxcUrlToHttp(profile.avatarUrl, 42, 42, 'crop') : null}
|
||||||
bgColor={colorMXID(mx.getUserId())}
|
bgColor={colorMXID(mx.getUserId())}
|
||||||
text={profile.displayName.slice(0, 1)}
|
text={profile.displayName}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -190,7 +190,7 @@ function SideBar() {
|
|||||||
tooltip={room.name}
|
tooltip={room.name}
|
||||||
bgColor={colorMXID(room.roomId)}
|
bgColor={colorMXID(room.roomId)}
|
||||||
imageSrc={room.getAvatarUrl(initMatrix.matrixClient.baseUrl, 42, 42, 'crop') || null}
|
imageSrc={room.getAvatarUrl(initMatrix.matrixClient.baseUrl, 42, 42, 'crop') || null}
|
||||||
text={room.name.slice(0, 1)}
|
text={room.name}
|
||||||
isUnread={notifications.hasNoti(sRoomId)}
|
isUnread={notifications.hasNoti(sRoomId)}
|
||||||
notificationCount={abbreviateNumber(notifications.getTotalNoti(sRoomId))}
|
notificationCount={abbreviateNumber(notifications.getTotalNoti(sRoomId))}
|
||||||
isAlert={notifications.getHighlightNoti(sRoomId) !== 0}
|
isAlert={notifications.getHighlightNoti(sRoomId) !== 0}
|
||||||
|
|||||||
@@ -249,15 +249,15 @@ function ProfileViewer() {
|
|||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
function renderProfile() {
|
function renderProfile() {
|
||||||
const member = room.getMember(userId) || mx.getUser(userId);
|
const member = room.getMember(userId) || mx.getUser(userId) || {};
|
||||||
const avatarMxc = member.getMxcAvatarUrl() || member.avatarUrl;
|
const avatarMxc = member.getMxcAvatarUrl?.() || member.avatarUrl;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="profile-viewer">
|
<div className="profile-viewer">
|
||||||
<div className="profile-viewer__user">
|
<div className="profile-viewer__user">
|
||||||
<Avatar
|
<Avatar
|
||||||
imageSrc={!avatarMxc ? null : mx.mxcUrlToHttp(avatarMxc, 80, 80, 'crop')}
|
imageSrc={!avatarMxc ? null : mx.mxcUrlToHttp(avatarMxc, 80, 80, 'crop')}
|
||||||
text={username.slice(0, 1)}
|
text={username}
|
||||||
bgColor={colorMXID(userId)}
|
bgColor={colorMXID(userId)}
|
||||||
size="large"
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import dateFormat from 'dateformat';
|
|||||||
import initMatrix from '../../../client/initMatrix';
|
import initMatrix from '../../../client/initMatrix';
|
||||||
import cons from '../../../client/state/cons';
|
import cons from '../../../client/state/cons';
|
||||||
import { redactEvent, sendReaction } from '../../../client/action/roomTimeline';
|
import { redactEvent, sendReaction } from '../../../client/action/roomTimeline';
|
||||||
import { getUsername, getUsernameOfRoomMember, doesRoomHaveUnread } from '../../../util/matrixUtil';
|
import { getUsername, getUsernameOfRoomMember } from '../../../util/matrixUtil';
|
||||||
import colorMXID from '../../../util/colorMXID';
|
import colorMXID from '../../../util/colorMXID';
|
||||||
import { diffMinutes, isNotInSameDay, getEventCords } from '../../../util/common';
|
import { diffMinutes, isNotInSameDay, getEventCords } from '../../../util/common';
|
||||||
import { openEmojiBoard, openProfileViewer, openReadReceipts } from '../../../client/action/navigation';
|
import { openEmojiBoard, openProfileViewer, openReadReceipts } from '../../../client/action/navigation';
|
||||||
@@ -191,6 +191,7 @@ function RoomViewContent({
|
|||||||
const [onPagination, setOnPagination] = useState(null);
|
const [onPagination, setOnPagination] = useState(null);
|
||||||
const [editEvent, setEditEvent] = useState(null);
|
const [editEvent, setEditEvent] = useState(null);
|
||||||
const mx = initMatrix.matrixClient;
|
const mx = initMatrix.matrixClient;
|
||||||
|
const noti = initMatrix.notifications;
|
||||||
|
|
||||||
function autoLoadTimeline() {
|
function autoLoadTimeline() {
|
||||||
if (timelineScroll.isScrollable() === true) return;
|
if (timelineScroll.isScrollable() === true) return;
|
||||||
@@ -199,7 +200,7 @@ function RoomViewContent({
|
|||||||
function trySendingReadReceipt() {
|
function trySendingReadReceipt() {
|
||||||
const { room, timeline } = roomTimeline;
|
const { room, timeline } = roomTimeline;
|
||||||
if (
|
if (
|
||||||
(doesRoomHaveUnread(room) || initMatrix.notifications.hasNoti(roomId))
|
(noti.doesRoomHaveUnread(room) || noti.hasNoti(roomId))
|
||||||
&& timeline.length !== 0) {
|
&& timeline.length !== 0) {
|
||||||
mx.sendReadReceipt(timeline[timeline.length - 1]);
|
mx.sendReadReceipt(timeline[timeline.length - 1]);
|
||||||
}
|
}
|
||||||
@@ -282,6 +283,7 @@ function RoomViewContent({
|
|||||||
|
|
||||||
let content = mEvent.getContent().body;
|
let content = mEvent.getContent().body;
|
||||||
if (typeof content === 'undefined') return null;
|
if (typeof content === 'undefined') return null;
|
||||||
|
const msgType = mEvent.getContent()?.msgtype;
|
||||||
let reply = null;
|
let reply = null;
|
||||||
let reactions = null;
|
let reactions = null;
|
||||||
let isMarkdown = mEvent.getContent().format === 'org.matrix.custom.html';
|
let isMarkdown = mEvent.getContent().format === 'org.matrix.custom.html';
|
||||||
@@ -356,7 +358,7 @@ function RoomViewContent({
|
|||||||
<button type="button" onClick={() => openProfileViewer(mEvent.sender.userId, roomId)}>
|
<button type="button" onClick={() => openProfileViewer(mEvent.sender.userId, roomId)}>
|
||||||
<Avatar
|
<Avatar
|
||||||
imageSrc={mEvent.sender.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop')}
|
imageSrc={mEvent.sender.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop')}
|
||||||
text={getUsernameOfRoomMember(mEvent.sender).slice(0, 1)}
|
text={getUsernameOfRoomMember(mEvent.sender)}
|
||||||
bgColor={senderMXIDColor}
|
bgColor={senderMXIDColor}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
@@ -379,8 +381,10 @@ function RoomViewContent({
|
|||||||
);
|
);
|
||||||
const userContent = (
|
const userContent = (
|
||||||
<MessageContent
|
<MessageContent
|
||||||
|
senderName={getUsernameOfRoomMember(mEvent.sender)}
|
||||||
isMarkdown={isMarkdown}
|
isMarkdown={isMarkdown}
|
||||||
content={isMedia(mEvent) ? genMediaContent(mEvent) : content}
|
content={isMedia(mEvent) ? genMediaContent(mEvent) : content}
|
||||||
|
msgType={msgType}
|
||||||
isEdited={isEdited}
|
isEdited={isEdited}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -496,6 +500,7 @@ function RoomViewContent({
|
|||||||
header={userHeader}
|
header={userHeader}
|
||||||
reply={userReply}
|
reply={userReply}
|
||||||
content={editEvent !== null && isEditingEvent ? null : userContent}
|
content={editEvent !== null && isEditingEvent ? null : userContent}
|
||||||
|
msgType={msgType}
|
||||||
editContent={editEvent !== null && isEditingEvent ? (
|
editContent={editEvent !== null && isEditingEvent ? (
|
||||||
<MessageEdit
|
<MessageEdit
|
||||||
content={content}
|
content={content}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function RoomViewHeader({ roomId }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Header>
|
<Header>
|
||||||
<Avatar imageSrc={avatarSrc} text={roomName.slice(0, 1)} bgColor={colorMXID(roomId)} size="small" />
|
<Avatar imageSrc={avatarSrc} text={roomName} bgColor={colorMXID(roomId)} size="small" />
|
||||||
<TitleWrapper>
|
<TitleWrapper>
|
||||||
<Text variant="h2">{roomName}</Text>
|
<Text variant="h2">{roomName}</Text>
|
||||||
{ typeof roomTopic !== 'undefined' && <p title={roomTopic} className="text text-b3">{roomTopic}</p>}
|
{ typeof roomTopic !== 'undefined' && <p title={roomTopic} className="text text-b3">{roomTopic}</p>}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ function Login({ loginFlow, baseUrl }) {
|
|||||||
const [typeIndex, setTypeIndex] = useState(0);
|
const [typeIndex, setTypeIndex] = useState(0);
|
||||||
const loginTypes = ['Username', 'Email'];
|
const loginTypes = ['Username', 'Email'];
|
||||||
const isPassword = loginFlow?.filter((flow) => flow.type === 'm.login.password')[0];
|
const isPassword = loginFlow?.filter((flow) => flow.type === 'm.login.password')[0];
|
||||||
const ssoProviders = loginFlow?.filter((flow) => flow.type.match(/^m.login.(sso|cas)$/))[0];
|
const ssoProviders = loginFlow?.filter((flow) => flow.type === 'm.login.sso')[0];
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
username: '', password: '', email: '', other: '',
|
username: '', password: '', email: '', other: '',
|
||||||
@@ -248,7 +248,7 @@ function Login({ loginFlow, baseUrl }) {
|
|||||||
{ssoProviders && isPassword && <Text className="sso__divider">OR</Text>}
|
{ssoProviders && isPassword && <Text className="sso__divider">OR</Text>}
|
||||||
{ssoProviders && (
|
{ssoProviders && (
|
||||||
<SSOButtons
|
<SSOButtons
|
||||||
type={ssoProviders.type.match(/^m.login.(sso|cas)$/)[1]}
|
type="sso"
|
||||||
identityProviders={ssoProviders.identity_providers}
|
identityProviders={ssoProviders.identity_providers}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
/>
|
/>
|
||||||
@@ -269,7 +269,7 @@ function Register({ registerInfo, loginFlow, baseUrl }) {
|
|||||||
const [process, setProcess] = useState({});
|
const [process, setProcess] = useState({});
|
||||||
const formRef = useRef();
|
const formRef = useRef();
|
||||||
|
|
||||||
const ssoProviders = loginFlow?.filter((flow) => flow.type.match(/^m.login.(sso|cas)$/))[0];
|
const ssoProviders = loginFlow?.filter((flow) => flow.type === 'm.login.sso')[0];
|
||||||
const isDisabled = registerInfo.errcode !== undefined;
|
const isDisabled = registerInfo.errcode !== undefined;
|
||||||
const { flows, params, session } = registerInfo;
|
const { flows, params, session } = registerInfo;
|
||||||
|
|
||||||
@@ -332,8 +332,8 @@ function Register({ registerInfo, loginFlow, baseUrl }) {
|
|||||||
actions.setSubmitting(false);
|
actions.setSubmitting(false);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
const msg = err.message || err.error;
|
const msg = err.message || err.error;
|
||||||
if (['M_USER_IN_USE', 'M_INVALID_USERNAME', 'M_EXCLUSIVE'].indexOf(err.errcode) > 0) {
|
if (['M_USER_IN_USE', 'M_INVALID_USERNAME', 'M_EXCLUSIVE'].indexOf(err.errcode) > -1) {
|
||||||
actions.setErrors({ username: err.errCode === 'M_USER_IN_USE' ? 'Username is already taken' : msg });
|
actions.setErrors({ username: err.errcode === 'M_USER_IN_USE' ? 'Username is already taken' : msg });
|
||||||
} else if (msg) actions.setErrors({ other: msg });
|
} else if (msg) actions.setErrors({ other: msg });
|
||||||
|
|
||||||
actions.setSubmitting(false);
|
actions.setSubmitting(false);
|
||||||
@@ -452,7 +452,7 @@ function Register({ registerInfo, loginFlow, baseUrl }) {
|
|||||||
)}
|
)}
|
||||||
{isDisabled && ssoProviders && (
|
{isDisabled && ssoProviders && (
|
||||||
<SSOButtons
|
<SSOButtons
|
||||||
type={ssoProviders.type.match(/^m.login.(sso|cas)$/)[1]}
|
type="sso"
|
||||||
identityProviders={ssoProviders.identity_providers}
|
identityProviders={ssoProviders.identity_providers}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.auth__base {
|
.auth__base {
|
||||||
--pattern-size: 48px;
|
--pattern-size: 48px;
|
||||||
min-height: 100vh;
|
min-height: 100%;
|
||||||
background-color: var(--bg-surface-low);
|
background-color: var(--bg-surface-low);
|
||||||
|
|
||||||
background-image: radial-gradient(rgba(0, 0, 0, 6%) 2px, rgba(0, 0, 0, 0%) 2px);
|
background-image: radial-gradient(rgba(0, 0, 0, 6%) 2px, rgba(0, 0, 0, 0%) 2px);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -75,7 +75,10 @@ async function completeRegisterStage(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await tempClient.registerRequest({
|
const result = await tempClient.registerRequest({
|
||||||
username, password, auth,
|
username,
|
||||||
|
password,
|
||||||
|
auth,
|
||||||
|
initial_device_display_name: cons.DEVICE_DISPLAY_NAME,
|
||||||
});
|
});
|
||||||
const data = { completed: result.completed || [] };
|
const data = { completed: result.completed || [] };
|
||||||
if (result.access_token) {
|
if (result.access_token) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class InitMatrix extends EventEmitter {
|
|||||||
sessionStore: new sdk.WebStorageSessionStore(global.localStorage),
|
sessionStore: new sdk.WebStorageSessionStore(global.localStorage),
|
||||||
cryptoStore: new sdk.IndexedDBCryptoStore(global.indexedDB, 'crypto-store'),
|
cryptoStore: new sdk.IndexedDBCryptoStore(global.indexedDB, 'crypto-store'),
|
||||||
deviceId: secret.deviceId,
|
deviceId: secret.deviceId,
|
||||||
|
timelineSupport: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.matrixClient.initCrypto();
|
await this.matrixClient.initCrypto();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const cons = {
|
const cons = {
|
||||||
version: '1.5.0',
|
version: '1.5.1',
|
||||||
secretKey: {
|
secretKey: {
|
||||||
ACCESS_TOKEN: 'cinny_access_token',
|
ACCESS_TOKEN: 'cinny_access_token',
|
||||||
DEVICE_ID: 'cinny_device_id',
|
DEVICE_ID: 'cinny_device_id',
|
||||||
|
|||||||
@@ -290,7 +290,13 @@ button {
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
}
|
}
|
||||||
textarea, input[type="text"] {
|
textarea,
|
||||||
|
input,
|
||||||
|
input[type],
|
||||||
|
input[type=text],
|
||||||
|
input[type=username],
|
||||||
|
input[type=password],
|
||||||
|
input[type=email] {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|||||||
@@ -48,30 +48,6 @@ async function isRoomAliasAvailable(alias) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doesRoomHaveUnread(room) {
|
|
||||||
const userId = initMatrix.matrixClient.getUserId();
|
|
||||||
const readUpToId = room.getEventReadUpTo(userId);
|
|
||||||
const supportEvents = ['m.room.message', 'm.room.encrypted', 'm.sticker'];
|
|
||||||
|
|
||||||
if (room.timeline.length
|
|
||||||
&& room.timeline[room.timeline.length - 1].sender
|
|
||||||
&& room.timeline[room.timeline.length - 1].sender.userId === userId
|
|
||||||
&& room.timeline[room.timeline.length - 1].getType() !== 'm.room.member') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = room.timeline.length - 1; i >= 0; i -= 1) {
|
|
||||||
const event = room.timeline[i];
|
|
||||||
|
|
||||||
if (event.getId() === readUpToId) return false;
|
|
||||||
|
|
||||||
if (supportEvents.includes(event.getType())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPowerLabel(powerLevel) {
|
function getPowerLabel(powerLevel) {
|
||||||
if (powerLevel > 9000) return 'Goku';
|
if (powerLevel > 9000) return 'Goku';
|
||||||
if (powerLevel > 100) return 'Founder';
|
if (powerLevel > 100) return 'Founder';
|
||||||
@@ -82,5 +58,5 @@ function getPowerLabel(powerLevel) {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
getBaseUrl, getUsername, getUsernameOfRoomMember,
|
getBaseUrl, getUsername, getUsernameOfRoomMember,
|
||||||
isRoomAliasAvailable, doesRoomHaveUnread, getPowerLabel,
|
isRoomAliasAvailable, getPowerLabel,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
||||||
const webpack = require('webpack');
|
|
||||||
const CopyPlugin = require("copy-webpack-plugin");
|
const CopyPlugin = require("copy-webpack-plugin");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@@ -66,9 +65,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': JSON.stringify(process.env),
|
|
||||||
}),
|
|
||||||
new CopyPlugin({
|
new CopyPlugin({
|
||||||
patterns: [
|
patterns: [
|
||||||
{ from: 'olm.wasm' },
|
{ from: 'olm.wasm' },
|
||||||
|
|||||||
Reference in New Issue
Block a user