Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/fix/17365
Conflicts: src/components/views/dialogs/InviteDialog.tsx
This commit is contained in:
commit
f2643151c6
79 changed files with 3953 additions and 859 deletions
|
@ -291,6 +291,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
|
||||||
|
|
||||||
.mx_Dialog_staticWrapper .mx_Dialog {
|
.mx_Dialog_staticWrapper .mx_Dialog {
|
||||||
z-index: 4010;
|
z-index: 4010;
|
||||||
|
contain: content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Dialog_background {
|
.mx_Dialog_background {
|
||||||
|
|
|
@ -38,6 +38,7 @@ limitations under the License.
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: $font-14px;
|
font-size: $font-14px;
|
||||||
z-index: 5001;
|
z-index: 5001;
|
||||||
|
contain: content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_ContextualMenu_right {
|
.mx_ContextualMenu_right {
|
||||||
|
|
|
@ -25,6 +25,7 @@ $roomListCollapsedWidth: 68px;
|
||||||
|
|
||||||
// Create a row-based flexbox for the GroupFilterPanel and the room list
|
// Create a row-based flexbox for the GroupFilterPanel and the room list
|
||||||
display: flex;
|
display: flex;
|
||||||
|
contain: content;
|
||||||
|
|
||||||
.mx_LeftPanel_GroupFilterPanelContainer {
|
.mx_LeftPanel_GroupFilterPanelContainer {
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
@ -70,6 +71,7 @@ $roomListCollapsedWidth: 68px;
|
||||||
// aligned correctly. This is also a row-based flexbox.
|
// aligned correctly. This is also a row-based flexbox.
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
contain: content;
|
||||||
|
|
||||||
&.mx_IndicatorScrollbar_leftOverflow {
|
&.mx_IndicatorScrollbar_leftOverflow {
|
||||||
mask-image: linear-gradient(90deg, transparent, black 5%);
|
mask-image: linear-gradient(90deg, transparent, black 5%);
|
||||||
|
|
|
@ -25,6 +25,7 @@ limitations under the License.
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
contain: strict;
|
||||||
|
|
||||||
.mx_RoomView_MessageList {
|
.mx_RoomView_MessageList {
|
||||||
padding: 14px 18px; // top and bottom is 4px smaller to balance with the padding set above
|
padding: 14px 18px; // top and bottom is 4px smaller to balance with the padding set above
|
||||||
|
|
|
@ -152,6 +152,7 @@ limitations under the License.
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
contain: content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_statusArea {
|
.mx_RoomView_statusArea {
|
||||||
|
@ -221,6 +222,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomView_MessageList li {
|
.mx_RoomView_MessageList li {
|
||||||
clear: both;
|
clear: both;
|
||||||
|
contain: content;
|
||||||
}
|
}
|
||||||
|
|
||||||
li.mx_RoomView_myReadMarker_container {
|
li.mx_RoomView_myReadMarker_container {
|
||||||
|
@ -237,6 +239,7 @@ hr.mx_RoomView_myReadMarker {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
will-change: width;
|
||||||
transition: width 400ms easeinsine 1s, opacity 400ms easeinsine 1s;
|
transition: width 400ms easeinsine 1s, opacity 400ms easeinsine 1s;
|
||||||
width: 99%;
|
width: 99%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
|
@ -21,5 +21,8 @@ limitations under the License.
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
content-visibility: auto;
|
||||||
|
contain-intrinsic-size: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,6 +328,7 @@ $SpaceRoomViewInnerWidth: 428px;
|
||||||
font-size: $font-15px;
|
font-size: $font-15px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
> hr {
|
> hr {
|
||||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_DecoratedRoomAvatar, .mx_ExtraTile {
|
.mx_DecoratedRoomAvatar, .mx_ExtraTile {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
contain: content;
|
||||||
|
|
||||||
&.mx_DecoratedRoomAvatar_cutout .mx_BaseAvatar {
|
&.mx_DecoratedRoomAvatar_cutout .mx_BaseAvatar {
|
||||||
mask-image: url('$(res)/img/element-icons/roomlist/decorated-avatar-mask.svg');
|
mask-image: url('$(res)/img/element-icons/roomlist/decorated-avatar-mask.svg');
|
||||||
|
|
|
@ -104,7 +104,7 @@ $left-gutter: 64px;
|
||||||
.mx_EventTile_line, .mx_EventTile_reply {
|
.mx_EventTile_line, .mx_EventTile_reply {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: $left-gutter;
|
padding-left: $left-gutter;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_timeline_rr_enabled,
|
.mx_RoomView_timeline_rr_enabled,
|
||||||
|
@ -280,6 +280,7 @@ $left-gutter: 64px;
|
||||||
height: $font-14px;
|
height: $font-14px;
|
||||||
width: $font-14px;
|
width: $font-14px;
|
||||||
|
|
||||||
|
will-change: left, top;
|
||||||
transition:
|
transition:
|
||||||
left var(--transition-short) ease-out,
|
left var(--transition-short) ease-out,
|
||||||
top var(--transition-standard) ease-out;
|
top var(--transition-standard) ease-out;
|
||||||
|
|
|
@ -115,8 +115,7 @@ $irc-line-height: $font-18px;
|
||||||
.mx_EventTile_line {
|
.mx_EventTile_line {
|
||||||
.mx_EventTile_e2eIcon,
|
.mx_EventTile_e2eIcon,
|
||||||
.mx_TextualEvent,
|
.mx_TextualEvent,
|
||||||
.mx_MTextBody,
|
.mx_MTextBody {
|
||||||
.mx_ReplyThread_wrapper_empty {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,16 +176,13 @@ $irc-line-height: $font-18px;
|
||||||
.mx_SenderProfile_hover {
|
.mx_SenderProfile_hover {
|
||||||
background-color: $primary-bg-color;
|
background-color: $primary-bg-color;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
> span {
|
> .mx_SenderProfile_name {
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
> .mx_SenderProfile_name {
|
min-width: var(--name-width);
|
||||||
overflow: hidden;
|
text-align: end;
|
||||||
text-overflow: ellipsis;
|
|
||||||
min-width: var(--name-width);
|
|
||||||
text-align: end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_JumpToBottomButton_scrollDown {
|
.mx_JumpToBottomButton_scrollDown {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: block;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
border-radius: 19px;
|
border-radius: 19px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -32,14 +32,14 @@ limitations under the License.
|
||||||
// first triggering the enter state with the newest breadcrumb off screen (-40px) then
|
// first triggering the enter state with the newest breadcrumb off screen (-40px) then
|
||||||
// sliding it into view.
|
// sliding it into view.
|
||||||
&.mx_RoomBreadcrumbs-enter {
|
&.mx_RoomBreadcrumbs-enter {
|
||||||
margin-left: -40px; // 32px for the avatar, 8px for the margin
|
transform: translateX(-40px); // 32px for the avatar, 8px for the margin
|
||||||
}
|
}
|
||||||
&.mx_RoomBreadcrumbs-enter-active {
|
&.mx_RoomBreadcrumbs-enter-active {
|
||||||
margin-left: 0;
|
transform: translateX(0);
|
||||||
|
|
||||||
// Timing function is as-requested by design.
|
// Timing function is as-requested by design.
|
||||||
// NOTE: The transition time MUST match the value passed to CSSTransition!
|
// NOTE: The transition time MUST match the value passed to CSSTransition!
|
||||||
transition: margin-left 640ms cubic-bezier(0.66, 0.02, 0.36, 1);
|
transition: transform 640ms cubic-bezier(0.66, 0.02, 0.36, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomBreadcrumbs_placeholder {
|
.mx_RoomBreadcrumbs_placeholder {
|
||||||
|
|
|
@ -61,6 +61,7 @@ limitations under the License.
|
||||||
&.mx_RoomSublist_headerContainer_sticky {
|
&.mx_RoomSublist_headerContainer_sticky {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 32px; // to match the header container
|
height: 32px; // to match the header container
|
||||||
|
// width set by JS because of a compat issue between Firefox and Chrome
|
||||||
width: calc(100% - 15px);
|
width: calc(100% - 15px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +198,7 @@ limitations under the License.
|
||||||
// as the box model should be top aligned. Happens in both FF and Chromium
|
// as the box model should be top aligned. Happens in both FF and Chromium
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-self: stretch;
|
||||||
|
|
||||||
mask-image: linear-gradient(0deg, transparent, black 4px);
|
mask-image: linear-gradient(0deg, transparent, black 4px);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@ limitations under the License.
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
|
||||||
|
contain: strict;
|
||||||
|
height: 40px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
// The tile is also a flexbox row itself
|
// The tile is also a flexbox row itself
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
|
2
src/@types/global.d.ts
vendored
2
src/@types/global.d.ts
vendored
|
@ -43,6 +43,7 @@ import TypingStore from "../stores/TypingStore";
|
||||||
import { EventIndexPeg } from "../indexing/EventIndexPeg";
|
import { EventIndexPeg } from "../indexing/EventIndexPeg";
|
||||||
import {VoiceRecordingStore} from "../stores/VoiceRecordingStore";
|
import {VoiceRecordingStore} from "../stores/VoiceRecordingStore";
|
||||||
import PerformanceMonitor from "../performance";
|
import PerformanceMonitor from "../performance";
|
||||||
|
import UIStore from "../stores/UIStore";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -82,6 +83,7 @@ declare global {
|
||||||
mxEventIndexPeg: EventIndexPeg;
|
mxEventIndexPeg: EventIndexPeg;
|
||||||
mxPerformanceMonitor: PerformanceMonitor;
|
mxPerformanceMonitor: PerformanceMonitor;
|
||||||
mxPerformanceEntryNames: any;
|
mxPerformanceEntryNames: any;
|
||||||
|
mxUIStore: UIStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Document {
|
interface Document {
|
||||||
|
|
|
@ -802,7 +802,10 @@ export default class CallHandler extends EventEmitter {
|
||||||
|
|
||||||
const mappedRoomId = CallHandler.sharedInstance().roomIdForCall(call);
|
const mappedRoomId = CallHandler.sharedInstance().roomIdForCall(call);
|
||||||
if (this.getCallForRoom(mappedRoomId)) {
|
if (this.getCallForRoom(mappedRoomId)) {
|
||||||
// ignore multiple incoming calls to the same room
|
console.log(
|
||||||
|
"Got incoming call for room " + mappedRoomId +
|
||||||
|
" but there's already a call for this room: ignoring",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -816,7 +816,9 @@ export default class CountlyAnalytics {
|
||||||
window.addEventListener("mousemove", this.onUserActivity);
|
window.addEventListener("mousemove", this.onUserActivity);
|
||||||
window.addEventListener("click", this.onUserActivity);
|
window.addEventListener("click", this.onUserActivity);
|
||||||
window.addEventListener("keydown", this.onUserActivity);
|
window.addEventListener("keydown", this.onUserActivity);
|
||||||
window.addEventListener("scroll", this.onUserActivity);
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
window.addEventListener("scroll", this.onUserActivity, { passive: true });
|
||||||
|
|
||||||
this.activityIntervalId = setInterval(() => {
|
this.activityIntervalId = setInterval(() => {
|
||||||
this.inactivityCounter++;
|
this.inactivityCounter++;
|
||||||
|
|
15
src/Login.ts
15
src/Login.ts
|
@ -31,12 +31,12 @@ interface IPasswordFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IdentityProviderBrand {
|
export enum IdentityProviderBrand {
|
||||||
Gitlab = "org.matrix.gitlab",
|
Gitlab = "gitlab",
|
||||||
Github = "org.matrix.github",
|
Github = "github",
|
||||||
Apple = "org.matrix.apple",
|
Apple = "apple",
|
||||||
Google = "org.matrix.google",
|
Google = "google",
|
||||||
Facebook = "org.matrix.facebook",
|
Facebook = "facebook",
|
||||||
Twitter = "org.matrix.twitter",
|
Twitter = "twitter",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IIdentityProvider {
|
export interface IIdentityProvider {
|
||||||
|
@ -48,7 +48,8 @@ export interface IIdentityProvider {
|
||||||
|
|
||||||
export interface ISSOFlow {
|
export interface ISSOFlow {
|
||||||
type: "m.login.sso" | "m.login.cas";
|
type: "m.login.sso" | "m.login.cas";
|
||||||
"org.matrix.msc2858.identity_providers": IIdentityProvider[]; // Unstable prefix for MSC2858
|
// eslint-disable-next-line camelcase
|
||||||
|
identity_providers: IIdentityProvider[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LoginFlow = ISSOFlow | IPasswordFlow;
|
export type LoginFlow = ISSOFlow | IPasswordFlow;
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2018 New Vector Ltd
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export default class AutoHideScrollbar extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this._collectContainerRef = this._collectContainerRef.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_collectContainerRef(ref) {
|
|
||||||
if (ref && !this.containerRef) {
|
|
||||||
this.containerRef = ref;
|
|
||||||
}
|
|
||||||
if (this.props.wrappedRef) {
|
|
||||||
this.props.wrappedRef(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getScrollTop() {
|
|
||||||
return this.containerRef.scrollTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (<div
|
|
||||||
ref={this._collectContainerRef}
|
|
||||||
style={this.props.style}
|
|
||||||
className={["mx_AutoHideScrollbar", this.props.className].join(" ")}
|
|
||||||
onScroll={this.props.onScroll}
|
|
||||||
onWheel={this.props.onWheel}
|
|
||||||
tabIndex={this.props.tabIndex}
|
|
||||||
>
|
|
||||||
{ this.props.children }
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
}
|
|
65
src/components/structures/AutoHideScrollbar.tsx
Normal file
65
src/components/structures/AutoHideScrollbar.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
className?: string;
|
||||||
|
onScroll?: () => void;
|
||||||
|
onWheel?: () => void;
|
||||||
|
style?: React.CSSProperties
|
||||||
|
tabIndex?: number,
|
||||||
|
wrappedRef?: (ref: HTMLDivElement) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AutoHideScrollbar extends React.Component<IProps> {
|
||||||
|
private containerRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
if (this.containerRef.current && this.props.onScroll) {
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.containerRef.current.addEventListener("scroll", this.props.onScroll, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.wrappedRef) {
|
||||||
|
this.props.wrappedRef(this.containerRef.current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
if (this.containerRef.current && this.props.onScroll) {
|
||||||
|
this.containerRef.current.removeEventListener("scroll", this.props.onScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getScrollTop(): number {
|
||||||
|
return this.containerRef.current.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (<div
|
||||||
|
ref={this.containerRef}
|
||||||
|
style={this.props.style}
|
||||||
|
className={["mx_AutoHideScrollbar", this.props.className].join(" ")}
|
||||||
|
onWheel={this.props.onWheel}
|
||||||
|
tabIndex={this.props.tabIndex}
|
||||||
|
>
|
||||||
|
{ this.props.children }
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,7 +59,9 @@ export default class IndicatorScrollbar extends React.Component {
|
||||||
_collectScroller(scroller) {
|
_collectScroller(scroller) {
|
||||||
if (scroller && !this._scrollElement) {
|
if (scroller && !this._scrollElement) {
|
||||||
this._scrollElement = scroller;
|
this._scrollElement = scroller;
|
||||||
this._scrollElement.addEventListener("scroll", this.checkOverflow);
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this._scrollElement.addEventListener("scroll", this.checkOverflow, { passive: true });
|
||||||
this.checkOverflow();
|
this.checkOverflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ const cssClasses = [
|
||||||
|
|
||||||
@replaceableComponent("structures.LeftPanel")
|
@replaceableComponent("structures.LeftPanel")
|
||||||
export default class LeftPanel extends React.Component<IProps, IState> {
|
export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
|
private ref: React.RefObject<HTMLDivElement> = createRef();
|
||||||
private listContainerRef: React.RefObject<HTMLDivElement> = createRef();
|
private listContainerRef: React.RefObject<HTMLDivElement> = createRef();
|
||||||
private groupFilterPanelWatcherRef: string;
|
private groupFilterPanelWatcherRef: string;
|
||||||
private bgImageWatcherRef: string;
|
private bgImageWatcherRef: string;
|
||||||
|
@ -93,6 +94,14 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
|
||||||
|
UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.listContainerRef.current?.addEventListener("scroll", this.onScroll, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
SettingsStore.unwatchSetting(this.groupFilterPanelWatcherRef);
|
SettingsStore.unwatchSetting(this.groupFilterPanelWatcherRef);
|
||||||
SettingsStore.unwatchSetting(this.bgImageWatcherRef);
|
SettingsStore.unwatchSetting(this.bgImageWatcherRef);
|
||||||
|
@ -100,6 +109,15 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
OwnProfileStore.instance.off(UPDATE_EVENT, this.onBackgroundImageUpdate);
|
OwnProfileStore.instance.off(UPDATE_EVENT, this.onBackgroundImageUpdate);
|
||||||
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
||||||
|
UIStore.instance.stopTrackingElementDimensions("ListContainer");
|
||||||
|
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
|
||||||
|
this.listContainerRef.current?.removeEventListener("scroll", this.onScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
|
||||||
|
if (prevState.activeSpace !== this.state.activeSpace) {
|
||||||
|
this.refreshStickyHeaders();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateActiveSpace = (activeSpace: Room) => {
|
private updateActiveSpace = (activeSpace: Room) => {
|
||||||
|
@ -245,10 +263,24 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
if (!header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
|
if (!header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
|
||||||
header.classList.add("mx_RoomSublist_headerContainer_sticky");
|
header.classList.add("mx_RoomSublist_headerContainer_sticky");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const listDimensions = UIStore.instance.getElementDimensions("ListContainer");
|
||||||
|
if (listDimensions) {
|
||||||
|
const headerRightMargin = 15; // calculated from margins and widths to align with non-sticky tiles
|
||||||
|
const headerStickyWidth = listDimensions.width - headerRightMargin;
|
||||||
|
const newWidth = `${headerStickyWidth}px`;
|
||||||
|
if (header.style.width !== newWidth) {
|
||||||
|
header.style.width = newWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!style.stickyTop && !style.stickyBottom) {
|
} else if (!style.stickyTop && !style.stickyBottom) {
|
||||||
if (header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
|
if (header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
|
||||||
header.classList.remove("mx_RoomSublist_headerContainer_sticky");
|
header.classList.remove("mx_RoomSublist_headerContainer_sticky");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.style.width) {
|
||||||
|
header.style.removeProperty('width');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +299,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => {
|
private onScroll = (ev: Event) => {
|
||||||
const list = ev.target as HTMLDivElement;
|
const list = ev.target as HTMLDivElement;
|
||||||
this.handleStickyHeaders(list);
|
this.handleStickyHeaders(list);
|
||||||
};
|
};
|
||||||
|
@ -407,6 +439,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
onBlur={this.onBlur}
|
onBlur={this.onBlur}
|
||||||
isMinimized={this.props.isMinimized}
|
isMinimized={this.props.isMinimized}
|
||||||
activeSpace={this.state.activeSpace}
|
activeSpace={this.state.activeSpace}
|
||||||
|
onListCollapse={this.refreshStickyHeaders}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
const containerClasses = classNames({
|
const containerClasses = classNames({
|
||||||
|
@ -420,7 +453,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses} ref={this.ref}>
|
||||||
{leftLeftPanel}
|
{leftLeftPanel}
|
||||||
<aside className="mx_LeftPanel_roomListContainer">
|
<aside className="mx_LeftPanel_roomListContainer">
|
||||||
{this.renderHeader()}
|
{this.renderHeader()}
|
||||||
|
@ -430,7 +463,6 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
<div className="mx_LeftPanel_roomListWrapper">
|
<div className="mx_LeftPanel_roomListWrapper">
|
||||||
<div
|
<div
|
||||||
className={roomListClasses}
|
className={roomListClasses}
|
||||||
onScroll={this.onScroll}
|
|
||||||
ref={this.listContainerRef}
|
ref={this.listContainerRef}
|
||||||
// Firefox sometimes makes this element focusable due to
|
// Firefox sometimes makes this element focusable due to
|
||||||
// overflow:scroll;, so force it out of tab order.
|
// overflow:scroll;, so force it out of tab order.
|
||||||
|
|
|
@ -232,6 +232,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
private accountPasswordTimer?: NodeJS.Timeout;
|
private accountPasswordTimer?: NodeJS.Timeout;
|
||||||
private focusComposer: boolean;
|
private focusComposer: boolean;
|
||||||
private subTitleStatus: string;
|
private subTitleStatus: string;
|
||||||
|
private prevWindowWidth: number;
|
||||||
|
|
||||||
private readonly loggedInView: React.RefObject<LoggedInViewType>;
|
private readonly loggedInView: React.RefObject<LoggedInViewType>;
|
||||||
private readonly dispatcherRef: any;
|
private readonly dispatcherRef: any;
|
||||||
|
@ -277,6 +278,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.prevWindowWidth = UIStore.instance.windowWidth || 1000;
|
||||||
UIStore.instance.on(UI_EVENTS.Resize, this.handleResize);
|
UIStore.instance.on(UI_EVENTS.Resize, this.handleResize);
|
||||||
|
|
||||||
this.pageChanging = false;
|
this.pageChanging = false;
|
||||||
|
@ -1821,13 +1823,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
const LHS_THRESHOLD = 1000;
|
const LHS_THRESHOLD = 1000;
|
||||||
const width = UIStore.instance.windowWidth;
|
const width = UIStore.instance.windowWidth;
|
||||||
|
|
||||||
if (width <= LHS_THRESHOLD && !this.state.collapseLhs) {
|
if (this.prevWindowWidth < LHS_THRESHOLD && width >= LHS_THRESHOLD) {
|
||||||
dis.dispatch({ action: 'hide_left_panel' });
|
|
||||||
}
|
|
||||||
if (width > LHS_THRESHOLD && this.state.collapseLhs) {
|
|
||||||
dis.dispatch({ action: 'show_left_panel' });
|
dis.dispatch({ action: 'show_left_panel' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.prevWindowWidth >= LHS_THRESHOLD && width < LHS_THRESHOLD) {
|
||||||
|
dis.dispatch({ action: 'hide_left_panel' });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.prevWindowWidth = width;
|
||||||
this.state.resizeNotifier.notifyWindowResized();
|
this.state.resizeNotifier.notifyWindowResized();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2087,6 +2091,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
onForgotPasswordClick={showPasswordReset ? this.onForgotPasswordClick : undefined}
|
onForgotPasswordClick={showPasswordReset ? this.onForgotPasswordClick : undefined}
|
||||||
onServerConfigChange={this.onServerConfigChange}
|
onServerConfigChange={this.onServerConfigChange}
|
||||||
fragmentAfterLogin={fragmentAfterLogin}
|
fragmentAfterLogin={fragmentAfterLogin}
|
||||||
|
defaultUsername={this.props.startingFragmentQueryParams.defaultUsername}
|
||||||
{...this.getServerProperties()}
|
{...this.getServerProperties()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -121,6 +121,9 @@ export default class MessagePanel extends React.Component {
|
||||||
// callback which is called when the panel is scrolled.
|
// callback which is called when the panel is scrolled.
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
|
|
||||||
|
// callback which is called when the user interacts with the room timeline
|
||||||
|
onUserScroll: PropTypes.func,
|
||||||
|
|
||||||
// callback which is called when more content is needed.
|
// callback which is called when more content is needed.
|
||||||
onFillRequest: PropTypes.func,
|
onFillRequest: PropTypes.func,
|
||||||
|
|
||||||
|
@ -645,39 +648,37 @@ export default class MessagePanel extends React.Component {
|
||||||
|
|
||||||
// use txnId as key if available so that we don't remount during sending
|
// use txnId as key if available so that we don't remount during sending
|
||||||
ret.push(
|
ret.push(
|
||||||
<li
|
<TileErrorBoundary key={mxEv.getTxnId() || eventId} mxEvent={mxEv}>
|
||||||
key={mxEv.getTxnId() || eventId}
|
<EventTile
|
||||||
ref={this._collectEventNode.bind(this, eventId)}
|
as="li"
|
||||||
data-scroll-tokens={scrollToken}
|
data-scroll-tokens={scrollToken}
|
||||||
>
|
ref={this._collectEventNode.bind(this, eventId)}
|
||||||
<TileErrorBoundary mxEvent={mxEv}>
|
alwaysShowTimestamps={this.props.alwaysShowTimestamps}
|
||||||
<EventTile
|
mxEvent={mxEv}
|
||||||
mxEvent={mxEv}
|
continuation={continuation}
|
||||||
continuation={continuation}
|
isRedacted={mxEv.isRedacted()}
|
||||||
isRedacted={mxEv.isRedacted()}
|
replacingEventId={mxEv.replacingEventId()}
|
||||||
replacingEventId={mxEv.replacingEventId()}
|
editState={isEditing && this.props.editState}
|
||||||
editState={isEditing && this.props.editState}
|
onHeightChanged={this._onHeightChanged}
|
||||||
onHeightChanged={this._onHeightChanged}
|
readReceipts={readReceipts}
|
||||||
readReceipts={readReceipts}
|
readReceiptMap={this._readReceiptMap}
|
||||||
readReceiptMap={this._readReceiptMap}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
checkUnmounting={this._isUnmounting}
|
||||||
checkUnmounting={this._isUnmounting}
|
eventSendStatus={mxEv.getAssociatedStatus()}
|
||||||
eventSendStatus={mxEv.getAssociatedStatus()}
|
tileShape={this.props.tileShape}
|
||||||
tileShape={this.props.tileShape}
|
isTwelveHour={this.props.isTwelveHour}
|
||||||
isTwelveHour={this.props.isTwelveHour}
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
permalinkCreator={this.props.permalinkCreator}
|
last={last}
|
||||||
last={last}
|
lastInSection={willWantDateSeparator}
|
||||||
lastInSection={willWantDateSeparator}
|
lastSuccessful={isLastSuccessful}
|
||||||
lastSuccessful={isLastSuccessful}
|
isSelectedEvent={highlight}
|
||||||
isSelectedEvent={highlight}
|
getRelationsForEvent={this.props.getRelationsForEvent}
|
||||||
getRelationsForEvent={this.props.getRelationsForEvent}
|
showReactions={this.props.showReactions}
|
||||||
showReactions={this.props.showReactions}
|
layout={this.props.layout}
|
||||||
layout={this.props.layout}
|
enableFlair={this.props.enableFlair}
|
||||||
enableFlair={this.props.enableFlair}
|
showReadReceipts={this.props.showReadReceipts}
|
||||||
showReadReceipts={this.props.showReadReceipts}
|
/>
|
||||||
/>
|
</TileErrorBoundary>,
|
||||||
</TileErrorBoundary>
|
|
||||||
</li>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -779,7 +780,7 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_collectEventNode = (eventId, node) => {
|
_collectEventNode = (eventId, node) => {
|
||||||
this.eventNodes[eventId] = node;
|
this.eventNodes[eventId] = node?.ref?.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
// once dynamic content in the events load, make the scrollPanel check the
|
// once dynamic content in the events load, make the scrollPanel check the
|
||||||
|
@ -885,6 +886,7 @@ export default class MessagePanel extends React.Component {
|
||||||
ref={this._scrollPanel}
|
ref={this._scrollPanel}
|
||||||
className={className}
|
className={className}
|
||||||
onScroll={this.props.onScroll}
|
onScroll={this.props.onScroll}
|
||||||
|
onUserScroll={this.props.onUserScroll}
|
||||||
onResize={this.onResize}
|
onResize={this.onResize}
|
||||||
onFillRequest={this.props.onFillRequest}
|
onFillRequest={this.props.onFillRequest}
|
||||||
onUnfillRequest={this.props.onUnfillRequest}
|
onUnfillRequest={this.props.onUnfillRequest}
|
||||||
|
|
|
@ -83,6 +83,7 @@ import { objectHasDiff } from "../../utils/objects";
|
||||||
import SpaceRoomView from "./SpaceRoomView";
|
import SpaceRoomView from "./SpaceRoomView";
|
||||||
import { IOpts } from "../../createRoom";
|
import { IOpts } from "../../createRoom";
|
||||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
|
import { omit } from 'lodash';
|
||||||
import UIStore from "../../stores/UIStore";
|
import UIStore from "../../stores/UIStore";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
@ -176,6 +177,7 @@ export interface IState {
|
||||||
statusBarVisible: boolean;
|
statusBarVisible: boolean;
|
||||||
// We load this later by asking the js-sdk to suggest a version for us.
|
// We load this later by asking the js-sdk to suggest a version for us.
|
||||||
// This object is the result of Room#getRecommendedVersion()
|
// This object is the result of Room#getRecommendedVersion()
|
||||||
|
|
||||||
upgradeRecommendation?: {
|
upgradeRecommendation?: {
|
||||||
version: string;
|
version: string;
|
||||||
needsUpgrade: boolean;
|
needsUpgrade: boolean;
|
||||||
|
@ -529,7 +531,20 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (objectHasDiff(this.props, nextProps) || objectHasDiff(this.state, nextState));
|
const hasPropsDiff = objectHasDiff(this.props, nextProps);
|
||||||
|
|
||||||
|
// React only shallow comparison and we only want to trigger
|
||||||
|
// a component re-render if a room requires an upgrade
|
||||||
|
const newUpgradeRecommendation = nextState.upgradeRecommendation || {}
|
||||||
|
|
||||||
|
const state = omit(this.state, ['upgradeRecommendation']);
|
||||||
|
const newState = omit(nextState, ['upgradeRecommendation'])
|
||||||
|
|
||||||
|
const hasStateDiff =
|
||||||
|
objectHasDiff(state, newState) ||
|
||||||
|
(newUpgradeRecommendation.needsUpgrade === true)
|
||||||
|
|
||||||
|
return hasPropsDiff || hasStateDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
@ -642,6 +657,17 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
SettingsStore.unwatchSetting(this.layoutWatcherRef);
|
SettingsStore.unwatchSetting(this.layoutWatcherRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onUserScroll = () => {
|
||||||
|
if (this.state.initialEventId && this.state.isInitialEventHighlighted) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_room',
|
||||||
|
room_id: this.state.room.roomId,
|
||||||
|
event_id: this.state.initialEventId,
|
||||||
|
highlighted: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onLayoutChange = () => {
|
private onLayoutChange = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
layout: SettingsStore.getValue("layout"),
|
layout: SettingsStore.getValue("layout"),
|
||||||
|
@ -812,7 +838,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private onEvent = (ev) => {
|
private onEvent = (ev) => {
|
||||||
if (ev.isBeingDecrypted() || ev.isDecryptionFailure() || ev.shouldAttemptDecryption()) return;
|
if (ev.isBeingDecrypted() || ev.isDecryptionFailure()) return;
|
||||||
this.handleEffects(ev);
|
this.handleEffects(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1513,8 +1539,10 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
// jump down to the bottom of this room, where new events are arriving
|
// jump down to the bottom of this room, where new events are arriving
|
||||||
private jumpToLiveTimeline = () => {
|
private jumpToLiveTimeline = () => {
|
||||||
this.messagePanel.jumpToLiveTimeline();
|
dis.dispatch({
|
||||||
dis.fire(Action.FocusComposer);
|
action: 'view_room',
|
||||||
|
room_id: this.state.room.roomId,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// jump up to wherever our read marker is
|
// jump up to wherever our read marker is
|
||||||
|
@ -1985,6 +2013,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
eventId={this.state.initialEventId}
|
eventId={this.state.initialEventId}
|
||||||
eventPixelOffset={this.state.initialEventPixelOffset}
|
eventPixelOffset={this.state.initialEventPixelOffset}
|
||||||
onScroll={this.onMessageListScroll}
|
onScroll={this.onMessageListScroll}
|
||||||
|
onUserScroll={this.onUserScroll}
|
||||||
onReadMarkerUpdated={this.updateTopUnreadMessagesBar}
|
onReadMarkerUpdated={this.updateTopUnreadMessagesBar}
|
||||||
showUrlPreview = {this.state.showUrlPreview}
|
showUrlPreview = {this.state.showUrlPreview}
|
||||||
className={messagePanelClassNames}
|
className={messagePanelClassNames}
|
||||||
|
@ -2011,6 +2040,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
highlight={this.state.room.getUnreadNotificationCount('highlight') > 0}
|
highlight={this.state.room.getUnreadNotificationCount('highlight') > 0}
|
||||||
numUnreadMessages={this.state.numUnreadMessages}
|
numUnreadMessages={this.state.numUnreadMessages}
|
||||||
onScrollToBottomClick={this.jumpToLiveTimeline}
|
onScrollToBottomClick={this.jumpToLiveTimeline}
|
||||||
|
roomId={this.state.roomId}
|
||||||
/>);
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,10 @@ export default class ScrollPanel extends React.Component {
|
||||||
*/
|
*/
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
|
|
||||||
|
/* onUserScroll: callback which is called when the user interacts with the room timeline
|
||||||
|
*/
|
||||||
|
onUserScroll: PropTypes.func,
|
||||||
|
|
||||||
/* className: classnames to add to the top-level div
|
/* className: classnames to add to the top-level div
|
||||||
*/
|
*/
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
@ -535,21 +539,29 @@ export default class ScrollPanel extends React.Component {
|
||||||
* @param {object} ev the keyboard event
|
* @param {object} ev the keyboard event
|
||||||
*/
|
*/
|
||||||
handleScrollKey = ev => {
|
handleScrollKey = ev => {
|
||||||
|
let isScrolling = false;
|
||||||
const roomAction = getKeyBindingsManager().getRoomAction(ev);
|
const roomAction = getKeyBindingsManager().getRoomAction(ev);
|
||||||
switch (roomAction) {
|
switch (roomAction) {
|
||||||
case RoomAction.ScrollUp:
|
case RoomAction.ScrollUp:
|
||||||
this.scrollRelative(-1);
|
this.scrollRelative(-1);
|
||||||
|
isScrolling = true;
|
||||||
break;
|
break;
|
||||||
case RoomAction.RoomScrollDown:
|
case RoomAction.RoomScrollDown:
|
||||||
this.scrollRelative(1);
|
this.scrollRelative(1);
|
||||||
|
isScrolling = true;
|
||||||
break;
|
break;
|
||||||
case RoomAction.JumpToFirstMessage:
|
case RoomAction.JumpToFirstMessage:
|
||||||
this.scrollToTop();
|
this.scrollToTop();
|
||||||
|
isScrolling = true;
|
||||||
break;
|
break;
|
||||||
case RoomAction.JumpToLatestMessage:
|
case RoomAction.JumpToLatestMessage:
|
||||||
this.scrollToBottom();
|
this.scrollToBottom();
|
||||||
|
isScrolling = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (isScrolling && this.props.onUserScroll) {
|
||||||
|
this.props.onUserScroll(ev);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Scroll the panel to bring the DOM node with the scroll token
|
/* Scroll the panel to bring the DOM node with the scroll token
|
||||||
|
@ -888,9 +900,8 @@ export default class ScrollPanel extends React.Component {
|
||||||
<AutoHideScrollbar
|
<AutoHideScrollbar
|
||||||
wrappedRef={this._collectScroll}
|
wrappedRef={this._collectScroll}
|
||||||
onScroll={this.onScroll}
|
onScroll={this.onScroll}
|
||||||
className={`mx_ScrollPanel ${this.props.className}`}
|
onWheel={this.props.onUserScroll}
|
||||||
style={this.props.style}
|
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
|
||||||
>
|
|
||||||
{ this.props.fixedChildren }
|
{ this.props.fixedChildren }
|
||||||
<div className="mx_RoomView_messageListWrapper">
|
<div className="mx_RoomView_messageListWrapper">
|
||||||
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite" role="list">
|
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite" role="list">
|
||||||
|
|
|
@ -417,9 +417,13 @@ const SpaceLanding = ({ space }) => {
|
||||||
{ inviteButton }
|
{ inviteButton }
|
||||||
{ settingsButton }
|
{ settingsButton }
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_SpaceRoomView_landing_topic">
|
<RoomTopic room={space}>
|
||||||
<RoomTopic room={space} />
|
{(topic, ref) => (
|
||||||
</div>
|
<div className="mx_SpaceRoomView_landing_topic" ref={ref}>
|
||||||
|
{ topic }
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</RoomTopic>
|
||||||
<SpaceFeedbackPrompt />
|
<SpaceFeedbackPrompt />
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
@ -437,7 +441,6 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const numFields = 3;
|
const numFields = 3;
|
||||||
const placeholders = [_t("General"), _t("Random"), _t("Support")];
|
const placeholders = [_t("General"), _t("Random"), _t("Support")];
|
||||||
// TODO vary default prefills for "Just Me" spaces
|
|
||||||
const [roomNames, setRoomName] = useStateArray(numFields, [_t("General"), _t("Random"), ""]);
|
const [roomNames, setRoomName] = useStateArray(numFields, [_t("General"), _t("Random"), ""]);
|
||||||
const fields = new Array(numFields).fill(0).map((_, i) => {
|
const fields = new Array(numFields).fill(0).map((_, i) => {
|
||||||
const name = "roomName" + i;
|
const name = "roomName" + i;
|
||||||
|
|
|
@ -36,7 +36,6 @@ import shouldHideEvent from '../../shouldHideEvent';
|
||||||
import EditorStateTransfer from '../../utils/EditorStateTransfer';
|
import EditorStateTransfer from '../../utils/EditorStateTransfer';
|
||||||
import {haveTileForEvent} from "../views/rooms/EventTile";
|
import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||||
import {UIFeature} from "../../settings/UIFeature";
|
import {UIFeature} from "../../settings/UIFeature";
|
||||||
import {objectHasDiff} from "../../utils/objects";
|
|
||||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
import { arrayFastClone } from "../../utils/arrays";
|
import { arrayFastClone } from "../../utils/arrays";
|
||||||
|
|
||||||
|
@ -94,6 +93,9 @@ class TimelinePanel extends React.Component {
|
||||||
// callback which is called when the panel is scrolled.
|
// callback which is called when the panel is scrolled.
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
|
|
||||||
|
// callback which is called when the user interacts with the room timeline
|
||||||
|
onUserScroll: PropTypes.func,
|
||||||
|
|
||||||
// callback which is called when the read-up-to mark is updated.
|
// callback which is called when the read-up-to mark is updated.
|
||||||
onReadMarkerUpdated: PropTypes.func,
|
onReadMarkerUpdated: PropTypes.func,
|
||||||
|
|
||||||
|
@ -258,37 +260,15 @@ class TimelinePanel extends React.Component {
|
||||||
console.warn("Replacing timelineSet on a TimelinePanel - confusion may ensue");
|
console.warn("Replacing timelineSet on a TimelinePanel - confusion may ensue");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newProps.eventId != this.props.eventId) {
|
const differentEventId = newProps.eventId != this.props.eventId;
|
||||||
|
const differentHighlightedEventId = newProps.highlightedEventId != this.props.highlightedEventId;
|
||||||
|
if (differentEventId || differentHighlightedEventId) {
|
||||||
console.log("TimelinePanel switching to eventId " + newProps.eventId +
|
console.log("TimelinePanel switching to eventId " + newProps.eventId +
|
||||||
" (was " + this.props.eventId + ")");
|
" (was " + this.props.eventId + ")");
|
||||||
return this._initTimeline(newProps);
|
return this._initTimeline(newProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
|
||||||
if (objectHasDiff(this.props, nextProps)) {
|
|
||||||
if (DEBUG) {
|
|
||||||
console.group("Timeline.shouldComponentUpdate: props change");
|
|
||||||
console.log("props before:", this.props);
|
|
||||||
console.log("props after:", nextProps);
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objectHasDiff(this.state, nextState)) {
|
|
||||||
if (DEBUG) {
|
|
||||||
console.group("Timeline.shouldComponentUpdate: state change");
|
|
||||||
console.log("state before:", this.state);
|
|
||||||
console.log("state after:", nextState);
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
// set a boolean to say we've been unmounted, which any pending
|
// set a boolean to say we've been unmounted, which any pending
|
||||||
// promises can use to throw away their results.
|
// promises can use to throw away their results.
|
||||||
|
@ -1456,6 +1436,7 @@ class TimelinePanel extends React.Component {
|
||||||
ourUserId={MatrixClientPeg.get().credentials.userId}
|
ourUserId={MatrixClientPeg.get().credentials.userId}
|
||||||
stickyBottom={stickyBottom}
|
stickyBottom={stickyBottom}
|
||||||
onScroll={this.onMessageListScroll}
|
onScroll={this.onMessageListScroll}
|
||||||
|
onUserScroll={this.props.onUserScroll}
|
||||||
onFillRequest={this.onMessageListFillRequest}
|
onFillRequest={this.onMessageListFillRequest}
|
||||||
onUnfillRequest={this.onMessageListUnfillRequest}
|
onUnfillRequest={this.onMessageListUnfillRequest}
|
||||||
isTwelveHour={this.state.isTwelveHour}
|
isTwelveHour={this.state.isTwelveHour}
|
||||||
|
|
|
@ -55,6 +55,7 @@ export default class ToastContainer extends React.Component<{}, IState> {
|
||||||
const totalCount = this.state.toasts.length;
|
const totalCount = this.state.toasts.length;
|
||||||
const isStacked = totalCount > 1;
|
const isStacked = totalCount > 1;
|
||||||
let toast;
|
let toast;
|
||||||
|
let containerClasses;
|
||||||
if (totalCount !== 0) {
|
if (totalCount !== 0) {
|
||||||
const topToast = this.state.toasts[0];
|
const topToast = this.state.toasts[0];
|
||||||
const {title, icon, key, component, className, props} = topToast;
|
const {title, icon, key, component, className, props} = topToast;
|
||||||
|
@ -79,16 +80,17 @@ export default class ToastContainer extends React.Component<{}, IState> {
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Toast_body">{React.createElement(component, toastProps)}</div>
|
<div className="mx_Toast_body">{React.createElement(component, toastProps)}</div>
|
||||||
</div>);
|
</div>);
|
||||||
|
|
||||||
|
containerClasses = classNames("mx_ToastContainer", {
|
||||||
|
"mx_ToastContainer_stacked": isStacked,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
return toast
|
||||||
const containerClasses = classNames("mx_ToastContainer", {
|
? (
|
||||||
"mx_ToastContainer_stacked": isStacked,
|
<div className={containerClasses} role="alert">
|
||||||
});
|
{toast}
|
||||||
|
</div>
|
||||||
return (
|
)
|
||||||
<div className={containerClasses} role="alert">
|
: null;
|
||||||
{toast}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ interface IProps {
|
||||||
fallbackHsUrl?: string;
|
fallbackHsUrl?: string;
|
||||||
defaultDeviceDisplayName?: string;
|
defaultDeviceDisplayName?: string;
|
||||||
fragmentAfterLogin?: string;
|
fragmentAfterLogin?: string;
|
||||||
|
defaultUsername?: string;
|
||||||
|
|
||||||
// Called when the user has logged in. Params:
|
// Called when the user has logged in. Params:
|
||||||
// - The object returned by the login API
|
// - The object returned by the login API
|
||||||
|
@ -119,7 +120,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
||||||
|
|
||||||
flows: null,
|
flows: null,
|
||||||
|
|
||||||
username: "",
|
username: props.defaultUsername? props.defaultUsername: '',
|
||||||
phoneCountry: null,
|
phoneCountry: null,
|
||||||
phoneNumber: "",
|
phoneNumber: "",
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,8 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
this.setState({
|
this.setState({
|
||||||
flows: e.data.flows,
|
flows: e.data.flows,
|
||||||
});
|
});
|
||||||
} else if (e.httpStatus === 403 && e.errcode === "M_UNKNOWN") {
|
} else if (e.httpStatus === 403 || e.errcode === "M_FORBIDDEN") {
|
||||||
|
// Check for 403 or M_FORBIDDEN, Synapse used to send 403 M_UNKNOWN but now sends 403 M_FORBIDDEN.
|
||||||
// At this point registration is pretty much disabled, but before we do that let's
|
// At this point registration is pretty much disabled, but before we do that let's
|
||||||
// quickly check to see if the server supports SSO instead. If it does, we'll send
|
// quickly check to see if the server supports SSO instead. If it does, we'll send
|
||||||
// the user off to the login page to figure their account out.
|
// the user off to the login page to figure their account out.
|
||||||
|
@ -467,7 +468,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
||||||
let ssoSection;
|
let ssoSection;
|
||||||
if (this.state.ssoFlow) {
|
if (this.state.ssoFlow) {
|
||||||
let continueWithSection;
|
let continueWithSection;
|
||||||
const providers = this.state.ssoFlow["org.matrix.msc2858.identity_providers"] || [];
|
const providers = this.state.ssoFlow.identity_providers || [];
|
||||||
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
|
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
|
||||||
if (providers.length > 1) {
|
if (providers.length > 1) {
|
||||||
// i18n: ssoButtons is a placeholder to help translators understand context
|
// i18n: ssoButtons is a placeholder to help translators understand context
|
||||||
|
|
|
@ -212,7 +212,7 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
|
||||||
autoComplete={true}
|
autoComplete={true}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
/>
|
/>
|
||||||
<AutoHideScrollbar className="mx_AddExistingToSpace_content" id="mx_AddExistingToSpace">
|
<AutoHideScrollbar className="mx_AddExistingToSpace_content">
|
||||||
{ rooms.length > 0 ? (
|
{ rooms.length > 0 ? (
|
||||||
<div className="mx_AddExistingToSpace_section">
|
<div className="mx_AddExistingToSpace_section">
|
||||||
<h3>{ _t("Rooms") }</h3>
|
<h3>{ _t("Rooms") }</h3>
|
||||||
|
|
|
@ -49,10 +49,11 @@ import {mediaFromMxc} from "../../../customisations/Media";
|
||||||
import {getAddressType} from "../../../UserAddress";
|
import {getAddressType} from "../../../UserAddress";
|
||||||
import BaseAvatar from '../avatars/BaseAvatar';
|
import BaseAvatar from '../avatars/BaseAvatar';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import { compare } from '../../../utils/strings';
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import {copyPlaintext, selectText} from "../../../utils/strings";
|
import { copyPlaintext, selectText } from "../../../utils/strings";
|
||||||
import * as ContextMenu from "../../structures/ContextMenu";
|
import * as ContextMenu from "../../structures/ContextMenu";
|
||||||
import {toRightOf} from "../../structures/ContextMenu";
|
import { toRightOf } from "../../structures/ContextMenu";
|
||||||
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
|
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
|
||||||
|
|
||||||
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
||||||
|
@ -587,7 +588,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
members.sort((a, b) => {
|
members.sort((a, b) => {
|
||||||
if (a.score === b.score) {
|
if (a.score === b.score) {
|
||||||
if (a.numRooms === b.numRooms) {
|
if (a.numRooms === b.numRooms) {
|
||||||
return a.member.userId.localeCompare(b.member.userId);
|
return compare(a.member.userId, b.member.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.numRooms - a.numRooms;
|
return b.numRooms - a.numRooms;
|
||||||
|
|
|
@ -73,9 +73,13 @@ const SpaceSettingsDialog: React.FC<IProps> = ({ matrixClient: cli, space, onFin
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
if (avatarChanged) {
|
if (avatarChanged) {
|
||||||
promises.push(cli.sendStateEvent(space.roomId, EventType.RoomAvatar, {
|
if (newAvatar) {
|
||||||
url: await cli.uploadContent(newAvatar),
|
promises.push(cli.sendStateEvent(space.roomId, EventType.RoomAvatar, {
|
||||||
}, ""));
|
url: await cli.uploadContent(newAvatar),
|
||||||
|
}, ""));
|
||||||
|
} else {
|
||||||
|
promises.push(cli.sendStateEvent(space.roomId, EventType.RoomAvatar, {}, ""));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nameChanged) {
|
if (nameChanged) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
import TextInputDialog from "../dialogs/TextInputDialog";
|
import TextInputDialog from "../dialogs/TextInputDialog";
|
||||||
import QuestionDialog from "../dialogs/QuestionDialog";
|
import QuestionDialog from "../dialogs/QuestionDialog";
|
||||||
import UIStore from "../../../stores/UIStore";
|
import UIStore from "../../../stores/UIStore";
|
||||||
|
import { compare } from "../../../utils/strings";
|
||||||
|
|
||||||
export const ALL_ROOMS = Symbol("ALL_ROOMS");
|
export const ALL_ROOMS = Symbol("ALL_ROOMS");
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s
|
||||||
|
|
||||||
protocolsList.forEach(({instances=[]}) => {
|
protocolsList.forEach(({instances=[]}) => {
|
||||||
[...instances].sort((b, a) => {
|
[...instances].sort((b, a) => {
|
||||||
return a.desc.localeCompare(b.desc);
|
return compare(a.desc, b.desc);
|
||||||
}).forEach(({desc, instance_id: instanceId}) => {
|
}).forEach(({desc, instance_id: instanceId}) => {
|
||||||
entries.push(
|
entries.push(
|
||||||
<MenuItemRadio
|
<MenuItemRadio
|
||||||
|
|
|
@ -73,7 +73,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
|
||||||
tooltipClassName={classNames("mx_AccessibleTooltipButton_tooltip", tooltipClassName)}
|
tooltipClassName={classNames("mx_AccessibleTooltipButton_tooltip", tooltipClassName)}
|
||||||
label={tooltip || title}
|
label={tooltip || title}
|
||||||
yOffset={yOffset}
|
yOffset={yOffset}
|
||||||
/> : <div />;
|
/> : null;
|
||||||
return (
|
return (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -116,7 +116,7 @@ export default class Flair extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.profiles.length === 0) {
|
if (this.state.profiles.length === 0) {
|
||||||
return <span className="mx_Flair" />;
|
return null;
|
||||||
}
|
}
|
||||||
const avatars = this.state.profiles.map((profile, index) => {
|
const avatars = this.state.profiles.map((profile, index) => {
|
||||||
return <FlairAvatar key={index} groupProfile={profile} />;
|
return <FlairAvatar key={index} groupProfile={profile} />;
|
||||||
|
|
|
@ -214,7 +214,7 @@ export default class ReplyThread extends React.Component {
|
||||||
|
|
||||||
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout) {
|
static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout) {
|
||||||
if (!ReplyThread.getParentEventId(parentEv)) {
|
if (!ReplyThread.getParentEventId(parentEv)) {
|
||||||
return <div className="mx_ReplyThread_wrapper_empty" />;
|
return null;
|
||||||
}
|
}
|
||||||
return <ReplyThread
|
return <ReplyThread
|
||||||
parentEv={parentEv}
|
parentEv={parentEv}
|
||||||
|
@ -269,36 +269,27 @@ export default class ReplyThread extends React.Component {
|
||||||
const {parentEv} = this.props;
|
const {parentEv} = this.props;
|
||||||
// at time of making this component we checked that props.parentEv has a parentEventId
|
// at time of making this component we checked that props.parentEv has a parentEventId
|
||||||
const ev = await this.getEvent(ReplyThread.getParentEventId(parentEv));
|
const ev = await this.getEvent(ReplyThread.getParentEventId(parentEv));
|
||||||
|
|
||||||
if (this.unmounted) return;
|
if (this.unmounted) return;
|
||||||
|
|
||||||
if (ev) {
|
if (ev) {
|
||||||
|
const loadedEv = await this.getNextEvent(ev);
|
||||||
this.setState({
|
this.setState({
|
||||||
events: [ev],
|
events: [ev],
|
||||||
}, this.loadNextEvent);
|
loadedEv,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({err: true});
|
this.setState({err: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadNextEvent() {
|
async getNextEvent(ev) {
|
||||||
if (this.unmounted) return;
|
try {
|
||||||
const ev = this.state.events[0];
|
const inReplyToEventId = ReplyThread.getParentEventId(ev);
|
||||||
const inReplyToEventId = ReplyThread.getParentEventId(ev);
|
return await this.getEvent(inReplyToEventId);
|
||||||
|
} catch (e) {
|
||||||
if (!inReplyToEventId) {
|
return null;
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadedEv = await this.getEvent(inReplyToEventId);
|
|
||||||
if (this.unmounted) return;
|
|
||||||
|
|
||||||
if (loadedEv) {
|
|
||||||
this.setState({loadedEv});
|
|
||||||
} else {
|
|
||||||
this.setState({err: true});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,13 +317,18 @@ export default class ReplyThread extends React.Component {
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
onQuoteClick() {
|
async onQuoteClick() {
|
||||||
const events = [this.state.loadedEv, ...this.state.events];
|
const events = [this.state.loadedEv, ...this.state.events];
|
||||||
|
|
||||||
|
let loadedEv = null;
|
||||||
|
if (events.length > 0) {
|
||||||
|
loadedEv = await this.getNextEvent(events[0]);
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
loadedEv: null,
|
loadedEv,
|
||||||
events,
|
events,
|
||||||
}, this.loadNextEvent);
|
});
|
||||||
|
|
||||||
dis.fire(Action.FocusComposer);
|
dis.fire(Action.FocusComposer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ interface IProps {
|
||||||
const MAX_PER_ROW = 6;
|
const MAX_PER_ROW = 6;
|
||||||
|
|
||||||
const SSOButtons: React.FC<IProps> = ({matrixClient, flow, loginType, fragmentAfterLogin, primary}) => {
|
const SSOButtons: React.FC<IProps> = ({matrixClient, flow, loginType, fragmentAfterLogin, primary}) => {
|
||||||
const providers = flow["org.matrix.msc2858.identity_providers"] || [];
|
const providers = flow.identity_providers || [];
|
||||||
if (providers.length < 2) {
|
if (providers.length < 2) {
|
||||||
return <div className="mx_SSOButtons">
|
return <div className="mx_SSOButtons">
|
||||||
<SSOButton
|
<SSOButton
|
||||||
|
|
|
@ -70,7 +70,10 @@ export default class Tooltip extends React.Component<IProps> {
|
||||||
this.tooltipContainer = document.createElement("div");
|
this.tooltipContainer = document.createElement("div");
|
||||||
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
||||||
document.body.appendChild(this.tooltipContainer);
|
document.body.appendChild(this.tooltipContainer);
|
||||||
window.addEventListener('scroll', this.renderTooltip, true);
|
window.addEventListener('scroll', this.renderTooltip, {
|
||||||
|
passive: true,
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
|
|
||||||
this.parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
this.parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
||||||
|
|
||||||
|
@ -85,7 +88,9 @@ export default class Tooltip extends React.Component<IProps> {
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
||||||
document.body.removeChild(this.tooltipContainer);
|
document.body.removeChild(this.tooltipContainer);
|
||||||
window.removeEventListener('scroll', this.renderTooltip, true);
|
window.removeEventListener('scroll', this.renderTooltip, {
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updatePosition(style: CSSProperties) {
|
private updatePosition(style: CSSProperties) {
|
||||||
|
|
|
@ -31,21 +31,23 @@ export default class SenderProfile extends React.Component {
|
||||||
|
|
||||||
static contextType = MatrixClientContext;
|
static contextType = MatrixClientContext;
|
||||||
|
|
||||||
state = {
|
constructor(props) {
|
||||||
userGroups: null,
|
super(props);
|
||||||
relatedGroups: [],
|
const senderId = this.props.mxEvent.getSender();
|
||||||
};
|
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
userGroups: FlairStore.cachedPublicisedGroups(senderId) || [],
|
||||||
|
relatedGroups: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.unmounted = false;
|
this.unmounted = false;
|
||||||
this._updateRelatedGroups();
|
this._updateRelatedGroups();
|
||||||
|
|
||||||
FlairStore.getPublicisedGroupsCached(
|
if (this.state.userGroups.length === 0) {
|
||||||
this.context, this.props.mxEvent.getSender(),
|
this.getPublicisedGroups();
|
||||||
).then((userGroups) => {
|
}
|
||||||
if (this.unmounted) return;
|
|
||||||
this.setState({userGroups});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.context.on('RoomState.events', this.onRoomStateEvents);
|
this.context.on('RoomState.events', this.onRoomStateEvents);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,15 @@ export default class SenderProfile extends React.Component {
|
||||||
this.context.removeListener('RoomState.events', this.onRoomStateEvents);
|
this.context.removeListener('RoomState.events', this.onRoomStateEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPublicisedGroups() {
|
||||||
|
if (!this.unmounted) {
|
||||||
|
const userGroups = await FlairStore.getPublicisedGroupsCached(
|
||||||
|
this.context, this.props.mxEvent.getSender(),
|
||||||
|
);
|
||||||
|
this.setState({userGroups});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onRoomStateEvents = event => {
|
onRoomStateEvents = event => {
|
||||||
if (event.getType() === 'm.room.related_groups' &&
|
if (event.getType() === 'm.room.related_groups' &&
|
||||||
event.getRoomId() === this.props.mxEvent.getRoomId()
|
event.getRoomId() === this.props.mxEvent.getRoomId()
|
||||||
|
@ -93,10 +104,10 @@ export default class SenderProfile extends React.Component {
|
||||||
const {msgtype} = mxEvent.getContent();
|
const {msgtype} = mxEvent.getContent();
|
||||||
|
|
||||||
if (msgtype === 'm.emote') {
|
if (msgtype === 'm.emote') {
|
||||||
return <span />; // emote message must include the name so don't duplicate it
|
return null; // emote message must include the name so don't duplicate it
|
||||||
}
|
}
|
||||||
|
|
||||||
let flair = <div />;
|
let flair = null;
|
||||||
if (this.props.enableFlair) {
|
if (this.props.enableFlair) {
|
||||||
const displayedGroups = this._getDisplayedGroups(
|
const displayedGroups = this._getDisplayedGroups(
|
||||||
this.state.userGroups, this.state.relatedGroups,
|
this.state.userGroups, this.state.relatedGroups,
|
||||||
|
@ -110,19 +121,12 @@ export default class SenderProfile extends React.Component {
|
||||||
|
|
||||||
const nameElem = name || '';
|
const nameElem = name || '';
|
||||||
|
|
||||||
// Name + flair
|
|
||||||
const nameFlair = <span>
|
|
||||||
<span className={`mx_SenderProfile_name ${colorClass}`}>
|
|
||||||
{ nameElem }
|
|
||||||
</span>
|
|
||||||
{ flair }
|
|
||||||
</span>;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_SenderProfile" dir="auto" onClick={this.props.onClick}>
|
<div className="mx_SenderProfile mx_SenderProfile_hover" dir="auto" onClick={this.props.onClick}>
|
||||||
<div className="mx_SenderProfile_hover">
|
<span className={`mx_SenderProfile_name ${colorClass}`}>
|
||||||
{ nameFlair }
|
{ nameElem }
|
||||||
</div>
|
</span>
|
||||||
|
{ flair }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,15 +278,15 @@ export default class TextualBody extends React.Component {
|
||||||
// pass only the first child which is the event tile otherwise this recurses on edited events
|
// pass only the first child which is the event tile otherwise this recurses on edited events
|
||||||
let links = this.findLinks([this._content.current]);
|
let links = this.findLinks([this._content.current]);
|
||||||
if (links.length) {
|
if (links.length) {
|
||||||
// de-dup the links (but preserve ordering)
|
// de-duplicate the links after stripping hashes as they don't affect the preview
|
||||||
const seen = new Set();
|
// using a set here maintains the order
|
||||||
links = links.filter((link) => {
|
links = Array.from(new Set(links.map(link => {
|
||||||
if (seen.has(link)) return false;
|
const url = new URL(link);
|
||||||
seen.add(link);
|
url.hash = "";
|
||||||
return true;
|
return url.toString();
|
||||||
});
|
})));
|
||||||
|
|
||||||
this.setState({ links: links });
|
this.setState({ links });
|
||||||
|
|
||||||
// lazy-load the hidden state of the preview widget from localstorage
|
// lazy-load the hidden state of the preview widget from localstorage
|
||||||
if (global.localStorage) {
|
if (global.localStorage) {
|
||||||
|
|
|
@ -168,6 +168,7 @@ export default class EditMessageComposer extends React.Component {
|
||||||
if (nextEvent) {
|
if (nextEvent) {
|
||||||
dis.dispatch({action: 'edit_event', event: nextEvent});
|
dis.dispatch({action: 'edit_event', event: nextEvent});
|
||||||
} else {
|
} else {
|
||||||
|
this._clearStoredEditorState();
|
||||||
dis.dispatch({action: 'edit_event', event: null});
|
dis.dispatch({action: 'edit_event', event: null});
|
||||||
dis.fire(Action.FocusComposer);
|
dis.fire(Action.FocusComposer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,6 +277,12 @@ interface IProps {
|
||||||
|
|
||||||
// Helper to build permalinks for the room
|
// Helper to build permalinks for the room
|
||||||
permalinkCreator?: RoomPermalinkCreator;
|
permalinkCreator?: RoomPermalinkCreator;
|
||||||
|
|
||||||
|
// Symbol of the root node
|
||||||
|
as?: string
|
||||||
|
|
||||||
|
// whether or not to always show timestamps
|
||||||
|
alwaysShowTimestamps?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -291,12 +297,15 @@ interface IState {
|
||||||
previouslyRequestedKeys: boolean;
|
previouslyRequestedKeys: boolean;
|
||||||
// The Relations model from the JS SDK for reactions to `mxEvent`
|
// The Relations model from the JS SDK for reactions to `mxEvent`
|
||||||
reactions: Relations;
|
reactions: Relations;
|
||||||
|
|
||||||
|
hover: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.rooms.EventTile")
|
@replaceableComponent("views.rooms.EventTile")
|
||||||
export default class EventTile extends React.Component<IProps, IState> {
|
export default class EventTile extends React.Component<IProps, IState> {
|
||||||
private suppressReadReceiptAnimation: boolean;
|
private suppressReadReceiptAnimation: boolean;
|
||||||
private isListeningForReceipts: boolean;
|
private isListeningForReceipts: boolean;
|
||||||
|
private ref: React.RefObject<unknown>;
|
||||||
private tile = React.createRef();
|
private tile = React.createRef();
|
||||||
private replyThread = React.createRef();
|
private replyThread = React.createRef();
|
||||||
|
|
||||||
|
@ -322,6 +331,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
previouslyRequestedKeys: false,
|
previouslyRequestedKeys: false,
|
||||||
// The Relations model from the JS SDK for reactions to `mxEvent`
|
// The Relations model from the JS SDK for reactions to `mxEvent`
|
||||||
reactions: this.getReactions(),
|
reactions: this.getReactions(),
|
||||||
|
|
||||||
|
hover: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// don't do RR animations until we are mounted
|
// don't do RR animations until we are mounted
|
||||||
|
@ -333,6 +344,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
// to determine if we've already subscribed and use a combination of other flags to find
|
// to determine if we've already subscribed and use a combination of other flags to find
|
||||||
// out if we should even be subscribed at all.
|
// out if we should even be subscribed at all.
|
||||||
this.isListeningForReceipts = false;
|
this.isListeningForReceipts = false;
|
||||||
|
|
||||||
|
this.ref = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -640,6 +653,11 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
let left = 0;
|
let left = 0;
|
||||||
|
|
||||||
const receipts = this.props.readReceipts || [];
|
const receipts = this.props.readReceipts || [];
|
||||||
|
|
||||||
|
if (receipts.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < receipts.length; ++i) {
|
for (let i = 0; i < receipts.length; ++i) {
|
||||||
const receipt = receipts[i];
|
const receipt = receipts[i];
|
||||||
|
|
||||||
|
@ -690,10 +708,14 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <span className="mx_EventTile_readAvatars">
|
return (
|
||||||
{ remText }
|
<div className="mx_EventTile_msgOption">
|
||||||
{ avatars }
|
<span className="mx_EventTile_readAvatars">
|
||||||
</span>;
|
{ remText }
|
||||||
|
{ avatars }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
onSenderProfileClick = event => {
|
onSenderProfileClick = event => {
|
||||||
|
@ -953,7 +975,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
onFocusChange={this.onActionBarFocusChange}
|
onFocusChange={this.onActionBarFocusChange}
|
||||||
/> : undefined;
|
/> : undefined;
|
||||||
|
|
||||||
const timestamp = this.props.mxEvent.getTs() ?
|
const showTimestamp = this.props.mxEvent.getTs() && (this.props.alwaysShowTimestamps || this.state.hover);
|
||||||
|
const timestamp = showTimestamp ?
|
||||||
<MessageTimestamp showTwelveHour={this.props.isTwelveHour} ts={this.props.mxEvent.getTs()} /> : null;
|
<MessageTimestamp showTwelveHour={this.props.isTwelveHour} ts={this.props.mxEvent.getTs()} /> : null;
|
||||||
|
|
||||||
const keyRequestHelpText =
|
const keyRequestHelpText =
|
||||||
|
@ -1016,11 +1039,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
let msgOption;
|
let msgOption;
|
||||||
if (this.props.showReadReceipts) {
|
if (this.props.showReadReceipts) {
|
||||||
const readAvatars = this.getReadAvatars();
|
const readAvatars = this.getReadAvatars();
|
||||||
msgOption = (
|
msgOption = readAvatars;
|
||||||
<div className="mx_EventTile_msgOption">
|
|
||||||
{ readAvatars }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this.props.tileShape) {
|
switch (this.props.tileShape) {
|
||||||
|
@ -1124,11 +1143,20 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
||||||
return (
|
return (
|
||||||
<div className={classes} tabIndex={-1} aria-live={ariaLive} aria-atomic="true">
|
React.createElement(this.props.as || "div", {
|
||||||
{ ircTimestamp }
|
"ref": this.ref,
|
||||||
{ sender }
|
"className": classes,
|
||||||
{ ircPadlock }
|
"tabIndex": -1,
|
||||||
<div className="mx_EventTile_line">
|
"aria-live": ariaLive,
|
||||||
|
"aria-atomic": "true",
|
||||||
|
"data-scroll-tokens": this.props["data-scroll-tokens"],
|
||||||
|
"onMouseEnter": () => this.setState({ hover: true }),
|
||||||
|
"onMouseLeave": () => this.setState({ hover: false }),
|
||||||
|
}, [
|
||||||
|
ircTimestamp,
|
||||||
|
sender,
|
||||||
|
ircPadlock,
|
||||||
|
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
||||||
{ groupTimestamp }
|
{ groupTimestamp }
|
||||||
{ groupPadlock }
|
{ groupPadlock }
|
||||||
{ thread }
|
{ thread }
|
||||||
|
@ -1145,16 +1173,12 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
{ keyRequestInfo }
|
{ keyRequestInfo }
|
||||||
{ reactionsRow }
|
{ reactionsRow }
|
||||||
{ actionBar }
|
{ actionBar }
|
||||||
</div>
|
</div>,
|
||||||
{msgOption}
|
msgOption,
|
||||||
{
|
avatar,
|
||||||
// The avatar goes after the event tile as it's absolutely positioned to be over the
|
|
||||||
// event tile line, so needs to be later in the DOM so it appears on top (this avoids
|
])
|
||||||
// the need for further z-indexing chaos)
|
)
|
||||||
}
|
|
||||||
{ avatar }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,8 @@ export default class MemberList extends React.Component {
|
||||||
member.user = cli.getUser(member.userId);
|
member.user = cli.getUser(member.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
member.sortName = (member.name[0] === '@' ? member.name.substr(1) : member.name).replace(SORT_REGEX, "");
|
||||||
|
|
||||||
// XXX: this user may have no lastPresenceTs value!
|
// XXX: this user may have no lastPresenceTs value!
|
||||||
// the right solution here is to fix the race rather than leave it as 0
|
// the right solution here is to fix the race rather than leave it as 0
|
||||||
});
|
});
|
||||||
|
@ -252,6 +254,8 @@ export default class MemberList extends React.Component {
|
||||||
m.membership === 'join' || m.membership === 'invite'
|
m.membership === 'join' || m.membership === 'invite'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
const language = SettingsStore.getValue("language");
|
||||||
|
this.collator = new Intl.Collator(language, { sensitivity: 'base', usePunctuation: true });
|
||||||
filteredAndSortedMembers.sort(this.memberSort);
|
filteredAndSortedMembers.sort(this.memberSort);
|
||||||
return filteredAndSortedMembers;
|
return filteredAndSortedMembers;
|
||||||
}
|
}
|
||||||
|
@ -351,13 +355,7 @@ export default class MemberList extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fourth by name (alphabetical)
|
// Fourth by name (alphabetical)
|
||||||
const nameA = (memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name).replace(SORT_REGEX, "");
|
return this.collator.compare(memberA.sortName, memberB.sortName);
|
||||||
const nameB = (memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name).replace(SORT_REGEX, "");
|
|
||||||
// console.log(`Comparing userA_name=${nameA} against userB_name=${nameB} - returning`);
|
|
||||||
return nameA.localeCompare(nameB, {
|
|
||||||
ignorePunctuation: true,
|
|
||||||
sensitivity: "base",
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onSearchQueryChanged = searchQuery => {
|
onSearchQueryChanged = searchQuery => {
|
||||||
|
@ -422,7 +420,7 @@ export default class MemberList extends React.Component {
|
||||||
} else {
|
} else {
|
||||||
// Is a 3pid invite
|
// Is a 3pid invite
|
||||||
return <EntityTile key={m.getStateKey()} name={m.getContent().display_name} suppressOnHover={true}
|
return <EntityTile key={m.getStateKey()} name={m.getContent().display_name} suppressOnHover={true}
|
||||||
onClick={() => this._onPending3pidInviteClick(m)} />;
|
onClick={() => this._onPending3pidInviteClick(m)} />;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -484,10 +482,10 @@ export default class MemberList extends React.Component {
|
||||||
if (this._getChildCountInvited() > 0) {
|
if (this._getChildCountInvited() > 0) {
|
||||||
invitedHeader = <h2>{ _t("Invited") }</h2>;
|
invitedHeader = <h2>{ _t("Invited") }</h2>;
|
||||||
invitedSection = <TruncatedList className="mx_MemberList_section mx_MemberList_invited" truncateAt={this.state.truncateAtInvited}
|
invitedSection = <TruncatedList className="mx_MemberList_section mx_MemberList_invited" truncateAt={this.state.truncateAtInvited}
|
||||||
createOverflowElement={this._createOverflowTileInvited}
|
createOverflowElement={this._createOverflowTileInvited}
|
||||||
getChildren={this._getChildrenInvited}
|
getChildren={this._getChildrenInvited}
|
||||||
getChildCount={this._getChildCountInvited}
|
getChildCount={this._getChildCountInvited}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const footer = (
|
const footer = (
|
||||||
|
@ -520,9 +518,9 @@ export default class MemberList extends React.Component {
|
||||||
>
|
>
|
||||||
<div className="mx_MemberList_wrapper">
|
<div className="mx_MemberList_wrapper">
|
||||||
<TruncatedList className="mx_MemberList_section mx_MemberList_joined" truncateAt={this.state.truncateAtJoined}
|
<TruncatedList className="mx_MemberList_section mx_MemberList_joined" truncateAt={this.state.truncateAtJoined}
|
||||||
createOverflowElement={this._createOverflowTileJoined}
|
createOverflowElement={this._createOverflowTileJoined}
|
||||||
getChildren={this._getChildrenJoined}
|
getChildren={this._getChildrenJoined}
|
||||||
getChildCount={this._getChildCountJoined} />
|
getChildCount={this._getChildCountJoined} />
|
||||||
{ invitedHeader }
|
{ invitedHeader }
|
||||||
{ invitedSection }
|
{ invitedSection }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,6 +55,7 @@ interface IProps {
|
||||||
onKeyDown: (ev: React.KeyboardEvent) => void;
|
onKeyDown: (ev: React.KeyboardEvent) => void;
|
||||||
onFocus: (ev: React.FocusEvent) => void;
|
onFocus: (ev: React.FocusEvent) => void;
|
||||||
onBlur: (ev: React.FocusEvent) => void;
|
onBlur: (ev: React.FocusEvent) => void;
|
||||||
|
onListCollapse?: (isExpanded: boolean) => void;
|
||||||
resizeNotifier: ResizeNotifier;
|
resizeNotifier: ResizeNotifier;
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
activeSpace: Room;
|
activeSpace: Room;
|
||||||
|
@ -538,6 +539,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
extraTiles={extraTiles}
|
extraTiles={extraTiles}
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)}
|
alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)}
|
||||||
|
onListCollapse={this.props.onListCollapse}
|
||||||
/>
|
/>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ interface IProps {
|
||||||
alwaysVisible?: boolean;
|
alwaysVisible?: boolean;
|
||||||
resizeNotifier: ResizeNotifier;
|
resizeNotifier: ResizeNotifier;
|
||||||
extraTiles?: ReactComponentElement<typeof ExtraTile>[];
|
extraTiles?: ReactComponentElement<typeof ExtraTile>[];
|
||||||
|
onListCollapse?: (isExpanded: boolean) => void;
|
||||||
|
|
||||||
// TODO: Account for https://github.com/vector-im/element-web/issues/14179
|
// TODO: Account for https://github.com/vector-im/element-web/issues/14179
|
||||||
}
|
}
|
||||||
|
@ -104,6 +105,7 @@ interface IState {
|
||||||
export default class RoomSublist extends React.Component<IProps, IState> {
|
export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
private headerButton = createRef<HTMLDivElement>();
|
private headerButton = createRef<HTMLDivElement>();
|
||||||
private sublistRef = createRef<HTMLDivElement>();
|
private sublistRef = createRef<HTMLDivElement>();
|
||||||
|
private tilesRef = createRef<HTMLDivElement>();
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private layout: ListLayout;
|
private layout: ListLayout;
|
||||||
private heightAtStart: number;
|
private heightAtStart: number;
|
||||||
|
@ -245,11 +247,15 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.tilesRef.current?.addEventListener("scroll", this.onScrollPrevent, { passive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
defaultDispatcher.unregister(this.dispatcherRef);
|
defaultDispatcher.unregister(this.dispatcherRef);
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
||||||
|
this.tilesRef.current?.removeEventListener("scroll", this.onScrollPrevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onListsUpdated = () => {
|
private onListsUpdated = () => {
|
||||||
|
@ -472,6 +478,9 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
private toggleCollapsed = () => {
|
private toggleCollapsed = () => {
|
||||||
this.layout.isCollapsed = this.state.isExpanded;
|
this.layout.isCollapsed = this.state.isExpanded;
|
||||||
this.setState({isExpanded: !this.layout.isCollapsed});
|
this.setState({isExpanded: !this.layout.isCollapsed});
|
||||||
|
if (this.props.onListCollapse) {
|
||||||
|
this.props.onListCollapse(!this.layout.isCollapsed)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onHeaderKeyDown = (ev: React.KeyboardEvent) => {
|
private onHeaderKeyDown = (ev: React.KeyboardEvent) => {
|
||||||
|
@ -751,7 +760,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScrollPrevent(e: React.UIEvent<HTMLDivElement>) {
|
private onScrollPrevent(e: Event) {
|
||||||
// the RoomTile calls scrollIntoView and the browser may scroll a div we do not wish to be scrollable
|
// the RoomTile calls scrollIntoView and the browser may scroll a div we do not wish to be scrollable
|
||||||
// this fixes https://github.com/vector-im/element-web/issues/14413
|
// this fixes https://github.com/vector-im/element-web/issues/14413
|
||||||
(e.target as HTMLDivElement).scrollTop = 0;
|
(e.target as HTMLDivElement).scrollTop = 0;
|
||||||
|
@ -880,7 +889,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
className="mx_RoomSublist_resizeBox"
|
className="mx_RoomSublist_resizeBox"
|
||||||
enable={handles}
|
enable={handles}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomSublist_tiles" onScroll={this.onScrollPrevent}>
|
<div className="mx_RoomSublist_tiles" ref={this.tilesRef}>
|
||||||
{visibleTiles}
|
{visibleTiles}
|
||||||
</div>
|
</div>
|
||||||
{showNButton}
|
{showNButton}
|
||||||
|
|
|
@ -62,13 +62,11 @@ export default class SimpleRoomHeader extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomHeader" >
|
<div className="mx_RoomHeader mx_RoomHeader_wrapper" >
|
||||||
<div className="mx_RoomHeader_wrapper">
|
<div className="mx_RoomHeader_simpleHeader">
|
||||||
<div className="mx_RoomHeader_simpleHeader">
|
{ icon }
|
||||||
{ icon }
|
{ this.props.title }
|
||||||
{ this.props.title }
|
{ cancelButton }
|
||||||
{ cancelButton }
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import Timer from '../../../utils/Timer';
|
||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import MemberAvatar from '../avatars/MemberAvatar';
|
import MemberAvatar from '../avatars/MemberAvatar';
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import { compare } from "../../../utils/strings";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// the room this statusbar is representing.
|
// the room this statusbar is representing.
|
||||||
|
@ -207,14 +208,14 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
|
||||||
usersTyping = usersTyping.concat(stoppedUsersOnTimer);
|
usersTyping = usersTyping.concat(stoppedUsersOnTimer);
|
||||||
// sort them so the typing members don't change order when
|
// sort them so the typing members don't change order when
|
||||||
// moved to delayedStopTypingTimers
|
// moved to delayedStopTypingTimers
|
||||||
usersTyping.sort((a, b) => a.name.localeCompare(b.name));
|
usersTyping.sort((a, b) => compare(a.name, b.name));
|
||||||
|
|
||||||
const typingString = WhoIsTyping.whoIsTypingString(
|
const typingString = WhoIsTyping.whoIsTypingString(
|
||||||
usersTyping,
|
usersTyping,
|
||||||
this.props.whoIsTypingLimit,
|
this.props.whoIsTypingLimit,
|
||||||
);
|
);
|
||||||
if (!typingString) {
|
if (!typingString) {
|
||||||
return (<div className="mx_WhoIsTypingTile_empty" />);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {EventType} from "matrix-js-sdk/src/@types/event";
|
||||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
||||||
|
import { compare } from "../../../../../utils/strings";
|
||||||
|
|
||||||
const plEventsToLabels = {
|
const plEventsToLabels = {
|
||||||
// These will be translated for us later.
|
// These will be translated for us later.
|
||||||
|
@ -312,7 +313,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||||
// comparator for sorting PL users lexicographically on PL descending, MXID ascending. (case-insensitive)
|
// comparator for sorting PL users lexicographically on PL descending, MXID ascending. (case-insensitive)
|
||||||
const comparator = (a, b) => {
|
const comparator = (a, b) => {
|
||||||
const plDiff = userLevels[b.key] - userLevels[a.key];
|
const plDiff = userLevels[b.key] - userLevels[a.key];
|
||||||
return plDiff !== 0 ? plDiff : a.key.toLocaleLowerCase().localeCompare(b.key.toLocaleLowerCase());
|
return plDiff !== 0 ? plDiff : compare(a.key.toLocaleLowerCase(), b.key.toLocaleLowerCase());
|
||||||
};
|
};
|
||||||
|
|
||||||
privilegedUsers.sort(comparator);
|
privilegedUsers.sort(comparator);
|
||||||
|
|
|
@ -35,9 +35,10 @@ import Field from '../../../elements/Field';
|
||||||
import EventTilePreview from '../../../elements/EventTilePreview';
|
import EventTilePreview from '../../../elements/EventTilePreview';
|
||||||
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
|
||||||
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||||
import {UIFeature} from "../../../../../settings/UIFeature";
|
import { UIFeature } from "../../../../../settings/UIFeature";
|
||||||
import {Layout} from "../../../../../settings/Layout";
|
import { Layout } from "../../../../../settings/Layout";
|
||||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||||
|
import { compare } from "../../../../../utils/strings";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
}
|
}
|
||||||
|
@ -295,7 +296,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
||||||
.map(p => ({id: p[0], name: p[1]})); // convert pairs to objects for code readability
|
.map(p => ({id: p[0], name: p[1]})); // convert pairs to objects for code readability
|
||||||
const builtInThemes = themes.filter(p => !p.id.startsWith("custom-"));
|
const builtInThemes = themes.filter(p => !p.id.startsWith("custom-"));
|
||||||
const customThemes = themes.filter(p => !builtInThemes.includes(p))
|
const customThemes = themes.filter(p => !builtInThemes.includes(p))
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
.sort((a, b) => compare(a.name, b.name));
|
||||||
const orderedThemes = [...builtInThemes, ...customThemes];
|
const orderedThemes = [...builtInThemes, ...customThemes];
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab_section mx_AppearanceUserSettingsTab_themeSection">
|
<div className="mx_SettingsTab_section mx_AppearanceUserSettingsTab_themeSection">
|
||||||
|
|
|
@ -3284,5 +3284,13 @@
|
||||||
"Add reaction": "Přidat reakci",
|
"Add reaction": "Přidat reakci",
|
||||||
"Send and receive voice messages": "Odeslat a přijmout hlasové zprávy",
|
"Send and receive voice messages": "Odeslat a přijmout hlasové zprávy",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Vaše zpětná vazba pomůže zlepšit prostory. Čím podrobnější bude, tím lépe.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Vaše zpětná vazba pomůže zlepšit prostory. Čím podrobnější bude, tím lépe.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Pokud odejdete, %(brand)s se znovu načte s vypnutými Prostory. Skupiny a vlastní značky budou opět viditelné."
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Pokud odejdete, %(brand)s se znovu načte s vypnutými Prostory. Skupiny a vlastní značky budou opět viditelné.",
|
||||||
|
"Space Autocomplete": "Automatické dokončení prostoru",
|
||||||
|
"Go to my space": "Přejít do mého prostoru",
|
||||||
|
"sends space invaders": "pošle space invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Odešle zadanou zprávu s efektem vesmíru",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Zjistěte, kdy se lidé připojí, odejdou nebo jsou pozváni do vaší aktivní místnosti",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Vykopnout, vykázat, pozvat lidi do této místnosti nebo odejít",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Vykopnout, vykázat, pozvat lidi do vaší aktivní místnosti nebo odejít",
|
||||||
|
"See when people join, leave, or are invited to this room": "Zjistěte, kdy se lidé připojí, odejdou nebo jsou pozváni do této místnosti"
|
||||||
}
|
}
|
||||||
|
|
|
@ -980,7 +980,7 @@
|
||||||
"Enable Emoji suggestions while typing": "Emojivorschläge während Eingabe",
|
"Enable Emoji suggestions while typing": "Emojivorschläge während Eingabe",
|
||||||
"Show a placeholder for removed messages": "Platzhalter für gelöschte Nachrichten",
|
"Show a placeholder for removed messages": "Platzhalter für gelöschte Nachrichten",
|
||||||
"Show join/leave messages (invites/kicks/bans unaffected)": "Betreten oder Verlassen von Benutzern (ausgen. Einladungen/Rauswürfe/Banne)",
|
"Show join/leave messages (invites/kicks/bans unaffected)": "Betreten oder Verlassen von Benutzern (ausgen. Einladungen/Rauswürfe/Banne)",
|
||||||
"Show avatar changes": "Avataränderungen anzeigen",
|
"Show avatar changes": "Avataränderungen",
|
||||||
"Show display name changes": "Änderungen von Anzeigenamen",
|
"Show display name changes": "Änderungen von Anzeigenamen",
|
||||||
"Send typing notifications": "Tippbenachrichtigungen senden",
|
"Send typing notifications": "Tippbenachrichtigungen senden",
|
||||||
"Show avatars in user and room mentions": "Avatare in Benutzer- und Raumerwähnungen",
|
"Show avatars in user and room mentions": "Avatare in Benutzer- und Raumerwähnungen",
|
||||||
|
@ -1200,11 +1200,11 @@
|
||||||
"Scissors": "Schere",
|
"Scissors": "Schere",
|
||||||
"<a>Upgrade</a> to your own domain": "<a>Upgrade</a> zu deiner eigenen Domain",
|
"<a>Upgrade</a> to your own domain": "<a>Upgrade</a> zu deiner eigenen Domain",
|
||||||
"Accept all %(invitedRooms)s invites": "Akzeptiere alle %(invitedRooms)s Einladungen",
|
"Accept all %(invitedRooms)s invites": "Akzeptiere alle %(invitedRooms)s Einladungen",
|
||||||
"Change room avatar": "Ändere Raumbild",
|
"Change room avatar": "Raumbild ändern",
|
||||||
"Change room name": "Ändere Raumname",
|
"Change room name": "Raumname ändern",
|
||||||
"Change main address for the room": "Ändere Hauptadresse für den Raum",
|
"Change main address for the room": "Hauptadresse ändern",
|
||||||
"Change history visibility": "Sichtbarkeit des Verlaufs ändern",
|
"Change history visibility": "Sichtbarkeit des Verlaufs ändern",
|
||||||
"Change permissions": "Ändere Berechtigungen",
|
"Change permissions": "Berechtigungen ändern",
|
||||||
"Change topic": "Thema ändern",
|
"Change topic": "Thema ändern",
|
||||||
"Modify widgets": "Widgets bearbeiten",
|
"Modify widgets": "Widgets bearbeiten",
|
||||||
"Default role": "Standard-Rolle",
|
"Default role": "Standard-Rolle",
|
||||||
|
@ -2378,7 +2378,7 @@
|
||||||
"A connection error occurred while trying to contact the server.": "Beim Versuch, den Server zu kontaktieren, ist ein Verbindungsfehler aufgetreten.",
|
"A connection error occurred while trying to contact the server.": "Beim Versuch, den Server zu kontaktieren, ist ein Verbindungsfehler aufgetreten.",
|
||||||
"You might have configured them in a client other than %(brand)s. You cannot tune them in %(brand)s but they still apply.": "Du hast sie ggf. in einem anderen Client als %(brand)s konfiguriert. Du kannst sie nicht in %(brand)s verändern, aber sie werden trotzdem angewandt.",
|
"You might have configured them in a client other than %(brand)s. You cannot tune them in %(brand)s but they still apply.": "Du hast sie ggf. in einem anderen Client als %(brand)s konfiguriert. Du kannst sie nicht in %(brand)s verändern, aber sie werden trotzdem angewandt.",
|
||||||
"Master private key:": "Privater Hauptschlüssel:",
|
"Master private key:": "Privater Hauptschlüssel:",
|
||||||
"Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Setze den Schriftnamen auf eine in deinem System installierte Schriftart & %(brand)s wird versuchen, sie zu verwenden.",
|
"Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Setze den Schriftnamen auf eine in deinem System installierte Schriftart und %(brand)s wird versuchen, sie zu verwenden.",
|
||||||
"Custom Tag": "Benutzerdefinierter Tag",
|
"Custom Tag": "Benutzerdefinierter Tag",
|
||||||
"You’re already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at <a>element.io/get-started</a>.": "Du bist bereits eingeloggt und kannst loslegen. Allerdings kannst du auch die neuesten Versionen der App für alle Plattformen unter <a>element.io/get-started</a> herunterladen.",
|
"You’re already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at <a>element.io/get-started</a>.": "Du bist bereits eingeloggt und kannst loslegen. Allerdings kannst du auch die neuesten Versionen der App für alle Plattformen unter <a>element.io/get-started</a> herunterladen.",
|
||||||
"You're all caught up.": "Alles gesichtet.",
|
"You're all caught up.": "Alles gesichtet.",
|
||||||
|
@ -2521,7 +2521,7 @@
|
||||||
"Ignored attempt to disable encryption": "Versuch, die Verschlüsselung zu deaktivieren, wurde ignoriert",
|
"Ignored attempt to disable encryption": "Versuch, die Verschlüsselung zu deaktivieren, wurde ignoriert",
|
||||||
"Failed to save your profile": "Speichern des Profils fehlgeschlagen",
|
"Failed to save your profile": "Speichern des Profils fehlgeschlagen",
|
||||||
"The operation could not be completed": "Die Operation konnte nicht abgeschlossen werden",
|
"The operation could not be completed": "Die Operation konnte nicht abgeschlossen werden",
|
||||||
"Remove messages sent by others": "Nachrichten von anderen entfernen",
|
"Remove messages sent by others": "Nachrichten von anderen löschen",
|
||||||
"Starting camera...": "Starte Kamera...",
|
"Starting camera...": "Starte Kamera...",
|
||||||
"Call connecting...": "Verbinde den Anruf...",
|
"Call connecting...": "Verbinde den Anruf...",
|
||||||
"Calling...": "Rufe an...",
|
"Calling...": "Rufe an...",
|
||||||
|
@ -2699,21 +2699,21 @@
|
||||||
"Switzerland": "Schweiz",
|
"Switzerland": "Schweiz",
|
||||||
"Sweden": "Schweden",
|
"Sweden": "Schweden",
|
||||||
"Swaziland": "Swasiland",
|
"Swaziland": "Swasiland",
|
||||||
"Svalbard & Jan Mayen": "Spitzbergen & Jan Mayen",
|
"Svalbard & Jan Mayen": "Spitzbergen und Jan Mayen",
|
||||||
"Suriname": "Surinam",
|
"Suriname": "Surinam",
|
||||||
"Sudan": "Sudan",
|
"Sudan": "Sudan",
|
||||||
"St. Vincent & Grenadines": "St. Vincent und die Grenadinen",
|
"St. Vincent & Grenadines": "St. Vincent und die Grenadinen",
|
||||||
"St. Pierre & Miquelon": "St. Pierre & Miquelon",
|
"St. Pierre & Miquelon": "St. Pierre und Miquelon",
|
||||||
"St. Martin": "St. Martin",
|
"St. Martin": "St. Martin",
|
||||||
"St. Lucia": "St. Lucia",
|
"St. Lucia": "St. Lucia",
|
||||||
"St. Kitts & Nevis": "St. Kitts & Nevis",
|
"St. Kitts & Nevis": "St. Kitts und Nevis",
|
||||||
"St. Helena": "St. Helena",
|
"St. Helena": "St. Helena",
|
||||||
"St. Barthélemy": "St. Barthélemy",
|
"St. Barthélemy": "St. Barthélemy",
|
||||||
"Sri Lanka": "Sri Lanka",
|
"Sri Lanka": "Sri Lanka",
|
||||||
"Spain": "Spanien",
|
"Spain": "Spanien",
|
||||||
"South Sudan": "Südsudan",
|
"South Sudan": "Südsudan",
|
||||||
"South Korea": "Südkorea",
|
"South Korea": "Südkorea",
|
||||||
"South Georgia & South Sandwich Islands": "Südgeorgien & Südliche Sandwichinseln",
|
"South Georgia & South Sandwich Islands": "Südgeorgien und Südliche Sandwichinseln",
|
||||||
"South Africa": "Südafrika",
|
"South Africa": "Südafrika",
|
||||||
"Somalia": "Somalia",
|
"Somalia": "Somalia",
|
||||||
"Solomon Islands": "Salomonen",
|
"Solomon Islands": "Salomonen",
|
||||||
|
@ -2815,7 +2815,7 @@
|
||||||
"Hungary": "Ungarn",
|
"Hungary": "Ungarn",
|
||||||
"Hong Kong": "Hongkong",
|
"Hong Kong": "Hongkong",
|
||||||
"Honduras": "Honduras",
|
"Honduras": "Honduras",
|
||||||
"Heard & McDonald Islands": "Heard & McDonald-Inseln",
|
"Heard & McDonald Islands": "Heard und McDonald-Inseln",
|
||||||
"Haiti": "Haiti",
|
"Haiti": "Haiti",
|
||||||
"Guyana": "Guyana",
|
"Guyana": "Guyana",
|
||||||
"Guinea-Bissau": "Guinea-Bissau",
|
"Guinea-Bissau": "Guinea-Bissau",
|
||||||
|
@ -2961,9 +2961,9 @@
|
||||||
"%(peerName)s held the call": "%(peerName)s hält den Anruf",
|
"%(peerName)s held the call": "%(peerName)s hält den Anruf",
|
||||||
"You held the call <a>Resume</a>": "Du hältst den Anruf <a>Fortsetzen</a>",
|
"You held the call <a>Resume</a>": "Du hältst den Anruf <a>Fortsetzen</a>",
|
||||||
"sends fireworks": "sendet Feuerwerk",
|
"sends fireworks": "sendet Feuerwerk",
|
||||||
"Sends the given message with fireworks": "Sendet die gewählte Nachricht mit Feuerwerk",
|
"Sends the given message with fireworks": "Sendet die Nachricht mit Feuerwerk",
|
||||||
"sends confetti": "sendet Konfetti",
|
"sends confetti": "sendet Konfetti",
|
||||||
"Sends the given message with confetti": "Sendet die gewählte Nachricht mit Konfetti",
|
"Sends the given message with confetti": "Sendet die Nachricht mit Konfetti",
|
||||||
"Show chat effects": "Chat-Effekte anzeigen",
|
"Show chat effects": "Chat-Effekte anzeigen",
|
||||||
"Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message": "Stellt ┬──┬ ノ( ゜-゜ノ) einer Klartextnachricht voran",
|
"Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message": "Stellt ┬──┬ ノ( ゜-゜ノ) einer Klartextnachricht voran",
|
||||||
"Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "Stellt (╯°□°)╯︵ ┻━┻ einer Klartextnachricht voran",
|
"Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "Stellt (╯°□°)╯︵ ┻━┻ einer Klartextnachricht voran",
|
||||||
|
@ -2976,7 +2976,7 @@
|
||||||
"%(name)s on hold": "%(name)s wird gehalten",
|
"%(name)s on hold": "%(name)s wird gehalten",
|
||||||
"You held the call <a>Switch</a>": "Du hältst den Anruf <a>Wechseln</a>",
|
"You held the call <a>Switch</a>": "Du hältst den Anruf <a>Wechseln</a>",
|
||||||
"sends snowfall": "sendet Schneeflocken",
|
"sends snowfall": "sendet Schneeflocken",
|
||||||
"Sends the given message with snowfall": "Sendet die gewählte Nachricht mit Schneeflocken",
|
"Sends the given message with snowfall": "Sendet die Nachricht mit Schneeflocken",
|
||||||
"Transfer": "Übertragen",
|
"Transfer": "Übertragen",
|
||||||
"Failed to transfer call": "Anruf-Übertragung fehlgeschlagen",
|
"Failed to transfer call": "Anruf-Übertragung fehlgeschlagen",
|
||||||
"A call can only be transferred to a single user.": "Ein Anruf kann nur auf einen einzelnen Nutzer übertragen werden.",
|
"A call can only be transferred to a single user.": "Ein Anruf kann nur auf einen einzelnen Nutzer übertragen werden.",
|
||||||
|
@ -3089,7 +3089,7 @@
|
||||||
"Apply": "Anwenden",
|
"Apply": "Anwenden",
|
||||||
"Create a new room": "Neuen Raum erstellen",
|
"Create a new room": "Neuen Raum erstellen",
|
||||||
"Suggested Rooms": "Vorgeschlagene Räume",
|
"Suggested Rooms": "Vorgeschlagene Räume",
|
||||||
"Add existing room": "Existierenden Raum",
|
"Add existing room": "Existierenden Raum hinzufügen",
|
||||||
"Send message": "Nachricht senden",
|
"Send message": "Nachricht senden",
|
||||||
"New room": "Neuer Raum",
|
"New room": "Neuer Raum",
|
||||||
"Share invite link": "Einladungslink teilen",
|
"Share invite link": "Einladungslink teilen",
|
||||||
|
@ -3253,7 +3253,7 @@
|
||||||
"What are some things you want to discuss in %(spaceName)s?": "Welche Themen willst du in %(spaceName)s besprechen?",
|
"What are some things you want to discuss in %(spaceName)s?": "Welche Themen willst du in %(spaceName)s besprechen?",
|
||||||
"Inviting...": "Einladen...",
|
"Inviting...": "Einladen...",
|
||||||
"Failed to create initial space rooms": "Fehler beim Initialisieren des Space",
|
"Failed to create initial space rooms": "Fehler beim Initialisieren des Space",
|
||||||
"You are the only person here. If you leave, no one will be able to join in the future, including you.": "Du bist die einzige Person hier. Wenn du den Space verlässt, ist er für immer verloren (eine lange Zeit).",
|
"You are the only person here. If you leave, no one will be able to join in the future, including you.": "Du bist die einzige Person hier. Wenn du ihn jetzt verlässt, ist er für immer verloren (eine lange Zeit).",
|
||||||
"Edit settings relating to your space.": "Einstellungen vom Space bearbeiten.",
|
"Edit settings relating to your space.": "Einstellungen vom Space bearbeiten.",
|
||||||
"Please choose a strong password": "Bitte gib ein sicheres Passwort ein",
|
"Please choose a strong password": "Bitte gib ein sicheres Passwort ein",
|
||||||
"If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Wenn du alles zurücksetzt, gehen alle verifizierten Anmeldungen, Benutzer und verschlüsselte Nachrichten verloren.",
|
"If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Wenn du alles zurücksetzt, gehen alle verifizierten Anmeldungen, Benutzer und verschlüsselte Nachrichten verloren.",
|
||||||
|
@ -3324,8 +3324,8 @@
|
||||||
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Die Betaversion ist für Browser, Desktop und Android verfügbar. Danke, dass Du die Betaversion testest.",
|
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Die Betaversion ist für Browser, Desktop und Android verfügbar. Danke, dass Du die Betaversion testest.",
|
||||||
"%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s wird mit deaktivierten Spaces neuladen und du kannst Communities und Custom Tags wieder verwenden können.",
|
"%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s wird mit deaktivierten Spaces neuladen und du kannst Communities und Custom Tags wieder verwenden können.",
|
||||||
"Spaces are a beta feature.": "Spaces sind in der Beta.",
|
"Spaces are a beta feature.": "Spaces sind in der Beta.",
|
||||||
"Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Wir haben Spaces entwickelt, damit ihr eure vielen Räume besser organisieren könnt. Um einen existierenden Space beitreten zu können musst du (noch) von jemandem eingeladen werden.",
|
"Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Wir haben Spaces entwickelt, damit ihr eure Räume besser organisieren könnt. Um einen existierenden Space beitreten zu können musst du (noch) von jemandem eingeladen werden.",
|
||||||
"Spaces are a new way to group rooms and people.": "Wir haben Spaces entwickelt, damit ihr eure vielen Räume besser organisieren könnt.",
|
"Spaces are a new way to group rooms and people.": "Wir haben Spaces entwickelt, damit ihr eure Räume besser organisieren könnt.",
|
||||||
"Message search initialisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen",
|
"Message search initialisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen",
|
||||||
"Send and receive voice messages": "Sprachnachrichten",
|
"Send and receive voice messages": "Sprachnachrichten",
|
||||||
"Search names and descriptions": "Nach Name und Beschreibung filtern",
|
"Search names and descriptions": "Nach Name und Beschreibung filtern",
|
||||||
|
@ -3341,5 +3341,7 @@
|
||||||
"Your access token gives full access to your account. Do not share it with anyone.": "Dein Zugriffstoken gibt vollen Zugriff auf dein Konto. Teile es niemals mit jemanden anderen.",
|
"Your access token gives full access to your account. Do not share it with anyone.": "Dein Zugriffstoken gibt vollen Zugriff auf dein Konto. Teile es niemals mit jemanden anderen.",
|
||||||
"Access Token": "Zugriffstoken",
|
"Access Token": "Zugriffstoken",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Dein Feedback hilfst uns, die Spaces zu verbessern. Je genauer, desto besser.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Dein Feedback hilfst uns, die Spaces zu verbessern. Je genauer, desto besser.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Durchs Verlassen lädt %(brand)s mit deaktivierten Spaces neu. Danach kannst du wieder Communities und Custom Tags verwenden."
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Durchs Verlassen lädt %(brand)s mit deaktivierten Spaces neu. Danach kannst du Communities und Custom Tags wieder verwenden.",
|
||||||
|
"sends space invaders": "sendet Space Invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Sendet die Nachricht mit Raumschiffen"
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,7 @@
|
||||||
"Add rooms to this community": "Aldoni ĉambrojn al ĉi tiu komunumo",
|
"Add rooms to this community": "Aldoni ĉambrojn al ĉi tiu komunumo",
|
||||||
"An email has been sent to %(emailAddress)s": "Retletero sendiĝis al %(emailAddress)s",
|
"An email has been sent to %(emailAddress)s": "Retletero sendiĝis al %(emailAddress)s",
|
||||||
"Please check your email to continue registration.": "Bonvolu kontroli vian retpoŝton por daŭrigi la registriĝon.",
|
"Please check your email to continue registration.": "Bonvolu kontroli vian retpoŝton por daŭrigi la registriĝon.",
|
||||||
"Token incorrect": "Malĝusta ĵetono",
|
"Token incorrect": "Malĝusta peco",
|
||||||
"A text message has been sent to %(msisdn)s": "Tekstmesaĝo sendiĝîs al %(msisdn)s",
|
"A text message has been sent to %(msisdn)s": "Tekstmesaĝo sendiĝîs al %(msisdn)s",
|
||||||
"Please enter the code it contains:": "Bonvolu enigi la enhavatan kodon:",
|
"Please enter the code it contains:": "Bonvolu enigi la enhavatan kodon:",
|
||||||
"Start authentication": "Komenci aŭtentikigon",
|
"Start authentication": "Komenci aŭtentikigon",
|
||||||
|
@ -769,7 +769,7 @@
|
||||||
"Failed to invite users to the room:": "Malsukcesis inviti uzantojn al la ĉambro:",
|
"Failed to invite users to the room:": "Malsukcesis inviti uzantojn al la ĉambro:",
|
||||||
"Opens the Developer Tools dialog": "Maflermas evoluigistan interagujon",
|
"Opens the Developer Tools dialog": "Maflermas evoluigistan interagujon",
|
||||||
"This homeserver has hit its Monthly Active User limit.": "Tiu ĉi hejmservilo atingis sian monatan limon de aktivaj uzantoj.",
|
"This homeserver has hit its Monthly Active User limit.": "Tiu ĉi hejmservilo atingis sian monatan limon de aktivaj uzantoj.",
|
||||||
"This homeserver has exceeded one of its resource limits.": "Tiu ĉi hejmservilo superis je unu el siaj risurcaj limoj.",
|
"This homeserver has exceeded one of its resource limits.": "Tiu ĉi hejmservilo superis je unu el siaj rimedaj limoj.",
|
||||||
"Unable to connect to Homeserver. Retrying...": "Ne povas konektiĝi al hejmservilo. Reprovante…",
|
"Unable to connect to Homeserver. Retrying...": "Ne povas konektiĝi al hejmservilo. Reprovante…",
|
||||||
"You do not have permission to invite people to this room.": "Vi ne havas permeson inviti personojn al la ĉambro.",
|
"You do not have permission to invite people to this room.": "Vi ne havas permeson inviti personojn al la ĉambro.",
|
||||||
"User %(user_id)s does not exist": "Uzanto %(user_id)s ne ekzistas",
|
"User %(user_id)s does not exist": "Uzanto %(user_id)s ne ekzistas",
|
||||||
|
@ -1569,7 +1569,7 @@
|
||||||
"Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Bloki aliĝojn al ĉi tiu ĉambro de uzantoj el aliaj Matrix-serviloj (Ĉi tiun agordon ne eblas poste ŝanĝi!)",
|
"Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Bloki aliĝojn al ĉi tiu ĉambro de uzantoj el aliaj Matrix-serviloj (Ĉi tiun agordon ne eblas poste ŝanĝi!)",
|
||||||
"Please fill why you're reporting.": "Bonvolu skribi, kial vi raportas.",
|
"Please fill why you're reporting.": "Bonvolu skribi, kial vi raportas.",
|
||||||
"Report Content to Your Homeserver Administrator": "Raporti enhavon al la administrantode via hejmservilo",
|
"Report Content to Your Homeserver Administrator": "Raporti enhavon al la administrantode via hejmservilo",
|
||||||
"Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.": "Per raporto de ĉi tiu mesaĝo vi sendos ĝian unikan « eventan identigilon » al la administranto de via hejmservilo. Se mesaĝoj en ĉi tiu ĉambro estas ĉifrataj, la administranto de via hejmservilo ne povos legi la tekston de la mesaĝo, nek rigardi dosierojn aŭ bildojn.",
|
"Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.": "Per raporto de ĉi tiu mesaĝo vi sendos ĝian unikan «identigilon de okazo» al la administranto de via hejmservilo. Se mesaĝoj en ĉi tiu ĉambro estas ĉifrataj, la administranto de via hejmservilo ne povos legi la tekston de la mesaĝo, nek rigardi dosierojn aŭ bildojn.",
|
||||||
"Send report": "Sendi raporton",
|
"Send report": "Sendi raporton",
|
||||||
"Command Help": "Helpo pri komando",
|
"Command Help": "Helpo pri komando",
|
||||||
"To continue you need to accept the terms of this service.": "Por pluigi, vi devas akcepti la uzokondiĉojn de ĉi tiu servo.",
|
"To continue you need to accept the terms of this service.": "Por pluigi, vi devas akcepti la uzokondiĉojn de ĉi tiu servo.",
|
||||||
|
@ -1653,7 +1653,7 @@
|
||||||
"Unencrypted": "Neĉifrita",
|
"Unencrypted": "Neĉifrita",
|
||||||
"Send a reply…": "Sendi respondon…",
|
"Send a reply…": "Sendi respondon…",
|
||||||
"Send a message…": "Sendi mesaĝon…",
|
"Send a message…": "Sendi mesaĝon…",
|
||||||
"Direct Messages": "Rektaj ĉambroj",
|
"Direct Messages": "Individuaj ĉambroj",
|
||||||
"<userName/> wants to chat": "<userName/> volas babili",
|
"<userName/> wants to chat": "<userName/> volas babili",
|
||||||
"Start chatting": "Ekbabili",
|
"Start chatting": "Ekbabili",
|
||||||
"Reject & Ignore user": "Rifuzi kaj malatenti uzanton",
|
"Reject & Ignore user": "Rifuzi kaj malatenti uzanton",
|
||||||
|
@ -1665,7 +1665,7 @@
|
||||||
"Start Verification": "Komenci kontrolon",
|
"Start Verification": "Komenci kontrolon",
|
||||||
"Trusted": "Fidata",
|
"Trusted": "Fidata",
|
||||||
"Not trusted": "Nefidata",
|
"Not trusted": "Nefidata",
|
||||||
"Direct message": "Rekta ĉambro",
|
"Direct message": "Individua ĉambro",
|
||||||
"Security": "Sekureco",
|
"Security": "Sekureco",
|
||||||
"Reactions": "Reagoj",
|
"Reactions": "Reagoj",
|
||||||
"More options": "Pliaj elektebloj",
|
"More options": "Pliaj elektebloj",
|
||||||
|
@ -1919,7 +1919,7 @@
|
||||||
"Failed to find the following users": "Malsukcesis trovi la jenajn uzantojn",
|
"Failed to find the following users": "Malsukcesis trovi la jenajn uzantojn",
|
||||||
"The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "La jenaj uzantoj eble ne ekzistas aŭ ne validas, kaj ne povas invitiĝi: %(csvNames)s",
|
"The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "La jenaj uzantoj eble ne ekzistas aŭ ne validas, kaj ne povas invitiĝi: %(csvNames)s",
|
||||||
"Recent Conversations": "Freŝaj interparoloj",
|
"Recent Conversations": "Freŝaj interparoloj",
|
||||||
"Recently Direct Messaged": "Freŝaj rektaj ĉambroj",
|
"Recently Direct Messaged": "Freŝe uzitaj individuaj ĉambroj",
|
||||||
"Go": "Iri",
|
"Go": "Iri",
|
||||||
"Your account is not secure": "Via konto ne estas sekura",
|
"Your account is not secure": "Via konto ne estas sekura",
|
||||||
"Your password": "Via pasvorto",
|
"Your password": "Via pasvorto",
|
||||||
|
@ -2312,7 +2312,7 @@
|
||||||
"Customise your appearance": "Adaptu vian aspekton",
|
"Customise your appearance": "Adaptu vian aspekton",
|
||||||
"Appearance Settings only affect this %(brand)s session.": "Agordoj de aspekto nur efikos sur ĉi tiun salutaĵon de %(brand)s.",
|
"Appearance Settings only affect this %(brand)s session.": "Agordoj de aspekto nur efikos sur ĉi tiun salutaĵon de %(brand)s.",
|
||||||
"Add users and servers you want to ignore here. Use asterisks to have %(brand)s match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Aldonu uzantojn kaj servilojn, kiujn vi volas malatenti, ĉi tien. Uzu steletojn por ke %(brand)s atendu iujn ajn signojn. Ekzemple, <code>@bot:*</code> malatentigus ĉiujn uzantojn, kiuj havas la nomon «bot» sur ĉiu ajn servilo.",
|
"Add users and servers you want to ignore here. Use asterisks to have %(brand)s match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Aldonu uzantojn kaj servilojn, kiujn vi volas malatenti, ĉi tien. Uzu steletojn por ke %(brand)s atendu iujn ajn signojn. Ekzemple, <code>@bot:*</code> malatentigus ĉiujn uzantojn, kiuj havas la nomon «bot» sur ĉiu ajn servilo.",
|
||||||
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "La administranto de via servilo malŝaltis implicitan tutvojan ĉifradon en privataj kaj rektaj ĉambroj.",
|
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "La administranto de via servilo malŝaltis implicitan tutvojan ĉifradon en privataj kaj individuaj ĉambroj.",
|
||||||
"Make this room low priority": "Doni al la ĉambro malaltan prioritaton",
|
"Make this room low priority": "Doni al la ĉambro malaltan prioritaton",
|
||||||
"Low priority rooms show up at the bottom of your room list in a dedicated section at the bottom of your room list": "Ĉambroj kun malalta prioritato montriĝas en aparta sekcio, en la suba parto de via ĉambrobreto,",
|
"Low priority rooms show up at the bottom of your room list in a dedicated section at the bottom of your room list": "Ĉambroj kun malalta prioritato montriĝas en aparta sekcio, en la suba parto de via ĉambrobreto,",
|
||||||
"The authenticity of this encrypted message can't be guaranteed on this device.": "La aŭtentikeco de ĉi tiu ĉifrita mesaĝo ne povas esti garantiita sur ĉi tiu aparato.",
|
"The authenticity of this encrypted message can't be guaranteed on this device.": "La aŭtentikeco de ĉi tiu ĉifrita mesaĝo ne povas esti garantiita sur ĉi tiu aparato.",
|
||||||
|
@ -2391,7 +2391,7 @@
|
||||||
"The person who invited you already left the room.": "La persono, kiu vin invitis, jam foriris de la ĉambro.",
|
"The person who invited you already left the room.": "La persono, kiu vin invitis, jam foriris de la ĉambro.",
|
||||||
"The person who invited you already left the room, or their server is offline.": "Aŭ la persono, kiu vin invitis, jam foriris de la ĉambro, aŭ ĝia servilo estas eksterreta.",
|
"The person who invited you already left the room, or their server is offline.": "Aŭ la persono, kiu vin invitis, jam foriris de la ĉambro, aŭ ĝia servilo estas eksterreta.",
|
||||||
"Change notification settings": "Ŝanĝi agordojn pri sciigoj",
|
"Change notification settings": "Ŝanĝi agordojn pri sciigoj",
|
||||||
"Show message previews for reactions in DMs": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en rektaj ĉambroj",
|
"Show message previews for reactions in DMs": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en individuaj ĉambroj",
|
||||||
"Show message previews for reactions in all rooms": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en ĉiuj ĉambroj",
|
"Show message previews for reactions in all rooms": "Montri antaŭrigardojn al mesaĝoj ĉe reagoj en ĉiuj ĉambroj",
|
||||||
"Your server isn't responding to some <a>requests</a>.": "Via servilo ne respondas al iuj <a>petoj</a>.",
|
"Your server isn't responding to some <a>requests</a>.": "Via servilo ne respondas al iuj <a>petoj</a>.",
|
||||||
"Server isn't responding": "Servilo ne respondas",
|
"Server isn't responding": "Servilo ne respondas",
|
||||||
|
@ -2729,10 +2729,10 @@
|
||||||
"Send images as you in your active room": "Sendi bildojn kiel vi en via aktiva ĉambro",
|
"Send images as you in your active room": "Sendi bildojn kiel vi en via aktiva ĉambro",
|
||||||
"Send images as you in this room": "Sendi bildojn kiel vi en ĉi tiu ĉambro",
|
"Send images as you in this room": "Sendi bildojn kiel vi en ĉi tiu ĉambro",
|
||||||
"The <b>%(capability)s</b> capability": "La kapablo <b>%(capability)s</b>",
|
"The <b>%(capability)s</b> capability": "La kapablo <b>%(capability)s</b>",
|
||||||
"See <b>%(eventType)s</b> events posted to your active room": "Vidi eventojn de speco <b>%(eventType)s</b> afiŝitajn al via aktiva ĉambro",
|
"See <b>%(eventType)s</b> events posted to your active room": "Vidi okazojn de speco <b>%(eventType)s</b> afiŝitajn al via aktiva ĉambro",
|
||||||
"Send <b>%(eventType)s</b> events as you in your active room": "Sendi eventojn de speco <b>%(eventType)s</b> kiel vi en via aktiva ĉambro",
|
"Send <b>%(eventType)s</b> events as you in your active room": "Sendi okazojn de speco <b>%(eventType)s</b> kiel vi en via aktiva ĉambro",
|
||||||
"See <b>%(eventType)s</b> events posted to this room": "Vidi eventojn de speco <b>%(eventType)s</b> afiŝitajn al ĉi tiu ĉambro",
|
"See <b>%(eventType)s</b> events posted to this room": "Vidi okazojn de speco <b>%(eventType)s</b> afiŝitajn al ĉi tiu ĉambro",
|
||||||
"Send <b>%(eventType)s</b> events as you in this room": "Sendi eventojn de speco <b>%(eventType)s</b> kiel vi en ĉi tiu ĉambro",
|
"Send <b>%(eventType)s</b> events as you in this room": "Sendi okazojn de speco <b>%(eventType)s</b> kiel vi en ĉi tiu ĉambro",
|
||||||
"See messages posted to your active room": "Vidi mesaĝojn senditajn al via aktiva ĉambro",
|
"See messages posted to your active room": "Vidi mesaĝojn senditajn al via aktiva ĉambro",
|
||||||
"See messages posted to this room": "Vidi mesaĝojn senditajn al ĉi tiu ĉambro",
|
"See messages posted to this room": "Vidi mesaĝojn senditajn al ĉi tiu ĉambro",
|
||||||
"Send messages as you in your active room": "Sendi mesaĝojn kiel vi en via aktiva ĉambro",
|
"Send messages as you in your active room": "Sendi mesaĝojn kiel vi en via aktiva ĉambro",
|
||||||
|
@ -3000,14 +3000,14 @@
|
||||||
"Send text messages as you in this room": "Sendi tekstajn mesaĝojn kiel vi en ĉi tiu ĉambro",
|
"Send text messages as you in this room": "Sendi tekstajn mesaĝojn kiel vi en ĉi tiu ĉambro",
|
||||||
"Change which room, message, or user you're viewing": "Ŝanĝu, kiun ĉambron, mesaĝon, aŭ uzanton vi rigardas",
|
"Change which room, message, or user you're viewing": "Ŝanĝu, kiun ĉambron, mesaĝon, aŭ uzanton vi rigardas",
|
||||||
"%(senderName)s has updated the widget layout": "%(senderName)s ĝisdatigis la aranĝon de la fenestrajoj",
|
"%(senderName)s has updated the widget layout": "%(senderName)s ĝisdatigis la aranĝon de la fenestrajoj",
|
||||||
"Converts the DM to a room": "Igas la ĉambron nerekta",
|
"Converts the DM to a room": "Malindividuigas la ĉambron",
|
||||||
"Converts the room to a DM": "Igas la ĉambron rekta",
|
"Converts the room to a DM": "Individuigas la ĉambron",
|
||||||
"Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "Via hejmservilo rifuzis vian saluton. Eble tio okazis, ĉar ĝi simple daŭris tro longe. Bonvolu reprovi. Se tio daŭros, bonvolu kontakti la administranton de via hejmservilo.",
|
"Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "Via hejmservilo rifuzis vian saluton. Eble tio okazis, ĉar ĝi simple daŭris tro longe. Bonvolu reprovi. Se tio daŭros, bonvolu kontakti la administranton de via hejmservilo.",
|
||||||
"Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Via hejmservilo estis neatingebla kaj ne povis vin salutigi. Bonvolu reprovi. Se tio daŭros, bonvolu kontakti la administranton de via hejmservilo.",
|
"Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Via hejmservilo estis neatingebla kaj ne povis vin salutigi. Bonvolu reprovi. Se tio daŭros, bonvolu kontakti la administranton de via hejmservilo.",
|
||||||
"Try again": "Reprovu",
|
"Try again": "Reprovu",
|
||||||
"We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Ni petis la foliumilon memori, kiun hejmservilon vi uzas por saluti, sed domaĝe, via foliumilo forgesis. Iru al la saluta paĝo kaj reprovu.",
|
"We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Ni petis la foliumilon memori, kiun hejmservilon vi uzas por saluti, sed domaĝe, via foliumilo forgesis. Iru al la saluta paĝo kaj reprovu.",
|
||||||
"We couldn't log you in": "Ni ne povis salutigi vin",
|
"We couldn't log you in": "Ni ne povis salutigi vin",
|
||||||
"%(creator)s created this DM.": "%(creator)s kreis ĉi tiun rektan ĉambron.",
|
"%(creator)s created this DM.": "%(creator)s kreis ĉi tiun individuan ĉambron.",
|
||||||
"Invalid URL": "Nevalida URL",
|
"Invalid URL": "Nevalida URL",
|
||||||
"Unable to validate homeserver": "Ne povas validigi hejmservilon",
|
"Unable to validate homeserver": "Ne povas validigi hejmservilon",
|
||||||
"Just a heads up, if you don't add an email and forget your password, you could <b>permanently lose access to your account</b>.": "Averte, se vi ne aldonos retpoŝtadreson kaj poste forgesos vian pasvorton, vi eble <b>por ĉiam perdos aliron al via konto</b>.",
|
"Just a heads up, if you don't add an email and forget your password, you could <b>permanently lose access to your account</b>.": "Averte, se vi ne aldonos retpoŝtadreson kaj poste forgesos vian pasvorton, vi eble <b>por ĉiam perdos aliron al via konto</b>.",
|
||||||
|
@ -3156,8 +3156,8 @@
|
||||||
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Pratipo de Aroj. Malkonforma kun Komunumoj, Komunumoj v2, kaj Propraj etikedoj. Bezonas konforman hejmservilon por iuj funkcioj.",
|
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Pratipo de Aroj. Malkonforma kun Komunumoj, Komunumoj v2, kaj Propraj etikedoj. Bezonas konforman hejmservilon por iuj funkcioj.",
|
||||||
"Verify this login to access your encrypted messages and prove to others that this login is really you.": "Kontrolu ĉi tiun saluton por aliri viajn ĉifritajn mesaĝojn, kaj pruvi al aliuloj, ke la salutanto vere estas vi.",
|
"Verify this login to access your encrypted messages and prove to others that this login is really you.": "Kontrolu ĉi tiun saluton por aliri viajn ĉifritajn mesaĝojn, kaj pruvi al aliuloj, ke la salutanto vere estas vi.",
|
||||||
"Verify with another session": "Knotroli per alia salutaĵo",
|
"Verify with another session": "Knotroli per alia salutaĵo",
|
||||||
"Original event source": "Originala fonto de evento",
|
"Original event source": "Originala fonto de okazo",
|
||||||
"Decrypted event source": "Malĉifrita fonto de evento",
|
"Decrypted event source": "Malĉifrita fonto de okazo",
|
||||||
"We'll create rooms for each of them. You can add more later too, including already existing ones.": "Por ĉiu el ili ni kreos ĉambron. Vi povos aldoni pliajn pli poste, inkluzive jam ekzistantajn.",
|
"We'll create rooms for each of them. You can add more later too, including already existing ones.": "Por ĉiu el ili ni kreos ĉambron. Vi povos aldoni pliajn pli poste, inkluzive jam ekzistantajn.",
|
||||||
"What projects are you working on?": "Kiujn projektojn vi prilaboras?",
|
"What projects are you working on?": "Kiujn projektojn vi prilaboras?",
|
||||||
"Let's create a room for each of them. You can add more later too, including already existing ones.": "Ni kreu ĉambron por ĉiu el ili. Vi povas aldoni pliajn poste, inkluzive jam ekzistantajn.",
|
"Let's create a room for each of them. You can add more later too, including already existing ones.": "Ni kreu ĉambron por ĉiu el ili. Vi povas aldoni pliajn poste, inkluzive jam ekzistantajn.",
|
||||||
|
@ -3218,5 +3218,107 @@
|
||||||
"Show options to enable 'Do not disturb' mode": "Montri elekteblojn por ŝalti sendistran reĝimon",
|
"Show options to enable 'Do not disturb' mode": "Montri elekteblojn por ŝalti sendistran reĝimon",
|
||||||
"%(deviceId)s from %(ip)s": "%(deviceId)s de %(ip)s",
|
"%(deviceId)s from %(ip)s": "%(deviceId)s de %(ip)s",
|
||||||
"Review to ensure your account is safe": "Kontrolu por certigi sekurecon de via konto",
|
"Review to ensure your account is safe": "Kontrolu por certigi sekurecon de via konto",
|
||||||
"Sends the given message as a spoiler": "Sendas la donitan mesaĝon kiel malkaŝon de intrigo"
|
"Sends the given message as a spoiler": "Sendas la donitan mesaĝon kiel malkaŝon de intrigo",
|
||||||
|
"Are you sure you wish to abort creation of the host? The process cannot be continued.": "Ĉu vi certe volas nuligi kreadon de la gastiganto? Ĉi tiu procedo ne estos daŭrigebla.",
|
||||||
|
"Confirm abort of host creation": "Konfirmu nuligon de kreado de gastiganto",
|
||||||
|
"Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. <a>Learn more</a>.": "Ĉu vi eksperimentemas? Laboratorioj estas la plej bona maniero frue akiri kaj testi novajn funkciojn, kaj helpi ilin formi antaŭ ilia plena ekuzo. <a>Eksciu plion</a>.",
|
||||||
|
"Your access token gives full access to your account. Do not share it with anyone.": "Via alirpeco donas plenan aliron al via konto. Donu ĝin al neniu.",
|
||||||
|
"We couldn't create your DM.": "Ni ne povis krei vian individuan ĉambron.",
|
||||||
|
"You may contact me if you have any follow up questions": "Vi povas min kontakti okaze de pliaj demandoj",
|
||||||
|
"To leave the beta, visit your settings.": "Por foriri de la prova versio, iru al viaj agordoj.",
|
||||||
|
"Your platform and username will be noted to help us use your feedback as much as we can.": "Via platformo kaj uzantonomo helpos al ni pli bone uzi viajn prikomentojn.",
|
||||||
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Viaj prikomentoj helpos plibonigi arojn. Kiom pli detale vi skribos, tiom pli bonos.",
|
||||||
|
"%(featureName)s beta feedback": "Komentoj pri la prova versio de %(featureName)s",
|
||||||
|
"Thank you for your feedback, we really appreciate it.": "Dankon pro viaj prikomentoj, ni vere ilin ŝatas.",
|
||||||
|
"Beta feedback": "Komentoj pri la prova versio",
|
||||||
|
"Want to add a new room instead?": "Ĉu vi volas anstataŭe aldoni novan ĉambron?",
|
||||||
|
"You can add existing spaces to a space.": "Vi povas arigi arojn.",
|
||||||
|
"Feeling experimental?": "Ĉu vi eksperimentemas?",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|one": "Aldonante ĉambron…",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|other": "Aldonante ĉambrojn… (%(progress)s el %(count)s)",
|
||||||
|
"Not all selected were added": "Ne ĉiuj elektitoj aldoniĝis",
|
||||||
|
"You are not allowed to view this server's rooms list": "Vi ne rajtas vidi liston de ĉambroj de tu ĉi servilo",
|
||||||
|
"Add reaction": "Aldoni reagon",
|
||||||
|
"Error processing voice message": "Eraris traktado de voĉmesaĝo",
|
||||||
|
"Delete recording": "Forigi registraĵon",
|
||||||
|
"Stop the recording": "Ĉesigi la registradon",
|
||||||
|
"We didn't find a microphone on your device. Please check your settings and try again.": "Ni ne trovis mikrofonon en via aparato. Bonvolu kontroli viajn agordojn kaj reprovi.",
|
||||||
|
"No microphone found": "Neniu mikrofono troviĝis",
|
||||||
|
"We were unable to access your microphone. Please check your browser settings and try again.": "Ni ne povis aliri vian mikrofonon. Bonvolu kontroli la agordojn de via foliumilo kaj reprovi.",
|
||||||
|
"Unable to access your microphone": "Ne povas aliri vian mikrofonon",
|
||||||
|
"%(count)s results in all spaces|one": "%(count)s rezulto en ĉiuj aroj",
|
||||||
|
"%(count)s results in all spaces|other": "%(count)s rezultoj en ĉiuj aroj",
|
||||||
|
"You have no ignored users.": "Vi malatentas neniujn uzantojn.",
|
||||||
|
"Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Aroj prezentas novan manieron grupigi ĉambrojn kaj personojn. Por aliĝi al jama spaco, vi bezonos inviton.",
|
||||||
|
"Please enter a name for the space": "Bonvolu enigi nomon por la aro",
|
||||||
|
"Play": "Ludi",
|
||||||
|
"Pause": "Paŭzigi",
|
||||||
|
"Connecting": "Konektante",
|
||||||
|
"Sends the given message with a space themed effect": "Sendas mesaĝon kun la efekto de kosmo",
|
||||||
|
"Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Permesi samtavolajn individuajn vokojn (kaj do videbligi vian IP-adreson al la alia vokanto)",
|
||||||
|
"Send and receive voice messages": "Sendi kaj ricevi voĉmesaĝojn",
|
||||||
|
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Prova versio disponeblas por reto, labortablo, kaj Androido. Iuj funkcioj eble ne disponeblas per via hejmservilo.",
|
||||||
|
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Vi povas forlasi la provan version iam ajn per la agordoj, aŭ per tuŝeto al la prova insigno, kiel tiu ĉi-supre.",
|
||||||
|
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s estos enlegita kun subetno de Aroj. Komunumoj kaj propraj etikedoj iĝos kaŝitaj.",
|
||||||
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Se vi foriros, %(brand)s estos enlegita sen subteno de Aroj. Komunumoj kaj propraj etikedoj ree estos videblaj.",
|
||||||
|
"Spaces are a new way to group rooms and people.": "Aroj prezentas novan manieron grupigi ĉambrojn kaj homojn.",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Vidu kiam oni aliĝas, foriras, aŭ invitiĝas al via aktiva ĉambro",
|
||||||
|
"See when people join, leave, or are invited to this room": "Vidu kiam oni aliĝas, foriras, aŭ invitiĝas al la ĉambro",
|
||||||
|
"This homeserver has been blocked by it's administrator.": "Tiu ĉi hejmservilo estas blokita de sia administranto.",
|
||||||
|
"This homeserver has been blocked by its administrator.": "Tiu ĉi hejmservilo estas blokita de sia administranto.",
|
||||||
|
"Modal Widget": "Reĝima fenestraĵo",
|
||||||
|
"Your message wasn't sent because this homeserver has been blocked by it's administrator. Please <a>contact your service administrator</a> to continue using the service.": "Via mesaĝo ne sendiĝis, ĉar ĉi tiu hejmservilo estas blokita de ĝia administranto. Bonvolu <a>kontakti la administranton de via servo</a> por daŭre uzadi la servon.",
|
||||||
|
"Element Web is experimental on mobile. For a better experience and the latest features, use our free native app.": "Elemento por la reto estas eksperimenta sur telefono. Por pli bona sperto kaj freŝaj funkcioj, uzu nian senpagan malfremdan aplikaĵon.",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Forpeli, forbari, aŭ inviti homojn al via aktiva ĉambro, kaj foririgi vin",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Forpeli, forbari, aŭ inviti personojn al la ĉambro, kaj foririgi vin",
|
||||||
|
"Consult first": "Unue konsulti",
|
||||||
|
"Continuing temporarily allows the %(hostSignupBrand)s setup process to access your account to fetch verified email addresses. This data is not stored.": "Provizora daŭrigo permesas al la agorda procedo de %(hostSignupBrand)s aliri vian konton por preni kontrolitajn retpoŝtadresojn. Tiuj ĉi datumoj de konserviĝos.",
|
||||||
|
"Access Token": "Alirpeco",
|
||||||
|
"Message search initialisation failed": "Malsukcesis komenci serĉadon de mesaĝoj",
|
||||||
|
"Consulting with %(transferTarget)s. <a>Transfer to %(transferee)s</a>": "Konsultante kun %(transferTarget)s. <a>Transdono al %(transferee)s</a>",
|
||||||
|
"sends space invaders": "sendas imiton de ludo « Space Invaders »",
|
||||||
|
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Prova versio disponeblas por reto, labortablo, kaj Androido. Dankon pro via provo.",
|
||||||
|
"Enter your Security Phrase a second time to confirm it.": "Enigu vian Sekurecan frazon duafoje por ĝin konfirmi.",
|
||||||
|
"Space Autocomplete": "Memaga finfaro de aro",
|
||||||
|
"Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Sen kontrolo, vi ne povos aliri al ĉiuj viaj mesaĝoj, kaj aliuloj vin povos vidi nefidata.",
|
||||||
|
"Verify your identity to access encrypted messages and prove your identity to others.": "Kontrolu vian identecon por aliri ĉifritajn mesaĝojn kaj pruvi vian identecon al aliuloj.",
|
||||||
|
"Use another login": "Uzi alian saluton",
|
||||||
|
"Please choose a strong password": "Bonvolu elekti fortan pasvorton",
|
||||||
|
"You can add more later too, including already existing ones.": "Vi povas aldoni pliajn poste, inkluzive tiujn, kiuj jam ekzistas.",
|
||||||
|
"Let's create a room for each of them.": "Kreu ni ĉambron por ĉiu el ili.",
|
||||||
|
"What are some things you want to discuss in %(spaceName)s?": "Pri kio volus vi diskuti en %(spaceName)s?",
|
||||||
|
"<b>This is an experimental feature.</b> For now, new users receiving an invite will have to open the invite on <link/> to actually join.": "<b>Ĉi tio estas prova funkcio.</b> Uzantoj, kiuj nun ricevos inviton, devos ĝin malfermi per <link/> por efektive aliĝi.",
|
||||||
|
"Go to my space": "Iri al mia aro",
|
||||||
|
"Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "Elektu aldonotajn ĉambrojn aŭ interparolojn. Ĉi tiu aro estas nur por vi, neniu estos informita. Vi povas aldoni pliajn pli poste.",
|
||||||
|
"What do you want to organise?": "Kion vi volas organizi?",
|
||||||
|
"Skip for now": "Preterpasi ĉi-foje",
|
||||||
|
"To join %(spaceName)s, turn on the <a>Spaces beta</a>": "Por aliĝi al %(spaceName)s, ŝaltu <a>la provan version de Aroj</a>",
|
||||||
|
"To view %(spaceName)s, turn on the <a>Spaces beta</a>": "Por vidi %(spaceName)s, ŝaltu la <a>provan version de Aroj</a>",
|
||||||
|
"Spaces are a beta feature.": "Aroj estas prova funkcio.",
|
||||||
|
"Search names and descriptions": "Serĉi nomojn kaj priskribojn",
|
||||||
|
"Select a room below first": "Unue elektu ĉambron de sube",
|
||||||
|
"You can select all or individual messages to retry or delete": "Vi povas elekti ĉiujn aŭ unuopajn mesaĝojn, por reprovi aŭ forigi",
|
||||||
|
"Sending": "Sendante",
|
||||||
|
"Retry all": "Reprovi ĉiujn",
|
||||||
|
"Delete all": "Forigi ĉiujn",
|
||||||
|
"Some of your messages have not been sent": "Kelkaj viaj mesaĝoj ne sendiĝis",
|
||||||
|
"Filter all spaces": "Filtri ĉiujn arojn",
|
||||||
|
"Communities are changing to Spaces": "Komunumoj iĝas Aroj",
|
||||||
|
"Verification requested": "Kontrolpeto",
|
||||||
|
"You are the only person here. If you leave, no one will be able to join in the future, including you.": "Vi estas la nura persono tie ĉi. Se vi foriros, neniu alia plu povos aliĝi, inkluzive vin mem.",
|
||||||
|
"Avatar": "Profilbildo",
|
||||||
|
"Join the beta": "Aliĝi al provado",
|
||||||
|
"Leave the beta": "Ĉesi provadon",
|
||||||
|
"Beta": "Prova",
|
||||||
|
"Tap for more info": "Klaku por pliaj informoj",
|
||||||
|
"Spaces is a beta feature": "Aroj estas prova funkcio",
|
||||||
|
"If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Se vi restarigos ĉion, vi rekomencos sen fidataj salutaĵoj, uzantoj, kaj eble ne povos vidi antaŭajn mesaĝojn.",
|
||||||
|
"Only do this if you have no other device to complete verification with.": "Faru tion ĉi nur se vi ne havas alian aparaton, per kiu vi kontrolus ceterajn.",
|
||||||
|
"Forgotten or lost all recovery methods? <a>Reset all</a>": "Ĉu vi forgesis aŭ perdis ĉiujn manierojn de rehavo? <a>Restarigu ĉion</a>",
|
||||||
|
"Reset everything": "Restarigi ĉion",
|
||||||
|
"Verify other login": "Kontroli alian saluton",
|
||||||
|
"Reset event store": "Restarigi deponejon de okazoj",
|
||||||
|
"If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few moments whilst the index is recreated": "Se vi tamen tion faras, sciu ke neniu el viaj mesaĝoj foriĝos, sed via sperto pri serĉado povas malboniĝi momente, dum la indekso estas refarata",
|
||||||
|
"You most likely do not want to reset your event index store": "Plej probable, vi ne volas restarigi vian deponejon de indeksoj de okazoj",
|
||||||
|
"Reset event store?": "Ĉu restarigi deponejon de okazoj?"
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@
|
||||||
"Add a topic": "Añadir un tema",
|
"Add a topic": "Añadir un tema",
|
||||||
"No media permissions": "Sin permisos para el medio",
|
"No media permissions": "Sin permisos para el medio",
|
||||||
"You may need to manually permit %(brand)s to access your microphone/webcam": "Probablemente necesites dar permisos manualmente a %(brand)s para tu micrófono/cámara",
|
"You may need to manually permit %(brand)s to access your microphone/webcam": "Probablemente necesites dar permisos manualmente a %(brand)s para tu micrófono/cámara",
|
||||||
"Are you sure you want to leave the room '%(roomName)s'?": "¿Salir de la sala «%(roomName)s?",
|
"Are you sure you want to leave the room '%(roomName)s'?": "¿Salir de la sala «%(roomName)s»?",
|
||||||
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "No se puede conectar al servidor base. Por favor, comprueba tu conexión, asegúrate de que el <a>certificado SSL del servidor</a> es de confiaza, y comprueba que no haya extensiones de navegador bloqueando las peticiones.",
|
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "No se puede conectar al servidor base. Por favor, comprueba tu conexión, asegúrate de que el <a>certificado SSL del servidor</a> es de confiaza, y comprueba que no haya extensiones de navegador bloqueando las peticiones.",
|
||||||
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s eliminó el nombre de la sala.",
|
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s eliminó el nombre de la sala.",
|
||||||
"Drop File Here": "Deje el fichero aquí",
|
"Drop File Here": "Deje el fichero aquí",
|
||||||
|
@ -1357,7 +1357,7 @@
|
||||||
"Compare a unique set of emoji if you don't have a camera on either device": "Comparar un conjunto de iconos si no tienes cámara en ninguno de los dispositivos",
|
"Compare a unique set of emoji if you don't have a camera on either device": "Comparar un conjunto de iconos si no tienes cámara en ninguno de los dispositivos",
|
||||||
"Start": "Empezar",
|
"Start": "Empezar",
|
||||||
"Waiting for %(displayName)s to verify…": "Esperando la verificación de %(displayName)s…",
|
"Waiting for %(displayName)s to verify…": "Esperando la verificación de %(displayName)s…",
|
||||||
"Review": "Revise",
|
"Review": "Revisar",
|
||||||
"in secret storage": "en almacén secreto",
|
"in secret storage": "en almacén secreto",
|
||||||
"Secret storage public key:": "Clave pública del almacén secreto:",
|
"Secret storage public key:": "Clave pública del almacén secreto:",
|
||||||
"in account data": "en datos de cuenta",
|
"in account data": "en datos de cuenta",
|
||||||
|
@ -1544,7 +1544,7 @@
|
||||||
"Theme added!": "¡Se añadió el tema!",
|
"Theme added!": "¡Se añadió el tema!",
|
||||||
"Custom theme URL": "URL de tema personalizado",
|
"Custom theme URL": "URL de tema personalizado",
|
||||||
"Add theme": "Añadir tema",
|
"Add theme": "Añadir tema",
|
||||||
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Para informar de un problema de seguridad relacionado con Matrix, por favor lea <a>Security Disclosure Policy</a> de Matrix.or.",
|
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Para informar de un problema de seguridad relacionado con Matrix, lee la <a>Política de divulgación de seguridad</a> de Matrix.org.",
|
||||||
"Keyboard Shortcuts": "Atajos de teclado",
|
"Keyboard Shortcuts": "Atajos de teclado",
|
||||||
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Personaliza tu experiencia con funciones experimentales. <a>Más información</a>.",
|
"Customise your experience with experimental labs features. <a>Learn more</a>.": "Personaliza tu experiencia con funciones experimentales. <a>Más información</a>.",
|
||||||
"Something went wrong. Please try again or view your console for hints.": "Algo salió mal. Por favor, inténtalo de nuevo o mira tu consola para encontrar pistas.",
|
"Something went wrong. Please try again or view your console for hints.": "Algo salió mal. Por favor, inténtalo de nuevo o mira tu consola para encontrar pistas.",
|
||||||
|
@ -2279,8 +2279,8 @@
|
||||||
"Create community": "Crear comunidad",
|
"Create community": "Crear comunidad",
|
||||||
"Failed to find the general chat for this community": "No se pudo encontrar el chat general de esta comunidad",
|
"Failed to find the general chat for this community": "No se pudo encontrar el chat general de esta comunidad",
|
||||||
"Security & privacy": "Seguridad y privacidad",
|
"Security & privacy": "Seguridad y privacidad",
|
||||||
"All settings": "Todos los ajustes",
|
"All settings": "Ajustes",
|
||||||
"Feedback": "Realimentación",
|
"Feedback": "Danos tu opinión",
|
||||||
"Community settings": "Configuración de la comunidad",
|
"Community settings": "Configuración de la comunidad",
|
||||||
"User settings": "Ajustes de usuario",
|
"User settings": "Ajustes de usuario",
|
||||||
"Switch to light mode": "Cambiar al tema claro",
|
"Switch to light mode": "Cambiar al tema claro",
|
||||||
|
@ -3305,5 +3305,15 @@
|
||||||
"Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. <a>Learn more</a>.": "¿Te apetece probar cosas nuevas? Los experimentos son la mejor manera de conseguir acceso anticipado a nuevas funcionalidades, probarlas y ayudar a mejorarlas antes de su lanzamiento. <a>Más información</a>.",
|
"Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. <a>Learn more</a>.": "¿Te apetece probar cosas nuevas? Los experimentos son la mejor manera de conseguir acceso anticipado a nuevas funcionalidades, probarlas y ayudar a mejorarlas antes de su lanzamiento. <a>Más información</a>.",
|
||||||
"Send and receive voice messages": "Enviar y recibir mensajes de voz",
|
"Send and receive voice messages": "Enviar y recibir mensajes de voz",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Tus comentarios ayudarán a mejorar los espacios. Cuanto más detalle incluyas, mejor.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Tus comentarios ayudarán a mejorar los espacios. Cuanto más detalle incluyas, mejor.",
|
||||||
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta disponible para la versión web, de escritorio o Android. Puede que algunas funcionalidades no estén disponibles en tu servidor base."
|
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta disponible para la versión web, de escritorio o Android. Puede que algunas funcionalidades no estén disponibles en tu servidor base.",
|
||||||
|
"Space Autocomplete": "Autocompletar espacios",
|
||||||
|
"Go to my space": "Ir a mi espacio",
|
||||||
|
"sends space invaders": "enviar space invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Envía un mensaje con efectos espaciales",
|
||||||
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Si sales, %(brand)s volverá a cargarse con los espacios desactivados. Las comunidades y las etiquetas personalizadas serán visibles de nuevo.",
|
||||||
|
"Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Permitir conexión directa (peer-to-peer) en las llamadas individuales (si lo activas, la otra parte podría ver tu dirección IP)",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Ver cuando alguien se una, salga o se le invite a tu sala activa",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Expulsar, vetar o invitar personas a esta sala, y hacerte salir de ella",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Expulsar, vetar o invitar a gente a tu sala activa, o hacerte salir",
|
||||||
|
"See when people join, leave, or are invited to this room": "Ver cuando alguien se une, sale o se le invita a la sala"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2950,5 +2950,58 @@
|
||||||
"A new login is accessing your account: %(name)s (%(deviceID)s) at %(ip)s": "Uusi kirjautuminen tilillesi: %(name)s (%(deviceID)s) osoitteesta %(ip)s",
|
"A new login is accessing your account: %(name)s (%(deviceID)s) at %(ip)s": "Uusi kirjautuminen tilillesi: %(name)s (%(deviceID)s) osoitteesta %(ip)s",
|
||||||
"This homeserver has been blocked by its administrator.": "Tämä kotipalvelin on ylläpitäjänsä estämä.",
|
"This homeserver has been blocked by its administrator.": "Tämä kotipalvelin on ylläpitäjänsä estämä.",
|
||||||
"You're already in a call with this person.": "Olet jo puhelussa tämän henkilön kanssa.",
|
"You're already in a call with this person.": "Olet jo puhelussa tämän henkilön kanssa.",
|
||||||
"Already in call": "Olet jo puhelussa"
|
"Already in call": "Olet jo puhelussa",
|
||||||
|
"Please choose a strong password": "Valitse vahva salasana",
|
||||||
|
"You can add more later too, including already existing ones.": "Voit lisätä niitä myöhemmin, mukaan lukien olemassa olevia.",
|
||||||
|
"Let's create a room for each of them.": "Tehdään huone jokaiselle.",
|
||||||
|
"What do you want to organise?": "Mitä haluat järjestää?",
|
||||||
|
"Random": "Satunnainen",
|
||||||
|
"Search names and descriptions": "Etsi nimistä ja kuvauksista",
|
||||||
|
"Failed to remove some rooms. Try again later": "Joitakin huoneita ei voitu poistaa. Yritä myöhemmin uudelleen.",
|
||||||
|
"Select a room below first": "Valitse ensin huone alta",
|
||||||
|
"You can select all or individual messages to retry or delete": "Voit valita kaikki tai yksittäisiä viestejä yritettäväksi uudelleen tai poistettavaksi",
|
||||||
|
"Sending": "Lähetetään",
|
||||||
|
"Retry all": "Yritä kaikkia uudelleen",
|
||||||
|
"Delete all": "Poista kaikki",
|
||||||
|
"Some of your messages have not been sent": "Osaa viesteistäsi ei ole lähetetty",
|
||||||
|
"You are the only person here. If you leave, no one will be able to join in the future, including you.": "Olet ainoa henkilö täällä. Jos lähdet, kukaan ei voi liittyä tulevaisuudessa, et myöskään sinä.",
|
||||||
|
"Beta": "Beeta",
|
||||||
|
"Tap for more info": "Lisää tietoa napauttamalla",
|
||||||
|
"The server is not configured to indicate what the problem is (CORS).": "Palvelinta ei ole säädetty ilmoittamaan, mikä ongelma on kyseessä (CORS).",
|
||||||
|
"Invited people will be able to read old messages.": "Kutsutut ihmiset voivat lukea vanhoja viestejä.",
|
||||||
|
"We couldn't create your DM.": "Yksityisviestiä ei voitu luoda.",
|
||||||
|
"Thank you for your feedback, we really appreciate it.": "Kiitos palautteesta, arvostamme sitä.",
|
||||||
|
"Beta feedback": "Palautetta beetaversiosta",
|
||||||
|
"Want to add a new room instead?": "Haluatko kuitenkin lisätä uuden huoneen?",
|
||||||
|
"Add existing rooms": "Lisää olemassa olevia huoneita",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|one": "Lisätään huonetta...",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|other": "Lisätään huoneita... (%(progress)s out of %(count)s)",
|
||||||
|
"Not all selected were added": "Kaikkia valittuja ei lisätty",
|
||||||
|
"You are not allowed to view this server's rooms list": "Sinulla ei ole oikeuksia nähdä tämän palvelimen huoneluetteloa",
|
||||||
|
"View message": "Näytä viesti",
|
||||||
|
"%(count)s people you know have already joined|one": "%(count)s tuntemasi henkilö on jo liittynyt",
|
||||||
|
"%(count)s people you know have already joined|other": "%(count)s tuntemaasi ihmistä on jo liittynyt",
|
||||||
|
"View all %(count)s members|one": "Näytä yksi jäsen",
|
||||||
|
"View all %(count)s members|other": "Näytä kaikki %(count)s jäsentä",
|
||||||
|
"Add reaction": "Lisää reaktio",
|
||||||
|
"Error processing voice message": "Virhe ääniviestin käsittelyssä",
|
||||||
|
"Delete recording": "Poista äänitys",
|
||||||
|
"Stop the recording": "Lopeta äänitys",
|
||||||
|
"Record a voice message": "Äänitä viesti",
|
||||||
|
"We were unable to access your microphone. Please check your browser settings and try again.": "Mikrofoniasi ei voitu käyttää. Tarkista selaimesi asetukset ja yritä uudelleen.",
|
||||||
|
"We didn't find a microphone on your device. Please check your settings and try again.": "Laitteestasi ei löytynyt mikrofonia. Tarkista asetuksesi ja yritä uudelleen.",
|
||||||
|
"No microphone found": "Mikrofonia ei löytynyt",
|
||||||
|
"Unable to access your microphone": "Mikrofonia ei voi käyttää",
|
||||||
|
"Quick actions": "Pikatoiminnot",
|
||||||
|
"%(seconds)ss left": "%(seconds)s s jäljellä",
|
||||||
|
"Failed to send": "Lähettäminen epäonnistui",
|
||||||
|
"You have no ignored users.": "Et ole sivuuttanut käyttäjiä.",
|
||||||
|
"Warn before quitting": "Varoita ennen lopettamista",
|
||||||
|
"Manage & explore rooms": "Hallitse ja selaa huoneita",
|
||||||
|
"Connecting": "Yhdistetään",
|
||||||
|
"unknown person": "tuntematon henkilö",
|
||||||
|
"Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Salli vertaisyhteydet 1:1-puheluille (jos otat tämän käyttöön, toinen osapuoli saattaa nähdä IP-osoitteesi)",
|
||||||
|
"Send and receive voice messages": "Lähetä ja vastaanota ääniviestejä",
|
||||||
|
"Show options to enable 'Do not disturb' mode": "Näytä asetukset Älä häiritse -tilan ottamiseksi käyttöön",
|
||||||
|
"%(deviceId)s from %(ip)s": "%(deviceId)s osoitteesta %(ip)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -936,7 +936,7 @@
|
||||||
"Failed to load group members": "Échec du chargement des membres du groupe",
|
"Failed to load group members": "Échec du chargement des membres du groupe",
|
||||||
"Failed to invite users to the room:": "Échec de l’invitation d'utilisateurs dans le salon :",
|
"Failed to invite users to the room:": "Échec de l’invitation d'utilisateurs dans le salon :",
|
||||||
"There was an error joining the room": "Une erreur est survenue en rejoignant le salon",
|
"There was an error joining the room": "Une erreur est survenue en rejoignant le salon",
|
||||||
"You do not have permission to invite people to this room.": "Vous n’avez pas la permission d’envoyer des invitations dans ce salon.",
|
"You do not have permission to invite people to this room.": "Vous n’avez pas la permission d’inviter des personnes dans ce salon.",
|
||||||
"User %(user_id)s does not exist": "L’utilisateur %(user_id)s n’existe pas",
|
"User %(user_id)s does not exist": "L’utilisateur %(user_id)s n’existe pas",
|
||||||
"Unknown server error": "Erreur de serveur inconnue",
|
"Unknown server error": "Erreur de serveur inconnue",
|
||||||
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Afficher un rappel pour activer la récupération de messages sécurisée dans les salons chiffrés",
|
"Show a reminder to enable Secure Message Recovery in encrypted rooms": "Afficher un rappel pour activer la récupération de messages sécurisée dans les salons chiffrés",
|
||||||
|
@ -3175,8 +3175,8 @@
|
||||||
"Delete": "Supprimer",
|
"Delete": "Supprimer",
|
||||||
"Jump to the bottom of the timeline when you send a message": "Sauter en bas du fil de discussion lorsque vous envoyez un message",
|
"Jump to the bottom of the timeline when you send a message": "Sauter en bas du fil de discussion lorsque vous envoyez un message",
|
||||||
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Prototype d’espaces. Incompatible avec les communautés, les communautés v2 et les étiquettes personnalisées. Nécessite un serveur d’accueil compatible pour certaines fonctionnalités.",
|
"Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Prototype d’espaces. Incompatible avec les communautés, les communautés v2 et les étiquettes personnalisées. Nécessite un serveur d’accueil compatible pour certaines fonctionnalités.",
|
||||||
"This homeserver has been blocked by it's administrator.": "Ce serveur d’accueil a été banni par ses administrateurs.",
|
"This homeserver has been blocked by it's administrator.": "Ce serveur d’accueil a été bloqué par son administrateur.",
|
||||||
"This homeserver has been blocked by its administrator.": "Ce serveur d’accueil a été banni par ses administrateurs.",
|
"This homeserver has been blocked by its administrator.": "Ce serveur d’accueil a été bloqué par son administrateur.",
|
||||||
"You're already in a call with this person.": "Vous êtes déjà en cours d’appel avec cette personne.",
|
"You're already in a call with this person.": "Vous êtes déjà en cours d’appel avec cette personne.",
|
||||||
"Already in call": "Déjà en cours d’appel",
|
"Already in call": "Déjà en cours d’appel",
|
||||||
"Space selection": "Sélection d’un espace",
|
"Space selection": "Sélection d’un espace",
|
||||||
|
@ -3344,5 +3344,13 @@
|
||||||
"To leave the beta, visit your settings.": "Pour quitter la bêta, consultez les paramètres.",
|
"To leave the beta, visit your settings.": "Pour quitter la bêta, consultez les paramètres.",
|
||||||
"Your platform and username will be noted to help us use your feedback as much as we can.": "Votre plateforme et nom d’utilisateur seront consignés pour nous aider à tirer le maximum de vos retours.",
|
"Your platform and username will be noted to help us use your feedback as much as we can.": "Votre plateforme et nom d’utilisateur seront consignés pour nous aider à tirer le maximum de vos retours.",
|
||||||
"Add reaction": "Ajouter une réaction",
|
"Add reaction": "Ajouter une réaction",
|
||||||
"Send and receive voice messages": "Envoyer et recevoir des messages vocaux"
|
"Send and receive voice messages": "Envoyer et recevoir des messages vocaux",
|
||||||
|
"See when people join, leave, or are invited to this room": "Voir quand une personne rejoint, quitte ou est invitée sur ce salon",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Exclure, bannir ou inviter une personne dans ce salon et vous permettre de partir",
|
||||||
|
"Space Autocomplete": "Autocomplétion d’espace",
|
||||||
|
"Go to my space": "Aller à mon espace",
|
||||||
|
"sends space invaders": "Envoie les Space Invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Envoyer le message avec un effet lié au thème de l’espace",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Afficher quand des personnes rejoignent, partent, ou sont invités dans votre salon actif",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Expulser, bannir ou inviter des personnes dans votre salon actif et en partir"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3367,5 +3367,13 @@
|
||||||
"Send and receive voice messages": "Enviar e recibir mensaxes de voz",
|
"Send and receive voice messages": "Enviar e recibir mensaxes de voz",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "A túa opinión axudaranos a mellorar os espazos. Canto máis detallada sexa moito mellor para nós.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "A túa opinión axudaranos a mellorar os espazos. Canto máis detallada sexa moito mellor para nós.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Se saes, %(brand)s volverá a cargar con Espazos desactivados. Comunidades e etiquetas personais serán visibles outra vez.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Se saes, %(brand)s volverá a cargar con Espazos desactivados. Comunidades e etiquetas personais serán visibles outra vez.",
|
||||||
"Message search initialisation failed": "Fallou a inicialización da busca de mensaxes"
|
"Message search initialisation failed": "Fallou a inicialización da busca de mensaxes",
|
||||||
|
"Space Autocomplete": "Autocompletado do espazo",
|
||||||
|
"Go to my space": "Ir ao meu espazo",
|
||||||
|
"sends space invaders": "enviar invasores espaciais",
|
||||||
|
"Sends the given message with a space themed effect": "Envía a mensaxe cun efecto de decorado espacial",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Mira cando alguén se une, sae ou é convidada á túa sala activa",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Expulsa, veta ou convida a persoas á túa sala activa, e fai que saias",
|
||||||
|
"See when people join, leave, or are invited to this room": "Mira cando se une alguén, sae ou é convidada a esta sala",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Expulsa, veta, ou convida persoas a esta sala, e fai que saias"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3359,5 +3359,16 @@
|
||||||
"Send and receive voice messages": "Hangüzenet küldése, fogadása",
|
"Send and receive voice messages": "Hangüzenet küldése, fogadása",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "A visszajelzése segítség a terek javításához. Minél részletesebb annál jobb.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "A visszajelzése segítség a terek javításához. Minél részletesebb annál jobb.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Távozás után %(brand)s Terek nélkül lesz újra betöltve. A közösségek és egyedi címkék újra megjelennek.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Távozás után %(brand)s Terek nélkül lesz újra betöltve. A közösségek és egyedi címkék újra megjelennek.",
|
||||||
"Message search initialisation failed": "Üzenet keresés beállítása sikertelen"
|
"Message search initialisation failed": "Üzenet keresés beállítása sikertelen",
|
||||||
|
"Space Autocomplete": "Tér automatikus kiegészítése",
|
||||||
|
"Go to my space": "Irány a teréhez",
|
||||||
|
"Spaces are a beta feature.": "A terek béta állapotban van.",
|
||||||
|
"Search names and descriptions": "Nevek és leírások keresése",
|
||||||
|
"You may contact me if you have any follow up questions": "Ha további kérdés merülne fel, kapcsolatba léphetnek velem",
|
||||||
|
"sends space invaders": "space invaders küldése",
|
||||||
|
"Sends the given message with a space themed effect": "Üzenet küldése világűrös effekttel",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Emberek belépésének, távozásának vagy meghívásának a megjelenítése az aktív szobájában",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Kirúgni, kitiltani vagy meghívni embereket az aktív szobába és, hogy ön elhagyja a szobát",
|
||||||
|
"See when people join, leave, or are invited to this room": "Emberek belépésének, távozásának vagy meghívásának a megjelenítése ebben a szobában",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Kirúgni, kitiltani vagy meghívni embereket ebbe a szobába és, hogy ön elhagyja a szobát"
|
||||||
}
|
}
|
||||||
|
|
|
@ -716,5 +716,9 @@
|
||||||
"%(duration)sm": "%(duration)sm",
|
"%(duration)sm": "%(duration)sm",
|
||||||
"%(duration)ss": "%(duration)ss",
|
"%(duration)ss": "%(duration)ss",
|
||||||
"Emoji picker": "Tjáningartáknmyndvalmynd",
|
"Emoji picker": "Tjáningartáknmyndvalmynd",
|
||||||
"Show less": "Sýna minna"
|
"Show less": "Sýna minna",
|
||||||
|
"%(count)s messages deleted.|one": "%(count)s skilaboð eytt.",
|
||||||
|
"%(count)s messages deleted.|other": "%(count)s skilaboðum eytt.",
|
||||||
|
"Message deleted on %(date)s": "Skilaboð eytt á %(date)s",
|
||||||
|
"Message edits": "Skilaboðs breytingar"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3367,5 +3367,13 @@
|
||||||
"Send and receive voice messages": "Invia e ricevi messaggi vocali",
|
"Send and receive voice messages": "Invia e ricevi messaggi vocali",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "La tua opinione aiuterà a migliorare gli spazi. Più dettagli dai, meglio è.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "La tua opinione aiuterà a migliorare gli spazi. Più dettagli dai, meglio è.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Se esci, %(brand)s si ricaricherà con gli spazi disattivati. Le comunità e le etichette personalizzate saranno di nuovo visibili.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Se esci, %(brand)s si ricaricherà con gli spazi disattivati. Le comunità e le etichette personalizzate saranno di nuovo visibili.",
|
||||||
"Message search initialisation failed": "Inizializzazione ricerca messaggi fallita"
|
"Message search initialisation failed": "Inizializzazione ricerca messaggi fallita",
|
||||||
|
"Space Autocomplete": "Autocompletamento spazio",
|
||||||
|
"Go to my space": "Vai nel mio spazio",
|
||||||
|
"sends space invaders": "invia space invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Invia il messaggio con un effetto a tema spaziale",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Buttare fuori, bandire o invitare persone nella tua stanza attiva e farti uscire",
|
||||||
|
"See when people join, leave, or are invited to this room": "Vedere quando le persone entrano, escono o sono invitate in questa stanza",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Buttare fuori, bandire o invitare persone in questa stanza e farti uscire",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Vedere quando le persone entrano, escono o sono invitate nella tua stanza attiva"
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,7 +351,7 @@
|
||||||
"Mirror local video feed": "ローカルビデオ映像送信",
|
"Mirror local video feed": "ローカルビデオ映像送信",
|
||||||
"Send analytics data": "分析データを送信する",
|
"Send analytics data": "分析データを送信する",
|
||||||
"Enable inline URL previews by default": "デフォルトでインライン URL プレビューを有効にする",
|
"Enable inline URL previews by default": "デフォルトでインライン URL プレビューを有効にする",
|
||||||
"Enable URL previews for this room (only affects you)": "この部屋の URL プレビューを有効にする (あなたにのみ影響する)",
|
"Enable URL previews for this room (only affects you)": "この部屋の URL プレビューを有効にする (あなたにのみ適用)",
|
||||||
"Enable URL previews by default for participants in this room": "この部屋の参加者のためにデフォルトで URL プレビューを有効にする",
|
"Enable URL previews by default for participants in this room": "この部屋の参加者のためにデフォルトで URL プレビューを有効にする",
|
||||||
"Room Colour": "部屋の色",
|
"Room Colour": "部屋の色",
|
||||||
"Enable widget screenshots on supported widgets": "サポートされているウィジェットでウィジェットのスクリーンショットを有効にする",
|
"Enable widget screenshots on supported widgets": "サポートされているウィジェットでウィジェットのスクリーンショットを有効にする",
|
||||||
|
@ -502,10 +502,10 @@
|
||||||
"You have <a>disabled</a> URL previews by default.": "デフォルトで URL プレビューが<a>無効</a>です。",
|
"You have <a>disabled</a> URL previews by default.": "デフォルトで URL プレビューが<a>無効</a>です。",
|
||||||
"URL previews are enabled by default for participants in this room.": "この部屋の参加者は、デフォルトで URL プレビューが有効です。",
|
"URL previews are enabled by default for participants in this room.": "この部屋の参加者は、デフォルトで URL プレビューが有効です。",
|
||||||
"URL previews are disabled by default for participants in this room.": "この部屋の参加者は、デフォルトで URL プレビューが無効です。",
|
"URL previews are disabled by default for participants in this room.": "この部屋の参加者は、デフォルトで URL プレビューが無効です。",
|
||||||
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "このような暗号化された部屋では、URL プレビューはデフォルトで無効になっており、あなたのホームサーバー(プレビューを作成する場所)がこの部屋に表示されているリンクに関する情報を収集できないようにしています。",
|
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "この部屋のように暗号化された部屋では、URL プレビューはデフォルトで無効になっています。あなたのホームサーバー (プレビューを作成する) にこの部屋でやり取りされたリンクの情報を収集されないようにするためです。",
|
||||||
"URL Previews": "URL プレビュー",
|
"URL Previews": "URL プレビュー",
|
||||||
"Historical": "履歴のある",
|
"Historical": "履歴のある",
|
||||||
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "メッセージにURLを入力すると、URLプレビューが表示され、タイトル、説明、ウェブサイトからの画像など、そのリンクに関する詳細情報が表示されます。",
|
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "メッセージに URL が含まれる場合、タイトル、説明、ウェブサイトの画像などが URL プレビューとして表示されます。",
|
||||||
"Error decrypting audio": "オーディオの復号化エラー",
|
"Error decrypting audio": "オーディオの復号化エラー",
|
||||||
"Error decrypting attachment": "添付ファイルの復号化エラー",
|
"Error decrypting attachment": "添付ファイルの復号化エラー",
|
||||||
"Decrypt %(text)s": "%(text)s を復号",
|
"Decrypt %(text)s": "%(text)s を復号",
|
||||||
|
@ -753,8 +753,8 @@
|
||||||
"Community %(groupId)s not found": "コミュニティ %(groupId)s が見つかりません",
|
"Community %(groupId)s not found": "コミュニティ %(groupId)s が見つかりません",
|
||||||
"Failed to load %(groupId)s": "%(groupId)s をロードできませんでした",
|
"Failed to load %(groupId)s": "%(groupId)s をロードできませんでした",
|
||||||
"Failed to reject invitation": "招待を拒否できませんでした",
|
"Failed to reject invitation": "招待を拒否できませんでした",
|
||||||
"This room is not public. You will not be able to rejoin without an invite.": "この部屋は公開されていません。 あなたは招待なしで再び参加することはできません。",
|
"This room is not public. You will not be able to rejoin without an invite.": "この部屋は公開されていません。再度参加するには、招待が必要です。",
|
||||||
"Are you sure you want to leave the room '%(roomName)s'?": "本当にこの部屋「%(roomName)s」から退出してよろしいですか?",
|
"Are you sure you want to leave the room '%(roomName)s'?": "この部屋「%(roomName)s」から退出してよろしいですか?",
|
||||||
"Failed to leave room": "部屋からの退出に失敗しました",
|
"Failed to leave room": "部屋からの退出に失敗しました",
|
||||||
"Can't leave Server Notices room": "サーバー通知部屋を離れることはできません",
|
"Can't leave Server Notices room": "サーバー通知部屋を離れることはできません",
|
||||||
"This room is used for important messages from the Homeserver, so you cannot leave it.": "この部屋はホームサーバーからの重要なメッセージに使用されるため、そこを離れることはできません。",
|
"This room is used for important messages from the Homeserver, so you cannot leave it.": "この部屋はホームサーバーからの重要なメッセージに使用されるため、そこを離れることはできません。",
|
||||||
|
@ -2406,7 +2406,7 @@
|
||||||
"Suggested Rooms": "おすすめの部屋",
|
"Suggested Rooms": "おすすめの部屋",
|
||||||
"Explore space rooms": "スペース内の部屋を探索します",
|
"Explore space rooms": "スペース内の部屋を探索します",
|
||||||
"You do not have permissions to add rooms to this space": "このスペースに部屋を追加する権限がありません",
|
"You do not have permissions to add rooms to this space": "このスペースに部屋を追加する権限がありません",
|
||||||
"Add existing room": "既存の部屋を追加します",
|
"Add existing room": "既存の部屋を追加",
|
||||||
"You do not have permissions to create new rooms in this space": "このスペースに新しい部屋を作成する権限がありません",
|
"You do not have permissions to create new rooms in this space": "このスペースに新しい部屋を作成する権限がありません",
|
||||||
"Send message": "メッセージを送ります",
|
"Send message": "メッセージを送ります",
|
||||||
"Invite to this space": "このスペースに招待します",
|
"Invite to this space": "このスペースに招待します",
|
||||||
|
@ -2417,8 +2417,8 @@
|
||||||
"Space options": "スペースのオプション",
|
"Space options": "スペースのオプション",
|
||||||
"Space Home": "スペースのホーム",
|
"Space Home": "スペースのホーム",
|
||||||
"New room": "新しい部屋",
|
"New room": "新しい部屋",
|
||||||
"Leave space": "スペースを離れる",
|
"Leave space": "スペースを退出",
|
||||||
"Invite people": "人々を招待する",
|
"Invite people": "人々を招待",
|
||||||
"Share your public space": "公開スペースを共有する",
|
"Share your public space": "公開スペースを共有する",
|
||||||
"Invite members": "参加者を招待する",
|
"Invite members": "参加者を招待する",
|
||||||
"Invite by email or username": "メールまたはユーザー名で招待する",
|
"Invite by email or username": "メールまたはユーザー名で招待する",
|
||||||
|
@ -2469,7 +2469,7 @@
|
||||||
"Invite to just this room": "この部屋に招待",
|
"Invite to just this room": "この部屋に招待",
|
||||||
"Invite to %(spaceName)s": "%(spaceName)s に招待",
|
"Invite to %(spaceName)s": "%(spaceName)s に招待",
|
||||||
"Quick actions": "クイックアクション",
|
"Quick actions": "クイックアクション",
|
||||||
"A private space for you and your teammates": "",
|
"A private space for you and your teammates": "あなたとチームメイトのプライベートスペース",
|
||||||
"Me and my teammates": "自分とチームメイト",
|
"Me and my teammates": "自分とチームメイト",
|
||||||
"Just me": "自分専用",
|
"Just me": "自分専用",
|
||||||
"Make sure the right people have access to %(name)s": "必要な人が %(name)s にアクセスできるようにします",
|
"Make sure the right people have access to %(name)s": "必要な人が %(name)s にアクセスできるようにします",
|
||||||
|
@ -2477,5 +2477,30 @@
|
||||||
"Beta": "Beta",
|
"Beta": "Beta",
|
||||||
"Tap for more info": "タップして詳細を表示",
|
"Tap for more info": "タップして詳細を表示",
|
||||||
"Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "スペースは、部屋や人をグループ化する新しい方法です。既存のスペースに参加するには、招待が必要です。",
|
"Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "スペースは、部屋や人をグループ化する新しい方法です。既存のスペースに参加するには、招待が必要です。",
|
||||||
"Check your devices": "デバイスを確認"
|
"Check your devices": "デバイスを確認",
|
||||||
|
"Invite to %(roomName)s": "%(roomName)s へ招待",
|
||||||
|
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta は、ウェブ、デスクトップ、Android で利用可能です。お使いのホームサーバーによっては一部機能が利用できない場合があります。",
|
||||||
|
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s はスペースが有効な状態で再読み込みされます。コミュニティとカスタムタグは非表示になります。",
|
||||||
|
"Communities are changing to Spaces": "コミュニティはスペースに生まれ変わります",
|
||||||
|
"Beta feedback": "Beta フィードバック",
|
||||||
|
"%(featureName)s beta feedback": "%(featureName)s Beta フィードバック",
|
||||||
|
"Send feedback": "フィードバックを送信",
|
||||||
|
"Manage & explore rooms": "部屋の管理および検索",
|
||||||
|
"Select a room below first": "以下から部屋を選択してください",
|
||||||
|
"A private space to organise your rooms": "部屋を整理するためのプライベートスペース",
|
||||||
|
"Private space": "プライベートスペース",
|
||||||
|
"Leave Space": "スペースを退出",
|
||||||
|
"Make this space private": "このスペースを非公開にする",
|
||||||
|
"Welcome %(name)s": "ようこそ、%(name)s",
|
||||||
|
"Are you sure you want to leave the space '%(spaceName)s'?": "このスペース「%(spaceName)s」から退出してよろしいですか?",
|
||||||
|
"This space is not public. You will not be able to rejoin without an invite.": "このスペースは公開されていません。再度参加するには、招待が必要です。",
|
||||||
|
"You are the only person here. If you leave, no one will be able to join in the future, including you.": "この部屋のメンバーはあなただけです。あなたが退出すると、今後あなたを含めて誰もこの部屋に参加できなくなります。",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|one": "部屋を追加中...",
|
||||||
|
"Adding rooms... (%(progress)s out of %(count)s)|other": "部屋を追加中... (%(progress)s / %(count)s)",
|
||||||
|
"Skip for now": "スキップ",
|
||||||
|
"What do you want to organise?": "どれを追加しますか?",
|
||||||
|
"Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "部屋や会話を追加できます。これはあなた専用のスペースで、他の人からは見えません。後から部屋や会話を追加することもできます。",
|
||||||
|
"Support": "サポート",
|
||||||
|
"You can change these anytime.": "ここで入力した情報はいつでも編集できます。",
|
||||||
|
"Add some details to help people recognise it.": "情報を入力してください。"
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@
|
||||||
"Fill screen": "Scherm vullen",
|
"Fill screen": "Scherm vullen",
|
||||||
"Filter room members": "Gespreksleden filteren",
|
"Filter room members": "Gespreksleden filteren",
|
||||||
"Forget room": "Gesprek vergeten",
|
"Forget room": "Gesprek vergeten",
|
||||||
"For security, this session has been signed out. Please sign in again.": "Wegens veiligheidsredenen is deze sessie afgemeld. Gelieve u opnieuw aan te melden.",
|
"For security, this session has been signed out. Please sign in again.": "Wegens veiligheidsredenen is deze sessie uitgelogd. Gelieve opnieuw inloggen.",
|
||||||
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s van %(fromPowerLevel)s naar %(toPowerLevel)s",
|
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s van %(fromPowerLevel)s naar %(toPowerLevel)s",
|
||||||
"Guests cannot join this room even if explicitly invited.": "Gasten - zelfs speficiek uitgenodigde - kunnen niet aan dit gesprek deelnemen.",
|
"Guests cannot join this room even if explicitly invited.": "Gasten - zelfs speficiek uitgenodigde - kunnen niet aan dit gesprek deelnemen.",
|
||||||
"Hangup": "Ophangen",
|
"Hangup": "Ophangen",
|
||||||
|
@ -249,7 +249,7 @@
|
||||||
"%(senderName)s set a profile picture.": "%(senderName)s heeft een profielfoto ingesteld.",
|
"%(senderName)s set a profile picture.": "%(senderName)s heeft een profielfoto ingesteld.",
|
||||||
"%(senderName)s set their display name to %(displayName)s.": "%(senderName)s heeft %(displayName)s als weergavenaam aangenomen.",
|
"%(senderName)s set their display name to %(displayName)s.": "%(senderName)s heeft %(displayName)s als weergavenaam aangenomen.",
|
||||||
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Tijd in 12-uursformaat tonen (bv. 2:30pm)",
|
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Tijd in 12-uursformaat tonen (bv. 2:30pm)",
|
||||||
"Signed Out": "Afgemeld",
|
"Signed Out": "Uitgelogd",
|
||||||
"Sign in": "Inloggen",
|
"Sign in": "Inloggen",
|
||||||
"Sign out": "Uitloggen",
|
"Sign out": "Uitloggen",
|
||||||
"%(count)s of your messages have not been sent.|other": "Enkele van uw berichten zijn niet verstuurd.",
|
"%(count)s of your messages have not been sent.|other": "Enkele van uw berichten zijn niet verstuurd.",
|
||||||
|
@ -350,8 +350,8 @@
|
||||||
"Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Weet u zeker dat u deze gebeurtenis wilt verwijderen? Besef wel dat het verwijderen van een van een gespreksnaams- of onderwerpswijziging die wijziging mogelijk teniet doet.",
|
"Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Weet u zeker dat u deze gebeurtenis wilt verwijderen? Besef wel dat het verwijderen van een van een gespreksnaams- of onderwerpswijziging die wijziging mogelijk teniet doet.",
|
||||||
"Unknown error": "Onbekende fout",
|
"Unknown error": "Onbekende fout",
|
||||||
"Incorrect password": "Onjuist wachtwoord",
|
"Incorrect password": "Onjuist wachtwoord",
|
||||||
"Unable to restore session": "Sessieherstel lukt niet",
|
"Unable to restore session": "Herstellen van sessie mislukt",
|
||||||
"If you have previously used a more recent version of %(brand)s, your session may be incompatible with this version. Close this window and return to the more recent version.": "Als u reeds een recentere versie van %(brand)s heeft gebruikt is uw sessie mogelijk onverenigbaar met deze versie. Sluit dit venster en ga terug naar die recentere versie.",
|
"If you have previously used a more recent version of %(brand)s, your session may be incompatible with this version. Close this window and return to the more recent version.": "Als u een recentere versie van %(brand)s heeft gebruikt is uw sessie mogelijk niet geschikt voor deze versie. Sluit dit venster en ga terug naar die recentere versie.",
|
||||||
"Unknown Address": "Onbekend adres",
|
"Unknown Address": "Onbekend adres",
|
||||||
"ex. @bob:example.com": "bv. @jan:voorbeeld.com",
|
"ex. @bob:example.com": "bv. @jan:voorbeeld.com",
|
||||||
"Add User": "Gebruiker toevoegen",
|
"Add User": "Gebruiker toevoegen",
|
||||||
|
@ -802,7 +802,7 @@
|
||||||
"Send Logs": "Logs versturen",
|
"Send Logs": "Logs versturen",
|
||||||
"Refresh": "Herladen",
|
"Refresh": "Herladen",
|
||||||
"We encountered an error trying to restore your previous session.": "Het herstel van uw vorige sessie is mislukt.",
|
"We encountered an error trying to restore your previous session.": "Het herstel van uw vorige sessie is mislukt.",
|
||||||
"Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Het legen van de opslag van uw browser zal het probleem misschien verhelpen, maar zal u ook uitloggen en uw gehele versleutelde gespreksgeschiedenis onleesbaar maken.",
|
"Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Het wissen van de browseropslag zal het probleem misschien verhelpen, maar zal u ook uitloggen en uw gehele versleutelde gespreksgeschiedenis onleesbaar maken.",
|
||||||
"Collapse Reply Thread": "Reactieketting dichtvouwen",
|
"Collapse Reply Thread": "Reactieketting dichtvouwen",
|
||||||
"Can't leave Server Notices room": "Kan servermeldingsgesprek niet verlaten",
|
"Can't leave Server Notices room": "Kan servermeldingsgesprek niet verlaten",
|
||||||
"This room is used for important messages from the Homeserver, so you cannot leave it.": "Dit gesprek is bedoeld voor belangrijke berichten van de homeserver, dus u kunt het niet verlaten.",
|
"This room is used for important messages from the Homeserver, so you cannot leave it.": "Dit gesprek is bedoeld voor belangrijke berichten van de homeserver, dus u kunt het niet verlaten.",
|
||||||
|
@ -1203,7 +1203,7 @@
|
||||||
"Please <a>contact your service administrator</a> to continue using this service.": "Gelieve <a>contact op te nemen met uw dienstbeheerder</a> om deze dienst te blijven gebruiken.",
|
"Please <a>contact your service administrator</a> to continue using this service.": "Gelieve <a>contact op te nemen met uw dienstbeheerder</a> om deze dienst te blijven gebruiken.",
|
||||||
"Failed to perform homeserver discovery": "Ontdekken van homeserver is mislukt",
|
"Failed to perform homeserver discovery": "Ontdekken van homeserver is mislukt",
|
||||||
"Sign in with single sign-on": "Inloggen met eenmalig inloggen",
|
"Sign in with single sign-on": "Inloggen met eenmalig inloggen",
|
||||||
"Create account": "Account aanmaken",
|
"Create account": "Registeren",
|
||||||
"Registration has been disabled on this homeserver.": "Registratie is uitgeschakeld op deze homeserver.",
|
"Registration has been disabled on this homeserver.": "Registratie is uitgeschakeld op deze homeserver.",
|
||||||
"Unable to query for supported registration methods.": "Kan ondersteunde registratiemethoden niet opvragen.",
|
"Unable to query for supported registration methods.": "Kan ondersteunde registratiemethoden niet opvragen.",
|
||||||
"Create your account": "Maak uw account aan",
|
"Create your account": "Maak uw account aan",
|
||||||
|
@ -1390,7 +1390,7 @@
|
||||||
"Failed to re-authenticate": "Opnieuw inloggen is mislukt",
|
"Failed to re-authenticate": "Opnieuw inloggen is mislukt",
|
||||||
"Enter your password to sign in and regain access to your account.": "Voer uw wachtwoord in om u aan te melden en toegang tot uw account te herkrijgen.",
|
"Enter your password to sign in and regain access to your account.": "Voer uw wachtwoord in om u aan te melden en toegang tot uw account te herkrijgen.",
|
||||||
"Forgotten your password?": "Wachtwoord vergeten?",
|
"Forgotten your password?": "Wachtwoord vergeten?",
|
||||||
"You're signed out": "U bent afgemeld",
|
"You're signed out": "U bent uitgelogd",
|
||||||
"Clear personal data": "Persoonlijke gegevens wissen",
|
"Clear personal data": "Persoonlijke gegevens wissen",
|
||||||
"Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Laat ons weten wat er verkeerd is gegaan, of nog beter, maak een foutrapport aan op GitHub, waarin u het probleem beschrijft.",
|
"Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Laat ons weten wat er verkeerd is gegaan, of nog beter, maak een foutrapport aan op GitHub, waarin u het probleem beschrijft.",
|
||||||
"Identity Server": "Identiteitsserver",
|
"Identity Server": "Identiteitsserver",
|
||||||
|
@ -1750,7 +1750,7 @@
|
||||||
"exists": "aanwezig",
|
"exists": "aanwezig",
|
||||||
"Sign In or Create Account": "Meld u aan of maak een account aan",
|
"Sign In or Create Account": "Meld u aan of maak een account aan",
|
||||||
"Use your account or create a new one to continue.": "Gebruik uw bestaande account of maak een nieuwe aan om verder te gaan.",
|
"Use your account or create a new one to continue.": "Gebruik uw bestaande account of maak een nieuwe aan om verder te gaan.",
|
||||||
"Create Account": "Account aanmaken",
|
"Create Account": "Registeren",
|
||||||
"Displays information about a user": "Geeft informatie weer over een gebruiker",
|
"Displays information about a user": "Geeft informatie weer over een gebruiker",
|
||||||
"Order rooms by name": "Gesprekken sorteren op naam",
|
"Order rooms by name": "Gesprekken sorteren op naam",
|
||||||
"Show rooms with unread notifications first": "Gesprekken met ongelezen meldingen eerst tonen",
|
"Show rooms with unread notifications first": "Gesprekken met ongelezen meldingen eerst tonen",
|
||||||
|
@ -2775,7 +2775,7 @@
|
||||||
"Attach files from chat or just drag and drop them anywhere in a room.": "Voeg bestanden toe vanuit het gesprek of sleep ze in een gesprek.",
|
"Attach files from chat or just drag and drop them anywhere in a room.": "Voeg bestanden toe vanuit het gesprek of sleep ze in een gesprek.",
|
||||||
"No files visible in this room": "Geen bestanden zichtbaar in dit gesprek",
|
"No files visible in this room": "Geen bestanden zichtbaar in dit gesprek",
|
||||||
"Sign in with SSO": "Inloggen met SSO",
|
"Sign in with SSO": "Inloggen met SSO",
|
||||||
"Use email to optionally be discoverable by existing contacts.": "Gebruik e-mail ook om optioneel ontdekt te worden door bestaande contacten.",
|
"Use email to optionally be discoverable by existing contacts.": "Optioneel kunt u uw e-mail ook gebruiken om ontdekt te worden door al bestaande contacten.",
|
||||||
"Use email or phone to optionally be discoverable by existing contacts.": "Gebruik e-mail of telefoon om optioneel ontdekt te kunnen worden door bestaande contacten.",
|
"Use email or phone to optionally be discoverable by existing contacts.": "Gebruik e-mail of telefoon om optioneel ontdekt te kunnen worden door bestaande contacten.",
|
||||||
"Add an email to be able to reset your password.": "Voeg een e-mail toe om uw wachtwoord te kunnen resetten.",
|
"Add an email to be able to reset your password.": "Voeg een e-mail toe om uw wachtwoord te kunnen resetten.",
|
||||||
"Forgot password?": "Wachtwoord vergeten?",
|
"Forgot password?": "Wachtwoord vergeten?",
|
||||||
|
@ -3211,7 +3211,7 @@
|
||||||
"To view %(spaceName)s, turn on the <a>Spaces beta</a>": "Om %(spaceName)s te bekijken moet u de <a>Spaces beta</a> inschakelen",
|
"To view %(spaceName)s, turn on the <a>Spaces beta</a>": "Om %(spaceName)s te bekijken moet u de <a>Spaces beta</a> inschakelen",
|
||||||
"Select a room below first": "Start met selecteren van een gesprek hieronder",
|
"Select a room below first": "Start met selecteren van een gesprek hieronder",
|
||||||
"Communities are changing to Spaces": "Gemeenschappen worden vervangen door Spaces",
|
"Communities are changing to Spaces": "Gemeenschappen worden vervangen door Spaces",
|
||||||
"Join the beta": "Aan beta deelnemen",
|
"Join the beta": "Beta inschakelen",
|
||||||
"Leave the beta": "Beta verlaten",
|
"Leave the beta": "Beta verlaten",
|
||||||
"Beta": "Beta",
|
"Beta": "Beta",
|
||||||
"Tap for more info": "Klik voor meer info",
|
"Tap for more info": "Klik voor meer info",
|
||||||
|
@ -3235,10 +3235,10 @@
|
||||||
"Please enter a name for the space": "Vul een naam in voor deze space",
|
"Please enter a name for the space": "Vul een naam in voor deze space",
|
||||||
"Connecting": "Verbinden",
|
"Connecting": "Verbinden",
|
||||||
"Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Peer-to-peer voor 1op1 oproepen toestaan (als u dit inschakelt kunnen andere personen mogelijk uw ipadres zien)",
|
"Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Peer-to-peer voor 1op1 oproepen toestaan (als u dit inschakelt kunnen andere personen mogelijk uw ipadres zien)",
|
||||||
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta beschikbaar voor web, desktop en Android. Sommige functies zijn nog niet beschikbaar op uw homeserver.",
|
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "De beta is beschikbaar voor web, desktop en Android. Sommige functies zijn nog niet beschikbaar op uw homeserver.",
|
||||||
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "U kunt de beta elk moment verlaten via instellingen of door op de beta badge hierboven te klikken.",
|
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "U kunt de beta elk moment verlaten via instellingen of door op de beta badge hierboven te klikken.",
|
||||||
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s zal herladen met Spaces ingeschakeld. Gemeenschappen en labels worden verborgen.",
|
"%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s zal herladen met Spaces ingeschakeld. Gemeenschappen en labels worden verborgen.",
|
||||||
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta beschikbaar voor web, desktop en Android. Bedankt dat u de beta wilt proberen.",
|
"Beta available for web, desktop and Android. Thank you for trying the beta.": "De beta is beschikbaar voor web, desktop en Android. Bedankt dat u de beta wilt proberen.",
|
||||||
"%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s zal herladen met Spaces uitgeschakeld. Gemeenschappen en labels zullen weer zichtbaar worden.",
|
"%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s zal herladen met Spaces uitgeschakeld. Gemeenschappen en labels zullen weer zichtbaar worden.",
|
||||||
"Spaces are a new way to group rooms and people.": "Spaces zijn de nieuwe manier om gesprekken en personen te groeperen.",
|
"Spaces are a new way to group rooms and people.": "Spaces zijn de nieuwe manier om gesprekken en personen te groeperen.",
|
||||||
"Message search initialisation failed": "Zoeken in berichten opstarten is mislukt",
|
"Message search initialisation failed": "Zoeken in berichten opstarten is mislukt",
|
||||||
|
@ -3253,5 +3253,13 @@
|
||||||
"Add reaction": "Reactie toevoegen",
|
"Add reaction": "Reactie toevoegen",
|
||||||
"Send and receive voice messages": "Stuur en ontvang spraakberichten",
|
"Send and receive voice messages": "Stuur en ontvang spraakberichten",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Uw feedback maakt spaces beter. Hoe meer details u kan geven, des te beter.",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Uw feedback maakt spaces beter. Hoe meer details u kan geven, des te beter.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Als u de pagina nu verlaat zal %(brand)s herladen met Spaces uitgeschakeld. Gemeenschappen en labels zullen weer zichtbaar worden."
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Als u de pagina nu verlaat zal %(brand)s herladen met Spaces uitgeschakeld. Gemeenschappen en labels zullen weer zichtbaar worden.",
|
||||||
|
"Space Autocomplete": "Space Autocomplete",
|
||||||
|
"Go to my space": "Ga naar mijn space",
|
||||||
|
"sends space invaders": "verstuur space invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Verstuur het bericht met een space-thema-effect",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Zie wanneer personen deelnemen, vertrekken of worden uitgenodigd in uw actieve gesprek",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Verwijder, verban of nodig personen uit voor uw actieve gesprek en uzelf laten vertrekken",
|
||||||
|
"See when people join, leave, or are invited to this room": "Zie wanneer personen deelnemen, vertrekken of worden uitgenodigd voor dit gesprek",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Verwijder, verban of verwijder personen uit dit gesprek en uzelf laten vertrekken"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3356,5 +3356,10 @@
|
||||||
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta e gatshme për web, desktop dhe Android. Faleminderit që provoni beta-n.",
|
"Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta e gatshme për web, desktop dhe Android. Faleminderit që provoni beta-n.",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Nëse ikni, %(brand)s-i do të ringarkohet me Hapësira të çaktivizuara. Bashkësitë dhe etiketat vetjake do të jenë sërish të dukshme.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Nëse ikni, %(brand)s-i do të ringarkohet me Hapësira të çaktivizuara. Bashkësitë dhe etiketat vetjake do të jenë sërish të dukshme.",
|
||||||
"Spaces are a new way to group rooms and people.": "Hapësirat janë një rrugë e re për të grupuar dhoma dhe njerëz.",
|
"Spaces are a new way to group rooms and people.": "Hapësirat janë një rrugë e re për të grupuar dhoma dhe njerëz.",
|
||||||
"Message search initialisation failed": "Dështoi gatitje kërkimi mesazhesh"
|
"Message search initialisation failed": "Dështoi gatitje kërkimi mesazhesh",
|
||||||
|
"Go to my space": "Kalo te hapësira ime",
|
||||||
|
"sends space invaders": "dërgon pushtues hapësire",
|
||||||
|
"Sends the given message with a space themed effect": "E dërgon mesazhin e dhënë me një efekt teme hapësinore",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Shihni kur persona vijnë, ikin ose janë ftuar në dhomën tuaj aktive",
|
||||||
|
"See when people join, leave, or are invited to this room": "Shihni kur persona vijnë, ikin ose janë ftuar në këtë dhomë"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3297,5 +3297,13 @@
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Om du lämnar så kommer %(brand)s att ladda om med utrymmen inaktiverade. Gemenskaper och anpassade taggar kommer att synas igen.",
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Om du lämnar så kommer %(brand)s att ladda om med utrymmen inaktiverade. Gemenskaper och anpassade taggar kommer att synas igen.",
|
||||||
"Spaces are a new way to group rooms and people.": "Utrymmen är nya sätt att gruppera rum och personer.",
|
"Spaces are a new way to group rooms and people.": "Utrymmen är nya sätt att gruppera rum och personer.",
|
||||||
"<b>This is an experimental feature.</b> For now, new users receiving an invite will have to open the invite on <link/> to actually join.": "<b>Det här är en experimentell funktion.</b> För tillfället så behöver nya inbjudna användare öppna inbjudan på <link/> för att faktiskt gå med.",
|
"<b>This is an experimental feature.</b> For now, new users receiving an invite will have to open the invite on <link/> to actually join.": "<b>Det här är en experimentell funktion.</b> För tillfället så behöver nya inbjudna användare öppna inbjudan på <link/> för att faktiskt gå med.",
|
||||||
"To join %(spaceName)s, turn on the <a>Spaces beta</a>": "För att gå med i %(spaceName)s, aktivera <a>utrymmesbetan</a>"
|
"To join %(spaceName)s, turn on the <a>Spaces beta</a>": "För att gå med i %(spaceName)s, aktivera <a>utrymmesbetan</a>",
|
||||||
|
"Space Autocomplete": "Utrymmesautokomplettering",
|
||||||
|
"Go to my space": "Gå till mitt utrymme",
|
||||||
|
"sends space invaders": "skickar Space Invaders",
|
||||||
|
"Sends the given message with a space themed effect": "Skickar det givna meddelandet med en effekt med rymdtema",
|
||||||
|
"See when people join, leave, or are invited to your active room": "Se när folk går med, lämnar eller bjuds in till ditt aktiva rum",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "Kicka, banna eller bjuda in folk till ditt aktiva rum, och tvinga dig att lämna",
|
||||||
|
"See when people join, leave, or are invited to this room": "Se när folk går med, lämnar eller bjuds in till det här rummet",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "Kicka, banna eller bjuda in folk till det här rummet, och tvinga dig att lämna"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -169,9 +169,9 @@
|
||||||
"No Webcams detected": "未偵測到網路攝影機",
|
"No Webcams detected": "未偵測到網路攝影機",
|
||||||
"No media permissions": "沒有媒體權限",
|
"No media permissions": "沒有媒體權限",
|
||||||
"You may need to manually permit %(brand)s to access your microphone/webcam": "您可能需要手動允許 %(brand)s 存取您的麥克風/網路攝影機",
|
"You may need to manually permit %(brand)s to access your microphone/webcam": "您可能需要手動允許 %(brand)s 存取您的麥克風/網路攝影機",
|
||||||
"Are you sure you want to leave the room '%(roomName)s'?": "您確定您要想要離開房間 '%(roomName)s' 嗎?",
|
"Are you sure you want to leave the room '%(roomName)s'?": "你確定你要想要離開房間 '%(roomName)s' 嗎?",
|
||||||
"Bans user with given id": "阻擋指定 ID 的使用者",
|
"Bans user with given id": "阻擋指定 ID 的使用者",
|
||||||
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "無法連線到家伺服器 - 請檢查您的連線,確保您的<a>家伺服器的 SSL 憑證</a>可被信任,而瀏覽器擴充套件也沒有阻擋請求。",
|
"Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.": "無法連線到家伺服器 - 請檢查你的連線,確保你的<a>家伺服器的 SSL 憑證</a>可被信任,而瀏覽器擴充套件也沒有阻擋請求。",
|
||||||
"%(senderName)s changed their profile picture.": "%(senderName)s 已經變更了他的基本資料圖片。",
|
"%(senderName)s changed their profile picture.": "%(senderName)s 已經變更了他的基本資料圖片。",
|
||||||
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s 變更了 %(powerLevelDiffText)s 權限等級。",
|
"%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s 變更了 %(powerLevelDiffText)s 權限等級。",
|
||||||
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s 將聊天室名稱變更為 %(roomName)s。",
|
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s 將聊天室名稱變更為 %(roomName)s。",
|
||||||
|
@ -838,7 +838,7 @@
|
||||||
"An error ocurred whilst trying to remove the widget from the room": "嘗試從聊天室移除小工具時發生錯誤",
|
"An error ocurred whilst trying to remove the widget from the room": "嘗試從聊天室移除小工具時發生錯誤",
|
||||||
"System Alerts": "系統警告",
|
"System Alerts": "系統警告",
|
||||||
"Only room administrators will see this warning": "僅聊天室管理員會看到此警告",
|
"Only room administrators will see this warning": "僅聊天室管理員會看到此警告",
|
||||||
"Please <a>contact your service administrator</a> to continue using the service.": "請<a>聯絡您的服務管理員</a>以繼續使用服務。",
|
"Please <a>contact your service administrator</a> to continue using the service.": "請<a>聯絡你的服務管理員</a>以繼續使用服務。",
|
||||||
"This homeserver has hit its Monthly Active User limit.": "這個主伺服器已經到達其每月活躍使用者限制。",
|
"This homeserver has hit its Monthly Active User limit.": "這個主伺服器已經到達其每月活躍使用者限制。",
|
||||||
"This homeserver has exceeded one of its resource limits.": "此主伺服器已經超過其中一項資源限制。",
|
"This homeserver has exceeded one of its resource limits.": "此主伺服器已經超過其中一項資源限制。",
|
||||||
"Upgrade Room Version": "更新聊天室版本",
|
"Upgrade Room Version": "更新聊天室版本",
|
||||||
|
@ -1160,7 +1160,7 @@
|
||||||
"Change": "變更",
|
"Change": "變更",
|
||||||
"Couldn't load page": "無法載入頁面",
|
"Couldn't load page": "無法載入頁面",
|
||||||
"This homeserver does not support communities": "此家伺服器不支援社群",
|
"This homeserver does not support communities": "此家伺服器不支援社群",
|
||||||
"A verification email will be sent to your inbox to confirm setting your new password.": "一封驗證用的電子郵件已經傳送到您的收件匣以確認您設定了新密碼。",
|
"A verification email will be sent to your inbox to confirm setting your new password.": "一封驗證用的電子郵件已經傳送到你的收件匣以確認你設定了新密碼。",
|
||||||
"Your password has been reset.": "您的密碼已重設。",
|
"Your password has been reset.": "您的密碼已重設。",
|
||||||
"This homeserver does not support login using email address.": "此家伺服器不支援使用電子郵件地址登入。",
|
"This homeserver does not support login using email address.": "此家伺服器不支援使用電子郵件地址登入。",
|
||||||
"Registration has been disabled on this homeserver.": "註冊已在此家伺服器上停用。",
|
"Registration has been disabled on this homeserver.": "註冊已在此家伺服器上停用。",
|
||||||
|
@ -1973,8 +1973,8 @@
|
||||||
"%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s 為此聊天室新增了替代位置 %(addresses)s。",
|
"%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s 為此聊天室新增了替代位置 %(addresses)s。",
|
||||||
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s 為此聊天室移除了替代位置 %(addresses)s。",
|
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s 為此聊天室移除了替代位置 %(addresses)s。",
|
||||||
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s 為此聊天室移除了替代位置 %(addresses)s。",
|
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s 為此聊天室移除了替代位置 %(addresses)s。",
|
||||||
"%(senderName)s changed the alternative addresses for this room.": "%(senderName)s 為此聊天是變更了替代位置。",
|
"%(senderName)s changed the alternative addresses for this room.": "%(senderName)s 為此聊天室變更了替代位置。",
|
||||||
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s 為此聊天是變更了主要及替代位置。",
|
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s 為此聊天室變更了主要及替代位置。",
|
||||||
"There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "更新聊天室的替代位置時發生錯誤。伺服器可能不允許這麼做,或是昱到了暫時性的故障。",
|
"There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "更新聊天室的替代位置時發生錯誤。伺服器可能不允許這麼做,或是昱到了暫時性的故障。",
|
||||||
"%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s 將聊天室名稱從 %(oldRoomName)s 變更為 %(newRoomName)s。",
|
"%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s 將聊天室名稱從 %(oldRoomName)s 變更為 %(newRoomName)s。",
|
||||||
"%(senderName)s changed the addresses for this room.": "%(senderName)s 變更了此聊天室的位置。",
|
"%(senderName)s changed the addresses for this room.": "%(senderName)s 變更了此聊天室的位置。",
|
||||||
|
@ -2889,7 +2889,7 @@
|
||||||
"Send messages as you in this room": "在此聊天室以您的身份傳送訊息",
|
"Send messages as you in this room": "在此聊天室以您的身份傳送訊息",
|
||||||
"The <b>%(capability)s</b> capability": "<b>%(capability)s</b> 能力",
|
"The <b>%(capability)s</b> capability": "<b>%(capability)s</b> 能力",
|
||||||
"See <b>%(eventType)s</b> events posted to your active room": "檢視發佈到您的活躍聊天室的 <b>%(eventType)s</b> 活動",
|
"See <b>%(eventType)s</b> events posted to your active room": "檢視發佈到您的活躍聊天室的 <b>%(eventType)s</b> 活動",
|
||||||
"Send <b>%(eventType)s</b> events as you in your active room": "以您的身份在您的活躍聊天是傳送 <b>%(eventType)s</b> 活動",
|
"Send <b>%(eventType)s</b> events as you in your active room": "以您的身份在您的活躍聊天室傳送 <b>%(eventType)s</b> 活動",
|
||||||
"See <b>%(eventType)s</b> events posted to this room": "檢視發佈到此聊天室的 <b>%(eventType)s</b> 活動",
|
"See <b>%(eventType)s</b> events posted to this room": "檢視發佈到此聊天室的 <b>%(eventType)s</b> 活動",
|
||||||
"Send <b>%(eventType)s</b> events as you in this room": "以您的身份在此聊天室傳送 <b>%(eventType)s</b> 活動",
|
"Send <b>%(eventType)s</b> events as you in this room": "以您的身份在此聊天室傳送 <b>%(eventType)s</b> 活動",
|
||||||
"with state key %(stateKey)s": "帶有狀態金鑰 %(stateKey)s",
|
"with state key %(stateKey)s": "帶有狀態金鑰 %(stateKey)s",
|
||||||
|
@ -2898,17 +2898,17 @@
|
||||||
"Send stickers to your active room as you": "以您的身份傳送貼圖到您活躍的聊天室",
|
"Send stickers to your active room as you": "以您的身份傳送貼圖到您活躍的聊天室",
|
||||||
"See when a sticker is posted in this room": "檢視貼圖在此聊天室中何時貼出",
|
"See when a sticker is posted in this room": "檢視貼圖在此聊天室中何時貼出",
|
||||||
"Send stickers to this room as you": "以您的身份傳送貼圖到此聊天室",
|
"Send stickers to this room as you": "以您的身份傳送貼圖到此聊天室",
|
||||||
"See when the avatar changes in your active room": "檢視您活躍聊天是的大頭照何時變更",
|
"See when the avatar changes in your active room": "檢視您活躍聊天室的大頭照何時變更",
|
||||||
"Change the avatar of your active room": "變更您活躍聊天是的大頭照",
|
"Change the avatar of your active room": "變更您活躍聊天室的大頭照",
|
||||||
"See when the avatar changes in this room": "檢視此聊天是的大頭照何時變更",
|
"See when the avatar changes in this room": "檢視此聊天室的大頭照何時變更",
|
||||||
"Change the avatar of this room": "變更此聊天室的大頭照",
|
"Change the avatar of this room": "變更此聊天室的大頭照",
|
||||||
"See when the name changes in your active room": "檢視您活躍聊天室的名稱何時變更",
|
"See when the name changes in your active room": "檢視您活躍聊天室的名稱何時變更",
|
||||||
"Change the name of your active room": "變更您活躍聊天室的名稱",
|
"Change the name of your active room": "變更您活躍聊天室的名稱",
|
||||||
"See when the name changes in this room": "檢視此聊天是的名稱何時變更",
|
"See when the name changes in this room": "檢視此聊天室的名稱何時變更",
|
||||||
"Change the name of this room": "變更此聊天室的名稱",
|
"Change the name of this room": "變更此聊天室的名稱",
|
||||||
"See when the topic changes in your active room": "檢視您活躍的聊天是的主題何時變更",
|
"See when the topic changes in your active room": "檢視您活躍的聊天室的主題何時變更",
|
||||||
"Change the topic of your active room": "變更您活躍聊天是的主題",
|
"Change the topic of your active room": "變更您活躍聊天室的主題",
|
||||||
"See when the topic changes in this room": "檢視此聊天是的主題何時變更",
|
"See when the topic changes in this room": "檢視此聊天室的主題何時變更",
|
||||||
"Change the topic of this room": "變更此聊天室的主題",
|
"Change the topic of this room": "變更此聊天室的主題",
|
||||||
"Change which room you're viewing": "變更您正在檢視的聊天室",
|
"Change which room you're viewing": "變更您正在檢視的聊天室",
|
||||||
"Send stickers into your active room": "傳送貼圖到您活躍的聊天室",
|
"Send stickers into your active room": "傳送貼圖到您活躍的聊天室",
|
||||||
|
@ -3226,7 +3226,7 @@
|
||||||
"Mark as suggested": "標記為建議",
|
"Mark as suggested": "標記為建議",
|
||||||
"Mark as not suggested": "標記為不建議",
|
"Mark as not suggested": "標記為不建議",
|
||||||
"Removing...": "正在移除……",
|
"Removing...": "正在移除……",
|
||||||
"Failed to remove some rooms. Try again later": "移除部份聊天是失敗。稍後再試",
|
"Failed to remove some rooms. Try again later": "移除部份聊天室失敗。稍後再試",
|
||||||
"%(count)s rooms and 1 space|one": "%(count)s 個聊天室與 1 個空間",
|
"%(count)s rooms and 1 space|one": "%(count)s 個聊天室與 1 個空間",
|
||||||
"%(count)s rooms and 1 space|other": "%(count)s 個聊天室與 1 個空間",
|
"%(count)s rooms and 1 space|other": "%(count)s 個聊天室與 1 個空間",
|
||||||
"%(count)s rooms and %(numSpaces)s spaces|one": "%(count)s 個聊天室與 %(numSpaces)s 個空間",
|
"%(count)s rooms and %(numSpaces)s spaces|one": "%(count)s 個聊天室與 %(numSpaces)s 個空間",
|
||||||
|
@ -3240,7 +3240,7 @@
|
||||||
"Open": "開啟",
|
"Open": "開啟",
|
||||||
"%(count)s messages deleted.|one": "已刪除 %(count)s 則訊息。",
|
"%(count)s messages deleted.|one": "已刪除 %(count)s 則訊息。",
|
||||||
"%(count)s messages deleted.|other": "已刪除 %(count)s 則訊息。",
|
"%(count)s messages deleted.|other": "已刪除 %(count)s 則訊息。",
|
||||||
"This usually only affects how the room is processed on the server. If you're having problems with your %(brand)s, please report a bug.": "這通常只影響伺服器如何處理聊天是。如果您的 %(brand)s 遇到問題,請回報臭蟲。",
|
"This usually only affects how the room is processed on the server. If you're having problems with your %(brand)s, please report a bug.": "這通常只影響伺服器如何處理聊天室。如果您的 %(brand)s 遇到問題,請回報臭蟲。",
|
||||||
"Invite to %(roomName)s": "邀請至 %(roomName)s",
|
"Invite to %(roomName)s": "邀請至 %(roomName)s",
|
||||||
"Edit devices": "編輯裝置",
|
"Edit devices": "編輯裝置",
|
||||||
"Invite People": "邀請夥伴",
|
"Invite People": "邀請夥伴",
|
||||||
|
@ -3370,5 +3370,13 @@
|
||||||
"Add reaction": "新增反應",
|
"Add reaction": "新增反應",
|
||||||
"Send and receive voice messages": "傳送與接收語音訊息",
|
"Send and receive voice messages": "傳送與接收語音訊息",
|
||||||
"Your feedback will help make spaces better. The more detail you can go into, the better.": "您的回饋意見將會讓空間變得更好。您可以輸入愈多細節愈好。",
|
"Your feedback will help make spaces better. The more detail you can go into, the better.": "您的回饋意見將會讓空間變得更好。您可以輸入愈多細節愈好。",
|
||||||
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "若您離開,%(brand)s 將在停用空間的情況下重新載入。社群與自訂標籤將再次可見。"
|
"If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "若您離開,%(brand)s 將在停用空間的情況下重新載入。社群與自訂標籤將再次可見。",
|
||||||
|
"Space Autocomplete": "空間自動完成",
|
||||||
|
"Go to my space": "到我的空間",
|
||||||
|
"sends space invaders": "傳送太空侵略者",
|
||||||
|
"Sends the given message with a space themed effect": "與太空主題效果一起傳送指定的訊息",
|
||||||
|
"See when people join, leave, or are invited to your active room": "檢視人們何時加入、離開或被邀請至您活躍的聊天室",
|
||||||
|
"Kick, ban, or invite people to your active room, and make you leave": "踢除、封鎖或邀請人們到您作用中的聊天室,然後讓您離開",
|
||||||
|
"See when people join, leave, or are invited to this room": "檢視人們何時加入、離開或被邀請至此聊天室",
|
||||||
|
"Kick, ban, or invite people to this room, and make you leave": "踢除、封鎖或邀請人們到此聊天室,然後讓您離開"
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import WidgetUtils from "../utils/WidgetUtils";
|
||||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
import { compare } from "../utils/strings";
|
||||||
|
|
||||||
const KIND_PREFERENCE = [
|
const KIND_PREFERENCE = [
|
||||||
// Ordered: first is most preferred, last is least preferred.
|
// Ordered: first is most preferred, last is least preferred.
|
||||||
|
@ -152,7 +153,7 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
if (kind === Kind.Account) {
|
if (kind === Kind.Account) {
|
||||||
// Order by state_keys (IDs)
|
// Order by state_keys (IDs)
|
||||||
managers.sort((a, b) => a.id.localeCompare(b.id));
|
managers.sort((a, b) => compare(a.id, b.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ordered.push(...managers);
|
ordered.push(...managers);
|
||||||
|
|
|
@ -65,6 +65,10 @@ class FlairStore extends EventEmitter {
|
||||||
delete this._userGroups[userId];
|
delete this._userGroups[userId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedPublicisedGroups(userId) {
|
||||||
|
return this._userGroups[userId];
|
||||||
|
}
|
||||||
|
|
||||||
getPublicisedGroupsCached(matrixClient, userId) {
|
getPublicisedGroupsCached(matrixClient, userId) {
|
||||||
if (this._userGroups[userId]) {
|
if (this._userGroups[userId]) {
|
||||||
return Promise.resolve(this._userGroups[userId]);
|
return Promise.resolve(this._userGroups[userId]);
|
||||||
|
|
|
@ -24,12 +24,14 @@ export enum UI_EVENTS {
|
||||||
|
|
||||||
export type ResizeObserverCallbackFunction = (entries: ResizeObserverEntry[]) => void;
|
export type ResizeObserverCallbackFunction = (entries: ResizeObserverEntry[]) => void;
|
||||||
|
|
||||||
|
|
||||||
export default class UIStore extends EventEmitter {
|
export default class UIStore extends EventEmitter {
|
||||||
private static _instance: UIStore = null;
|
private static _instance: UIStore = null;
|
||||||
|
|
||||||
private resizeObserver: ResizeObserver;
|
private resizeObserver: ResizeObserver;
|
||||||
|
|
||||||
|
private uiElementDimensions = new Map<string, DOMRectReadOnly>();
|
||||||
|
private trackedUiElements = new Map<Element, string>();
|
||||||
|
|
||||||
public windowWidth: number;
|
public windowWidth: number;
|
||||||
public windowHeight: number;
|
public windowHeight: number;
|
||||||
|
|
||||||
|
@ -60,14 +62,51 @@ export default class UIStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private resizeObserverCallback = (entries: ResizeObserverEntry[]) => {
|
public getElementDimensions(name: string): DOMRectReadOnly {
|
||||||
const { width, height } = entries
|
return this.uiElementDimensions.get(name);
|
||||||
.find(entry => entry.target === document.body)
|
}
|
||||||
.contentRect;
|
|
||||||
|
|
||||||
this.windowWidth = width;
|
public trackElementDimensions(name: string, element: Element): void {
|
||||||
this.windowHeight = height;
|
this.trackedUiElements.set(element, name);
|
||||||
|
this.resizeObserver.observe(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public stopTrackingElementDimensions(name: string): void {
|
||||||
|
let trackedElement: Element;
|
||||||
|
this.trackedUiElements.forEach((trackedElementName, element) => {
|
||||||
|
if (trackedElementName === name) {
|
||||||
|
trackedElement = element;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (trackedElement) {
|
||||||
|
this.resizeObserver.unobserve(trackedElement);
|
||||||
|
this.uiElementDimensions.delete(name);
|
||||||
|
this.trackedUiElements.delete(trackedElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public isTrackingElementDimensions(name: string): boolean {
|
||||||
|
return this.uiElementDimensions.has(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private resizeObserverCallback = (entries: ResizeObserverEntry[]) => {
|
||||||
|
const windowEntry = entries.find(entry => entry.target === document.body);
|
||||||
|
|
||||||
|
if (windowEntry) {
|
||||||
|
this.windowWidth = windowEntry.contentRect.width;
|
||||||
|
this.windowHeight = windowEntry.contentRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.forEach(entry => {
|
||||||
|
const trackedElementName = this.trackedUiElements.get(entry.target);
|
||||||
|
if (trackedElementName) {
|
||||||
|
this.uiElementDimensions.set(trackedElementName, entry.contentRect);
|
||||||
|
this.emit(trackedElementName, UI_EVENTS.Resize, entry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.emit(UI_EVENTS.Resize, entries);
|
this.emit(UI_EVENTS.Resize, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.mxUIStore = UIStore.instance;
|
||||||
|
|
|
@ -426,8 +426,10 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
return; // don't do anything on rooms that aren't visible
|
return; // don't do anything on rooms that aren't visible
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause === RoomUpdateCause.NewRoom && !this.prefilterConditions.every(c => c.isVisible(room))) {
|
if ((cause === RoomUpdateCause.NewRoom || cause === RoomUpdateCause.PossibleTagChange) &&
|
||||||
return; // don't do anything on new rooms which ought not to be shown
|
!this.prefilterConditions.every(c => c.isVisible(room))
|
||||||
|
) {
|
||||||
|
return; // don't do anything on new/moved rooms which ought not to be shown
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldUpdate = await this.algorithm.handleRoomUpdate(room, cause);
|
const shouldUpdate = await this.algorithm.handleRoomUpdate(room, cause);
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { TagID } from "../../models";
|
import { TagID } from "../../models";
|
||||||
import { IAlgorithm } from "./IAlgorithm";
|
import { IAlgorithm } from "./IAlgorithm";
|
||||||
|
import { compare } from "../../../../utils/strings";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts rooms according to the browser's determination of alphabetic.
|
* Sorts rooms according to the browser's determination of alphabetic.
|
||||||
|
@ -24,7 +25,7 @@ import { IAlgorithm } from "./IAlgorithm";
|
||||||
export class AlphabeticAlgorithm implements IAlgorithm {
|
export class AlphabeticAlgorithm implements IAlgorithm {
|
||||||
public async sortRooms(rooms: Room[], tagId: TagID): Promise<Room[]> {
|
public async sortRooms(rooms: Room[], tagId: TagID): Promise<Room[]> {
|
||||||
return rooms.sort((a, b) => {
|
return rooms.sort((a, b) => {
|
||||||
return a.name.localeCompare(b.name);
|
return compare(a.name, b.name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { SettingLevel } from "../../settings/SettingLevel";
|
import { SettingLevel } from "../../settings/SettingLevel";
|
||||||
import { arrayFastClone } from "../../utils/arrays";
|
import { arrayFastClone } from "../../utils/arrays";
|
||||||
import { UPDATE_EVENT } from "../AsyncStore";
|
import { UPDATE_EVENT } from "../AsyncStore";
|
||||||
|
import { compare } from "../../utils/strings";
|
||||||
|
|
||||||
export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout";
|
export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout";
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ export class WidgetLayoutStore extends ReadyWatchingStore {
|
||||||
|
|
||||||
if (orderA === orderB) {
|
if (orderA === orderB) {
|
||||||
// We just need a tiebreak
|
// We just need a tiebreak
|
||||||
return a.id.localeCompare(b.id);
|
return compare(a.id, b.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return orderA - orderB;
|
return orderA - orderB;
|
||||||
|
|
|
@ -73,3 +73,14 @@ export function copyNode(ref: Element): boolean {
|
||||||
selectText(ref);
|
selectText(ref);
|
||||||
return document.execCommand('copy');
|
return document.execCommand('copy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const collator = new Intl.Collator();
|
||||||
|
/**
|
||||||
|
* Performant language-sensitive string comparison
|
||||||
|
* @param a the first string to compare
|
||||||
|
* @param b the second string to compare
|
||||||
|
*/
|
||||||
|
export function compare(a: string, b: string): number {
|
||||||
|
return collator.compare(a, b);
|
||||||
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ describe('MessagePanel', function() {
|
||||||
const rm = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_RoomView_myReadMarker_container');
|
const rm = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_RoomView_myReadMarker_container');
|
||||||
|
|
||||||
// it should follow the <li> which wraps the event tile for event 4
|
// it should follow the <li> which wraps the event tile for event 4
|
||||||
const eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode;
|
const eventContainer = ReactDOM.findDOMNode(tiles[4]);
|
||||||
expect(rm.previousSibling).toEqual(eventContainer);
|
expect(rm.previousSibling).toEqual(eventContainer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ describe('MessagePanel', function() {
|
||||||
const tiles = TestUtils.scryRenderedComponentsWithType(
|
const tiles = TestUtils.scryRenderedComponentsWithType(
|
||||||
mp, sdk.getComponent('rooms.EventTile'));
|
mp, sdk.getComponent('rooms.EventTile'));
|
||||||
const tileContainers = tiles.map(function(t) {
|
const tileContainers = tiles.map(function(t) {
|
||||||
return ReactDOM.findDOMNode(t).parentNode;
|
return ReactDOM.findDOMNode(t);
|
||||||
});
|
});
|
||||||
|
|
||||||
// find the <li> which wraps the read marker
|
// find the <li> which wraps the read marker
|
||||||
|
@ -460,7 +460,7 @@ describe('MessagePanel', function() {
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
const Dates = res.find(sdk.getComponent('messages.DateSeparator'));
|
const Dates = res.find(sdk.getComponent('messages.DateSeparator'));
|
||||||
|
|
||||||
expect(Dates.length).toEqual(1);
|
expect(Dates.length).toEqual(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -133,7 +133,7 @@ describe('Login', function() {
|
||||||
root.setState({
|
root.setState({
|
||||||
flows: [{
|
flows: [{
|
||||||
"type": "m.login.sso",
|
"type": "m.login.sso",
|
||||||
"org.matrix.msc2858.identity_providers": [{
|
"identity_providers": [{
|
||||||
id: "a",
|
id: "a",
|
||||||
name: "Provider 1",
|
name: "Provider 1",
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import sdk from '../../../skinned-sdk';
|
||||||
|
|
||||||
import {Room, RoomMember, User} from 'matrix-js-sdk';
|
import {Room, RoomMember, User} from 'matrix-js-sdk';
|
||||||
|
|
||||||
|
import { compare } from "../../../../src/utils/strings";
|
||||||
|
|
||||||
function generateRoomId() {
|
function generateRoomId() {
|
||||||
return '!' + Math.random().toString().slice(2, 10) + ':domain';
|
return '!' + Math.random().toString().slice(2, 10) + ':domain';
|
||||||
}
|
}
|
||||||
|
@ -173,7 +175,7 @@ describe('MemberList', () => {
|
||||||
if (!groupChange) {
|
if (!groupChange) {
|
||||||
const nameA = memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name;
|
const nameA = memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name;
|
||||||
const nameB = memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name;
|
const nameB = memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name;
|
||||||
const nameCompare = nameB.localeCompare(nameA);
|
const nameCompare = compare(nameB, nameA);
|
||||||
console.log("Comparing name");
|
console.log("Comparing name");
|
||||||
expect(nameCompare).toBeGreaterThanOrEqual(0);
|
expect(nameCompare).toBeGreaterThanOrEqual(0);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8438,9 +8438,9 @@ write@1.0.3:
|
||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
|
|
||||||
ws@^7.2.3:
|
ws@^7.2.3:
|
||||||
version "7.4.2"
|
version "7.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||||
integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==
|
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||||
|
|
||||||
xml-name-validator@^3.0.0:
|
xml-name-validator@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
|
|
Loading…
Reference in a new issue