Compare commits

..
1 Commits
Author SHA1 Message Date
Ajay Bura adf53caeff Fix crash in room without create state event 2022-05-12 13:19:34 +05:30
25 changed files with 2081 additions and 2309 deletions

No files matched your search

+1 -2
View File
@@ -1,3 +1,2 @@
github: ajbura
liberapay: ajbura
open_collective: cinny
liberapay: ajbura
+3 -7
View File
@@ -12,26 +12,22 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Setup node
uses: actions/setup-node@v3.3.0
with:
node-version: 17.9.0
- name: Build app
run: npm ci && npm run build
- name: Upload artifact
uses: actions/upload-artifact@v3.1.0
uses: actions/upload-artifact@v3.0.0
with:
name: previewbuild
path: dist
retention-days: 1
- name: Get PR info
uses: actions/github-script@v6.1.0
uses: actions/github-script@v6.0.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@v3.1.0
uses: actions/upload-artifact@v3.0.0
with:
name: pr.json
path: pr.json
+2 -5
View File
@@ -6,9 +6,6 @@ on:
- completed
jobs:
get-build-and-deploy:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
if: >
${{ github.event.workflow_run.conclusion == 'success' }}
@@ -17,7 +14,7 @@ jobs:
# workflow_run action (https://github.com/actions/download-artifact/issues/60)
# so instead we get this mess:
- name: Download artifact
uses: actions/github-script@v6.1.0
uses: actions/github-script@v6.0.0
with:
script: |
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
@@ -51,7 +48,7 @@ jobs:
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@v6.1.0
uses: actions/github-script@v6.0.0
with:
script: |
var fs = require('fs');
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Build Docker image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v2.10.0
with:
context: .
push: false
+2 -7
View File
@@ -9,17 +9,12 @@ jobs:
deploy-to-netlify:
name: 'Deploy'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Setup node
uses: actions/setup-node@v3.3.0
with:
node-version: 17.9.0
- name: Build and deploy to Netlify
uses: jsmrcaga/action-netlify-deploy@53de32e559b0b3833615b9788c7a090cd2fddb03
uses: jsmrcaga/action-netlify-deploy@fb6a5f936a4b06a8f7793e69fc5a022ffe39807a
with:
install_command: "npm ci"
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
+23 -54
View File
@@ -5,56 +5,14 @@ on:
types: [published]
jobs:
create-release-tar:
name: 'Create release tar'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Setup node
uses: actions/setup-node@v3.3.0
with:
node-version: 17.9.0
- name: Build
run: |
npm ci
npm run build
- name: Get version from tag
id: vars
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
- name: Create tar.gz
run: tar -czvf cinny-${{ steps.vars.outputs.tag }}.tar.gz dist
- name: Sign tar.gz
run: |
echo '${{ secrets.GNUPG_KEY }}' | gpg --batch --import
# Sadly a few lines in the private key match a few lines in the public key,
# As a result just --export --armor gives us a few lines replaced with ***
# making it useless for importing the signing key. Instead, we dump it as
# non-armored and hex-encode it so that its printable.
echo "PGP Signing key, in raw PGP format in hex. Import with cat ... | xxd -r -p - | gpg --import"
gpg --export | xxd -p
echo '${{ secrets.GNUPG_PASSPHRASE }}' | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --armor --detach-sign cinny-${{ steps.vars.outputs.tag }}.tar.gz
- name: Upload tagged release
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
with:
files: |
cinny-${{ steps.vars.outputs.tag }}.tar.gz
cinny-${{ steps.vars.outputs.tag }}.tar.gz.asc
deploy-to-netlify:
name: 'Deploy to Netlify'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Setup node
uses: actions/setup-node@v3.3.0
with:
node-version: 17.9.0
- name: Build and deploy to Netlify
uses: jsmrcaga/action-netlify-deploy@53de32e559b0b3833615b9788c7a090cd2fddb03
uses: jsmrcaga/action-netlify-deploy@fb6a5f936a4b06a8f7793e69fc5a022ffe39807a
with:
install_command: "npm ci"
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
@@ -62,34 +20,45 @@ jobs:
BUILD_DIRECTORY: "dist"
NETLIFY_DEPLOY_MESSAGE: "Prod deploy v${{ github.ref }}"
NETLIFY_DEPLOY_TO_PROD: true
- name: Get version from tag
id: vars
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
- name: Create tar.gz
run: tar -czvf cinny-${{ steps.vars.outputs.tag }}.tar.gz dist
- name: Sign tar.gz
uses: actionhippie/gpgsign@4e28208b142cae93e1582401dcda1cf79e4f72c0
with:
private_key: ${{ secrets.GNUPG_KEY }}
passphrase: ${{ secrets.GNUPG_PASSPHRASE }}
detach_sign: true
files: cinny-${{ steps.vars.outputs.tag }}.tar.gz
- name: Upload tagged release
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
with:
files: |
cinny-${{ steps.vars.outputs.tag }}.tar.gz
cinny-${{ steps.vars.outputs.tag }}.tar.gz.asc
push-to-dockerhub:
push_to_dockerhub:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to Docker Hub
uses: docker/login-action@v2.0.0
uses: docker/login-action@v1.14.1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4.0.1
uses: docker/metadata-action@v3.8.0
with:
images: ajbura/cinny
- name: Build and push Docker image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v2.10.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+1 -1
View File
@@ -10,7 +10,7 @@ RUN npm run build
## App
FROM nginx:1.23.0-alpine
FROM nginx:1.21.6-alpine
COPY --from=builder /src/dist /app
+16 -70
View File
@@ -1,27 +1,23 @@
<p align="center">
<img src="https://raw.githubusercontent.com/ajbura/cinny/dev/public/res/svg/cinny.svg?sanitize=true"
height="16">
<span><b>Cinny</b></span>
</p>
<p align="center">
<a href="https://github.com/ajbura/cinny/releases">
<img alt="GitHub release downloads" src="https://img.shields.io/github/downloads/ajbura/cinny/total?logo=github&style=social"></a>
<a href="https://hub.docker.com/r/ajbura/cinny">
<img alt="DockerHub downloads" src="https://img.shields.io/docker/pulls/ajbura/cinny?logo=docker&style=social"></a>
<a href="https://fosstodon.org/@cinnyapp">
<img alt="Follow on Mastodon" src="https://img.shields.io/mastodon/follow/106845779685925461?domain=https%3A%2F%2Ffosstodon.org&logo=mastodon&style=social"></a>
<a href="https://twitter.com/intent/follow?screen_name=cinnyapp">
<img alt="Follow on Twitter" src="https://img.shields.io/twitter/follow/cinnyapp?logo=twitter&style=social"></a>
<a href="https://cinny.in/#sponsor">
<img alt="Sponsor Cinny" src="https://img.shields.io/opencollective/all/cinny?logo=opencollective&style=social"></a>
</p>
# Cinny
**Cinny** is a Matrix client focusing primarily on simple, elegant and secure interface. The main goal is to have a client that is easy on end user
and feels a modern chat application.
[![Star](https://img.shields.io/github/stars/ajbura/cinny)](https://github.com/ajbura/cinny/tree/dev)
[![Chat](https://img.shields.io/badge/chat-on%20matrix-orange)](https://matrix.to/#/#cinny:matrix.org)
[![Twitter](https://img.shields.io/twitter/url?url=https://twitter.com/@cinnyapp)](https://twitter.com/@cinnyapp)
[![Support](https://img.shields.io/badge/sponsor-open%20collective-blue.svg)](https://opencollective.com/cinny)
## Table of Contents
- [About](#about)
- [Getting Started](https://cinny.in)
- [Contributing](./CONTRIBUTING.md)
- [Roadmap](https://github.com/ajbura/cinny/projects/11)
## About <a name = "about"></a>
Cinny is a [Matrix](https://matrix.org) client focusing primarily on simple, elegant and secure interface.
![preview](https://github.com/cinnyapp/cinny-site/blob/main/assets/preview-light.png)
## Building and Running
### Running pre-compiled
@@ -29,57 +25,7 @@ and feels a modern chat application.
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.
<details>
<summary>PGP Public Key to verify pre-compiled tarball</summary>
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
UeGsouhyuITLwEhScounZDqop+Dx
=Zg+6
-----END PGP PUBLIC KEY BLOCK-----
```
</details>
### Building from source
> We recommend using a version manager as versions change very quickly. You will likely need to switch
between multiple Node.js versions based on the needs of different projects you're working on. [NVM on windows](https://github.com/coreybutler/nvm-windows#installation--upgrades) on Windows and [nvm](https://github.com/nvm-sh/nvm) on Linux/macOS are pretty good choices. Also recommended nodejs version is 16.15.0 LTS.
Execute the following commands to compile the app from its source code:
@@ -90,7 +36,7 @@ npm run build # Compiles the app into the dist/ directory
You can then copy the files to a webserver's webroot of your choice.
To serve a development version of the app locally for testing, you need to use the command `npm start`.
To serve a development version of the app locally for testing, you may also use the command `npm start`.
### Running with Docker
+3 -4
View File
@@ -6,7 +6,6 @@
"halogen.city",
"kde.org",
"matrix.org",
"mozilla.org"
],
"allowCustomHomeservers": true
}
"chat.mozilla.org"
]
}
+1958 -2037
View File
File diff suppressed because it is too large. Load diff
+24 -24
View File
@@ -1,11 +1,11 @@
{
"name": "cinny",
"version": "2.0.4",
"version": "2.0.0",
"description": "Yet another matrix client",
"main": "index.js",
"engines": {
"npm": ">=6.14.8 <=8.5.5",
"node": ">=14.15.0 <=17.9.0"
"npm": ">=6.14.11",
"node": ">=14.6.0"
},
"scripts": {
"start": "webpack serve --config ./webpack.dev.js --open",
@@ -15,8 +15,8 @@
"author": "Ajay Bura",
"license": "MIT",
"dependencies": {
"@fontsource/inter": "^4.5.11",
"@fontsource/roboto": "^4.5.7",
"@fontsource/inter": "^4.5.10",
"@fontsource/roboto": "^4.5.5",
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
"@tippyjs/react": "^4.2.6",
"babel-polyfill": "^6.26.0",
@@ -26,10 +26,10 @@
"file-saver": "^2.0.5",
"flux": "^4.0.3",
"formik": "^2.2.9",
"html-react-parser": "^2.0.0",
"katex": "^0.15.6",
"html-react-parser": "^1.4.12",
"katex": "^0.15.3",
"linkifyjs": "^2.1.9",
"matrix-js-sdk": "^18.1.0",
"matrix-js-sdk": "^17.1.0",
"micromark": "^3.0.10",
"micromark-extension-gfm": "^2.0.1",
"micromark-extension-math": "^2.0.2",
@@ -49,39 +49,39 @@
"twemoji": "^14.0.2"
},
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@babel/core": "^7.17.10",
"@babel/preset-env": "^7.17.10",
"@babel/preset-react": "^7.16.7",
"assert": "^2.0.0",
"babel-loader": "^8.2.5",
"browserify-fs": "^1.0.0",
"buffer": "^6.0.3",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"copy-webpack-plugin": "^10.2.4",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.0.0",
"eslint": "^8.19.0",
"css-minimizer-webpack-plugin": "^3.4.1",
"eslint": "^8.14.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.5.0",
"favicons": "^6.2.2",
"favicons-webpack-plugin": "^5.0.2",
"html-loader": "^3.1.2",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^2.6.1",
"mini-css-extract-plugin": "^2.6.0",
"path-browserify": "^1.0.1",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"url": "^0.11.0",
"util": "^0.12.4",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0",
"webpack-merge": "^5.7.3"
}
}
+2 -11
View File
@@ -123,26 +123,17 @@ const MessageReplyWrapper = React.memo(({ roomTimeline, eventId }) => {
const eTimeline = await mx.getEventTimeline(timelineSet, eventId);
await roomTimeline.decryptAllEventsOfTimeline(eTimeline);
let mEvent = eTimeline.getTimelineSet().findEventById(eventId);
const editedList = roomTimeline.editedTimeline.get(mEvent.getId());
if (editedList) {
mEvent = editedList[editedList.length - 1];
}
const mEvent = eTimeline.getTimelineSet().findEventById(eventId);
const rawBody = mEvent.getContent().body;
const username = getUsernameOfRoomMember(mEvent.sender);
if (isMountedRef.current === false) return;
const fallbackBody = mEvent.isRedacted() ? '*** This message has been deleted ***' : '*** Unable to load reply ***';
let parsedBody = parseReply(rawBody)?.body ?? rawBody ?? fallbackBody;
if (editedList && parsedBody.startsWith(' * ')) {
parsedBody = parsedBody.slice(3);
}
setReply({
to: username,
color: colorMXID(mEvent.getSender()),
body: parsedBody,
body: parseReply(rawBody)?.body ?? rawBody ?? fallbackBody,
event: mEvent,
});
} catch {
@@ -118,7 +118,7 @@ function RoomAliases({ roomId }) {
const loadLocalAliases = async () => {
let local = [];
try {
const result = await mx.getLocalAliases(roomId);
const result = await mx.unstableGetLocalAliases(roomId);
local = result.aliases.filter((alias) => !aliases.published.includes(alias));
} catch {
local = [];
@@ -20,7 +20,7 @@ const items = [{
type: cons.notifs.DEFAULT,
}, {
iconSrc: BellRingIC,
text: 'All messages',
text: 'All message',
type: cons.notifs.ALL_MESSAGES,
}, {
iconSrc: BellPingIC,
+2 -3
View File
@@ -1,6 +1,5 @@
import emojisData from 'emojibase-data/en/compact.json';
import joypixels from 'emojibase-data/en/shortcodes/joypixels.json';
import emojibase from 'emojibase-data/en/shortcodes/emojibase.json';
import shortcodes from 'emojibase-data/en/shortcodes/joypixels.json';
const emojiGroups = [{
name: 'Smileys & people',
@@ -53,7 +52,7 @@ function addToGroup(emoji) {
const emojis = [];
emojisData.forEach((emoji) => {
const myShortCodes = joypixels[emoji.hexcode] || emojibase[emoji.hexcode];
const myShortCodes = shortcodes[emoji.hexcode];
if (!myShortCodes) return;
const em = {
...emoji,
+1 -1
View File
@@ -4,7 +4,7 @@ import { emojis } from './emoji';
const eventType = 'io.element.recent_emoji';
function getRecentEmojisRaw() {
return initMatrix.matrixClient.getAccountData(eventType)?.getContent().recent_emoji ?? [];
return initMatrix.matrixClient.getAccountData(eventType).getContent().recent_emoji ?? [];
}
export function getRecentEmojis(limit) {
+13 -1
View File
@@ -6,7 +6,7 @@ import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import * as roomActions from '../../../client/action/room';
import { selectRoom } from '../../../client/action/navigation';
import { hasDMWith, hasDevices } from '../../../util/matrixUtil';
import { hasDMWith } from '../../../util/matrixUtil';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
@@ -103,6 +103,18 @@ function InviteUser({
updateIsSearching(false);
}
async function hasDevices(userId) {
try {
const usersDeviceMap = await mx.downloadKeys([userId, mx.getUserId()]);
return Object.values(usersDeviceMap).every((userDevices) =>
Object.keys(userDevices).length > 0,
);
} catch (e) {
console.error("Error determining if it's possible to encrypt to all users: ", e);
return false;
}
}
async function createDM(userId) {
if (mx.getUserId() === userId) return;
const dmRoomId = hasDMWith(userId);
@@ -11,7 +11,7 @@ import { selectRoom, openReusableContextMenu } from '../../../client/action/navi
import * as roomActions from '../../../client/action/room';
import {
getUsername, getUsernameOfRoomMember, getPowerLabel, hasDMWith, hasDevices
getUsername, getUsernameOfRoomMember, getPowerLabel, hasDMWith
} from '../../../util/matrixUtil';
import { getEventCords } from '../../../util/common';
import colorMXID from '../../../util/colorMXID';
@@ -201,7 +201,7 @@ function ProfileFooter({ roomId, userId, onRequestClose }) {
// Create new DM
try {
setIsCreatingDM(true);
await roomActions.createDM(userId, await hasDevices(userId));
await roomActions.createDM(userId);
} catch {
if (isMountedRef.current === false) return;
setIsCreatingDM(false);
+1 -2
View File
@@ -155,7 +155,6 @@ function DeviceManage() {
const lastIP = device.last_seen_ip;
const lastTS = device.last_seen_ts;
const isCurrentDevice = mx.deviceId === deviceId;
const canVerify = isVerified === false && (isMeVerified || isCurrentDevice);
return (
<SettingTile
@@ -172,7 +171,7 @@ function DeviceManage() {
? <Spinner size="small" />
: (
<>
{(isCSEnabled && canVerify) && <Button onClick={() => verify(deviceId, isCurrentDevice)} variant="positive">Verify</Button>}
{((isMeVerified && isVerified === false) || (isCurrentDevice && isVerified === false)) && <Button onClick={() => verify(deviceId, isCurrentDevice)} variant="positive">Verify</Button>}
<IconButton size="small" onClick={() => handleRename(device)} src={PencilIC} tooltip="Rename" />
<IconButton size="small" onClick={() => handleRemove(device)} src={BinIC} tooltip="Remove session" />
</>
+5 -7
View File
@@ -93,13 +93,12 @@ function Homeserver({ onChange }) {
const result = await (await fetch(configFileUrl, { method: 'GET' })).json();
const selectedHs = result?.defaultHomeserver;
const hsList = result?.homeserverList;
const allowCustom = result?.allowCustomHomeservers ?? true;
if (!hsList?.length > 0 || selectedHs < 0 || selectedHs >= hsList?.length) {
throw new Error();
}
setHs({ selected: hsList[selectedHs], list: hsList, allowCustom: allowCustom });
setHs({ selected: hsList[selectedHs], list: hsList });
} catch {
setHs({ selected: 'matrix.org', list: ['matrix.org'], allowCustom: true });
setHs({ selected: 'matrix.org', list: ['matrix.org'] });
}
}, []);
@@ -107,15 +106,14 @@ function Homeserver({ onChange }) {
const { value } = e.target;
setProcess({ isLoading: false });
debounce._(async () => {
setHs({ ...hs, selected: value.trim() });
setHs({ selected: value.trim(), list: hs.list });
}, 700)();
};
return (
<>
<div className="homeserver-form">
<Input name="homeserver" onChange={handleHsInput} value={hs?.selected} forwardRef={hsRef} label="Homeserver"
disabled={hs === null || !hs.allowCustom} />
<Input name="homeserver" onChange={handleHsInput} value={hs?.selected} forwardRef={hsRef} label="Homeserver" />
<ContextMenu
placement="right"
content={(hideMenu) => (
@@ -128,7 +126,7 @@ function Homeserver({ onChange }) {
onClick={() => {
hideMenu();
hsRef.current.value = hsName;
setHs({ ...hs, selected: hsName });
setHs({ selected: hsName, list: hs.list });
}}
>
{hsName}
+15 -46
View File
@@ -2,60 +2,25 @@ import { openSearch, toggleRoomSettings } from '../action/navigation';
import navigation from '../state/navigation';
import { markAsRead } from '../action/notifications';
function shouldFocusMessageField(code) {
// do not focus on F keys
if (/^F\d+$/.test(code)) return false;
// do not focus on numlock/scroll lock
if (
code.metaKey
|| code.startsWith('OS')
|| code.startsWith('Meta')
|| code.startsWith('Shift')
|| code.startsWith('Alt')
|| code.startsWith('Control')
|| code.startsWith('Arrow')
|| code === 'Tab'
|| code === 'Space'
|| code === 'Enter'
|| code === 'NumLock'
|| code === 'ScrollLock'
) {
return false;
}
return true;
}
function listenKeyboard(event) {
// Ctrl/Cmd +
if (event.ctrlKey || event.metaKey) {
// open search modal
if (event.code === 'KeyK') {
// k - for search Modal
if (event.keyCode === 75) {
event.preventDefault();
if (navigation.isRawModalVisible) return;
openSearch();
}
// focus message field on paste
if (event.code === 'KeyV') {
if (navigation.isRawModalVisible) return;
const msgTextarea = document.getElementById('message-textarea');
const { activeElement } = document;
if (activeElement !== msgTextarea
&& ['input', 'textarea'].includes(activeElement.tagName.toLowerCase())
) return;
msgTextarea?.focus();
}
}
if (!event.ctrlKey && !event.altKey && !event.metaKey) {
if (!event.ctrlKey && !event.altKey) {
if (navigation.isRawModalVisible) return;
if (['input', 'textarea'].includes(document.activeElement.tagName.toLowerCase())) {
if (['text', 'textarea'].includes(document.activeElement.type)) {
return;
}
if (event.code === 'Escape') {
// esc
if (event.keyCode === 27) {
if (navigation.isRoomSettings) {
toggleRoomSettings();
return;
@@ -66,12 +31,16 @@ function listenKeyboard(event) {
}
}
// focus the text field on most keypresses
if (shouldFocusMessageField(event.code)) {
// press any key to focus and type in message field
const msgTextarea = document.getElementById('message-textarea');
msgTextarea?.focus();
// Don't allow these keys to type/focus message field
if ((event.keyCode !== 8 && event.keyCode < 48)
|| (event.keyCode >= 91 && event.keyCode <= 93)
|| (event.keyCode >= 112 && event.keyCode <= 183)) {
return;
}
// press any key to focus and type in message field
const msgTextarea = document.getElementById('message-textarea');
msgTextarea?.focus();
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
const cons = {
version: '2.0.4',
version: '2.0.0',
secretKey: {
ACCESS_TOKEN: 'cinny_access_token',
DEVICE_ID: 'cinny_device_id',
+2 -7
View File
@@ -14,7 +14,7 @@ class Navigation extends EventEmitter {
this.isRoomSettings = false;
this.recentRooms = [];
this.rawModelStack = [];
this.isRawModalVisible = false;
}
_setSpacePath(roomId) {
@@ -47,13 +47,8 @@ class Navigation extends EventEmitter {
}
}
get isRawModalVisible() {
return this.rawModelStack.length > 0;
}
setIsRawModalVisible(visible) {
if (visible) this.rawModelStack.push(true);
else this.rawModelStack.pop();
this.isRawModalVisible = visible;
}
navigate(action) {
-13
View File
@@ -199,16 +199,3 @@ export function getSSKeyInfo(key) {
return undefined;
}
}
export async function hasDevices(userId) {
const mx = initMatrix.matrixClient;
try {
const usersDeviceMap = await mx.downloadKeys([userId, mx.getUserId()]);
return Object.values(usersDeviceMap).every((userDevices) =>
Object.keys(userDevices).length > 0,
);
} catch (e) {
console.error("Error determining if it's possible to encrypt to all users: ", e);
return false;
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ function transformSpanTag(tagName, attribs) {
}
function transformATag(tagName, attribs) {
const userLink = decodeURIComponent(attribs.href).match(/^https?:\/\/matrix.to\/#\/(@.+:.+)/);
const userLink = attribs.href.match(/^https?:\/\/matrix.to\/#\/(@.+:.+)/);
if (userLink !== null) {
// convert user link to pill
const userId = userLink[1];