diff --git a/package.json b/package.json index e0883f5556..d6845e0981 100644 --- a/package.json +++ b/package.json @@ -151,7 +151,7 @@ "@typescript-eslint/eslint-plugin": "^4.17.0", "@typescript-eslint/parser": "^4.17.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", - "allchange": "^1.0.0", + "allchange": "^1.0.2", "babel-jest": "^26.6.3", "chokidar": "^3.5.1", "concurrently": "^5.3.0", diff --git a/res/css/_common.scss b/res/css/_common.scss index 5fcc10add0..a16e7d4d8f 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -381,11 +381,6 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { font-size: $font-14px; color: $primary-content; word-wrap: break-word; - - a { - color: $accent-color; - cursor: pointer; - } } .mx_Dialog_buttons { diff --git a/res/css/structures/_ScrollPanel.scss b/res/css/structures/_ScrollPanel.scss index 82caeae29d..a668594bba 100644 --- a/res/css/structures/_ScrollPanel.scss +++ b/res/css/structures/_ScrollPanel.scss @@ -15,8 +15,6 @@ limitations under the License. */ .mx_ScrollPanel { - contain: strict; - .mx_RoomView_MessageList { position: relative; display: flex; diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 1c58dfb95b..447c878f14 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -514,7 +514,7 @@ $hover-select-border: 4px; .mx_EventTile:hover .mx_EventTile_body pre, .mx_EventTile.focus-visible:focus-within .mx_EventTile_body pre { - border: 1px solid #e5e5e5; // deliberate constant as we're behind an invert filter + border: 1px solid $tertiary-content; } .mx_EventTile_pre_container { diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index e11e828864..8fd45c49ae 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -250,7 +250,15 @@ export default class CallHandler extends EventEmitter { * @returns {boolean} */ private areAnyCallsUnsilenced(): boolean { - return this.calls.size > this.silencedCalls.size; + for (const call of this.calls.values()) { + if ( + call.state === CallState.Ringing && + !this.isCallSilenced(call.callId) + ) { + return true; + } + } + return false; } private async checkProtocols(maxTries) { @@ -878,6 +886,8 @@ export default class CallHandler extends EventEmitter { break; case 'hangup': case 'reject': + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + if (!this.calls.get(payload.room_id)) { return; // no call to hangup } @@ -890,11 +900,15 @@ export default class CallHandler extends EventEmitter { // the hangup event away) break; case 'hangup_all': + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + for (const call of this.calls.values()) { call.hangup(CallErrorCode.UserHangup, false); } break; case 'answer': { + this.stopRingingIfPossible(this.calls.get(payload.room_id).callId); + if (!this.calls.has(payload.room_id)) { return; // no call to answer } @@ -929,6 +943,12 @@ export default class CallHandler extends EventEmitter { } }; + private stopRingingIfPossible(callId: string): void { + this.silencedCalls.delete(callId); + if (this.areAnyCallsUnsilenced()) return; + this.pause(AudioID.Ring); + } + private async dialNumber(number: string) { const results = await this.pstnLookup(number); if (!results || results.length === 0 || !results[0].userid) { diff --git a/src/components/structures/LeftPanelWidget.tsx b/src/components/structures/LeftPanelWidget.tsx index 144c0e3051..331e428355 100644 --- a/src/components/structures/LeftPanelWidget.tsx +++ b/src/components/structures/LeftPanelWidget.tsx @@ -115,7 +115,7 @@ const LeftPanelWidget: React.FC = () => { aria-expanded={expanded} aria-level={1} onClick={() => { - setExpanded(e => !e); + setExpanded(!expanded); }} > ; widget: Widget; @@ -97,10 +89,7 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent< }; private closeAndTryRemember(approved: Capability[]) { - if (this.state.rememberSelection) { - setRememberedCapabilitiesForWidget(this.props.widget, approved); - } - this.props.onFinished({ approved }); + this.props.onFinished({ approved, remember: this.state.rememberSelection }); } public render() { diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index d9e97d570b..081b1a8698 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -149,10 +149,12 @@ export default class SecurityRoomSettingsTab extends React.Componentnew encrypted room for " + "the conversation you plan to have.", null, - { "a": (sub) => { - dialog.close(); - this.createNewRoom(false, true); - }}> { sub } }, + { "a": (sub) => { + dialog.close(); + this.createNewRoom(false, true); + }}> { sub } }, ) }

, @@ -248,10 +250,12 @@ export default class SecurityRoomSettingsTab extends React.Component { - dialog.close(); - this.createNewRoom(true, false); - }}> { sub } , + "a": (sub) => { + dialog.close(); + this.createNewRoom(true, false); + }}> { sub } , }, ) }

, diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 45c7d6bd2e..30bea42346 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -34,9 +34,7 @@ import { MatrixClientPeg } from "../../MatrixClientPeg"; import ActiveRoomObserver from "../../ActiveRoomObserver"; import Modal from "../../Modal"; import WidgetOpenIDPermissionsDialog from "../../components/views/dialogs/WidgetOpenIDPermissionsDialog"; -import WidgetCapabilitiesPromptDialog, { - getRememberedCapabilitiesForWidget, -} from "../../components/views/dialogs/WidgetCapabilitiesPromptDialog"; +import WidgetCapabilitiesPromptDialog from "../../components/views/dialogs/WidgetCapabilitiesPromptDialog"; import { WidgetPermissionCustomisations } from "../../customisations/WidgetPermissions"; import { OIDCState, WidgetPermissionStore } from "./WidgetPermissionStore"; import { WidgetType } from "../../widgets/WidgetType"; @@ -50,6 +48,14 @@ import { Room } from "matrix-js-sdk"; // TODO: Purge this from the universe +function getRememberedCapabilitiesForWidget(widget: Widget): Capability[] { + return JSON.parse(localStorage.getItem(`widget_${widget.id}_approved_caps`) || "[]"); +} + +function setRememberedCapabilitiesForWidget(widget: Widget, caps: Capability[]) { + localStorage.setItem(`widget_${widget.id}_approved_caps`, JSON.stringify(caps)); +} + export class StopGapWidgetDriver extends WidgetDriver { private allowedCapabilities: Set; @@ -102,6 +108,7 @@ export class StopGapWidgetDriver extends WidgetDriver { } } // TODO: Do something when the widget requests new capabilities not yet asked for + let rememberApproved = false; if (missing.size > 0) { try { const [result] = await Modal.createTrackedDialog( @@ -113,12 +120,19 @@ export class StopGapWidgetDriver extends WidgetDriver { widgetKind: this.forWidgetKind, }).finished; (result.approved || []).forEach(cap => allowedSoFar.add(cap)); + rememberApproved = result.remember; } catch (e) { console.error("Non-fatal error getting capabilities: ", e); } } - return new Set(iterableUnion(allowedSoFar, requested)); + const allAllowed = new Set(iterableUnion(allowedSoFar, requested)); + + if (rememberApproved) { + setRememberedCapabilitiesForWidget(this.forWidget, Array.from(allAllowed)); + } + + return allAllowed; } public async sendEvent( @@ -136,6 +150,9 @@ export class StopGapWidgetDriver extends WidgetDriver { if (stateKey !== null) { // state event r = await client.sendStateEvent(roomId, eventType, content, stateKey); + } else if (eventType === EventType.RoomRedaction) { + // special case: extract the `redacts` property and call redact + r = await client.redactEvent(roomId, content['redacts']); } else { // message event r = await client.sendEvent(roomId, eventType, content); diff --git a/yarn.lock b/yarn.lock index 80c6ac5155..0c9514ae30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2036,10 +2036,10 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" -allchange@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/allchange/-/allchange-1.0.1.tgz#f32a75f65ab182d044d18e8baa43bd1c9be982f6" - integrity sha512-lj8HZcvQ04RsNqwLWjCYSDvchrW4nnjlOZ3z+VGhA78M7KootV0eRwlvTlYJec73jsz/Ts59kVArgooEsACOog== +allchange@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/allchange/-/allchange-1.0.2.tgz#86b9190e12b7ede4f230ae763cbd504c48fd907b" + integrity sha512-qJv1t2yvBThkes8g/dPMt8CGu+04U+q5QjCJn2Ngp92edZU8DJBfKGyGXo7w1iV48LVuQKQDfMsdIWhP7zHdlQ== dependencies: "@actions/core" "^1.4.0" "@actions/github" "^5.0.0"