Compare commits

...

13 Commits

Author SHA1 Message Date
Ajay Bura
a6fdf9010b v2.0.2 2022-05-14 09:38:58 +05:30
Ajay Bura
941dae0625 Remove globally exposed var 2022-05-14 08:28:31 +05:30
Ajay Bura
4a715bfd17 Fix pasting not working #551 2022-05-14 08:24:21 +05:30
Ajay Bura
0b70c7e490 v2.0.1 2022-05-13 16:39:54 +05:30
Ajay Bura
0539836714 Fix space and enter focus message field 2022-05-13 15:38:18 +05:30
Ash
c08b0e654b Add allowCustomHomeservers config option (#525)
* feat: Add allowCustomHomeservers config option

* fix: Do not lock the homeserver input when the selection is changed
2022-05-12 17:13:14 +05:30
Dean Bassett
b3cb48319a Add the ability to focus on paste (#545)
* pasting should focus the message field

also refactored a small amount to use KeyEvent.code
instead of KeyEvent.keyCode, which is deprecated.

fixes ajbura/cinny#544

* fix lint

* comments
2022-05-12 16:58:19 +05:30
Ajay Bura
44553cc375 Fix crash in room without create state event (#546) 2022-05-12 16:32:39 +05:30
Ajay Bura
fbe287a702 Fix message edit isn't reflected in reply #421 2022-05-12 13:45:23 +05:30
Ajay Bura
5863dcdf67 Fix join with alias (#533) 2022-05-11 20:56:49 +05:30
Ajay Bura
f77bee25ef Remove forget room on leave 2022-05-11 20:53:21 +05:30
Ajay Bura
c11328a064 Fix crash on leaving room (#532) 2022-05-11 20:25:54 +05:30
Ajay Bura
d04de2fba0 Add badges 2022-05-08 13:52:05 +05:30
12 changed files with 81 additions and 32 deletions

View File

@@ -1,5 +1,10 @@
# Cinny # Cinny
[![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 ## Table of Contents
- [About](#about) - [About](#about)

View File

@@ -7,5 +7,6 @@
"kde.org", "kde.org",
"matrix.org", "matrix.org",
"chat.mozilla.org" "chat.mozilla.org"
] ],
"allowCustomHomeservers": true
} }

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cinny", "name": "cinny",
"version": "2.0.0", "version": "2.0.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cinny", "name": "cinny",
"version": "2.0.0", "version": "2.0.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fontsource/inter": "^4.5.10", "@fontsource/inter": "^4.5.10",

View File

@@ -1,6 +1,6 @@
{ {
"name": "cinny", "name": "cinny",
"version": "2.0.0", "version": "2.0.2",
"description": "Yet another matrix client", "description": "Yet another matrix client",
"main": "index.js", "main": "index.js",
"engines": { "engines": {

View File

@@ -123,17 +123,26 @@ const MessageReplyWrapper = React.memo(({ roomTimeline, eventId }) => {
const eTimeline = await mx.getEventTimeline(timelineSet, eventId); const eTimeline = await mx.getEventTimeline(timelineSet, eventId);
await roomTimeline.decryptAllEventsOfTimeline(eTimeline); await roomTimeline.decryptAllEventsOfTimeline(eTimeline);
const mEvent = eTimeline.getTimelineSet().findEventById(eventId); let mEvent = eTimeline.getTimelineSet().findEventById(eventId);
const editedList = roomTimeline.editedTimeline.get(mEvent.getId());
if (editedList) {
mEvent = editedList[editedList.length - 1];
}
const rawBody = mEvent.getContent().body; const rawBody = mEvent.getContent().body;
const username = getUsernameOfRoomMember(mEvent.sender); const username = getUsernameOfRoomMember(mEvent.sender);
if (isMountedRef.current === false) return; if (isMountedRef.current === false) return;
const fallbackBody = mEvent.isRedacted() ? '*** This message has been deleted ***' : '*** Unable to load reply ***'; 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({ setReply({
to: username, to: username,
color: colorMXID(mEvent.getSender()), color: colorMXID(mEvent.getSender()),
body: parseReply(rawBody)?.body ?? rawBody ?? fallbackBody, body: parsedBody,
event: mEvent, event: mEvent,
}); });
} catch { } catch {

View File

@@ -70,7 +70,7 @@ function RoomVisibility({ roomId }) {
const noSpaceParent = currentState.getStateEvents('m.space.parent').length === 0; const noSpaceParent = currentState.getStateEvents('m.space.parent').length === 0;
const mCreate = currentState.getStateEvents('m.room.create')[0]?.getContent(); const mCreate = currentState.getStateEvents('m.room.create')[0]?.getContent();
const roomVersion = Number(mCreate.room_version); const roomVersion = Number(mCreate?.room_version ?? 0);
const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0; const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel); const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel);

View File

@@ -63,7 +63,7 @@ function JoinAliasContent({ term, requestClose }) {
if (alias.startsWith('#')) { if (alias.startsWith('#')) {
try { try {
const aliasData = await mx.resolveRoomAlias(alias); const aliasData = await mx.resolveRoomAlias(alias);
via = aliasData?.servers || []; via = aliasData?.servers.slice(0, 3) || [];
if (mountStore.getItem()) { if (mountStore.getItem()) {
setProcess(`Joining ${alias}...`); setProcess(`Joining ${alias}...`);
} }

View File

@@ -93,12 +93,13 @@ function Homeserver({ onChange }) {
const result = await (await fetch(configFileUrl, { method: 'GET' })).json(); const result = await (await fetch(configFileUrl, { method: 'GET' })).json();
const selectedHs = result?.defaultHomeserver; const selectedHs = result?.defaultHomeserver;
const hsList = result?.homeserverList; const hsList = result?.homeserverList;
const allowCustom = result?.allowCustomHomeservers ?? true;
if (!hsList?.length > 0 || selectedHs < 0 || selectedHs >= hsList?.length) { if (!hsList?.length > 0 || selectedHs < 0 || selectedHs >= hsList?.length) {
throw new Error(); throw new Error();
} }
setHs({ selected: hsList[selectedHs], list: hsList }); setHs({ selected: hsList[selectedHs], list: hsList, allowCustom: allowCustom });
} catch { } catch {
setHs({ selected: 'matrix.org', list: ['matrix.org'] }); setHs({ selected: 'matrix.org', list: ['matrix.org'], allowCustom: true });
} }
}, []); }, []);
@@ -106,14 +107,15 @@ function Homeserver({ onChange }) {
const { value } = e.target; const { value } = e.target;
setProcess({ isLoading: false }); setProcess({ isLoading: false });
debounce._(async () => { debounce._(async () => {
setHs({ selected: value.trim(), list: hs.list }); setHs({ ...hs, selected: value.trim() });
}, 700)(); }, 700)();
}; };
return ( return (
<> <>
<div className="homeserver-form"> <div className="homeserver-form">
<Input name="homeserver" onChange={handleHsInput} value={hs?.selected} forwardRef={hsRef} label="Homeserver" /> <Input name="homeserver" onChange={handleHsInput} value={hs?.selected} forwardRef={hsRef} label="Homeserver"
disabled={hs === null || !hs.allowCustom} />
<ContextMenu <ContextMenu
placement="right" placement="right"
content={(hideMenu) => ( content={(hideMenu) => (
@@ -126,7 +128,7 @@ function Homeserver({ onChange }) {
onClick={() => { onClick={() => {
hideMenu(); hideMenu();
hsRef.current.value = hsName; hsRef.current.value = hsName;
setHs({ selected: hsName, list: hs.list }); setHs({ ...hs, selected: hsName });
}} }}
> >
{hsName} {hsName}

View File

@@ -118,7 +118,6 @@ async function leave(roomId) {
const isDM = initMatrix.roomList.directs.has(roomId); const isDM = initMatrix.roomList.directs.has(roomId);
try { try {
await mx.leave(roomId); await mx.leave(roomId);
await mx.forget(roomId);
appDispatcher.dispatch({ appDispatcher.dispatch({
type: cons.actions.room.LEAVE, type: cons.actions.room.LEAVE,
roomId, roomId,

View File

@@ -2,25 +2,57 @@ import { openSearch, toggleRoomSettings } from '../action/navigation';
import navigation from '../state/navigation'; import navigation from '../state/navigation';
import { markAsRead } from '../action/notifications'; 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) { function listenKeyboard(event) {
// Ctrl/Cmd + // Ctrl/Cmd +
if (event.ctrlKey || event.metaKey) { if (event.ctrlKey || event.metaKey) {
// k - for search Modal // open search modal
if (event.keyCode === 75) { if (event.code === 'KeyK') {
event.preventDefault(); event.preventDefault();
if (navigation.isRawModalVisible) return; if (navigation.isRawModalVisible) return;
openSearch(); openSearch();
} }
// focus message field on paste
if (event.code === 'KeyV') {
if (navigation.isRawModalVisible) return;
const msgTextarea = document.getElementById('message-textarea');
if (document.activeElement !== msgTextarea && document.activeElement.tagName.toLowerCase() === 'input') return;
msgTextarea?.focus();
}
} }
if (!event.ctrlKey && !event.altKey) { if (!event.ctrlKey && !event.altKey && !event.metaKey) {
if (navigation.isRawModalVisible) return; if (navigation.isRawModalVisible) return;
if (['text', 'textarea'].includes(document.activeElement.type)) { if (document.activeElement.tagName.toLowerCase() === 'input') {
return; return;
} }
// esc if (event.code === 'Escape') {
if (event.keyCode === 27) {
if (navigation.isRoomSettings) { if (navigation.isRoomSettings) {
toggleRoomSettings(); toggleRoomSettings();
return; return;
@@ -31,18 +63,14 @@ function listenKeyboard(event) {
} }
} }
// Don't allow these keys to type/focus message field // focus the text field on most keypresses
if ((event.keyCode !== 8 && event.keyCode < 48) if (shouldFocusMessageField(event.code)) {
|| (event.keyCode >= 91 && event.keyCode <= 93)
|| (event.keyCode >= 112 && event.keyCode <= 183)) {
return;
}
// press any key to focus and type in message field // press any key to focus and type in message field
const msgTextarea = document.getElementById('message-textarea'); const msgTextarea = document.getElementById('message-textarea');
msgTextarea?.focus(); msgTextarea?.focus();
} }
} }
}
function initHotkeys() { function initHotkeys() {
document.body.addEventListener('keydown', listenKeyboard); document.body.addEventListener('keydown', listenKeyboard);

View File

@@ -1,5 +1,5 @@
const cons = { const cons = {
version: '2.0.0', version: '2.0.2',
secretKey: { secretKey: {
ACCESS_TOKEN: 'cinny_access_token', ACCESS_TOKEN: 'cinny_access_token',
DEVICE_ID: 'cinny_device_id', DEVICE_ID: 'cinny_device_id',

View File

@@ -14,7 +14,7 @@ class Navigation extends EventEmitter {
this.isRoomSettings = false; this.isRoomSettings = false;
this.recentRooms = []; this.recentRooms = [];
this.isRawModalVisible = false; this.rawModelStack = [];
} }
_setSpacePath(roomId) { _setSpacePath(roomId) {
@@ -47,8 +47,13 @@ class Navigation extends EventEmitter {
} }
} }
get isRawModalVisible() {
return this.rawModelStack.length > 0;
}
setIsRawModalVisible(visible) { setIsRawModalVisible(visible) {
this.isRawModalVisible = visible; if (visible) this.rawModelStack.push(true);
else this.rawModelStack.pop();
} }
navigate(action) { navigate(action) {