Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/fix/19304
This commit is contained in:
commit
8ee6a08639
59 changed files with 2430 additions and 1066 deletions
|
@ -39,6 +39,7 @@
|
||||||
@import "./structures/_ViewSource.scss";
|
@import "./structures/_ViewSource.scss";
|
||||||
@import "./structures/auth/_CompleteSecurity.scss";
|
@import "./structures/auth/_CompleteSecurity.scss";
|
||||||
@import "./structures/auth/_Login.scss";
|
@import "./structures/auth/_Login.scss";
|
||||||
|
@import "./structures/auth/_SetupEncryptionBody.scss";
|
||||||
@import "./views/audio_messages/_AudioPlayer.scss";
|
@import "./views/audio_messages/_AudioPlayer.scss";
|
||||||
@import "./views/audio_messages/_PlayPauseButton.scss";
|
@import "./views/audio_messages/_PlayPauseButton.scss";
|
||||||
@import "./views/audio_messages/_PlaybackContainer.scss";
|
@import "./views/audio_messages/_PlaybackContainer.scss";
|
||||||
|
|
|
@ -33,6 +33,19 @@ limitations under the License.
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_CompleteSecurity_skip {
|
||||||
|
mask: url('$(res)/img/feather-customised/cancel.svg');
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center;
|
||||||
|
mask-size: cover;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background-color: $dialog-close-fg-color;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_CompleteSecurity_body {
|
.mx_CompleteSecurity_body {
|
||||||
font-size: $font-15px;
|
font-size: $font-15px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,9 +14,11 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createContext } from "react";
|
.mx_SetupEncryptionBody_reset {
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
color: $light-fg-color;
|
||||||
|
margin-top: $font-14px;
|
||||||
|
|
||||||
const MatrixClientContext = createContext<MatrixClient>(undefined);
|
a.mx_SetupEncryptionBody_reset_link:is(:link, :hover, :visited) {
|
||||||
MatrixClientContext.displayName = "MatrixClientContext";
|
color: $warning-color;
|
||||||
export default MatrixClientContext;
|
}
|
||||||
|
}
|
|
@ -75,7 +75,7 @@ limitations under the License.
|
||||||
@mixin ProgressBarBorderRadius 8px;
|
@mixin ProgressBarBorderRadius 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AddExistingToSpace_progressText {
|
.mx_AddExistingToSpaceDialog_progressText {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: $font-15px;
|
font-size: $font-15px;
|
||||||
line-height: $font-24px;
|
line-height: $font-24px;
|
||||||
|
|
|
@ -74,6 +74,7 @@ limitations under the License.
|
||||||
font-size: $font-12px;
|
font-size: $font-12px;
|
||||||
line-height: $font-15px;
|
line-height: $font-15px;
|
||||||
color: $secondary-content;
|
color: $secondary-content;
|
||||||
|
margin-top: -13px; // match height of buttons to prevent height changing
|
||||||
|
|
||||||
.mx_ProgressBar {
|
.mx_ProgressBar {
|
||||||
height: 8px;
|
height: 8px;
|
||||||
|
|
|
@ -67,5 +67,7 @@ limitations under the License.
|
||||||
|
|
||||||
> .mx_AccessibleButton_kind_link {
|
> .mx_AccessibleButton_kind_link {
|
||||||
padding-left: 0; // to align with left side
|
padding-left: 0; // to align with left side
|
||||||
|
padding-right: 0;
|
||||||
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,15 +142,11 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi
|
||||||
// space rooms cannot be DMs so skip the rest
|
// space rooms cannot be DMs so skip the rest
|
||||||
if (SpaceStore.spacesEnabled && room.isSpaceRoom()) return null;
|
if (SpaceStore.spacesEnabled && room.isSpaceRoom()) return null;
|
||||||
|
|
||||||
let otherMember = null;
|
// If the room is not a DM don't fallback to a member avatar
|
||||||
const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
|
if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) return null;
|
||||||
if (otherUserId) {
|
|
||||||
otherMember = room.getMember(otherUserId);
|
// If there are only two members in the DM use the avatar of the other member
|
||||||
} else {
|
const otherMember = room.getAvatarFallbackMember();
|
||||||
// if the room is not marked as a 1:1, but only has max 2 members
|
|
||||||
// then still try to show any avatar (pref. other member)
|
|
||||||
otherMember = room.getAvatarFallbackMember();
|
|
||||||
}
|
|
||||||
if (otherMember?.getMxcAvatarUrl()) {
|
if (otherMember?.getMxcAvatarUrl()) {
|
||||||
return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
|
return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,15 @@ export interface IInviteResult {
|
||||||
*
|
*
|
||||||
* @param {string} roomId The ID of the room to invite to
|
* @param {string} roomId The ID of the room to invite to
|
||||||
* @param {string[]} addresses Array of strings of addresses to invite. May be matrix IDs or 3pids.
|
* @param {string[]} addresses Array of strings of addresses to invite. May be matrix IDs or 3pids.
|
||||||
|
* @param {function} progressCallback optional callback, fired after each invite.
|
||||||
* @returns {Promise} Promise
|
* @returns {Promise} Promise
|
||||||
*/
|
*/
|
||||||
export function inviteMultipleToRoom(roomId: string, addresses: string[]): Promise<IInviteResult> {
|
export function inviteMultipleToRoom(
|
||||||
const inviter = new MultiInviter(roomId);
|
roomId: string,
|
||||||
|
addresses: string[],
|
||||||
|
progressCallback?: () => void,
|
||||||
|
): Promise<IInviteResult> {
|
||||||
|
const inviter = new MultiInviter(roomId, progressCallback);
|
||||||
return inviter.invite(addresses).then(states => Promise.resolve({ states, inviter }));
|
return inviter.invite(addresses).then(states => Promise.resolve({ states, inviter }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +109,8 @@ export function isValid3pidInvite(event: MatrixEvent): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inviteUsersToRoom(roomId: string, userIds: string[]): Promise<void> {
|
export function inviteUsersToRoom(roomId: string, userIds: string[], progressCallback?: () => void): Promise<void> {
|
||||||
return inviteMultipleToRoom(roomId, userIds).then((result) => {
|
return inviteMultipleToRoom(roomId, userIds, progressCallback).then((result) => {
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||||
showAnyInviteErrors(result.states, room, result.inviter);
|
showAnyInviteErrors(result.states, room, result.inviter);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
|
|
@ -452,7 +452,9 @@ function setBotOptions(event: MessageEvent<any>, roomId: string, userId: string)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBotPower(event: MessageEvent<any>, roomId: string, userId: string, level: number): void {
|
async function setBotPower(
|
||||||
|
event: MessageEvent<any>, roomId: string, userId: string, level: number, ignoreIfGreater?: boolean,
|
||||||
|
): Promise<void> {
|
||||||
if (!(Number.isInteger(level) && level >= 0)) {
|
if (!(Number.isInteger(level) && level >= 0)) {
|
||||||
sendError(event, _t('Power level must be positive integer.'));
|
sendError(event, _t('Power level must be positive integer.'));
|
||||||
return;
|
return;
|
||||||
|
@ -465,22 +467,34 @@ function setBotPower(event: MessageEvent<any>, roomId: string, userId: string, l
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client.getStateEvent(roomId, "m.room.power_levels", "").then((powerLevels) => {
|
try {
|
||||||
const powerEvent = new MatrixEvent(
|
const powerLevels = await client.getStateEvent(roomId, "m.room.power_levels", "");
|
||||||
|
|
||||||
|
// If the PL is equal to or greater than the requested PL, ignore.
|
||||||
|
if (ignoreIfGreater === true) {
|
||||||
|
// As per https://matrix.org/docs/spec/client_server/r0.6.0#m-room-power-levels
|
||||||
|
const currentPl = (
|
||||||
|
powerLevels.content.users && powerLevels.content.users[userId]
|
||||||
|
) || powerLevels.content.users_default || 0;
|
||||||
|
|
||||||
|
if (currentPl >= level) {
|
||||||
|
return sendResponse(event, {
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await client.setPowerLevel(roomId, userId, level, new MatrixEvent(
|
||||||
{
|
{
|
||||||
type: "m.room.power_levels",
|
type: "m.room.power_levels",
|
||||||
content: powerLevels,
|
content: powerLevels,
|
||||||
},
|
},
|
||||||
);
|
));
|
||||||
|
return sendResponse(event, {
|
||||||
client.setPowerLevel(roomId, userId, level, powerEvent).then(() => {
|
success: true,
|
||||||
sendResponse(event, {
|
|
||||||
success: true,
|
|
||||||
});
|
|
||||||
}, (err) => {
|
|
||||||
sendError(event, err.message ? err.message : _t('Failed to send request.'), err);
|
|
||||||
});
|
});
|
||||||
});
|
} catch (err) {
|
||||||
|
sendError(event, err.message ? err.message : _t('Failed to send request.'), err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMembershipState(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function getMembershipState(event: MessageEvent<any>, roomId: string, userId: string): void {
|
||||||
|
@ -678,7 +692,7 @@ const onMessage = function(event: MessageEvent<any>): void {
|
||||||
setBotOptions(event, roomId, userId);
|
setBotOptions(event, roomId, userId);
|
||||||
break;
|
break;
|
||||||
case Action.SetBotPower:
|
case Action.SetBotPower:
|
||||||
setBotPower(event, roomId, userId, event.data.level);
|
setBotPower(event, roomId, userId, event.data.level, event.data.ignoreIfGreater);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn("Unhandled postMessage event with action '" + event.data.action +"'");
|
console.warn("Unhandled postMessage event with action '" + event.data.action +"'");
|
||||||
|
|
|
@ -226,6 +226,11 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onClick = (ev: React.MouseEvent) => {
|
||||||
|
// Don't allow clicks to escape the context menu wrapper
|
||||||
|
ev.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
private onKeyDown = (ev: React.KeyboardEvent) => {
|
private onKeyDown = (ev: React.KeyboardEvent) => {
|
||||||
// don't let keyboard handling escape the context menu
|
// don't let keyboard handling escape the context menu
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
@ -383,6 +388,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
|
||||||
className={classNames("mx_ContextualMenu_wrapper", this.props.wrapperClassName)}
|
className={classNames("mx_ContextualMenu_wrapper", this.props.wrapperClassName)}
|
||||||
style={{ ...position, ...wrapperStyle }}
|
style={{ ...position, ...wrapperStyle }}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
|
onClick={this.onClick}
|
||||||
onContextMenu={this.onContextMenuPreventBubbling}
|
onContextMenu={this.onContextMenuPreventBubbling}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -48,6 +48,8 @@ import Spinner from "../views/elements/Spinner";
|
||||||
import TileErrorBoundary from '../views/messages/TileErrorBoundary';
|
import TileErrorBoundary from '../views/messages/TileErrorBoundary';
|
||||||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||||
import EditorStateTransfer from "../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../utils/EditorStateTransfer";
|
||||||
|
import { logger } from 'matrix-js-sdk/src/logger';
|
||||||
|
import { Action } from '../../dispatcher/actions';
|
||||||
|
|
||||||
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||||
const continuedTypes = [EventType.Sticker, EventType.RoomMessage];
|
const continuedTypes = [EventType.Sticker, EventType.RoomMessage];
|
||||||
|
@ -287,6 +289,15 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
||||||
ghostReadMarkers,
|
ghostReadMarkers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pendingEditItem = this.pendingEditItem;
|
||||||
|
if (!this.props.editState && this.props.room && pendingEditItem) {
|
||||||
|
defaultDispatcher.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: this.props.room.findEventById(pendingEditItem),
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateRoomMembersCount = (): void => {
|
private calculateRoomMembersCount = (): void => {
|
||||||
|
@ -550,10 +561,14 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
||||||
return { nextEvent, nextTile };
|
return { nextEvent, nextTile };
|
||||||
}
|
}
|
||||||
|
|
||||||
private get roomHasPendingEdit(): string {
|
private get pendingEditItem(): string | undefined {
|
||||||
return this.props.room && localStorage.getItem(`mx_edit_room_${this.props.room.roomId}`);
|
try {
|
||||||
|
return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}_${this.context.timelineRenderingType}`);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(err);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getEventTiles(): ReactNode[] {
|
private getEventTiles(): ReactNode[] {
|
||||||
this.eventNodes = {};
|
this.eventNodes = {};
|
||||||
|
|
||||||
|
@ -663,13 +678,6 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.props.editState && this.roomHasPendingEdit) {
|
|
||||||
defaultDispatcher.dispatch({
|
|
||||||
action: "edit_event",
|
|
||||||
event: this.props.room.findEventById(this.roomHasPendingEdit),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grouper) {
|
if (grouper) {
|
||||||
ret.push(...grouper.getTiles());
|
ret.push(...grouper.getTiles());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ import { Layout } from "../../settings/Layout";
|
||||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
import RightPanelStore from "../../stores/RightPanelStore";
|
import RightPanelStore from "../../stores/RightPanelStore";
|
||||||
import { haveTileForEvent } from "../views/rooms/EventTile";
|
import { haveTileForEvent } from "../views/rooms/EventTile";
|
||||||
import RoomContext from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext, { withMatrixClientHOC, MatrixClientProps } from "../../contexts/MatrixClientContext";
|
||||||
import { E2EStatus, shieldStatusForRoom } from '../../utils/ShieldUtils';
|
import { E2EStatus, shieldStatusForRoom } from '../../utils/ShieldUtils';
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
||||||
|
@ -91,6 +91,7 @@ import TopUnreadMessagesBar from "../views/rooms/TopUnreadMessagesBar";
|
||||||
import SpaceStore from "../../stores/SpaceStore";
|
import SpaceStore from "../../stores/SpaceStore";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
let debuglog = function(msg: string) {};
|
let debuglog = function(msg: string) {};
|
||||||
|
@ -102,7 +103,7 @@ if (DEBUG) {
|
||||||
debuglog = logger.log.bind(console);
|
debuglog = logger.log.bind(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IRoomProps extends MatrixClientProps {
|
||||||
threepidInvite: IThreepidInvite;
|
threepidInvite: IThreepidInvite;
|
||||||
oobData?: IOOBData;
|
oobData?: IOOBData;
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ interface IProps {
|
||||||
onRegistered?(credentials: IMatrixClientCreds): void;
|
onRegistered?(credentials: IMatrixClientCreds): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IState {
|
export interface IRoomState {
|
||||||
room?: Room;
|
room?: Room;
|
||||||
roomId?: string;
|
roomId?: string;
|
||||||
roomAlias?: string;
|
roomAlias?: string;
|
||||||
|
@ -187,10 +188,12 @@ export interface IState {
|
||||||
// if it did we don't want the room to be marked as read as soon as it is loaded.
|
// if it did we don't want the room to be marked as read as soon as it is loaded.
|
||||||
wasContextSwitch?: boolean;
|
wasContextSwitch?: boolean;
|
||||||
editState?: EditorStateTransfer;
|
editState?: EditorStateTransfer;
|
||||||
|
timelineRenderingType: TimelineRenderingType;
|
||||||
|
liveTimeline?: EventTimeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("structures.RoomView")
|
@replaceableComponent("structures.RoomView")
|
||||||
export default class RoomView extends React.Component<IProps, IState> {
|
export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
private readonly dispatcherRef: string;
|
private readonly dispatcherRef: string;
|
||||||
private readonly roomStoreToken: EventSubscription;
|
private readonly roomStoreToken: EventSubscription;
|
||||||
private readonly rightPanelStoreToken: EventSubscription;
|
private readonly rightPanelStoreToken: EventSubscription;
|
||||||
|
@ -247,6 +250,8 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
showDisplaynameChanges: true,
|
showDisplaynameChanges: true,
|
||||||
matrixClientIsReady: this.context && this.context.isInitialSyncComplete(),
|
matrixClientIsReady: this.context && this.context.isInitialSyncComplete(),
|
||||||
dragCounter: 0,
|
dragCounter: 0,
|
||||||
|
timelineRenderingType: TimelineRenderingType.Room,
|
||||||
|
liveTimeline: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
@ -336,7 +341,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const roomId = RoomViewStore.getRoomId();
|
const roomId = RoomViewStore.getRoomId();
|
||||||
|
|
||||||
const newState: Pick<IState, any> = {
|
const newState: Pick<IRoomState, any> = {
|
||||||
roomId,
|
roomId,
|
||||||
roomAlias: RoomViewStore.getRoomAlias(),
|
roomAlias: RoomViewStore.getRoomAlias(),
|
||||||
roomLoading: RoomViewStore.isRoomLoading(),
|
roomLoading: RoomViewStore.isRoomLoading(),
|
||||||
|
@ -808,7 +813,9 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
this.onSearchClick();
|
this.onSearchClick();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "edit_event": {
|
case Action.EditEvent: {
|
||||||
|
// Quit early if we're trying to edit events in wrong rendering context
|
||||||
|
if (payload.timelineRenderingType !== this.state.timelineRenderingType) return;
|
||||||
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
|
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
|
||||||
this.setState({ editState }, () => {
|
this.setState({ editState }, () => {
|
||||||
if (payload.event) {
|
if (payload.event) {
|
||||||
|
@ -932,6 +939,10 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
this.updateE2EStatus(room);
|
this.updateE2EStatus(room);
|
||||||
this.updatePermissions(room);
|
this.updatePermissions(room);
|
||||||
this.checkWidgets(room);
|
this.checkWidgets(room);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
liveTimeline: room.getLiveTimeline(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private async calculateRecommendedVersion(room: Room) {
|
private async calculateRecommendedVersion(room: Room) {
|
||||||
|
@ -2086,3 +2097,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RoomViewWithMatrixClient = withMatrixClientHOC(RoomView);
|
||||||
|
export default RoomViewWithMatrixClient;
|
||||||
|
|
|
@ -410,50 +410,39 @@ export const HierarchyLevel = ({
|
||||||
|
|
||||||
const INITIAL_PAGE_SIZE = 20;
|
const INITIAL_PAGE_SIZE = 20;
|
||||||
|
|
||||||
export const useSpaceSummary = (space: Room): {
|
export const useRoomHierarchy = (space: Room): {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
rooms: IHierarchyRoom[];
|
rooms: IHierarchyRoom[];
|
||||||
hierarchy: RoomHierarchy;
|
hierarchy: RoomHierarchy;
|
||||||
loadMore(pageSize?: number): Promise <void>;
|
loadMore(pageSize?: number): Promise <void>;
|
||||||
} => {
|
} => {
|
||||||
const [rooms, setRooms] = useState<IHierarchyRoom[]>([]);
|
const [rooms, setRooms] = useState<IHierarchyRoom[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [hierarchy, setHierarchy] = useState<RoomHierarchy>();
|
const [hierarchy, setHierarchy] = useState<RoomHierarchy>();
|
||||||
|
|
||||||
const resetHierarchy = useCallback(() => {
|
const resetHierarchy = useCallback(() => {
|
||||||
const hierarchy = new RoomHierarchy(space, INITIAL_PAGE_SIZE);
|
const hierarchy = new RoomHierarchy(space, INITIAL_PAGE_SIZE);
|
||||||
setHierarchy(hierarchy);
|
|
||||||
|
|
||||||
let discard = false;
|
|
||||||
hierarchy.load().then(() => {
|
hierarchy.load().then(() => {
|
||||||
if (discard) return;
|
if (space !== hierarchy.root) return; // discard stale results
|
||||||
setRooms(hierarchy.rooms);
|
setRooms(hierarchy.rooms);
|
||||||
setLoading(false);
|
|
||||||
});
|
});
|
||||||
|
setHierarchy(hierarchy);
|
||||||
return () => {
|
|
||||||
discard = true;
|
|
||||||
};
|
|
||||||
}, [space]);
|
}, [space]);
|
||||||
useEffect(resetHierarchy, [resetHierarchy]);
|
useEffect(resetHierarchy, [resetHierarchy]);
|
||||||
|
|
||||||
useDispatcher(defaultDispatcher, (payload => {
|
useDispatcher(defaultDispatcher, (payload => {
|
||||||
if (payload.action === Action.UpdateSpaceHierarchy) {
|
if (payload.action === Action.UpdateSpaceHierarchy) {
|
||||||
setLoading(true);
|
|
||||||
setRooms([]); // TODO
|
setRooms([]); // TODO
|
||||||
resetHierarchy();
|
resetHierarchy();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const loadMore = useCallback(async (pageSize?: number) => {
|
const loadMore = useCallback(async (pageSize?: number) => {
|
||||||
if (loading || !hierarchy.canLoadMore || hierarchy.noSupport) return;
|
if (hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport) return;
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
await hierarchy.load(pageSize);
|
await hierarchy.load(pageSize);
|
||||||
setRooms(hierarchy.rooms);
|
setRooms(hierarchy.rooms);
|
||||||
setLoading(false);
|
}, [hierarchy]);
|
||||||
}, [loading, hierarchy]);
|
|
||||||
|
|
||||||
|
const loading = hierarchy?.loading ?? true;
|
||||||
return { loading, rooms, hierarchy, loadMore };
|
return { loading, rooms, hierarchy, loadMore };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -587,7 +576,7 @@ const SpaceHierarchy = ({
|
||||||
|
|
||||||
const [selected, setSelected] = useState(new Map<string, Set<string>>()); // Map<parentId, Set<childId>>
|
const [selected, setSelected] = useState(new Map<string, Set<string>>()); // Map<parentId, Set<childId>>
|
||||||
|
|
||||||
const { loading, rooms, hierarchy, loadMore } = useSpaceSummary(space);
|
const { loading, rooms, hierarchy, loadMore } = useRoomHierarchy(space);
|
||||||
|
|
||||||
const filteredRoomSet = useMemo<Set<IHierarchyRoom>>(() => {
|
const filteredRoomSet = useMemo<Set<IHierarchyRoom>>(() => {
|
||||||
if (!rooms?.length) return new Set();
|
if (!rooms?.length) return new Set();
|
||||||
|
|
|
@ -34,6 +34,8 @@ import { SetRightPanelPhasePayload } from '../../dispatcher/payloads/SetRightPan
|
||||||
import { Action } from '../../dispatcher/actions';
|
import { Action } from '../../dispatcher/actions';
|
||||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||||
import { E2EStatus } from '../../utils/ShieldUtils';
|
import { E2EStatus } from '../../utils/ShieldUtils';
|
||||||
|
import EditorStateTransfer from '../../utils/EditorStateTransfer';
|
||||||
|
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -47,10 +49,14 @@ interface IProps {
|
||||||
interface IState {
|
interface IState {
|
||||||
replyToEvent?: MatrixEvent;
|
replyToEvent?: MatrixEvent;
|
||||||
thread?: Thread;
|
thread?: Thread;
|
||||||
|
editState?: EditorStateTransfer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("structures.ThreadView")
|
@replaceableComponent("structures.ThreadView")
|
||||||
export default class ThreadView extends React.Component<IProps, IState> {
|
export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
|
static contextType = RoomContext;
|
||||||
|
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private timelinePanelRef: React.RefObject<TimelinePanel> = React.createRef();
|
private timelinePanelRef: React.RefObject<TimelinePanel> = React.createRef();
|
||||||
|
|
||||||
|
@ -90,6 +96,23 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
this.setupThread(payload.event);
|
this.setupThread(payload.event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch (payload.action) {
|
||||||
|
case Action.EditEvent: {
|
||||||
|
// Quit early if it's not a thread context
|
||||||
|
if (payload.timelineRenderingType !== TimelineRenderingType.Thread) return;
|
||||||
|
// Quit early if that's not a thread event
|
||||||
|
if (payload.event && !payload.event.getThread()) return;
|
||||||
|
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
|
||||||
|
this.setState({ editState }, () => {
|
||||||
|
if (payload.event) {
|
||||||
|
this.timelinePanelRef.current?.scrollToEventIfNeeded(payload.event.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private setupThread = (mxEv: MatrixEvent) => {
|
private setupThread = (mxEv: MatrixEvent) => {
|
||||||
|
@ -124,44 +147,53 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<BaseCard
|
<RoomContext.Provider value={{
|
||||||
className="mx_ThreadView"
|
...this.context,
|
||||||
onClose={this.props.onClose}
|
timelineRenderingType: TimelineRenderingType.Thread,
|
||||||
previousPhase={RightPanelPhases.RoomSummary}
|
liveTimeline: this.state?.thread?.timelineSet?.getLiveTimeline(),
|
||||||
withoutScrollContainer={true}
|
}}>
|
||||||
>
|
|
||||||
{ this.state.thread && (
|
<BaseCard
|
||||||
<TimelinePanel
|
className="mx_ThreadView"
|
||||||
ref={this.timelinePanelRef}
|
onClose={this.props.onClose}
|
||||||
showReadReceipts={false} // No RR support in thread's MVP
|
previousPhase={RightPanelPhases.RoomSummary}
|
||||||
manageReadReceipts={false} // No RR support in thread's MVP
|
withoutScrollContainer={true}
|
||||||
manageReadMarkers={false} // No RM support in thread's MVP
|
>
|
||||||
sendReadReceiptOnLoad={false} // No RR support in thread's MVP
|
{ this.state.thread && (
|
||||||
timelineSet={this.state?.thread?.timelineSet}
|
<TimelinePanel
|
||||||
showUrlPreview={true}
|
ref={this.timelinePanelRef}
|
||||||
tileShape={TileShape.Thread}
|
showReadReceipts={false} // No RR support in thread's MVP
|
||||||
empty={<div>empty</div>}
|
manageReadReceipts={false} // No RR support in thread's MVP
|
||||||
alwaysShowTimestamps={true}
|
manageReadMarkers={false} // No RM support in thread's MVP
|
||||||
layout={Layout.Group}
|
sendReadReceiptOnLoad={false} // No RR support in thread's MVP
|
||||||
hideThreadedMessages={false}
|
timelineSet={this.state?.thread?.timelineSet}
|
||||||
hidden={false}
|
showUrlPreview={true}
|
||||||
showReactions={true}
|
tileShape={TileShape.Thread}
|
||||||
className="mx_RoomView_messagePanel mx_GroupLayout"
|
empty={<div>empty</div>}
|
||||||
|
alwaysShowTimestamps={true}
|
||||||
|
layout={Layout.Group}
|
||||||
|
hideThreadedMessages={false}
|
||||||
|
hidden={false}
|
||||||
|
showReactions={true}
|
||||||
|
className="mx_RoomView_messagePanel mx_GroupLayout"
|
||||||
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
|
membersLoaded={true}
|
||||||
|
editState={this.state.editState}
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
|
||||||
|
{ this.state?.thread?.timelineSet && (<MessageComposer
|
||||||
|
room={this.props.room}
|
||||||
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
|
replyInThread={true}
|
||||||
|
replyToEvent={this.state?.thread?.replyToEvent}
|
||||||
|
showReplyPreview={false}
|
||||||
permalinkCreator={this.props.permalinkCreator}
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
membersLoaded={true}
|
e2eStatus={this.props.e2eStatus}
|
||||||
/>
|
compact={true}
|
||||||
) }
|
/>) }
|
||||||
<MessageComposer
|
</BaseCard>
|
||||||
room={this.props.room}
|
</RoomContext.Provider>
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
|
||||||
replyInThread={true}
|
|
||||||
replyToEvent={this.state?.thread?.replyToEvent}
|
|
||||||
showReplyPreview={false}
|
|
||||||
permalinkCreator={this.props.permalinkCreator}
|
|
||||||
e2eStatus={this.props.e2eStatus}
|
|
||||||
compact={true}
|
|
||||||
/>
|
|
||||||
</BaseCard>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import * as sdk from '../../../index';
|
||||||
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
|
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
|
||||||
import SetupEncryptionBody from "./SetupEncryptionBody";
|
import SetupEncryptionBody from "./SetupEncryptionBody";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import AccessibleButton from '../../views/elements/AccessibleButton';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onFinished: () => void;
|
onFinished: () => void;
|
||||||
|
@ -27,6 +28,7 @@ interface IProps {
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
phase: Phase;
|
phase: Phase;
|
||||||
|
lostKeys: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("structures.auth.CompleteSecurity")
|
@replaceableComponent("structures.auth.CompleteSecurity")
|
||||||
|
@ -36,12 +38,17 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
store.on("update", this.onStoreUpdate);
|
store.on("update", this.onStoreUpdate);
|
||||||
store.start();
|
store.start();
|
||||||
this.state = { phase: store.phase };
|
this.state = { phase: store.phase, lostKeys: store.lostKeys() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private onStoreUpdate = (): void => {
|
private onStoreUpdate = (): void => {
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
this.setState({ phase: store.phase });
|
this.setState({ phase: store.phase, lostKeys: store.lostKeys() });
|
||||||
|
};
|
||||||
|
|
||||||
|
private onSkipClick = (): void => {
|
||||||
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
|
store.skip();
|
||||||
};
|
};
|
||||||
|
|
||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
|
@ -53,15 +60,20 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
|
||||||
public render() {
|
public render() {
|
||||||
const AuthPage = sdk.getComponent("auth.AuthPage");
|
const AuthPage = sdk.getComponent("auth.AuthPage");
|
||||||
const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody");
|
const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody");
|
||||||
const { phase } = this.state;
|
const { phase, lostKeys } = this.state;
|
||||||
let icon;
|
let icon;
|
||||||
let title;
|
let title;
|
||||||
|
|
||||||
if (phase === Phase.Loading) {
|
if (phase === Phase.Loading) {
|
||||||
return null;
|
return null;
|
||||||
} else if (phase === Phase.Intro) {
|
} else if (phase === Phase.Intro) {
|
||||||
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
if (lostKeys) {
|
||||||
title = _t("Verify this login");
|
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
||||||
|
title = _t("Unable to verify this login");
|
||||||
|
} else {
|
||||||
|
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
||||||
|
title = _t("Verify this login");
|
||||||
|
}
|
||||||
} else if (phase === Phase.Done) {
|
} else if (phase === Phase.Done) {
|
||||||
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_verified" />;
|
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_verified" />;
|
||||||
title = _t("Session verified");
|
title = _t("Session verified");
|
||||||
|
@ -71,16 +83,29 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
|
||||||
} else if (phase === Phase.Busy) {
|
} else if (phase === Phase.Busy) {
|
||||||
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
||||||
title = _t("Verify this login");
|
title = _t("Verify this login");
|
||||||
|
} else if (phase === Phase.ConfirmReset) {
|
||||||
|
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
|
||||||
|
title = _t("Really reset verification keys?");
|
||||||
|
} else if (phase === Phase.Finished) {
|
||||||
|
// SetupEncryptionBody will take care of calling onFinished, we don't need to do anything
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown phase ${phase}`);
|
throw new Error(`Unknown phase ${phase}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let skipButton;
|
||||||
|
if (phase === Phase.Intro || phase === Phase.ConfirmReset) {
|
||||||
|
skipButton = (
|
||||||
|
<AccessibleButton onClick={this.onSkipClick} className="mx_CompleteSecurity_skip" aria-label={_t("Skip verification for now")} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthPage>
|
<AuthPage>
|
||||||
<CompleteSecurityBody>
|
<CompleteSecurityBody>
|
||||||
<h2 className="mx_CompleteSecurity_header">
|
<h2 className="mx_CompleteSecurity_header">
|
||||||
{ icon }
|
{ icon }
|
||||||
{ title }
|
{ title }
|
||||||
|
{ skipButton }
|
||||||
</h2>
|
</h2>
|
||||||
<div className="mx_CompleteSecurity_body">
|
<div className="mx_CompleteSecurity_body">
|
||||||
<SetupEncryptionBody onFinished={this.props.onFinished} />
|
<SetupEncryptionBody onFinished={this.props.onFinished} />
|
||||||
|
|
|
@ -46,6 +46,7 @@ interface IState {
|
||||||
phase: Phase;
|
phase: Phase;
|
||||||
verificationRequest: VerificationRequest;
|
verificationRequest: VerificationRequest;
|
||||||
backupInfo: IKeyBackupInfo;
|
backupInfo: IKeyBackupInfo;
|
||||||
|
lostKeys: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("structures.auth.SetupEncryptionBody")
|
@replaceableComponent("structures.auth.SetupEncryptionBody")
|
||||||
|
@ -62,6 +63,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
// Because of the latter, it lives in the state.
|
// Because of the latter, it lives in the state.
|
||||||
verificationRequest: store.verificationRequest,
|
verificationRequest: store.verificationRequest,
|
||||||
backupInfo: store.backupInfo,
|
backupInfo: store.backupInfo,
|
||||||
|
lostKeys: store.lostKeys(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +77,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
phase: store.phase,
|
phase: store.phase,
|
||||||
verificationRequest: store.verificationRequest,
|
verificationRequest: store.verificationRequest,
|
||||||
backupInfo: store.backupInfo,
|
backupInfo: store.backupInfo,
|
||||||
|
lostKeys: store.lostKeys(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,11 +108,6 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private onSkipClick = () => {
|
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
|
||||||
store.skip();
|
|
||||||
};
|
|
||||||
|
|
||||||
private onSkipConfirmClick = () => {
|
private onSkipConfirmClick = () => {
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
store.skipConfirm();
|
store.skipConfirm();
|
||||||
|
@ -120,6 +118,22 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
store.returnAfterSkip();
|
store.returnAfterSkip();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onResetClick = (ev: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
|
store.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResetConfirmClick = () => {
|
||||||
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
|
store.resetConfirm();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResetBackClick = () => {
|
||||||
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
|
store.returnAfterReset();
|
||||||
|
};
|
||||||
|
|
||||||
private onDoneClick = () => {
|
private onDoneClick = () => {
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
store.done();
|
store.done();
|
||||||
|
@ -132,6 +146,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
public render() {
|
public render() {
|
||||||
const {
|
const {
|
||||||
phase,
|
phase,
|
||||||
|
lostKeys,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
if (this.state.verificationRequest) {
|
if (this.state.verificationRequest) {
|
||||||
|
@ -143,43 +158,67 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
isRoomEncrypted={false}
|
isRoomEncrypted={false}
|
||||||
/>;
|
/>;
|
||||||
} else if (phase === Phase.Intro) {
|
} else if (phase === Phase.Intro) {
|
||||||
const store = SetupEncryptionStore.sharedInstance();
|
if (lostKeys) {
|
||||||
let recoveryKeyPrompt;
|
return (
|
||||||
if (store.keyInfo && keyHasPassphrase(store.keyInfo)) {
|
<div>
|
||||||
recoveryKeyPrompt = _t("Use Security Key or Phrase");
|
<p>{ _t(
|
||||||
} else if (store.keyInfo) {
|
"It looks like you don't have a Security Key or any other devices you can " +
|
||||||
recoveryKeyPrompt = _t("Use Security Key");
|
"verify against. This device will not be able to access old encrypted messages. " +
|
||||||
}
|
"In order to verify your identity on this device, you'll need to reset " +
|
||||||
|
"your verification keys.",
|
||||||
|
) }</p>
|
||||||
|
|
||||||
let useRecoveryKeyButton;
|
<div className="mx_CompleteSecurity_actionRow">
|
||||||
if (recoveryKeyPrompt) {
|
<AccessibleButton kind="primary" onClick={this.onResetConfirmClick}>
|
||||||
useRecoveryKeyButton = <AccessibleButton kind="link" onClick={this.onUsePassphraseClick}>
|
{ _t("Proceed with reset") }
|
||||||
{ recoveryKeyPrompt }
|
</AccessibleButton>
|
||||||
</AccessibleButton>;
|
</div>
|
||||||
}
|
|
||||||
|
|
||||||
let verifyButton;
|
|
||||||
if (store.hasDevicesToVerifyAgainst) {
|
|
||||||
verifyButton = <AccessibleButton kind="primary" onClick={this.onVerifyClick}>
|
|
||||||
{ _t("Use another login") }
|
|
||||||
</AccessibleButton>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p>{ _t(
|
|
||||||
"Verify your identity to access encrypted messages and prove your identity to others.",
|
|
||||||
) }</p>
|
|
||||||
|
|
||||||
<div className="mx_CompleteSecurity_actionRow">
|
|
||||||
{ verifyButton }
|
|
||||||
{ useRecoveryKeyButton }
|
|
||||||
<AccessibleButton kind="danger" onClick={this.onSkipClick}>
|
|
||||||
{ _t("Skip") }
|
|
||||||
</AccessibleButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
} else {
|
||||||
|
const store = SetupEncryptionStore.sharedInstance();
|
||||||
|
let recoveryKeyPrompt;
|
||||||
|
if (store.keyInfo && keyHasPassphrase(store.keyInfo)) {
|
||||||
|
recoveryKeyPrompt = _t("Verify with Security Key or Phrase");
|
||||||
|
} else if (store.keyInfo) {
|
||||||
|
recoveryKeyPrompt = _t("Verify with Security Key");
|
||||||
|
}
|
||||||
|
|
||||||
|
let useRecoveryKeyButton;
|
||||||
|
if (recoveryKeyPrompt) {
|
||||||
|
useRecoveryKeyButton = <AccessibleButton kind="primary" onClick={this.onUsePassphraseClick}>
|
||||||
|
{ recoveryKeyPrompt }
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let verifyButton;
|
||||||
|
if (store.hasDevicesToVerifyAgainst) {
|
||||||
|
verifyButton = <AccessibleButton kind="primary" onClick={this.onVerifyClick}>
|
||||||
|
{ _t("Verify with another login") }
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>{ _t(
|
||||||
|
"Verify your identity to access encrypted messages and prove your identity to others.",
|
||||||
|
) }</p>
|
||||||
|
|
||||||
|
<div className="mx_CompleteSecurity_actionRow">
|
||||||
|
{ verifyButton }
|
||||||
|
{ useRecoveryKeyButton }
|
||||||
|
</div>
|
||||||
|
<div className="mx_SetupEncryptionBody_reset">
|
||||||
|
{ _t("Forgotten or lost all recovery methods? <a>Reset all</a>", null, {
|
||||||
|
a: (sub) => <a
|
||||||
|
href=""
|
||||||
|
onClick={this.onResetClick}
|
||||||
|
className="mx_SetupEncryptionBody_reset_link">{ sub }</a>,
|
||||||
|
}) }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (phase === Phase.Done) {
|
} else if (phase === Phase.Done) {
|
||||||
let message;
|
let message;
|
||||||
if (this.state.backupInfo) {
|
if (this.state.backupInfo) {
|
||||||
|
@ -215,14 +254,13 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
) }</p>
|
) }</p>
|
||||||
<div className="mx_CompleteSecurity_actionRow">
|
<div className="mx_CompleteSecurity_actionRow">
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
className="warning"
|
kind="danger_outline"
|
||||||
kind="secondary"
|
|
||||||
onClick={this.onSkipConfirmClick}
|
onClick={this.onSkipConfirmClick}
|
||||||
>
|
>
|
||||||
{ _t("Skip") }
|
{ _t("I'll verify later") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
kind="danger"
|
kind="primary"
|
||||||
onClick={this.onSkipBackClick}
|
onClick={this.onSkipBackClick}
|
||||||
>
|
>
|
||||||
{ _t("Go Back") }
|
{ _t("Go Back") }
|
||||||
|
@ -230,6 +268,30 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (phase === Phase.ConfirmReset) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>{ _t(
|
||||||
|
"Resetting your verification keys cannot be undone. After resetting, " +
|
||||||
|
"you won't have access to old encrypted messages, and any friends who " +
|
||||||
|
"have previously verified you will see security warnings until you " +
|
||||||
|
"re-verify with them.",
|
||||||
|
) }</p>
|
||||||
|
<p>{ _t(
|
||||||
|
"Please only proceed if you're sure you've lost all of your other " +
|
||||||
|
"devices and your security key.",
|
||||||
|
) }</p>
|
||||||
|
|
||||||
|
<div className="mx_CompleteSecurity_actionRow">
|
||||||
|
<AccessibleButton kind="danger_outline" onClick={this.onResetConfirmClick}>
|
||||||
|
{ _t("Proceed with reset") }
|
||||||
|
</AccessibleButton>
|
||||||
|
<AccessibleButton kind="primary" onClick={this.onResetBackClick}>
|
||||||
|
{ _t("Go Back") }
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else if (phase === Phase.Busy || phase === Phase.Loading) {
|
} else if (phase === Phase.Busy || phase === Phase.Loading) {
|
||||||
return <Spinner />;
|
return <Spinner />;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -39,6 +39,8 @@ import dis from "../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import { UserTab } from "./UserSettingsDialog";
|
import { UserTab } from "./UserSettingsDialog";
|
||||||
import TagOrderActions from "../../../actions/TagOrderActions";
|
import TagOrderActions from "../../../actions/TagOrderActions";
|
||||||
|
import { inviteUsersToRoom } from "../../../RoomInvite";
|
||||||
|
import ProgressBar from "../elements/ProgressBar";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
@ -90,10 +92,22 @@ export interface IGroupSummary {
|
||||||
}
|
}
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
|
enum Progress {
|
||||||
|
NotStarted,
|
||||||
|
ValidatingInputs,
|
||||||
|
FetchingData,
|
||||||
|
CreatingSpace,
|
||||||
|
InvitingUsers,
|
||||||
|
// anything beyond here is inviting user n - 4
|
||||||
|
}
|
||||||
|
|
||||||
const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, groupId, onFinished }) => {
|
const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, groupId, onFinished }) => {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string>(null);
|
const [error, setError] = useState<string>(null);
|
||||||
const [busy, setBusy] = useState(false);
|
|
||||||
|
const [progress, setProgress] = useState(Progress.NotStarted);
|
||||||
|
const [numInvites, setNumInvites] = useState(0);
|
||||||
|
const busy = progress > 0;
|
||||||
|
|
||||||
const [avatar, setAvatar] = useState<File>(null); // undefined means to remove avatar
|
const [avatar, setAvatar] = useState<File>(null); // undefined means to remove avatar
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
@ -122,30 +136,34 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
|
||||||
if (busy) return;
|
if (busy) return;
|
||||||
|
|
||||||
setError(null);
|
setError(null);
|
||||||
setBusy(true);
|
setProgress(Progress.ValidatingInputs);
|
||||||
|
|
||||||
// require & validate the space name field
|
// require & validate the space name field
|
||||||
if (!(await spaceNameField.current.validate({ allowEmpty: false }))) {
|
if (!(await spaceNameField.current.validate({ allowEmpty: false }))) {
|
||||||
setBusy(false);
|
setProgress(0);
|
||||||
spaceNameField.current.focus();
|
spaceNameField.current.focus();
|
||||||
spaceNameField.current.validate({ allowEmpty: false, focused: true });
|
spaceNameField.current.validate({ allowEmpty: false, focused: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// validate the space name alias field but do not require it
|
// validate the space name alias field but do not require it
|
||||||
if (joinRule === JoinRule.Public && !(await spaceAliasField.current.validate({ allowEmpty: true }))) {
|
if (joinRule === JoinRule.Public && !(await spaceAliasField.current.validate({ allowEmpty: true }))) {
|
||||||
setBusy(false);
|
setProgress(0);
|
||||||
spaceAliasField.current.focus();
|
spaceAliasField.current.focus();
|
||||||
spaceAliasField.current.validate({ allowEmpty: true, focused: true });
|
spaceAliasField.current.validate({ allowEmpty: true, focused: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
setProgress(Progress.FetchingData);
|
||||||
|
|
||||||
const [rooms, members, invitedMembers] = await Promise.all([
|
const [rooms, members, invitedMembers] = await Promise.all([
|
||||||
cli.getGroupRooms(groupId).then(parseRoomsResponse) as Promise<IGroupRoom[]>,
|
cli.getGroupRooms(groupId).then(parseRoomsResponse) as Promise<IGroupRoom[]>,
|
||||||
cli.getGroupUsers(groupId).then(parseMembersResponse) as Promise<GroupMember[]>,
|
cli.getGroupUsers(groupId).then(parseMembersResponse) as Promise<GroupMember[]>,
|
||||||
cli.getGroupInvitedUsers(groupId).then(parseMembersResponse) as Promise<GroupMember[]>,
|
cli.getGroupInvitedUsers(groupId).then(parseMembersResponse) as Promise<GroupMember[]>,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
setNumInvites(members.length + invitedMembers.length);
|
||||||
|
|
||||||
const viaMap = new Map<string, string[]>();
|
const viaMap = new Map<string, string[]>();
|
||||||
for (const { roomId, canonicalAlias } of rooms) {
|
for (const { roomId, canonicalAlias } of rooms) {
|
||||||
const room = cli.getRoom(roomId);
|
const room = cli.getRoom(roomId);
|
||||||
|
@ -167,6 +185,8 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setProgress(Progress.CreatingSpace);
|
||||||
|
|
||||||
const spaceAvatar = avatar !== undefined ? avatar : groupSummary.profile.avatar_url;
|
const spaceAvatar = avatar !== undefined ? avatar : groupSummary.profile.avatar_url;
|
||||||
const roomId = await createSpace(name, joinRule === JoinRule.Public, alias, topic, spaceAvatar, {
|
const roomId = await createSpace(name, joinRule === JoinRule.Public, alias, topic, spaceAvatar, {
|
||||||
creation_content: {
|
creation_content: {
|
||||||
|
@ -179,11 +199,16 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
|
||||||
via: viaMap.get(roomId) || [],
|
via: viaMap.get(roomId) || [],
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
invite: [...members, ...invitedMembers].map(m => m.userId).filter(m => m !== cli.getUserId()),
|
// we do not specify the inviters here because Synapse applies a limit and this may cause it to trip
|
||||||
}, {
|
}, {
|
||||||
andView: false,
|
andView: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setProgress(Progress.InvitingUsers);
|
||||||
|
|
||||||
|
const userIds = [...members, ...invitedMembers].map(m => m.userId).filter(m => m !== cli.getUserId());
|
||||||
|
await inviteUsersToRoom(roomId, userIds, () => setProgress(p => p + 1));
|
||||||
|
|
||||||
// eagerly remove it from the community panel
|
// eagerly remove it from the community panel
|
||||||
dis.dispatch(TagOrderActions.removeTag(cli, groupId));
|
dis.dispatch(TagOrderActions.removeTag(cli, groupId));
|
||||||
|
|
||||||
|
@ -250,7 +275,7 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
|
||||||
setError(e);
|
setError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
setBusy(false);
|
setProgress(Progress.NotStarted);
|
||||||
};
|
};
|
||||||
|
|
||||||
let footer;
|
let footer;
|
||||||
|
@ -267,13 +292,41 @@ const CreateSpaceFromCommunityDialog: React.FC<IProps> = ({ matrixClient: cli, g
|
||||||
{ _t("Retry") }
|
{ _t("Retry") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</>;
|
</>;
|
||||||
|
} else if (busy) {
|
||||||
|
let description: string;
|
||||||
|
switch (progress) {
|
||||||
|
case Progress.ValidatingInputs:
|
||||||
|
case Progress.FetchingData:
|
||||||
|
description = _t("Fetching data...");
|
||||||
|
break;
|
||||||
|
case Progress.CreatingSpace:
|
||||||
|
description = _t("Creating Space...");
|
||||||
|
break;
|
||||||
|
case Progress.InvitingUsers:
|
||||||
|
default:
|
||||||
|
description = _t("Adding rooms... (%(progress)s out of %(count)s)", {
|
||||||
|
count: numInvites,
|
||||||
|
progress,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer = <span>
|
||||||
|
<ProgressBar
|
||||||
|
value={progress > Progress.FetchingData ? progress : 0}
|
||||||
|
max={numInvites + Progress.InvitingUsers}
|
||||||
|
/>
|
||||||
|
<div className="mx_CreateSpaceFromCommunityDialog_progressText">
|
||||||
|
{ description }
|
||||||
|
</div>
|
||||||
|
</span>;
|
||||||
} else {
|
} else {
|
||||||
footer = <>
|
footer = <>
|
||||||
<AccessibleButton kind="primary_outline" disabled={busy} onClick={() => onFinished()}>
|
<AccessibleButton kind="primary_outline" onClick={() => onFinished()}>
|
||||||
{ _t("Cancel") }
|
{ _t("Cancel") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<AccessibleButton kind="primary" disabled={busy} onClick={onCreateSpaceClick}>
|
<AccessibleButton kind="primary" onClick={onCreateSpaceClick}>
|
||||||
{ busy ? _t("Creating...") : _t("Create Space") }
|
{ _t("Create Space") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { Action } from '../../../dispatcher/actions';
|
||||||
import { RightPanelPhases } from '../../../stores/RightPanelStorePhases';
|
import { RightPanelPhases } from '../../../stores/RightPanelStorePhases';
|
||||||
import { aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
|
import { aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
|
||||||
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
|
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
import Toolbar from "../../../accessibility/Toolbar";
|
import Toolbar from "../../../accessibility/Toolbar";
|
||||||
import { RovingAccessibleTooltipButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
|
import { RovingAccessibleTooltipButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
@ -128,11 +128,6 @@ const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusC
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum ActionBarRenderingContext {
|
|
||||||
Room,
|
|
||||||
Thread
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMessageActionBarProps {
|
interface IMessageActionBarProps {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
reactions?: Relations;
|
reactions?: Relations;
|
||||||
|
@ -142,7 +137,6 @@ interface IMessageActionBarProps {
|
||||||
permalinkCreator?: RoomPermalinkCreator;
|
permalinkCreator?: RoomPermalinkCreator;
|
||||||
onFocusChange?: (menuDisplayed: boolean) => void;
|
onFocusChange?: (menuDisplayed: boolean) => void;
|
||||||
toggleThreadExpanded: () => void;
|
toggleThreadExpanded: () => void;
|
||||||
renderingContext?: ActionBarRenderingContext;
|
|
||||||
isQuoteExpanded?: boolean;
|
isQuoteExpanded?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,10 +144,6 @@ interface IMessageActionBarProps {
|
||||||
export default class MessageActionBar extends React.PureComponent<IMessageActionBarProps> {
|
export default class MessageActionBar extends React.PureComponent<IMessageActionBarProps> {
|
||||||
public static contextType = RoomContext;
|
public static contextType = RoomContext;
|
||||||
|
|
||||||
public static defaultProps = {
|
|
||||||
renderingContext: ActionBarRenderingContext.Room,
|
|
||||||
};
|
|
||||||
|
|
||||||
public componentDidMount(): void {
|
public componentDidMount(): void {
|
||||||
if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) {
|
if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) {
|
||||||
this.props.mxEvent.on("Event.status", this.onSent);
|
this.props.mxEvent.on("Event.status", this.onSent);
|
||||||
|
@ -217,8 +207,9 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
|
|
||||||
private onEditClick = (ev: React.MouseEvent): void => {
|
private onEditClick = (ev: React.MouseEvent): void => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'edit_event',
|
action: Action.EditEvent,
|
||||||
event: this.props.mxEvent,
|
event: this.props.mxEvent,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -298,7 +289,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
// Like the resend button, the react and reply buttons need to appear before the edit.
|
// Like the resend button, the react and reply buttons need to appear before the edit.
|
||||||
// The only catch is we do the reply button first so that we can make sure the react
|
// The only catch is we do the reply button first so that we can make sure the react
|
||||||
// button is the very first button without having to do length checks for `splice()`.
|
// button is the very first button without having to do length checks for `splice()`.
|
||||||
if (this.context.canReply && this.props.renderingContext === ActionBarRenderingContext.Room) {
|
if (this.context.canReply && this.context.timelineRenderingType === TimelineRenderingType.Room) {
|
||||||
toolbarOpts.splice(0, 0, <>
|
toolbarOpts.splice(0, 0, <>
|
||||||
<RovingAccessibleTooltipButton
|
<RovingAccessibleTooltipButton
|
||||||
className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton"
|
className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton"
|
||||||
|
|
|
@ -49,16 +49,18 @@ const EncryptionInfo: React.FC<IProps> = ({
|
||||||
isSelfVerification,
|
isSelfVerification,
|
||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
let content: JSX.Element;
|
let content: JSX.Element;
|
||||||
if (waitingForOtherParty || waitingForNetwork) {
|
if (waitingForOtherParty && isSelfVerification) {
|
||||||
|
content = (
|
||||||
|
<div>
|
||||||
|
{ _t("To proceed, please accept the verification request on your other login.") }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (waitingForOtherParty || waitingForNetwork) {
|
||||||
let text: string;
|
let text: string;
|
||||||
if (waitingForOtherParty) {
|
if (waitingForOtherParty) {
|
||||||
if (isSelfVerification) {
|
text = _t("Waiting for %(displayName)s to accept…", {
|
||||||
text = _t("Accept on your other login…");
|
displayName: (member as User).displayName || (member as RoomMember).name || member.userId,
|
||||||
} else {
|
});
|
||||||
text = _t("Waiting for %(displayName)s to accept…", {
|
|
||||||
displayName: (member as User).displayName || (member as RoomMember).name || member.userId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
text = _t("Accepting…");
|
text = _t("Accepting…");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import { parseEvent } from '../../../editor/deserialize';
|
||||||
import { CommandPartCreator, Part, PartCreator, Type } from '../../../editor/parts';
|
import { CommandPartCreator, Part, PartCreator, Type } from '../../../editor/parts';
|
||||||
import EditorStateTransfer from '../../../utils/EditorStateTransfer';
|
import EditorStateTransfer from '../../../utils/EditorStateTransfer';
|
||||||
import BasicMessageComposer, { REGEX_EMOTICON } from "./BasicMessageComposer";
|
import BasicMessageComposer, { REGEX_EMOTICON } from "./BasicMessageComposer";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|
||||||
import { Command, CommandCategories, getCommand } from '../../../SlashCommands';
|
import { Command, CommandCategories, getCommand } from '../../../SlashCommands';
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import CountlyAnalytics from "../../../CountlyAnalytics";
|
import CountlyAnalytics from "../../../CountlyAnalytics";
|
||||||
|
@ -36,7 +35,7 @@ import { getKeyBindingsManager, MessageComposerAction } from '../../../KeyBindin
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import SendHistoryManager from '../../../SendHistoryManager';
|
import SendHistoryManager from '../../../SendHistoryManager';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import { MsgType } from 'matrix-js-sdk/src/@types/event';
|
import { MsgType, UNSTABLE_ELEMENT_REPLY_IN_THREAD } from 'matrix-js-sdk/src/@types/event';
|
||||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||||
import QuestionDialog from "../dialogs/QuestionDialog";
|
import QuestionDialog from "../dialogs/QuestionDialog";
|
||||||
|
@ -46,6 +45,8 @@ import { createRedactEventDialog } from '../dialogs/ConfirmRedactDialog';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { withMatrixClientHOC, MatrixClientProps } from '../../../contexts/MatrixClientContext';
|
||||||
|
import RoomContext, { TimelineRenderingType } from '../../../contexts/RoomContext';
|
||||||
|
|
||||||
function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
|
function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
|
||||||
const html = mxEvent.getContent().formatted_body;
|
const html = mxEvent.getContent().formatted_body;
|
||||||
|
@ -66,7 +67,11 @@ function getTextReplyFallback(mxEvent: MatrixEvent): string {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEditContent(model: EditorModel, editedEvent: MatrixEvent): IContent {
|
function createEditContent(
|
||||||
|
model: EditorModel,
|
||||||
|
editedEvent: MatrixEvent,
|
||||||
|
renderingContext?: TimelineRenderingType,
|
||||||
|
): IContent {
|
||||||
const isEmote = containsEmote(model);
|
const isEmote = containsEmote(model);
|
||||||
if (isEmote) {
|
if (isEmote) {
|
||||||
model = stripEmoteCommand(model);
|
model = stripEmoteCommand(model);
|
||||||
|
@ -99,41 +104,49 @@ function createEditContent(model: EditorModel, editedEvent: MatrixEvent): IConte
|
||||||
contentBody.formatted_body = `${htmlPrefix} * ${formattedBody}`;
|
contentBody.formatted_body = `${htmlPrefix} * ${formattedBody}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.assign({
|
const relation = {
|
||||||
"m.new_content": newContent,
|
"m.new_content": newContent,
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
"rel_type": "m.replace",
|
"rel_type": "m.replace",
|
||||||
"event_id": editedEvent.getId(),
|
"event_id": editedEvent.getId(),
|
||||||
},
|
},
|
||||||
}, contentBody);
|
};
|
||||||
|
|
||||||
|
if (renderingContext === TimelineRenderingType.Thread) {
|
||||||
|
relation['m.relates_to'][UNSTABLE_ELEMENT_REPLY_IN_THREAD.name] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign(relation, contentBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IEditMessageComposerProps extends MatrixClientProps {
|
||||||
editState: EditorStateTransfer;
|
editState: EditorStateTransfer;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
saveDisabled: boolean;
|
saveDisabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.rooms.EditMessageComposer")
|
@replaceableComponent("views.rooms.EditMessageComposer")
|
||||||
export default class EditMessageComposer extends React.Component<IProps, IState> {
|
class EditMessageComposer extends React.Component<IEditMessageComposerProps, IState> {
|
||||||
static contextType = MatrixClientContext;
|
static contextType = RoomContext;
|
||||||
context!: React.ContextType<typeof MatrixClientContext>;
|
context!: React.ContextType<typeof RoomContext>;
|
||||||
|
|
||||||
private readonly editorRef = createRef<BasicMessageComposer>();
|
private readonly editorRef = createRef<BasicMessageComposer>();
|
||||||
private readonly dispatcherRef: string;
|
private readonly dispatcherRef: string;
|
||||||
private model: EditorModel = null;
|
private model: EditorModel = null;
|
||||||
|
|
||||||
constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
|
constructor(props: IEditMessageComposerProps, context: React.ContextType<typeof RoomContext>) {
|
||||||
super(props);
|
super(props);
|
||||||
this.context = context; // otherwise React will only set it prior to render due to type def above
|
this.context = context; // otherwise React will only set it prior to render due to type def above
|
||||||
|
|
||||||
const isRestored = this.createEditorModel();
|
const isRestored = this.createEditorModel();
|
||||||
const ev = this.props.editState.getEvent();
|
const ev = this.props.editState.getEvent();
|
||||||
|
|
||||||
|
const renderingContext = this.context.timelineRenderingType;
|
||||||
|
const editContent = createEditContent(this.model, ev, renderingContext);
|
||||||
this.state = {
|
this.state = {
|
||||||
saveDisabled: !isRestored || !this.isContentModified(createEditContent(this.model, ev)["m.new_content"]),
|
saveDisabled: !isRestored || !this.isContentModified(editContent["m.new_content"]),
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("beforeunload", this.saveStoredEditorState);
|
window.addEventListener("beforeunload", this.saveStoredEditorState);
|
||||||
|
@ -141,7 +154,7 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRoom(): Room {
|
private getRoom(): Room {
|
||||||
return this.context.getRoom(this.props.editState.getEvent().getRoomId());
|
return this.props.mxClient.getRoom(this.props.editState.getEvent().getRoomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private onKeyDown = (event: KeyboardEvent): void => {
|
private onKeyDown = (event: KeyboardEvent): void => {
|
||||||
|
@ -162,10 +175,17 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
if (this.editorRef.current?.isModified() || !this.editorRef.current?.isCaretAtStart()) {
|
if (this.editorRef.current?.isModified() || !this.editorRef.current?.isCaretAtStart()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const previousEvent = findEditableEvent(this.getRoom(), false,
|
const previousEvent = findEditableEvent({
|
||||||
this.props.editState.getEvent().getId());
|
events: this.events,
|
||||||
|
isForward: false,
|
||||||
|
fromEventId: this.props.editState.getEvent().getId(),
|
||||||
|
});
|
||||||
if (previousEvent) {
|
if (previousEvent) {
|
||||||
dis.dispatch({ action: 'edit_event', event: previousEvent });
|
dis.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: previousEvent,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -174,12 +194,24 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
if (this.editorRef.current?.isModified() || !this.editorRef.current?.isCaretAtEnd()) {
|
if (this.editorRef.current?.isModified() || !this.editorRef.current?.isCaretAtEnd()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nextEvent = findEditableEvent(this.getRoom(), true, this.props.editState.getEvent().getId());
|
const nextEvent = findEditableEvent({
|
||||||
|
events: this.events,
|
||||||
|
isForward: true,
|
||||||
|
fromEventId: this.props.editState.getEvent().getId(),
|
||||||
|
});
|
||||||
if (nextEvent) {
|
if (nextEvent) {
|
||||||
dis.dispatch({ action: 'edit_event', event: nextEvent });
|
dis.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: nextEvent,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.clearStoredEditorState();
|
this.clearStoredEditorState();
|
||||||
dis.dispatch({ action: 'edit_event', event: null });
|
dis.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: null,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
dis.fire(Action.FocusSendMessageComposer);
|
dis.fire(Action.FocusSendMessageComposer);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -189,16 +221,27 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
};
|
};
|
||||||
|
|
||||||
private get editorRoomKey(): string {
|
private get editorRoomKey(): string {
|
||||||
return `mx_edit_room_${this.getRoom().roomId}`;
|
return `mx_edit_room_${this.getRoom().roomId}_${this.context.timelineRenderingType}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get editorStateKey(): string {
|
private get editorStateKey(): string {
|
||||||
return `mx_edit_state_${this.props.editState.getEvent().getId()}`;
|
return `mx_edit_state_${this.props.editState.getEvent().getId()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get events(): MatrixEvent[] {
|
||||||
|
const liveTimelineEvents = this.context.liveTimeline.getEvents();
|
||||||
|
const pendingEvents = this.getRoom().getPendingEvents();
|
||||||
|
const isInThread = Boolean(this.props.editState.getEvent().getThread());
|
||||||
|
return liveTimelineEvents.concat(isInThread ? [] : pendingEvents);
|
||||||
|
}
|
||||||
|
|
||||||
private cancelEdit = (): void => {
|
private cancelEdit = (): void => {
|
||||||
this.clearStoredEditorState();
|
this.clearStoredEditorState();
|
||||||
dis.dispatch({ action: "edit_event", event: null });
|
dis.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: null,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
dis.fire(Action.FocusSendMessageComposer);
|
dis.fire(Action.FocusSendMessageComposer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -326,8 +369,8 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
const position = this.model.positionForOffset(caret.offset, caret.atNodeEnd);
|
const position = this.model.positionForOffset(caret.offset, caret.atNodeEnd);
|
||||||
this.editorRef.current?.replaceEmoticon(position, REGEX_EMOTICON);
|
this.editorRef.current?.replaceEmoticon(position, REGEX_EMOTICON);
|
||||||
}
|
}
|
||||||
|
const renderingContext = this.context.timelineRenderingType;
|
||||||
const editContent = createEditContent(this.model, editedEvent);
|
const editContent = createEditContent(this.model, editedEvent, renderingContext);
|
||||||
const newContent = editContent["m.new_content"];
|
const newContent = editContent["m.new_content"];
|
||||||
|
|
||||||
let shouldSend = true;
|
let shouldSend = true;
|
||||||
|
@ -381,7 +424,7 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
if (shouldSend) {
|
if (shouldSend) {
|
||||||
this.cancelPreviousPendingEdit();
|
this.cancelPreviousPendingEdit();
|
||||||
const prom = this.context.sendMessage(roomId, editContent);
|
const prom = this.props.mxClient.sendMessage(roomId, editContent);
|
||||||
this.clearStoredEditorState();
|
this.clearStoredEditorState();
|
||||||
dis.dispatch({ action: "message_sent" });
|
dis.dispatch({ action: "message_sent" });
|
||||||
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent);
|
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent);
|
||||||
|
@ -389,7 +432,11 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the event editing and focus composer
|
// close the event editing and focus composer
|
||||||
dis.dispatch({ action: "edit_event", event: null });
|
dis.dispatch({
|
||||||
|
action: Action.EditEvent,
|
||||||
|
event: null,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
|
});
|
||||||
dis.fire(Action.FocusSendMessageComposer);
|
dis.fire(Action.FocusSendMessageComposer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,7 +447,7 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
previousEdit.status === EventStatus.QUEUED ||
|
previousEdit.status === EventStatus.QUEUED ||
|
||||||
previousEdit.status === EventStatus.NOT_SENT
|
previousEdit.status === EventStatus.NOT_SENT
|
||||||
)) {
|
)) {
|
||||||
this.context.cancelPendingEvent(previousEdit);
|
this.props.mxClient.cancelPendingEvent(previousEdit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +475,7 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
private createEditorModel(): boolean {
|
private createEditorModel(): boolean {
|
||||||
const { editState } = this.props;
|
const { editState } = this.props;
|
||||||
const room = this.getRoom();
|
const room = this.getRoom();
|
||||||
const partCreator = new CommandPartCreator(room, this.context);
|
const partCreator = new CommandPartCreator(room, this.props.mxClient);
|
||||||
|
|
||||||
let parts;
|
let parts;
|
||||||
let isRestored = false;
|
let isRestored = false;
|
||||||
|
@ -493,3 +540,6 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EditMessageComposerWithMatrixClient = withMatrixClientHOC(EditMessageComposer);
|
||||||
|
export default EditMessageComposerWithMatrixClient;
|
||||||
|
|
|
@ -53,7 +53,7 @@ import SenderProfile from '../messages/SenderProfile';
|
||||||
import MessageTimestamp from '../messages/MessageTimestamp';
|
import MessageTimestamp from '../messages/MessageTimestamp';
|
||||||
import TooltipButton from '../elements/TooltipButton';
|
import TooltipButton from '../elements/TooltipButton';
|
||||||
import ReadReceiptMarker from "./ReadReceiptMarker";
|
import ReadReceiptMarker from "./ReadReceiptMarker";
|
||||||
import MessageActionBar, { ActionBarRenderingContext } from "../messages/MessageActionBar";
|
import MessageActionBar from "../messages/MessageActionBar";
|
||||||
import ReactionsRow from '../messages/ReactionsRow';
|
import ReactionsRow from '../messages/ReactionsRow';
|
||||||
import { getEventDisplayInfo } from '../../../utils/EventUtils';
|
import { getEventDisplayInfo } from '../../../utils/EventUtils';
|
||||||
import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
|
import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
|
||||||
|
@ -1063,9 +1063,6 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const showMessageActionBar = !isEditing && !this.props.forExport;
|
const showMessageActionBar = !isEditing && !this.props.forExport;
|
||||||
const renderingContext = this.props.tileShape === TileShape.Thread
|
|
||||||
? ActionBarRenderingContext.Thread
|
|
||||||
: ActionBarRenderingContext.Room;
|
|
||||||
const actionBar = showMessageActionBar ? <MessageActionBar
|
const actionBar = showMessageActionBar ? <MessageActionBar
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
reactions={this.state.reactions}
|
reactions={this.state.reactions}
|
||||||
|
@ -1073,7 +1070,6 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
getTile={this.getTile}
|
getTile={this.getTile}
|
||||||
getReplyThread={this.getReplyThread}
|
getReplyThread={this.getReplyThread}
|
||||||
onFocusChange={this.onActionBarFocusChange}
|
onFocusChange={this.onActionBarFocusChange}
|
||||||
renderingContext={renderingContext}
|
|
||||||
isQuoteExpanded={isQuoteExpanded}
|
isQuoteExpanded={isQuoteExpanded}
|
||||||
toggleThreadExpanded={() => this.setQuoteExpanded(!isQuoteExpanded)}
|
toggleThreadExpanded={() => this.setQuoteExpanded(!isQuoteExpanded)}
|
||||||
/> : undefined;
|
/> : undefined;
|
||||||
|
@ -1178,6 +1174,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
onHeightChanged={this.props.onHeightChanged}
|
onHeightChanged={this.props.onHeightChanged}
|
||||||
tileShape={this.props.tileShape}
|
tileShape={this.props.tileShape}
|
||||||
|
editState={this.props.editState}
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
]);
|
]);
|
||||||
|
@ -1211,6 +1208,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
onHeightChanged={this.props.onHeightChanged}
|
onHeightChanged={this.props.onHeightChanged}
|
||||||
tileShape={this.props.tileShape}
|
tileShape={this.props.tileShape}
|
||||||
|
editState={this.props.editState}
|
||||||
|
replacingEventId={this.props.replacingEventId}
|
||||||
/>
|
/>
|
||||||
{ actionBar }
|
{ actionBar }
|
||||||
</div>,
|
</div>,
|
||||||
|
@ -1231,6 +1230,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
tileShape={this.props.tileShape}
|
tileShape={this.props.tileShape}
|
||||||
onHeightChanged={this.props.onHeightChanged}
|
onHeightChanged={this.props.onHeightChanged}
|
||||||
|
editState={this.props.editState}
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
<a
|
<a
|
||||||
|
|
|
@ -45,7 +45,7 @@ import { RecordingState } from "../../../audio/VoiceRecording";
|
||||||
import Tooltip, { Alignment } from "../elements/Tooltip";
|
import Tooltip, { Alignment } from "../elements/Tooltip";
|
||||||
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import { E2EStatus } from '../../../utils/ShieldUtils';
|
import { E2EStatus } from '../../../utils/ShieldUtils';
|
||||||
import SendMessageComposer from "./SendMessageComposer";
|
import SendMessageComposer, { SendMessageComposer as SendMessageComposerClass } from "./SendMessageComposer";
|
||||||
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import EditorModel from "../../../editor/model";
|
import EditorModel from "../../../editor/model";
|
||||||
|
@ -219,8 +219,8 @@ interface IState {
|
||||||
@replaceableComponent("views.rooms.MessageComposer")
|
@replaceableComponent("views.rooms.MessageComposer")
|
||||||
export default class MessageComposer extends React.Component<IProps, IState> {
|
export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private messageComposerInput: SendMessageComposer;
|
private messageComposerInput = createRef<SendMessageComposerClass>();
|
||||||
private voiceRecordingButton: VoiceRecordComposerTile;
|
private voiceRecordingButton = createRef<VoiceRecordComposerTile>();
|
||||||
private ref: React.RefObject<HTMLDivElement> = createRef();
|
private ref: React.RefObject<HTMLDivElement> = createRef();
|
||||||
private instanceId: number;
|
private instanceId: number;
|
||||||
|
|
||||||
|
@ -378,14 +378,14 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendMessage = async () => {
|
private sendMessage = async () => {
|
||||||
if (this.state.haveRecording && this.voiceRecordingButton) {
|
if (this.state.haveRecording && this.voiceRecordingButton.current) {
|
||||||
// There shouldn't be any text message to send when a voice recording is active, so
|
// There shouldn't be any text message to send when a voice recording is active, so
|
||||||
// just send out the voice recording.
|
// just send out the voice recording.
|
||||||
await this.voiceRecordingButton.send();
|
await this.voiceRecordingButton.current?.send();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messageComposerInput.sendMessage();
|
this.messageComposerInput.current?.sendMessage();
|
||||||
};
|
};
|
||||||
|
|
||||||
private onChange = (model: EditorModel) => {
|
private onChange = (model: EditorModel) => {
|
||||||
|
@ -460,7 +460,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<AccessibleTooltipButton
|
<AccessibleTooltipButton
|
||||||
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
|
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
|
||||||
onClick={() => this.voiceRecordingButton?.onRecordStartEndClick()}
|
onClick={() => this.voiceRecordingButton.current?.onRecordStartEndClick()}
|
||||||
title={_t("Send voice message")}
|
title={_t("Send voice message")}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
@ -521,7 +521,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
if (!this.state.tombstone && this.state.canSendMessages) {
|
if (!this.state.tombstone && this.state.canSendMessages) {
|
||||||
controls.push(
|
controls.push(
|
||||||
<SendMessageComposer
|
<SendMessageComposer
|
||||||
ref={(c) => this.messageComposerInput = c}
|
ref={this.messageComposerInput}
|
||||||
key="controls_input"
|
key="controls_input"
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
placeholder={this.renderPlaceholderText()}
|
placeholder={this.renderPlaceholderText()}
|
||||||
|
@ -535,7 +535,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
controls.push(<VoiceRecordComposerTile
|
controls.push(<VoiceRecordComposerTile
|
||||||
key="controls_voice_record"
|
key="controls_voice_record"
|
||||||
ref={c => this.voiceRecordingButton = c}
|
ref={this.voiceRecordingButton}
|
||||||
room={this.props.room} />);
|
room={this.props.room} />);
|
||||||
} else if (this.state.tombstone) {
|
} else if (this.state.tombstone) {
|
||||||
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
const replacementRoomId = this.state.tombstone.getContent()['replacement_room'];
|
||||||
|
|
|
@ -35,6 +35,8 @@ import InviteReason from "../elements/InviteReason";
|
||||||
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
||||||
import Spinner from "../elements/Spinner";
|
import Spinner from "../elements/Spinner";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
import { UIFeature } from "../../../settings/UIFeature";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
|
||||||
const MemberEventHtmlReasonField = "io.element.html_reason";
|
const MemberEventHtmlReasonField = "io.element.html_reason";
|
||||||
|
|
||||||
|
@ -339,8 +341,10 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
case MessageCase.NotLoggedIn: {
|
case MessageCase.NotLoggedIn: {
|
||||||
title = _t("Join the conversation with an account");
|
title = _t("Join the conversation with an account");
|
||||||
primaryActionLabel = _t("Sign Up");
|
if (SettingsStore.getValue(UIFeature.Registration)) {
|
||||||
primaryActionHandler = this.onRegisterClick;
|
primaryActionLabel = _t("Sign Up");
|
||||||
|
primaryActionHandler = this.onRegisterClick;
|
||||||
|
}
|
||||||
secondaryActionLabel = _t("Sign In");
|
secondaryActionLabel = _t("Sign In");
|
||||||
secondaryActionHandler = this.onLoginClick;
|
secondaryActionHandler = this.onLoginClick;
|
||||||
if (this.props.previewLoading) {
|
if (this.props.previewLoading) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import EMOJI_REGEX from 'emojibase-regex';
|
||||||
import { IContent, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
import { IContent, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||||
import { DebouncedFunc, throttle } from 'lodash';
|
import { DebouncedFunc, throttle } from 'lodash';
|
||||||
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
|
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import EditorModel from '../../../editor/model';
|
import EditorModel from '../../../editor/model';
|
||||||
|
@ -40,7 +41,7 @@ import { Command, CommandCategories, getCommand } from '../../../SlashCommands';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import { _t, _td } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
import ContentMessages from '../../../ContentMessages';
|
import ContentMessages from '../../../ContentMessages';
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import { withMatrixClientHOC, MatrixClientProps } from "../../../contexts/MatrixClientContext";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import { containsEmoji } from "../../../effects/utils";
|
import { containsEmoji } from "../../../effects/utils";
|
||||||
import { CHAT_EFFECTS } from '../../../effects';
|
import { CHAT_EFFECTS } from '../../../effects';
|
||||||
|
@ -55,8 +56,7 @@ import ErrorDialog from "../dialogs/ErrorDialog";
|
||||||
import QuestionDialog from "../dialogs/QuestionDialog";
|
import QuestionDialog from "../dialogs/QuestionDialog";
|
||||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
import { decorateStartSendingTime, sendRoundTripMetric } from "../../../sendTimePerformanceMetrics";
|
import { decorateStartSendingTime, sendRoundTripMetric } from "../../../sendTimePerformanceMetrics";
|
||||||
|
import RoomContext from '../../../contexts/RoomContext';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
|
||||||
|
|
||||||
function addReplyToMessageContent(
|
function addReplyToMessageContent(
|
||||||
content: IContent,
|
content: IContent,
|
||||||
|
@ -130,7 +130,7 @@ export function isQuickReaction(model: EditorModel): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface ISendMessageComposerProps extends MatrixClientProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
permalinkCreator: RoomPermalinkCreator;
|
permalinkCreator: RoomPermalinkCreator;
|
||||||
|
@ -141,10 +141,8 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.rooms.SendMessageComposer")
|
@replaceableComponent("views.rooms.SendMessageComposer")
|
||||||
export default class SendMessageComposer extends React.Component<IProps> {
|
export class SendMessageComposer extends React.Component<ISendMessageComposerProps> {
|
||||||
static contextType = MatrixClientContext;
|
static contextType = RoomContext;
|
||||||
context!: React.ContextType<typeof MatrixClientContext>;
|
|
||||||
|
|
||||||
private readonly prepareToEncrypt?: DebouncedFunc<() => void>;
|
private readonly prepareToEncrypt?: DebouncedFunc<() => void>;
|
||||||
private readonly editorRef = createRef<BasicMessageComposer>();
|
private readonly editorRef = createRef<BasicMessageComposer>();
|
||||||
private model: EditorModel = null;
|
private model: EditorModel = null;
|
||||||
|
@ -152,26 +150,25 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private sendHistoryManager: SendHistoryManager;
|
private sendHistoryManager: SendHistoryManager;
|
||||||
|
|
||||||
constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
|
constructor(props: ISendMessageComposerProps, context: React.ContextType<typeof RoomContext>) {
|
||||||
super(props);
|
super(props);
|
||||||
this.context = context; // otherwise React will only set it prior to render due to type def above
|
if (this.props.mxClient.isCryptoEnabled() && this.props.mxClient.isRoomEncrypted(this.props.room.roomId)) {
|
||||||
if (this.context.isCryptoEnabled() && this.context.isRoomEncrypted(this.props.room.roomId)) {
|
|
||||||
this.prepareToEncrypt = throttle(() => {
|
this.prepareToEncrypt = throttle(() => {
|
||||||
this.context.prepareToEncrypt(this.props.room);
|
this.props.mxClient.prepareToEncrypt(this.props.room);
|
||||||
}, 60000, { leading: true, trailing: false });
|
}, 60000, { leading: true, trailing: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("beforeunload", this.saveStoredEditorState);
|
window.addEventListener("beforeunload", this.saveStoredEditorState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: IProps): void {
|
public componentDidUpdate(prevProps: ISendMessageComposerProps): void {
|
||||||
const replyToEventChanged = this.props.replyInThread && (this.props.replyToEvent !== prevProps.replyToEvent);
|
const replyToEventChanged = this.props.replyInThread && (this.props.replyToEvent !== prevProps.replyToEvent);
|
||||||
if (replyToEventChanged) {
|
if (replyToEventChanged) {
|
||||||
this.model.reset([]);
|
this.model.reset([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.replyInThread && this.props.replyToEvent && (!prevProps.replyToEvent || replyToEventChanged)) {
|
if (this.props.replyInThread && this.props.replyToEvent && (!prevProps.replyToEvent || replyToEventChanged)) {
|
||||||
const partCreator = new CommandPartCreator(this.props.room, this.context);
|
const partCreator = new CommandPartCreator(this.props.room, this.props.mxClient);
|
||||||
const parts = this.restoreStoredEditorState(partCreator) || [];
|
const parts = this.restoreStoredEditorState(partCreator) || [];
|
||||||
this.model.reset(parts);
|
this.model.reset(parts);
|
||||||
this.editorRef.current?.focus();
|
this.editorRef.current?.focus();
|
||||||
|
@ -202,13 +199,20 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
case MessageComposerAction.EditPrevMessage:
|
case MessageComposerAction.EditPrevMessage:
|
||||||
// selection must be collapsed and caret at start
|
// selection must be collapsed and caret at start
|
||||||
if (this.editorRef.current?.isSelectionCollapsed() && this.editorRef.current?.isCaretAtStart()) {
|
if (this.editorRef.current?.isSelectionCollapsed() && this.editorRef.current?.isCaretAtStart()) {
|
||||||
const editEvent = findEditableEvent(this.props.room, false);
|
const events =
|
||||||
|
this.context.liveTimeline.getEvents()
|
||||||
|
.concat(this.props.replyInThread ? [] : this.props.room.getPendingEvents());
|
||||||
|
const editEvent = findEditableEvent({
|
||||||
|
events,
|
||||||
|
isForward: false,
|
||||||
|
});
|
||||||
if (editEvent) {
|
if (editEvent) {
|
||||||
// We're selecting history, so prevent the key event from doing anything else
|
// We're selecting history, so prevent the key event from doing anything else
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'edit_event',
|
action: Action.EditEvent,
|
||||||
event: editEvent,
|
event: editEvent,
|
||||||
|
timelineRenderingType: this.context.timelineRenderingType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,7 +279,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendQuickReaction(): void {
|
private sendQuickReaction(): void {
|
||||||
const timeline = this.props.room.getLiveTimeline();
|
const timeline = this.context.liveTimeline();
|
||||||
const events = timeline.getEvents();
|
const events = timeline.getEvents();
|
||||||
const reaction = this.model.parts[1].text;
|
const reaction = this.model.parts[1].text;
|
||||||
for (let i = events.length - 1; i >= 0; i--) {
|
for (let i = events.length - 1; i >= 0; i--) {
|
||||||
|
@ -448,7 +452,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
decorateStartSendingTime(content);
|
decorateStartSendingTime(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const prom = this.context.sendMessage(roomId, content);
|
const prom = this.props.mxClient.sendMessage(roomId, content);
|
||||||
if (replyToEvent) {
|
if (replyToEvent) {
|
||||||
// Clear reply_to_event as we put the message into the queue
|
// Clear reply_to_event as we put the message into the queue
|
||||||
// if the send fails, retry will handle resending.
|
// if the send fails, retry will handle resending.
|
||||||
|
@ -465,7 +469,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
});
|
});
|
||||||
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
|
if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
|
||||||
prom.then(resp => {
|
prom.then(resp => {
|
||||||
sendRoundTripMetric(this.context, roomId, resp.event_id);
|
sendRoundTripMetric(this.props.mxClient, roomId, resp.event_id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, !!replyToEvent, content);
|
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, !!replyToEvent, content);
|
||||||
|
@ -490,7 +494,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
|
|
||||||
// TODO: [REACT-WARNING] Move this to constructor
|
// TODO: [REACT-WARNING] Move this to constructor
|
||||||
UNSAFE_componentWillMount() { // eslint-disable-line
|
UNSAFE_componentWillMount() { // eslint-disable-line
|
||||||
const partCreator = new CommandPartCreator(this.props.room, this.context);
|
const partCreator = new CommandPartCreator(this.props.room, this.props.mxClient);
|
||||||
const parts = this.restoreStoredEditorState(partCreator) || [];
|
const parts = this.restoreStoredEditorState(partCreator) || [];
|
||||||
this.model = new EditorModel(parts, partCreator);
|
this.model = new EditorModel(parts, partCreator);
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
@ -577,7 +581,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
// it puts the filename in as text/plain which we want to ignore.
|
// it puts the filename in as text/plain which we want to ignore.
|
||||||
if (clipboardData.files.length && !clipboardData.types.includes("text/rtf")) {
|
if (clipboardData.files.length && !clipboardData.types.includes("text/rtf")) {
|
||||||
ContentMessages.sharedInstance().sendContentListToRoom(
|
ContentMessages.sharedInstance().sendContentListToRoom(
|
||||||
Array.from(clipboardData.files), this.props.room.roomId, this.context,
|
Array.from(clipboardData.files), this.props.room.roomId, this.props.mxClient,
|
||||||
);
|
);
|
||||||
return true; // to skip internal onPaste handler
|
return true; // to skip internal onPaste handler
|
||||||
}
|
}
|
||||||
|
@ -608,3 +612,6 @@ export default class SendMessageComposer extends React.Component<IProps> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SendMessageComposerWithMatrixClient = withMatrixClientHOC(SendMessageComposer);
|
||||||
|
export default SendMessageComposerWithMatrixClient;
|
||||||
|
|
|
@ -121,24 +121,24 @@ export default class VerificationShowSas extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
|
|
||||||
let confirm;
|
let confirm;
|
||||||
if (this.state.pending || this.state.cancelling) {
|
if (this.state.pending && this.props.isSelf) {
|
||||||
|
let text;
|
||||||
|
// device shouldn't be null in this situation but it can be, eg. if the device is
|
||||||
|
// logged out during verification
|
||||||
|
if (this.props.device) {
|
||||||
|
text = _t("Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…", {
|
||||||
|
deviceName: this.props.device ? this.props.device.getDisplayName() : '',
|
||||||
|
deviceId: this.props.device ? this.props.device.deviceId : '',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
text = _t("Waiting for you to verify on your other session…");
|
||||||
|
}
|
||||||
|
confirm = <p>{ text }</p>;
|
||||||
|
} else if (this.state.pending || this.state.cancelling) {
|
||||||
let text;
|
let text;
|
||||||
if (this.state.pending) {
|
if (this.state.pending) {
|
||||||
if (this.props.isSelf) {
|
const { displayName } = this.props;
|
||||||
// device shouldn't be null in this situation but it can be, eg. if the device is
|
text = _t("Waiting for %(displayName)s to verify…", { displayName });
|
||||||
// logged out during verification
|
|
||||||
if (this.props.device) {
|
|
||||||
text = _t("Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…", {
|
|
||||||
deviceName: this.props.device ? this.props.device.getDisplayName() : '',
|
|
||||||
deviceId: this.props.device ? this.props.device.deviceId : '',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
text = _t("Waiting for your other session to verify…");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const { displayName } = this.props;
|
|
||||||
text = _t("Waiting for %(displayName)s to verify…", { displayName });
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
text = _t("Cancelling…");
|
text = _t("Cancelling…");
|
||||||
}
|
}
|
||||||
|
|
46
src/contexts/MatrixClientContext.tsx
Normal file
46
src/contexts/MatrixClientContext.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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, { ComponentClass, createContext, forwardRef, useContext } from "react";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
|
||||||
|
const MatrixClientContext = createContext<MatrixClient>(undefined);
|
||||||
|
MatrixClientContext.displayName = "MatrixClientContext";
|
||||||
|
export default MatrixClientContext;
|
||||||
|
|
||||||
|
export interface MatrixClientProps {
|
||||||
|
mxClient: MatrixClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matrixHOC = <ComposedComponentProps extends {}>(
|
||||||
|
ComposedComponent: ComponentClass<ComposedComponentProps>,
|
||||||
|
) => {
|
||||||
|
type ComposedComponentInstance = InstanceType<typeof ComposedComponent>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
|
||||||
|
const TypedComponent = ComposedComponent;
|
||||||
|
|
||||||
|
return forwardRef<ComposedComponentInstance, Omit<ComposedComponentProps, 'mxClient'>>(
|
||||||
|
(props, ref) => {
|
||||||
|
const client = useContext(MatrixClientContext);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return <TypedComponent ref={ref} {...props} mxClient={client} />;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export const withMatrixClientHOC = matrixHOC;
|
|
@ -16,10 +16,15 @@ limitations under the License.
|
||||||
|
|
||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
|
|
||||||
import { IState } from "../components/structures/RoomView";
|
import { IRoomState } from "../components/structures/RoomView";
|
||||||
import { Layout } from "../settings/Layout";
|
import { Layout } from "../settings/Layout";
|
||||||
|
|
||||||
const RoomContext = createContext<IState>({
|
export enum TimelineRenderingType {
|
||||||
|
Room,
|
||||||
|
Thread
|
||||||
|
}
|
||||||
|
|
||||||
|
const RoomContext = createContext<IRoomState>({
|
||||||
roomLoading: true,
|
roomLoading: true,
|
||||||
peekLoading: false,
|
peekLoading: false,
|
||||||
shouldPeek: true,
|
shouldPeek: true,
|
||||||
|
@ -53,6 +58,8 @@ const RoomContext = createContext<IState>({
|
||||||
showDisplaynameChanges: true,
|
showDisplaynameChanges: true,
|
||||||
matrixClientIsReady: false,
|
matrixClientIsReady: false,
|
||||||
dragCounter: 0,
|
dragCounter: 0,
|
||||||
|
timelineRenderingType: TimelineRenderingType.Room,
|
||||||
|
liveTimeline: undefined,
|
||||||
});
|
});
|
||||||
RoomContext.displayName = "RoomContext";
|
RoomContext.displayName = "RoomContext";
|
||||||
export default RoomContext;
|
export default RoomContext;
|
||||||
|
|
|
@ -128,7 +128,7 @@ export enum Action {
|
||||||
* Start a call transfer to a phone number
|
* Start a call transfer to a phone number
|
||||||
* payload: TransferCallPayload
|
* payload: TransferCallPayload
|
||||||
*/
|
*/
|
||||||
TransferCallToPhoneNumber = "transfer_call_to_phone_number",
|
TransferCallToPhoneNumber = "transfer_call_to_phone_number",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when CallHandler has checked for PSTN protocol support
|
* Fired when CallHandler has checked for PSTN protocol support
|
||||||
|
@ -205,4 +205,9 @@ export enum Action {
|
||||||
* Should be used with SettingUpdatedPayload.
|
* Should be used with SettingUpdatedPayload.
|
||||||
*/
|
*/
|
||||||
SettingUpdated = "setting_updated",
|
SettingUpdated = "setting_updated",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires when a user starts to edit event (e.g. up arrow in compositor)
|
||||||
|
*/
|
||||||
|
EditEvent = "edit_event",
|
||||||
}
|
}
|
||||||
|
|
|
@ -2901,7 +2901,7 @@
|
||||||
"e.g. my-space": "např. můj-prostor",
|
"e.g. my-space": "např. můj-prostor",
|
||||||
"Silence call": "Ztlumit zvonění",
|
"Silence call": "Ztlumit zvonění",
|
||||||
"Sound on": "Zvuk zapnutý",
|
"Sound on": "Zvuk zapnutý",
|
||||||
"Show all rooms in Home": "Zobrazit všechny místnosti na domácí obrazovce",
|
"Show all rooms in Home": "Zobrazit všechny místnosti na úvodní obrazovce",
|
||||||
"Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Prototyp Nahlášování moderátorům. V místnostech, které podporují moderování, vám tlačítko `nahlásit` umožní nahlásit zneužití moderátorům místnosti",
|
"Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Prototyp Nahlášování moderátorům. V místnostech, které podporují moderování, vám tlačítko `nahlásit` umožní nahlásit zneužití moderátorům místnosti",
|
||||||
"%(senderName)s changed the <a>pinned messages</a> for the room.": "%(senderName)s změnil(a) <a>připnuté zprávy</a> v místnosti.",
|
"%(senderName)s changed the <a>pinned messages</a> for the room.": "%(senderName)s změnil(a) <a>připnuté zprávy</a> v místnosti.",
|
||||||
"%(senderName)s kicked %(targetName)s": "%(senderName)s vykopl(a) uživatele %(targetName)s",
|
"%(senderName)s kicked %(targetName)s": "%(senderName)s vykopl(a) uživatele %(targetName)s",
|
||||||
|
@ -3056,7 +3056,7 @@
|
||||||
"Want to add a new space instead?": "Chcete místo toho přidat nový prostor?",
|
"Want to add a new space instead?": "Chcete místo toho přidat nový prostor?",
|
||||||
"Decrypting": "Dešifrování",
|
"Decrypting": "Dešifrování",
|
||||||
"Show all rooms": "Zobrazit všechny místnosti",
|
"Show all rooms": "Zobrazit všechny místnosti",
|
||||||
"All rooms you're in will appear in Home.": "Všechny místnosti, ve kterých se nacházíte, se zobrazí na domovské obrazovce.",
|
"All rooms you're in will appear in Home.": "Všechny místnosti, ve kterých se nacházíte, se zobrazí na úvodní obrazovce.",
|
||||||
"Send pseudonymous analytics data": "Odeslat pseudonymní analytická data",
|
"Send pseudonymous analytics data": "Odeslat pseudonymní analytická data",
|
||||||
"Missed call": "Zmeškaný hovor",
|
"Missed call": "Zmeškaný hovor",
|
||||||
"Call declined": "Hovor odmítnut",
|
"Call declined": "Hovor odmítnut",
|
||||||
|
@ -3158,9 +3158,51 @@
|
||||||
"This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Tato místnost se nachází v některých prostorech, jejichž nejste správcem. V těchto prostorech bude stará místnost stále zobrazena, ale lidé budou vyzváni, aby se připojili k nové místnosti.",
|
"This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Tato místnost se nachází v některých prostorech, jejichž nejste správcem. V těchto prostorech bude stará místnost stále zobrazena, ale lidé budou vyzváni, aby se připojili k nové místnosti.",
|
||||||
"Before you upgrade": "Než provedete aktualizaci",
|
"Before you upgrade": "Než provedete aktualizaci",
|
||||||
"To join a space you'll need an invite.": "Pro připojení k prostoru potřebujete pozvánku.",
|
"To join a space you'll need an invite.": "Pro připojení k prostoru potřebujete pozvánku.",
|
||||||
"You can also make Spaces from <a>communities</a>.": "Můžete také vytvořit prostory ze <a>skupin</a>.",
|
"You can also make Spaces from <a>communities</a>.": "Prostory můžete vytvořit také ze <a>skupin</a>.",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Dočasně zobrazit skupiny místo prostorů pro tuto relaci. Podpora bude v blízké budoucnosti odstraněna. Toto provede přenačtení Elementu.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Dočasně zobrazit skupiny místo prostorů pro tuto relaci. Podpora bude v blízké budoucnosti odstraněna. Toto provede přenačtení Elementu.",
|
||||||
"Display Communities instead of Spaces": "Zobrazit skupiny místo prostorů",
|
"Display Communities instead of Spaces": "Zobrazit skupiny místo prostorů",
|
||||||
"Joining space …": "Připojování k prostoru…",
|
"Joining space …": "Připojování k prostoru…",
|
||||||
"%(reactors)s reacted with %(content)s": "%(reactors)s reagoval(a) na %(content)s"
|
"%(reactors)s reacted with %(content)s": "%(reactors)s reagoval(a) na %(content)s",
|
||||||
|
"Would you like to leave the rooms in this space?": "Chcete odejít z místností v tomto prostoru?",
|
||||||
|
"You are about to leave <spaceName/>.": "Odcházíte z <spaceName/>.",
|
||||||
|
"Leave some rooms": "Odejít z některých místností",
|
||||||
|
"Don't leave any rooms": "Neodcházet z žádné místnosti",
|
||||||
|
"Leave all rooms": "Odejít ze všech místností",
|
||||||
|
"Expand quotes │ ⇧+click": "Rozbalit uvozovky │ ⇧+kliknutí",
|
||||||
|
"Collapse quotes │ ⇧+click": "Sbalit uvozovky │ ⇧+kliknutí",
|
||||||
|
"Include Attachments": "Zahrnout přílohy",
|
||||||
|
"Size Limit": "Omezení velikosti",
|
||||||
|
"Format": "Formát",
|
||||||
|
"Select from the options below to export chats from your timeline": "Vyberte jednu z níže uvedených možností pro export chatů z časové osy",
|
||||||
|
"Export Chat": "Exportovat chat",
|
||||||
|
"Exporting your data": "Exportování dat",
|
||||||
|
"Stop": "Zastavit",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Opravdu chcete ukončit export dat? Pokud ano, budete muset začít znovu.",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "Váš export proběhl úspěšně. Najdete jej ve složce pro stažené soubory.",
|
||||||
|
"The export was cancelled successfully": "Export byl úspěšně zrušen",
|
||||||
|
"Export Successful": "Export proběhl úspěšně",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "Počet zpráv",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "Počet zpráv může být pouze číslo mezi %(min)s a %(max)s",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "Velikost může být pouze číslo mezi %(min)s MB a %(max)s MB",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "Zadejte číslo mezi %(min)s a %(max)s",
|
||||||
|
"In reply to <a>this message</a>": "V odpovědi na <a>tuto zprávu</a>",
|
||||||
|
"Export chat": "Exportovat chat",
|
||||||
|
"File Attached": "Přiložený soubor",
|
||||||
|
"Error fetching file": "Chyba při načítání souboru",
|
||||||
|
"Topic: %(topic)s": "Téma: %(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "Toto je začátek exportu <roomName/>. Exportováno pomocí <exporterDetails/> v %(exportDate)s.",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s vytvořil(a) tuto místnost.",
|
||||||
|
"Media omitted - file size limit exceeded": "Vynechaná média - překročen limit velikosti souboru",
|
||||||
|
"Media omitted": "Vynechaná média",
|
||||||
|
"Current Timeline": "Aktuální časová osa",
|
||||||
|
"Specify a number of messages": "Zadejte počet zpráv",
|
||||||
|
"From the beginning": "Od začátku",
|
||||||
|
"Plain Text": "Prostý text",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "Opravdu chcete skončit během tohoto exportu?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s poslal(a) nálepku.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s změnil(a) avatar místnosti.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s v %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3134,5 +3134,26 @@
|
||||||
"Joining space …": "Space beitreten…",
|
"Joining space …": "Space beitreten…",
|
||||||
"To join a space you'll need an invite.": "Um einem Space beizutreten brauchst du eine Einladung.",
|
"To join a space you'll need an invite.": "Um einem Space beizutreten brauchst du eine Einladung.",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "In dieser Sitzung temporär Communities statt Spaces anzeigen. Unterstützung hierfür wird in naher Zukunft entfernt. Dies wird Element neu laden.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "In dieser Sitzung temporär Communities statt Spaces anzeigen. Unterstützung hierfür wird in naher Zukunft entfernt. Dies wird Element neu laden.",
|
||||||
"Display Communities instead of Spaces": "Communities statt Spaces anzeigen"
|
"Display Communities instead of Spaces": "Communities statt Spaces anzeigen",
|
||||||
|
"To join this Space, hide communities in your <a>preferences</a>": "<a>Deaktiviere Communities in den Einstellungen</a>, um diesen Space beizutreten.",
|
||||||
|
"To view this Space, hide communities in your <a>preferences</a>": "<a>Deaktiviere Communities in den Einstellungen</a>, um diesen Space anzuzeigen.",
|
||||||
|
"To join %(communityName)s, swap to communities in your <a>preferences</a>": "Um %(communityName)s beizutreten, <a>aktiviere Communities in den Einstellungen</a>",
|
||||||
|
"To view %(communityName)s, swap to communities in your <a>preferences</a>": "Um %(communityName)s anzuzeigen, <a>aktiviere Communities in den Einstellungen</a>",
|
||||||
|
"Private community": "Private Community",
|
||||||
|
"Public community": "Öffentliche Community",
|
||||||
|
"You are about to leave <spaceName/>.": "Du bist dabei, <spaceName/> zu verlassen.",
|
||||||
|
"Leave some rooms": "Zu verlassende Räume auswählen",
|
||||||
|
"Leave all rooms": "Alle Räume verlassen",
|
||||||
|
"Don't leave any rooms": "Räume nicht verlassen",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s hat mit %(content)s reagiert",
|
||||||
|
"Some encryption parameters have been changed.": "Einige Verschlüsselungsoptionen wurden geändert.",
|
||||||
|
"Message": "Nachricht",
|
||||||
|
"Message didn't send. Click for info.": "Nachricht nicht gesendet. Klicke für Details.",
|
||||||
|
"To avoid these issues, create a <a>new public room</a> for the conversation you plan to have.": "<a>Erstelle einen neuen Raum für deine Konversation</a>, um diese Probleme zu umgehen.",
|
||||||
|
"<b>It's not recommended to make encrypted rooms public.</b> It will mean anyone can find and join the room, so anyone can read messages. You'll get none of the benefits of encryption. Encrypting messages in a public room will make receiving and sending messages slower.": "<b>Es ist nicht sinnvoll, verschlüsselte Räume öffentlich zu machen.</b> Da jeder den Raum betreten kann, kann auch jeder Nachrichten lesen, was die Verschlüsselung sinnlos macht. Außerdem wird das Senden und Empfangen von Nachrichten langsamer werden.",
|
||||||
|
"Select the roles required to change various parts of the space": "Wähle, von wem folgende Aktionen ausgeführt werden können",
|
||||||
|
"Upgrade anyway": "Trotzdem upgraden",
|
||||||
|
"This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Dieser Raum ist in einigen Spaces, in denen du nicht Admin bist. Daher wird dort noch der alte Raum angezeigt, die Leute werden aber auf den neuen Raum hingewiesen.",
|
||||||
|
"Before you upgrade": "Bevor du upgradest",
|
||||||
|
"You can also make Spaces from <a>communities</a>.": "Du kannst Spaces auch aus <a>Communities</a> erstellen."
|
||||||
}
|
}
|
||||||
|
|
|
@ -947,8 +947,8 @@
|
||||||
"Verify this session by confirming the following number appears on its screen.": "Verify this session by confirming the following number appears on its screen.",
|
"Verify this session by confirming the following number appears on its screen.": "Verify this session by confirming the following number appears on its screen.",
|
||||||
"Verify this user by confirming the following number appears on their screen.": "Verify this user by confirming the following number appears on their screen.",
|
"Verify this user by confirming the following number appears on their screen.": "Verify this user by confirming the following number appears on their screen.",
|
||||||
"Unable to find a supported verification method.": "Unable to find a supported verification method.",
|
"Unable to find a supported verification method.": "Unable to find a supported verification method.",
|
||||||
"Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…",
|
"Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…": "Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…",
|
||||||
"Waiting for your other session to verify…": "Waiting for your other session to verify…",
|
"Waiting for you to verify on your other session…": "Waiting for you to verify on your other session…",
|
||||||
"Waiting for %(displayName)s to verify…": "Waiting for %(displayName)s to verify…",
|
"Waiting for %(displayName)s to verify…": "Waiting for %(displayName)s to verify…",
|
||||||
"Cancelling…": "Cancelling…",
|
"Cancelling…": "Cancelling…",
|
||||||
"They match": "They match",
|
"They match": "They match",
|
||||||
|
@ -1803,7 +1803,7 @@
|
||||||
"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.": "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.",
|
"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.": "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.",
|
||||||
"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.": "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.",
|
"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.": "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.",
|
||||||
"Back": "Back",
|
"Back": "Back",
|
||||||
"Accept on your other login…": "Accept on your other login…",
|
"To proceed, please accept the verification request on your other login.": "To proceed, please accept the verification request on your other login.",
|
||||||
"Waiting for %(displayName)s to accept…": "Waiting for %(displayName)s to accept…",
|
"Waiting for %(displayName)s to accept…": "Waiting for %(displayName)s to accept…",
|
||||||
"Accepting…": "Accepting…",
|
"Accepting…": "Accepting…",
|
||||||
"Start Verification": "Start Verification",
|
"Start Verification": "Start Verification",
|
||||||
|
@ -2280,6 +2280,8 @@
|
||||||
"<SpaceName/> has been made and everyone who was a part of the community has been invited to it.": "<SpaceName/> has been made and everyone who was a part of the community has been invited to it.",
|
"<SpaceName/> has been made and everyone who was a part of the community has been invited to it.": "<SpaceName/> has been made and everyone who was a part of the community has been invited to it.",
|
||||||
"To create a Space from another community, just pick the community in Preferences.": "To create a Space from another community, just pick the community in Preferences.",
|
"To create a Space from another community, just pick the community in Preferences.": "To create a Space from another community, just pick the community in Preferences.",
|
||||||
"Failed to migrate community": "Failed to migrate community",
|
"Failed to migrate community": "Failed to migrate community",
|
||||||
|
"Fetching data...": "Fetching data...",
|
||||||
|
"Creating Space...": "Creating Space...",
|
||||||
"Create Space from community": "Create Space from community",
|
"Create Space from community": "Create Space from community",
|
||||||
"A link to the Space will be put in your community description.": "A link to the Space will be put in your community description.",
|
"A link to the Space will be put in your community description.": "A link to the Space will be put in your community description.",
|
||||||
"All rooms will be added and all community members will be invited.": "All rooms will be added and all community members will be invited.",
|
"All rooms will be added and all community members will be invited.": "All rooms will be added and all community members will be invited.",
|
||||||
|
@ -2982,8 +2984,11 @@
|
||||||
"Could not load user profile": "Could not load user profile",
|
"Could not load user profile": "Could not load user profile",
|
||||||
"Decrypted event source": "Decrypted event source",
|
"Decrypted event source": "Decrypted event source",
|
||||||
"Original event source": "Original event source",
|
"Original event source": "Original event source",
|
||||||
|
"Unable to verify this login": "Unable to verify this login",
|
||||||
"Verify this login": "Verify this login",
|
"Verify this login": "Verify this login",
|
||||||
"Session verified": "Session verified",
|
"Session verified": "Session verified",
|
||||||
|
"Really reset verification keys?": "Really reset verification keys?",
|
||||||
|
"Skip verification for now": "Skip verification for now",
|
||||||
"Failed to send email": "Failed to send email",
|
"Failed to send email": "Failed to send email",
|
||||||
"The email address linked to your account must be entered.": "The email address linked to your account must be entered.",
|
"The email address linked to your account must be entered.": "The email address linked to your account must be entered.",
|
||||||
"A new password must be entered.": "A new password must be entered.",
|
"A new password must be entered.": "A new password must be entered.",
|
||||||
|
@ -3037,13 +3042,18 @@
|
||||||
"Create account": "Create account",
|
"Create account": "Create account",
|
||||||
"Host account on": "Host account on",
|
"Host account on": "Host account on",
|
||||||
"Decide where your account is hosted": "Decide where your account is hosted",
|
"Decide where your account is hosted": "Decide where your account is hosted",
|
||||||
"Use Security Key or Phrase": "Use Security Key or Phrase",
|
"It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.": "It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.",
|
||||||
"Use Security Key": "Use Security Key",
|
"Proceed with reset": "Proceed with reset",
|
||||||
"Use another login": "Use another login",
|
"Verify with Security Key or Phrase": "Verify with Security Key or Phrase",
|
||||||
|
"Verify with Security Key": "Verify with Security Key",
|
||||||
|
"Verify with another login": "Verify with another login",
|
||||||
"Verify your identity to access encrypted messages and prove your identity to others.": "Verify your identity to access encrypted messages and prove your identity to others.",
|
"Verify your identity to access encrypted messages and prove your identity to others.": "Verify your identity to access encrypted messages and prove your identity to others.",
|
||||||
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.",
|
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.",
|
||||||
"Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.",
|
"Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.",
|
||||||
"Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.",
|
"Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.",
|
||||||
|
"I'll verify later": "I'll verify later",
|
||||||
|
"Resetting your verification keys cannot be undone. After resetting, you won't have access to old encrypted messages, and any friends who have previously verified you will see security warnings until you re-verify with them.": "Resetting your verification keys cannot be undone. After resetting, you won't have access to old encrypted messages, and any friends who have previously verified you will see security warnings until you re-verify with them.",
|
||||||
|
"Please only proceed if you're sure you've lost all of your other devices and your security key.": "Please only proceed if you're sure you've lost all of your other devices and your security key.",
|
||||||
"Failed to re-authenticate due to a homeserver problem": "Failed to re-authenticate due to a homeserver problem",
|
"Failed to re-authenticate due to a homeserver problem": "Failed to re-authenticate due to a homeserver problem",
|
||||||
"Incorrect password": "Incorrect password",
|
"Incorrect password": "Incorrect password",
|
||||||
"Failed to re-authenticate": "Failed to re-authenticate",
|
"Failed to re-authenticate": "Failed to re-authenticate",
|
||||||
|
|
|
@ -3099,5 +3099,62 @@
|
||||||
"What kind of Space do you want to create?": "Kian aron volas vi krei?",
|
"What kind of Space do you want to create?": "Kian aron volas vi krei?",
|
||||||
"All rooms you're in will appear in Home.": "Ĉiuj ĉambroj, kie vi estas, aperos en la ĉefpaĝo.",
|
"All rooms you're in will appear in Home.": "Ĉiuj ĉambroj, kie vi estas, aperos en la ĉefpaĝo.",
|
||||||
"Show all rooms in Home": "Montri ĉiujn ĉambrojn en ĉefpaĝo",
|
"Show all rooms in Home": "Montri ĉiujn ĉambrojn en ĉefpaĝo",
|
||||||
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s fiksis <a>mesaĝon</a> al ĉi tiu ĉambro. Vidu ĉiujn <b>fiksitajn mesaĝojn</b>."
|
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s fiksis <a>mesaĝon</a> al ĉi tiu ĉambro. Vidu ĉiujn <b>fiksitajn mesaĝojn</b>.",
|
||||||
|
"To avoid these issues, create a <a>new encrypted room</a> for the conversation you plan to have.": "Por eviti tiujn problemojn, kreu <a>novan ĉifritan ĉambron</a> por la planata interparolo.",
|
||||||
|
"<b>It's not recommended to add encryption to public rooms.</b>Anyone can find and join public rooms, so anyone can read messages in them. You'll get none of the benefits of encryption, and you won't be able to turn it off later. Encrypting messages in a public room will make receiving and sending messages slower.": "<b>Ne rekomendate estas aldoni ĉifradon al publikaj ĉambroj.</b> Ĉiu ajn povas trovi publikajn ĉambrojn kaj aliĝi, do ĉiu ajn povas legi ties mesaĝojn. Vi havos neniujn avantaĝojn de ĉifrado, kaj vi ne povos ĝin malŝalti pli poste. Ĉifrado en publikaj ĉambroj malrapidigos ricevadon kaj sendadon de mesaĝoj.",
|
||||||
|
"Are you sure you want to add encryption to this public room?": "Ĉu vi certas, ke vi volas aldoni ĉifradon al ĉi tiu publika ĉambro?",
|
||||||
|
"Select the roles required to change various parts of the space": "Elekti rolojn bezonatajn por ŝanĝado de diversaj partoj de la aro",
|
||||||
|
"Change description": "Ŝanĝi priskribon",
|
||||||
|
"Change main address for the space": "Ŝanĝi ĉefadreson de aro",
|
||||||
|
"Change space name": "Ŝanĝi nomon de aro",
|
||||||
|
"Change space avatar": "Ŝanĝi bildon de aro",
|
||||||
|
"Upgrade anyway": "Tamen gradaltigi",
|
||||||
|
"This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Ĉi tiu ĉambro estas en iuj aroj, kiujn vi ne administras. En tiuj aroj, la malnova ĉambro aperos, sed tie oni ricevos avizon aliĝi al la nova.",
|
||||||
|
"Before you upgrade": "Antaŭ ol vi gradaltigos",
|
||||||
|
"Anyone in <spaceName/> can find and join. You can select other spaces too.": "Ĉiu en <spaceName/> povas trovi kaj aliĝi. Vi povas elekti ankaŭ aliajn arojn.",
|
||||||
|
"Currently, %(count)s spaces have access|one": "Nun, aro povas aliri",
|
||||||
|
"& %(count)s more|one": "kaj %(count)s pli",
|
||||||
|
"To join a space you'll need an invite.": "Por aliĝi al aro, vi bezonas inviton.",
|
||||||
|
"You can also make Spaces from <a>communities</a>.": "Vi ankaŭ povas krei Arojn el <a>komunumoj</a>.",
|
||||||
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Provizore montri komunumojn anstataŭ arojn por tiu ĉi salutaĵo. Subteno de tio ĉi baldaŭ malaperos. Ĉi tio re-enlegos Elementon.",
|
||||||
|
"Display Communities instead of Spaces": "Montri komunumojn anstataŭ arojn",
|
||||||
|
"Autoplay videos": "Memage ludi filmojn",
|
||||||
|
"Autoplay GIFs": "Memage ludi GIF-ojn",
|
||||||
|
"Multiple integration managers (requires manual setup)": "Pluraj kunigiloj (bezonas permanan agordon)",
|
||||||
|
"Threaded messaging": "Mesaĝaj fadenoj",
|
||||||
|
"%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s malfiksis mesaĝon de ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.",
|
||||||
|
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s malfiksis <a>mesaĝon</a> de ĉi tiu ĉambro. Vidu ĉiujn <b>fiksitajn mesaĝojn</b>.",
|
||||||
|
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.",
|
||||||
|
"To join this Space, hide communities in your <a>preferences</a>": "Por aliĝi al ĉi tiu aro, kaŝu komunumojn per viaj <a>agordoj</a>",
|
||||||
|
"To view this Space, hide communities in your <a>preferences</a>": "Por vidi ĉi tiun aron, kaŝu komunumojn per viaj <a>agordoj</a>",
|
||||||
|
"Rooms and spaces": "Ĉambroj kaj aroj",
|
||||||
|
"Results": "Rezultoj",
|
||||||
|
"To join %(communityName)s, swap to communities in your <a>preferences</a>": "Por aliĝi al %(communityName)s, ŝaltu komunumojn en viaj <a>agordoj</a>",
|
||||||
|
"To view %(communityName)s, swap to communities in your <a>preferences</a>": "Por vidi komunumon %(communityName)s, ŝaltu komunumojn en viaj <a>agordoj</a>",
|
||||||
|
"Private community": "Privata komunumo",
|
||||||
|
"Public community": "Publika komunumo",
|
||||||
|
"Forward": "Plusendi",
|
||||||
|
"Would you like to leave the rooms in this space?": "Ĉu vi volus foriri de la ĉambroj en ĉi tiu aro?",
|
||||||
|
"You are about to leave <spaceName/>.": "Vi foriros de <spaceName/>.",
|
||||||
|
"Leave some rooms": "Foriri de iuj ĉambroj",
|
||||||
|
"Leave all rooms": "Foriri de ĉiuj ĉambroj",
|
||||||
|
"Don't leave any rooms": "Foriru de neniuj ĉambroj",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s reagis per %(content)s",
|
||||||
|
"Thread": "Fadeno",
|
||||||
|
"Some encryption parameters have been changed.": "Ŝanĝiĝis iuj parametroj de ĉifrado.",
|
||||||
|
"Role in <RoomName/>": "Rolo en <RoomName/>",
|
||||||
|
"Message": "Mesaĝo",
|
||||||
|
"Show threads": "Montri fadenojn",
|
||||||
|
"Joining space …": "Aliĝante al aro…",
|
||||||
|
"Explore %(spaceName)s": "Esplori aron %(spaceName)s",
|
||||||
|
"Message didn't send. Click for info.": "Mesaĝo ne sendiĝis. Klaku por akiri informojn.",
|
||||||
|
"Send a sticker": "Sendi glumarkon",
|
||||||
|
"Reply to thread…": "Respondi al fadeno…",
|
||||||
|
"Reply to encrypted thread…": "Respondi al ĉifrita fadeno…",
|
||||||
|
"Add emoji": "Aldoni bildosignon",
|
||||||
|
"To avoid these issues, create a <a>new public room</a> for the conversation you plan to have.": "Por eviti ĉi tiujn problemojn, kreu <a>novan publikan ĉambron</a> por la dezirata interparolo.",
|
||||||
|
"<b>It's not recommended to make encrypted rooms public.</b> It will mean anyone can find and join the room, so anyone can read messages. You'll get none of the benefits of encryption. Encrypting messages in a public room will make receiving and sending messages slower.": "<b>Publikigo de ĉifrataj ĉambroj estas malrekomendata.</b> Ĝi implicas, ke ĉiu povos trovi la ĉambron kaj aliĝi al ĝi, kaj ĉiu do povos legi mesaĝojn. Vi havos neniujn avantaĝojn de ĉifrado. Ĉifrado de mesaĝoj en publika ĉambro malrapidigos iliajn ricevadon kaj sendadon.",
|
||||||
|
"Are you sure you want to make this encrypted room public?": "Ĉu vi certas, ke vi volas publikigi ĉi tiun ĉifratan ĉambron?",
|
||||||
|
"Unknown failure": "Nekonata malsukceso",
|
||||||
|
"Failed to update the join rules": "Malsukcesis ĝisdatigi regulojn pri aliĝo"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2705,7 +2705,7 @@
|
||||||
"Invite by username": "Kutsu kasutajanime alusel",
|
"Invite by username": "Kutsu kasutajanime alusel",
|
||||||
"What projects are you working on?": "Mis ettevõtmistega sa tegeled?",
|
"What projects are you working on?": "Mis ettevõtmistega sa tegeled?",
|
||||||
"Decrypted event source": "Sündmuse dekrüptitud lähtekood",
|
"Decrypted event source": "Sündmuse dekrüptitud lähtekood",
|
||||||
"Original event source": "Algse sündmuse lähtekood",
|
"Original event source": "Sündmuse töötlemata lähtekood",
|
||||||
"Failed to remove some rooms. Try again later": "Mõnede jututubade eemaldamine ei õnnestunud. Proovi hiljem uuesti",
|
"Failed to remove some rooms. Try again later": "Mõnede jututubade eemaldamine ei õnnestunud. Proovi hiljem uuesti",
|
||||||
"Removing...": "Eemaldan...",
|
"Removing...": "Eemaldan...",
|
||||||
"Mark as not suggested": "Eemalda soovitus",
|
"Mark as not suggested": "Eemalda soovitus",
|
||||||
|
@ -3158,5 +3158,47 @@
|
||||||
"Before you upgrade": "Enne uuendamist",
|
"Before you upgrade": "Enne uuendamist",
|
||||||
"To join a space you'll need an invite.": "Kogukonnakeskusega liitumiseks vajad kutset.",
|
"To join a space you'll need an invite.": "Kogukonnakeskusega liitumiseks vajad kutset.",
|
||||||
"%(reactors)s reacted with %(content)s": "%(reactors)s kasutajat reageeris järgnevalt: %(content)s",
|
"%(reactors)s reacted with %(content)s": "%(reactors)s kasutajat reageeris järgnevalt: %(content)s",
|
||||||
"Joining space …": "Liitun kohukonnakeskusega…"
|
"Joining space …": "Liitun kohukonnakeskusega…",
|
||||||
|
"Would you like to leave the rooms in this space?": "Kas sa soovid lahkuda ka selle kogukonna jututubadest?",
|
||||||
|
"You are about to leave <spaceName/>.": "Sa oled lahkumas <spaceName/> kogukonnast.",
|
||||||
|
"Leave some rooms": "Lahku mõnedest jututubadest",
|
||||||
|
"Leave all rooms": "Lahku kõikidest jututubadest",
|
||||||
|
"Don't leave any rooms": "Ära lahku ühestki jututoast",
|
||||||
|
"Expand quotes │ ⇧+click": "Näita tsitaate │ ⇧+click",
|
||||||
|
"Collapse quotes │ ⇧+click": "Ahenda tsitaadid │ ⇧+click",
|
||||||
|
"Media omitted": "Osa meediat jäi eksportimata",
|
||||||
|
"Media omitted - file size limit exceeded": "Osa meediat jäi vahele failisuuruse piirangu tõttu",
|
||||||
|
"Include Attachments": "Kaasa manused",
|
||||||
|
"Size Limit": "Andmemahu piir",
|
||||||
|
"Format": "Vorming",
|
||||||
|
"Select from the options below to export chats from your timeline": "Kui soovid oma ajajoonelt mõnda vestlust eksportida, siis vali tingimused alljärgnevalt",
|
||||||
|
"Export Chat": "Ekspordi vestlus",
|
||||||
|
"Exporting your data": "Ekspordin sinu andmeid",
|
||||||
|
"Stop": "Peata",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Kas sa oled kindel, et soovid oma andmete eksporti katkestada? Kui nii toimid, siis pead hiljem uuesti alustama.",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "Sinu andmete eksport õnnestus. Faili leiad tavapärasest allalaadimiste kaustast.",
|
||||||
|
"The export was cancelled successfully": "Ekspordi tühistamine õnnestus",
|
||||||
|
"Export Successful": "Eksport õnnestus",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "Sõnumite arv",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "Sõnumite arv saab olla ainult number%(min)s ja %(max)s vahemikust",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "Suurus saab olla number %(min)s MB ja %(max)s MB vahemikust",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "Sisesta number %(min)s ja %(max)s vahemikust",
|
||||||
|
"In reply to <a>this message</a>": "Vastuseks <a>sellele sõnumile</a>",
|
||||||
|
"Export chat": "Ekspordi vestlus",
|
||||||
|
"File Attached": "Fail on manustatud",
|
||||||
|
"Error fetching file": "Viga faili laadimisel",
|
||||||
|
"Topic: %(topic)s": "Teema: %(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "See on <roomName/> jututoast eksporditud andmekogu. Viited: <exporterDetails/>, %(exportDate)s.",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s lõi selle jututoa.",
|
||||||
|
"Current Timeline": "Praegune ajajoon",
|
||||||
|
"Specify a number of messages": "Määra sõnumite arv",
|
||||||
|
"From the beginning": "Algusest alates",
|
||||||
|
"Plain Text": "Vormindamata tekst",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "Kas sa oled kindel, et soovid lõpetada tegevuse selle ekspordi ajal?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s saatis kleepsu.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s muutis jututoa tunnuspilti.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3162,5 +3162,12 @@
|
||||||
"To join a space you'll need an invite.": "Vous avez besoin d’une invitation pour rejoindre un espace.",
|
"To join a space you'll need an invite.": "Vous avez besoin d’une invitation pour rejoindre un espace.",
|
||||||
"You can also make Spaces from <a>communities</a>.": "Vous pouvez également créer des espaces à partir de <a>communautés</a>.",
|
"You can also make Spaces from <a>communities</a>.": "Vous pouvez également créer des espaces à partir de <a>communautés</a>.",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Montre temporairement les communautés au lieu des espaces pour cette session. Il ne sera plus possible de le faire dans un futur proche. Cela va recharger Element.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Montre temporairement les communautés au lieu des espaces pour cette session. Il ne sera plus possible de le faire dans un futur proche. Cela va recharger Element.",
|
||||||
"Display Communities instead of Spaces": "Afficher les communautés au lieu des espaces"
|
"Display Communities instead of Spaces": "Afficher les communautés au lieu des espaces",
|
||||||
|
"Would you like to leave the rooms in this space?": "Voulez-vous quitter les salons de cet espace ?",
|
||||||
|
"You are about to leave <spaceName/>.": "Vous êtes sur le point de quitter <spaceName/>.",
|
||||||
|
"Leave some rooms": "Quitter certains salons",
|
||||||
|
"Leave all rooms": "Quitter tous les salons",
|
||||||
|
"Don't leave any rooms": "Ne quitter aucun salon",
|
||||||
|
"Expand quotes │ ⇧+click": "Développer les citations │ ⇧+clic",
|
||||||
|
"Collapse quotes │ ⇧+click": "Réduire les citations │ ⇧+clic"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3157,5 +3157,14 @@
|
||||||
"To join a space you'll need an invite.": "Para unirte a un espazo precisas un convite.",
|
"To join a space you'll need an invite.": "Para unirte a un espazo precisas un convite.",
|
||||||
"You can also make Spaces from <a>communities</a>.": "Tamén podes crear Espazos a partir de <a>comunidades</a>.",
|
"You can also make Spaces from <a>communities</a>.": "Tamén podes crear Espazos a partir de <a>comunidades</a>.",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "De xeito temporal, mostrar comunidades no lugar de Espazos durante esta sesión. Esta función vai ser eliminada en próximas versións. Reiniciará Element.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "De xeito temporal, mostrar comunidades no lugar de Espazos durante esta sesión. Esta función vai ser eliminada en próximas versións. Reiniciará Element.",
|
||||||
"Display Communities instead of Spaces": "Mostrar Comunidades no lugar de Espazos"
|
"Display Communities instead of Spaces": "Mostrar Comunidades no lugar de Espazos",
|
||||||
|
"Would you like to leave the rooms in this space?": "Queres sair destas salas neste espazo?",
|
||||||
|
"You are about to leave <spaceName/>.": "Vas saír de <spaceName/>.",
|
||||||
|
"Leave some rooms": "Sair de algunhas salas",
|
||||||
|
"Leave all rooms": "Sair de tódalas salas",
|
||||||
|
"Don't leave any rooms": "Non saír de ningunha sala",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s reaccionou con %(content)s",
|
||||||
|
"Joining space …": "Uníndote ao espazo…",
|
||||||
|
"Expand quotes │ ⇧+click": "Despregar citas | ⇧+click",
|
||||||
|
"Collapse quotes │ ⇧+click": "Pechar citas | ⇧+click"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3164,5 +3164,35 @@
|
||||||
"You are about to leave <spaceName/>.": "Éppen el akarja hagyni <spaceName/> teret.",
|
"You are about to leave <spaceName/>.": "Éppen el akarja hagyni <spaceName/> teret.",
|
||||||
"Leave some rooms": "Kilépés néhány szobából",
|
"Leave some rooms": "Kilépés néhány szobából",
|
||||||
"Leave all rooms": "Kilépés minden szobából",
|
"Leave all rooms": "Kilépés minden szobából",
|
||||||
"Don't leave any rooms": "Ne lépjen ki egy szobából sem"
|
"Don't leave any rooms": "Ne lépjen ki egy szobából sem",
|
||||||
|
"Expand quotes │ ⇧+click": "Idézetek megnyitása │ ⇧+kattintás",
|
||||||
|
"Collapse quotes │ ⇧+click": "Idézetek bezárása│ ⇧+kattintás",
|
||||||
|
"Include Attachments": "Csatolmányokkal együtt",
|
||||||
|
"Size Limit": "Méret korlát",
|
||||||
|
"Format": "Formátum",
|
||||||
|
"Export Chat": "Beszélgetés kimentése",
|
||||||
|
"Exporting your data": "Adatai kimentése",
|
||||||
|
"Stop": "Állj",
|
||||||
|
"The export was cancelled successfully": "Az exportálás sikeresen félbeszakítva",
|
||||||
|
"Export Successful": "Exportálás sikeres",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "Üzenetek száma",
|
||||||
|
"In reply to <a>this message</a>": "Válasz erre az <a>üzenetre</a>",
|
||||||
|
"Export chat": "Beszélgetés kimentése",
|
||||||
|
"File Attached": "Fájl csatolva",
|
||||||
|
"Error fetching file": "Fájl letöltés hiba",
|
||||||
|
"Topic: %(topic)s": "Téma: %(topic)s",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s hozta létre ezt a szobát.",
|
||||||
|
"Media omitted - file size limit exceeded": "Média fájl kihagyva - fájl méret korlát túllépés",
|
||||||
|
"Media omitted": "Média nélkül",
|
||||||
|
"Current Timeline": "Aktuális idővonal",
|
||||||
|
"Specify a number of messages": "Üzenetek számának megadása",
|
||||||
|
"From the beginning": "Az elejétől",
|
||||||
|
"Plain Text": "Sima szöveg",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "Biztos, hogy kilép az exportálás közben?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s matricát küldött.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s megváltoztatta a szoba avatar képét.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@
|
||||||
"The version of %(brand)s": "Versi %(brand)s",
|
"The version of %(brand)s": "Versi %(brand)s",
|
||||||
"Your language of choice": "Pilihan bahasamu",
|
"Your language of choice": "Pilihan bahasamu",
|
||||||
"Your homeserver's URL": "URL Homeserver Anda",
|
"Your homeserver's URL": "URL Homeserver Anda",
|
||||||
"e.g. %(exampleValue)s": "",
|
"e.g. %(exampleValue)s": "mis. %(exampleValue)s",
|
||||||
"Every page you use in the app": "Setiap halaman yang digunakan di app",
|
"Every page you use in the app": "Setiap halaman yang digunakan di app",
|
||||||
"e.g. <CurrentPageURL>": "e.g. <URLHalamanSaatIni>",
|
"e.g. <CurrentPageURL>": "e.g. <URLHalamanSaatIni>",
|
||||||
"Your device resolution": "Resolusi perangkat Anda",
|
"Your device resolution": "Resolusi perangkat Anda",
|
||||||
|
@ -214,5 +214,5 @@
|
||||||
"Explore rooms": "Jelajahi ruang",
|
"Explore rooms": "Jelajahi ruang",
|
||||||
"Sign In": "Masuk",
|
"Sign In": "Masuk",
|
||||||
"Create Account": "Buat Akun",
|
"Create Account": "Buat Akun",
|
||||||
"Identity server": "Server Identitas"
|
"Identity server": "Server identitas"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1218,14 +1218,14 @@
|
||||||
"Do not use an identity server": "Non usare un server di identità",
|
"Do not use an identity server": "Non usare un server di identità",
|
||||||
"You do not have the required permissions to use this command.": "Non hai l'autorizzazione necessaria per usare questo comando.",
|
"You do not have the required permissions to use this command.": "Non hai l'autorizzazione necessaria per usare questo comando.",
|
||||||
"Use an identity server": "Usa un server di identità",
|
"Use an identity server": "Usa un server di identità",
|
||||||
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server di identità per invitare via email. Clicca \"Continua\" per usare quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.",
|
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server d'identità per invitare via email. Clicca \"Continua\" per usare quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.",
|
||||||
"Use an identity server to invite by email. Manage in Settings.": "Usa un server di identità per invitare via email. Gestisci nelle impostazioni.",
|
"Use an identity server to invite by email. Manage in Settings.": "Usa un server di identità per invitare via email. Gestisci nelle impostazioni.",
|
||||||
"Upgrade the room": "Aggiorna la stanza",
|
"Upgrade the room": "Aggiorna la stanza",
|
||||||
"Enable room encryption": "Attiva la crittografia della stanza",
|
"Enable room encryption": "Attiva la crittografia della stanza",
|
||||||
"Deactivate user?": "Disattivare l'utente?",
|
"Deactivate user?": "Disattivare l'utente?",
|
||||||
"Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Disattivare questo utente lo disconnetterà e ne impedirà nuovi accessi. In aggiunta, abbandonerà tutte le stanze in cui è presente. Questa azione non può essere annullata. Sei sicuro di volere disattivare questo utente?",
|
"Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Disattivare questo utente lo disconnetterà e ne impedirà nuovi accessi. In aggiunta, abbandonerà tutte le stanze in cui è presente. Questa azione non può essere annullata. Sei sicuro di volere disattivare questo utente?",
|
||||||
"Deactivate user": "Disattiva utente",
|
"Deactivate user": "Disattiva utente",
|
||||||
"Use an identity server to invite by email. <default>Use the default (%(defaultIdentityServerName)s)</default> or manage in <settings>Settings</settings>.": "Usa un server di identità per invitare via email. <default>Usa quello predefinito (%(defaultIdentityServerName)s)</default> o gestiscilo nelle <settings>impostazioni</settings>.",
|
"Use an identity server to invite by email. <default>Use the default (%(defaultIdentityServerName)s)</default> or manage in <settings>Settings</settings>.": "Usa un server d'identità per invitare via email. <default>Usa quello predefinito (%(defaultIdentityServerName)s)</default> o gestiscilo nelle <settings>impostazioni</settings>.",
|
||||||
"Use an identity server to invite by email. Manage in <settings>Settings</settings>.": "Usa un server di identità per invitare via email. Gestisci nelle <settings>impostazioni</settings>.",
|
"Use an identity server to invite by email. Manage in <settings>Settings</settings>.": "Usa un server di identità per invitare via email. Gestisci nelle <settings>impostazioni</settings>.",
|
||||||
"Sends a message as plain text, without interpreting it as markdown": "Invia un messaggio in testo semplice, senza interpretarlo come markdown",
|
"Sends a message as plain text, without interpreting it as markdown": "Invia un messaggio in testo semplice, senza interpretarlo come markdown",
|
||||||
"Error changing power level": "Errore cambiando il livello di poteri",
|
"Error changing power level": "Errore cambiando il livello di poteri",
|
||||||
|
@ -1236,11 +1236,11 @@
|
||||||
"This invite to %(roomName)s was sent to %(email)s": "Questo invito per %(roomName)s è stato inviato a %(email)s",
|
"This invite to %(roomName)s was sent to %(email)s": "Questo invito per %(roomName)s è stato inviato a %(email)s",
|
||||||
"Use an identity server in Settings to receive invites directly in %(brand)s.": "Usa un server di identià nelle impostazioni per ricevere inviti direttamente in %(brand)s.",
|
"Use an identity server in Settings to receive invites directly in %(brand)s.": "Usa un server di identià nelle impostazioni per ricevere inviti direttamente in %(brand)s.",
|
||||||
"Share this email in Settings to receive invites directly in %(brand)s.": "Condividi questa email nelle impostazioni per ricevere inviti direttamente in %(brand)s.",
|
"Share this email in Settings to receive invites directly in %(brand)s.": "Condividi questa email nelle impostazioni per ricevere inviti direttamente in %(brand)s.",
|
||||||
"Change identity server": "Cambia Identity Server",
|
"Change identity server": "Cambia server d'identità",
|
||||||
"Disconnect from the identity server <current /> and connect to <new /> instead?": "Disconnettersi dall'Identity Server <current /> e connettesi invece a <new />?",
|
"Disconnect from the identity server <current /> and connect to <new /> instead?": "Disconnettersi dal server d'identità <current /> e connettesi invece a <new />?",
|
||||||
"Disconnect identity server": "Disconnetti dall'Identity Server",
|
"Disconnect identity server": "Disconnetti dal server d'identità",
|
||||||
"You are still <b>sharing your personal data</b> on the identity server <idserver />.": "Stai ancora <b> fornendo le tue informazioni personali </b> sull'Identity Server <idserver />.",
|
"You are still <b>sharing your personal data</b> on the identity server <idserver />.": "Stai ancora <b> fornendo le tue informazioni personali </b> sul server d'identità <idserver />.",
|
||||||
"We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Ti suggeriamo di rimuovere il tuo indirizzo email e numero di telefono dall'Identity Server prima di disconnetterti.",
|
"We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Ti suggeriamo di rimuovere il tuo indirizzo email e numero di telefono dal server d'identità prima di disconnetterti.",
|
||||||
"Disconnect anyway": "Disconnetti comunque",
|
"Disconnect anyway": "Disconnetti comunque",
|
||||||
"Error changing power level requirement": "Errore nella modifica del livello dei permessi",
|
"Error changing power level requirement": "Errore nella modifica del livello dei permessi",
|
||||||
"An error occurred changing the room's power level requirements. Ensure you have sufficient permissions and try again.": "C'é stato un errore nel cambio di libelli dei permessi. Assicurati di avere i permessi necessari e riprova.",
|
"An error occurred changing the room's power level requirements. Ensure you have sufficient permissions and try again.": "C'é stato un errore nel cambio di libelli dei permessi. Assicurati di avere i permessi necessari e riprova.",
|
||||||
|
@ -3161,5 +3161,12 @@
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Mostra temporaneamente le comunità invece degli spazi per questa sessione. Il supporto per questa azione verrà rimosso nel breve termine. Element verrà ricaricato.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Mostra temporaneamente le comunità invece degli spazi per questa sessione. Il supporto per questa azione verrà rimosso nel breve termine. Element verrà ricaricato.",
|
||||||
"Display Communities instead of Spaces": "Mostra le comunità invece degli spazi",
|
"Display Communities instead of Spaces": "Mostra le comunità invece degli spazi",
|
||||||
"%(reactors)s reacted with %(content)s": "%(reactors)s ha reagito con %(content)s",
|
"%(reactors)s reacted with %(content)s": "%(reactors)s ha reagito con %(content)s",
|
||||||
"Joining space …": "Ingresso nello spazio …"
|
"Joining space …": "Ingresso nello spazio …",
|
||||||
|
"Would you like to leave the rooms in this space?": "Vuoi uscire dalle stanze di questo spazio?",
|
||||||
|
"You are about to leave <spaceName/>.": "Stai per uscire da <spaceName/>.",
|
||||||
|
"Leave some rooms": "Esci da alcune stanze",
|
||||||
|
"Leave all rooms": "Esci da tutte le stanze",
|
||||||
|
"Don't leave any rooms": "Non uscire da alcuna stanza",
|
||||||
|
"Expand quotes │ ⇧+click": "Espandi le menzioni │ ⇧+clic",
|
||||||
|
"Collapse quotes │ ⇧+click": "Riduci le menzioni │ ⇧+clic"
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@
|
||||||
"This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "이 과정으로 암호화한 방에서 받은 메시지의 키를 로컬 파일로 내보낼 수 있습니다. 그런 다음 나중에 다른 Matrix 클라이언트에서 파일을 가져와서, 해당 클라이언트에서도 이 메시지를 복호화할 수 있도록 할 수 있습니다.",
|
"This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "이 과정으로 암호화한 방에서 받은 메시지의 키를 로컬 파일로 내보낼 수 있습니다. 그런 다음 나중에 다른 Matrix 클라이언트에서 파일을 가져와서, 해당 클라이언트에서도 이 메시지를 복호화할 수 있도록 할 수 있습니다.",
|
||||||
"The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "내보낸 파일이 있으면 누구든 암호화한 메시지를 복호화해서 읽을 수 있으므로, 보안에 신경을 써야 합니다. 이런 이유로 내보낸 파일을 암호화하도록 아래에 암호를 입력하는 것을 추천합니다. 같은 암호를 사용해야 데이터를 불러올 수 있을 것입니다.",
|
"The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "내보낸 파일이 있으면 누구든 암호화한 메시지를 복호화해서 읽을 수 있으므로, 보안에 신경을 써야 합니다. 이런 이유로 내보낸 파일을 암호화하도록 아래에 암호를 입력하는 것을 추천합니다. 같은 암호를 사용해야 데이터를 불러올 수 있을 것입니다.",
|
||||||
"This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "이 과정으로 다른 Matrix 클라이언트에서 내보낸 암호화 키를 가져올 수 있습니다. 그런 다음 이전 클라이언트에서 복호화할 수 있는 모든 메시지를 복호화할 수 있습니다.",
|
"This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "이 과정으로 다른 Matrix 클라이언트에서 내보낸 암호화 키를 가져올 수 있습니다. 그런 다음 이전 클라이언트에서 복호화할 수 있는 모든 메시지를 복호화할 수 있습니다.",
|
||||||
"The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "내보낸 파일이 암호로 보호되어 있습니다. 파일을 복호화하려면, 여기에 암호를 입력해야 합니다.",
|
"The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "내보낸 파일이 암호로 보호되어 있습니다. 파일을 복호화하려면, 여기에 암호를 입력해야 합니다.",
|
||||||
"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.": "이 이벤트를 감추길(삭제하길) 원하세요? 방 이름을 삭제하거나 주제를 바꾸면, 다시 생길 수도 있습니다.",
|
"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.": "이 이벤트를 감추길(삭제하길) 원하세요? 방 이름을 삭제하거나 주제를 바꾸면, 다시 생길 수도 있습니다.",
|
||||||
"Unable to restore session": "세션을 복구할 수 없음",
|
"Unable to restore session": "세션을 복구할 수 없음",
|
||||||
"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.": "이전에 최근 버전의 %(brand)s을 썼다면, 세션이 이 버전과 맞지 않을 것입니다. 창을 닫고 최근 버전으로 돌아가세요.",
|
"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.": "이전에 최근 버전의 %(brand)s을 썼다면, 세션이 이 버전과 맞지 않을 것입니다. 창을 닫고 최근 버전으로 돌아가세요.",
|
||||||
|
@ -840,7 +840,7 @@
|
||||||
"There was an error joining the room": "방에 참가하는 동안 오류가 발생했습니다",
|
"There was an error joining the room": "방에 참가하는 동안 오류가 발생했습니다",
|
||||||
"Sorry, your homeserver is too old to participate in this room.": "죄송합니다, 이 방에 참여하기엔 홈서버가 너무 오래됬습니다.",
|
"Sorry, your homeserver is too old to participate in this room.": "죄송합니다, 이 방에 참여하기엔 홈서버가 너무 오래됬습니다.",
|
||||||
"Custom user status messages": "맞춤 사용자 상태 메시지",
|
"Custom user status messages": "맞춤 사용자 상태 메시지",
|
||||||
"Group & filter rooms by custom tags (refresh to apply changes)": "맞춤 태그로 방을 그룹 & 필터\n(변경 사항을 적용하려면 새로고침)",
|
"Group & filter rooms by custom tags (refresh to apply changes)": "맞춤 태그로 방을 그룹 & 필터 (변경 사항을 적용하려면 새로고침)",
|
||||||
"You do not have the required permissions to use this command.": "이 명령어를 사용하기 위해 필요한 권한이 없습니다.",
|
"You do not have the required permissions to use this command.": "이 명령어를 사용하기 위해 필요한 권한이 없습니다.",
|
||||||
"Render simple counters in room header": "방 헤더에 간단한 카운터 표현",
|
"Render simple counters in room header": "방 헤더에 간단한 카운터 표현",
|
||||||
"Enable Emoji suggestions while typing": "입력 중 이모지 제안 켜기",
|
"Enable Emoji suggestions while typing": "입력 중 이모지 제안 켜기",
|
||||||
|
@ -1414,10 +1414,13 @@
|
||||||
"Create Account": "계정 만들기",
|
"Create Account": "계정 만들기",
|
||||||
"Integration manager": "통합 관리자",
|
"Integration manager": "통합 관리자",
|
||||||
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your integration manager.": "이 위젯을 사용하면 <helpcon /> %(widgetDomain)s & 통합 관리자와 데이터를 공유합니다.",
|
"Using this widget may share data <helpIcon /> with %(widgetDomain)s & your integration manager.": "이 위젯을 사용하면 <helpcon /> %(widgetDomain)s & 통합 관리자와 데이터를 공유합니다.",
|
||||||
"Identity server is": "ID 서버:",
|
"Identity server is": "ID 서버는",
|
||||||
"Identity server": "ID 서버",
|
"Identity server": "ID 서버",
|
||||||
"Identity server (%(server)s)": "ID 서버 (%(server)s)",
|
"Identity server (%(server)s)": "ID 서버 (%(server)s)",
|
||||||
"Could not connect to identity server": "ID 서버에 연결할 수 없음",
|
"Could not connect to identity server": "ID 서버에 연결할 수 없음",
|
||||||
"Not a valid identity server (status code %(code)s)": "올바르지 않은 ID 서버 (상태 코드 %(code)s)",
|
"Not a valid identity server (status code %(code)s)": "올바르지 않은 ID 서버 (상태 코드 %(code)s)",
|
||||||
"Identity server URL must be HTTPS": "ID 서버 URL은 HTTPS이어야 함"
|
"Identity server URL must be HTTPS": "ID 서버 URL은 HTTPS이어야 함",
|
||||||
|
"Appearance": "모습",
|
||||||
|
"Appearance Settings only affect this %(brand)s session.": "모습 설정은 이 %(brand)s 세션에만 영향을 끼칩니다.",
|
||||||
|
"Customise your appearance": "모습 개인화하기"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"Microphone": "Mikrofons",
|
"Microphone": "Mikrofons",
|
||||||
"Camera": "Kamera",
|
"Camera": "Kamera",
|
||||||
"Advanced": "Papildu",
|
"Advanced": "Papildu",
|
||||||
"Always show message timestamps": "Vienmēr rādīt ziņojumu laika zīmogu",
|
"Always show message timestamps": "Vienmēr rādīt ziņas laika zīmogu",
|
||||||
"Authentication": "Autentifikācija",
|
"Authentication": "Autentifikācija",
|
||||||
"%(items)s and %(lastItem)s": "%(items)s un %(lastItem)s",
|
"%(items)s and %(lastItem)s": "%(items)s un %(lastItem)s",
|
||||||
"A new password must be entered.": "Nepieciešams ievadīt jauno paroli.",
|
"A new password must be entered.": "Nepieciešams ievadīt jauno paroli.",
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
"Are you sure you want to reject the invitation?": "Vai tiešām vēlaties noraidīt šo uzaicinājumu?",
|
"Are you sure you want to reject the invitation?": "Vai tiešām vēlaties noraidīt šo uzaicinājumu?",
|
||||||
"Attachment": "Pielikums",
|
"Attachment": "Pielikums",
|
||||||
"Ban": "Liegt pieeju",
|
"Ban": "Liegt pieeju",
|
||||||
"Banned users": "Lietotāji, kuriem liegta pieeju",
|
"Banned users": "Lietotāji, kuriem liegta pieeja",
|
||||||
"Bans user with given id": "Liedz pieeju lietotājam ar norādīto id",
|
"Bans user with given id": "Liedz pieeju lietotājam ar norādīto 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.": "Neizdodas savienoties ar bāzes serveri. Pārbaudi tīkla savienojumu un pārliecinies, ka <a> bāzes servera SSL sertifikāts</a> ir uzticams, kā arī pārlūkā instalētie paplašinājumi nebloķē pieprasījumus.",
|
"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.": "Neizdodas savienoties ar bāzes serveri. Pārbaudi tīkla savienojumu un pārliecinies, ka <a> bāzes servera SSL sertifikāts</a> ir uzticams, kā arī pārlūkā instalētie paplašinājumi nebloķē pieprasījumus.",
|
||||||
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Neizdodas savienoties ar bāzes serveri izmantojot HTTP protokolu, kad pārlūka adreses laukā norādīts HTTPS protokols. Tā vietā izmanto HTTPS vai <a>iespējo nedrošos skriptus</a>.",
|
"Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or <a>enable unsafe scripts</a>.": "Neizdodas savienoties ar bāzes serveri izmantojot HTTP protokolu, kad pārlūka adreses laukā norādīts HTTPS protokols. Tā vietā izmanto HTTPS vai <a>iespējo nedrošos skriptus</a>.",
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s nomainīja istabas nosaukumu uz %(roomName)s.",
|
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s nomainīja istabas nosaukumu uz %(roomName)s.",
|
||||||
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s dzēsa istabas nosaukumu.",
|
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s dzēsa istabas nosaukumu.",
|
||||||
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s nomainīja istabas tematu uz \"%(topic)s\".",
|
"%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s nomainīja istabas tematu uz \"%(topic)s\".",
|
||||||
"Changes your display nickname": "Nomaina jūsu parādāmo vārdu",
|
"Changes your display nickname": "Maina jūsu parādāmo vārdu",
|
||||||
"Close": "Aizvērt",
|
"Close": "Aizvērt",
|
||||||
"Command error": "Komandas kļūda",
|
"Command error": "Komandas kļūda",
|
||||||
"Commands": "Komandas",
|
"Commands": "Komandas",
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
"Decrypt %(text)s": "Atšifrēt %(text)s",
|
"Decrypt %(text)s": "Atšifrēt %(text)s",
|
||||||
"Deops user with given id": "Atceļ operatora statusu lietotājam ar norādīto Id",
|
"Deops user with given id": "Atceļ operatora statusu lietotājam ar norādīto Id",
|
||||||
"Default": "Noklusējuma",
|
"Default": "Noklusējuma",
|
||||||
"Disinvite": "Atsaukt",
|
"Disinvite": "Atsaukt uzaicinājumu",
|
||||||
"Displays action": "Parāda darbību",
|
"Displays action": "Parāda darbību",
|
||||||
"Download %(text)s": "Lejupielādēt: %(text)s",
|
"Download %(text)s": "Lejupielādēt: %(text)s",
|
||||||
"Email": "Epasts",
|
"Email": "Epasts",
|
||||||
|
@ -75,12 +75,12 @@
|
||||||
"Failed to set display name": "Neizdevās iestatīt parādāmo vārdu",
|
"Failed to set display name": "Neizdevās iestatīt parādāmo vārdu",
|
||||||
"Failed to unban": "Neizdevās atbanot/atbloķēt (atcelt pieejas liegumu)",
|
"Failed to unban": "Neizdevās atbanot/atbloķēt (atcelt pieejas liegumu)",
|
||||||
"Failed to upload profile picture!": "Neizdevās augšupielādēt profila attēlu!",
|
"Failed to upload profile picture!": "Neizdevās augšupielādēt profila attēlu!",
|
||||||
"Failed to verify email address: make sure you clicked the link in the email": "Neizdevās apstiprināt epasta adresi. Pārbaudi, vai Tu esi noklikšķinājis/usi saiti epasta ziņā",
|
"Failed to verify email address: make sure you clicked the link in the email": "Neizdevās apstiprināt epasta adresi. Pārbaudi, vai esat noklikšķinājis/usi saiti epasta ziņā",
|
||||||
"Failure to create room": "Neizdevās izveidot istabu",
|
"Failure to create room": "Neizdevās izveidot istabu",
|
||||||
"Favourite": "Izlase",
|
"Favourite": "Izlase",
|
||||||
"Favourites": "Izlase",
|
"Favourites": "Izlase",
|
||||||
"Filter room members": "Filtrēt istabas biedrus",
|
"Filter room members": "Atfiltrēt istabas dalībniekus",
|
||||||
"Forget room": "\"Aizmirst\" istabu",
|
"Forget room": "Aizmirst istabu",
|
||||||
"For security, this session has been signed out. Please sign in again.": "Drošības nolūkos šī sesija ir pārtraukta. Lūdzu, pieraksties par jaunu.",
|
"For security, this session has been signed out. Please sign in again.": "Drošības nolūkos šī sesija ir pārtraukta. Lūdzu, pieraksties par jaunu.",
|
||||||
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s no %(fromPowerLevel)s uz %(toPowerLevel)s",
|
"%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s no %(fromPowerLevel)s uz %(toPowerLevel)s",
|
||||||
"Hangup": "Beigt zvanu",
|
"Hangup": "Beigt zvanu",
|
||||||
|
@ -107,9 +107,9 @@
|
||||||
"Leave room": "Pamest istabu",
|
"Leave room": "Pamest istabu",
|
||||||
"Logout": "Izrakstīties",
|
"Logout": "Izrakstīties",
|
||||||
"Low priority": "Zema prioritāte",
|
"Low priority": "Zema prioritāte",
|
||||||
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem no brīža, kad tie tika uzaicināti.",
|
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem no brīža, kad tie tika uzaicināti.",
|
||||||
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem ar brīdi, kad tie pievienojās.",
|
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem ar brīdi, kad tie pievienojās.",
|
||||||
"%(senderName)s made future room history visible to all room members.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem.",
|
"%(senderName)s made future room history visible to all room members.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem.",
|
||||||
"%(senderName)s made future room history visible to anyone.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu ikvienam.",
|
"%(senderName)s made future room history visible to anyone.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu ikvienam.",
|
||||||
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu nepazīstamajiem (%(visibility)s).",
|
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu nepazīstamajiem (%(visibility)s).",
|
||||||
"Missing room_id in request": "Iztrūkstošs room_id pieprasījumā",
|
"Missing room_id in request": "Iztrūkstošs room_id pieprasījumā",
|
||||||
|
@ -193,7 +193,7 @@
|
||||||
"This phone number is already in use": "Šis telefona numurs jau tiek izmantots",
|
"This phone number is already in use": "Šis telefona numurs jau tiek izmantots",
|
||||||
"This room": "Šajā istabā",
|
"This room": "Šajā istabā",
|
||||||
"This room is not accessible by remote Matrix servers": "Šī istaba nav pieejama no citiem Matrix serveriem",
|
"This room is not accessible by remote Matrix servers": "Šī istaba nav pieejama no citiem Matrix serveriem",
|
||||||
"Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Notika mēģinājums ielādēt šīs istabas specifisku laikpaziņojumu sadaļu, bet Tev nav atļaujas skatīt šo ziņu.",
|
"Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Notika mēģinājums specifisku posmu šīs istabas laika skalā, bet jums nav atļaujas skatīt konkrēto ziņu.",
|
||||||
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Mēģinājums ielādēt šīs istabas čata vēstures izvēlēto posmu neizdevās, jo tas netika atrasts.",
|
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Mēģinājums ielādēt šīs istabas čata vēstures izvēlēto posmu neizdevās, jo tas netika atrasts.",
|
||||||
"Unable to add email address": "Neizdevās pievienot epasta adresi",
|
"Unable to add email address": "Neizdevās pievienot epasta adresi",
|
||||||
"Unable to remove contact information": "Neizdevās dzēst kontaktinformāciju",
|
"Unable to remove contact information": "Neizdevās dzēst kontaktinformāciju",
|
||||||
|
@ -204,9 +204,9 @@
|
||||||
"Unnamed Room": "Istaba bez nosaukuma",
|
"Unnamed Room": "Istaba bez nosaukuma",
|
||||||
"Cancel": "Atcelt",
|
"Cancel": "Atcelt",
|
||||||
"Create new room": "Izveidot jaunu istabu",
|
"Create new room": "Izveidot jaunu istabu",
|
||||||
"Dismiss": "Aizvērt/atcelt",
|
"Dismiss": "Aizvērt",
|
||||||
"You have <a>enabled</a> URL previews by default.": "URL priekšskatījumi pēc noklusējuma jums ir<a>iespējoti</a> .",
|
"You have <a>enabled</a> URL previews by default.": "URL priekšskatījumi pēc noklusējuma jums ir<a>iespējoti</a> .",
|
||||||
"Upload avatar": "Augšupielādēt avataru (profila attēlu)",
|
"Upload avatar": "Augšupielādēt avataru",
|
||||||
"Upload Failed": "Augšupielāde (nosūtīšana) neizdevās",
|
"Upload Failed": "Augšupielāde (nosūtīšana) neizdevās",
|
||||||
"Upload file": "Augšupielādēt failu",
|
"Upload file": "Augšupielādēt failu",
|
||||||
"Upload new:": "Augšupielādēt jaunu:",
|
"Upload new:": "Augšupielādēt jaunu:",
|
||||||
|
@ -312,7 +312,7 @@
|
||||||
"Create": "Izveidot",
|
"Create": "Izveidot",
|
||||||
"Featured Rooms:": "Ieteiktās istabas:",
|
"Featured Rooms:": "Ieteiktās istabas:",
|
||||||
"Featured Users:": "Ieteiktie lietotāji:",
|
"Featured Users:": "Ieteiktie lietotāji:",
|
||||||
"Automatically replace plain text Emoji": "Automātiski aizvietot tekstu ar emocīšiem (emoji)",
|
"Automatically replace plain text Emoji": "Automātiski aizstāt vienkāršā teksta emocijzīmes",
|
||||||
"Failed to upload image": "Neizdevās augšupielādēt attēlu",
|
"Failed to upload image": "Neizdevās augšupielādēt attēlu",
|
||||||
"%(widgetName)s widget added by %(senderName)s": "%(senderName)s pievienoja %(widgetName)s vidžetu",
|
"%(widgetName)s widget added by %(senderName)s": "%(senderName)s pievienoja %(widgetName)s vidžetu",
|
||||||
"%(widgetName)s widget removed by %(senderName)s": "%(senderName)s dzēsa vidžetu %(widgetName)s",
|
"%(widgetName)s widget removed by %(senderName)s": "%(senderName)s dzēsa vidžetu %(widgetName)s",
|
||||||
|
@ -322,7 +322,7 @@
|
||||||
"Send": "Sūtīt",
|
"Send": "Sūtīt",
|
||||||
"Leave": "Pamest",
|
"Leave": "Pamest",
|
||||||
"Unnamed room": "Nenosaukta istaba",
|
"Unnamed room": "Nenosaukta istaba",
|
||||||
"Guests can join": "Var pievienoties viesi",
|
"Guests can join": "Viesi var pievienoties",
|
||||||
"The platform you're on": "Izmantotā operētājsistēma",
|
"The platform you're on": "Izmantotā operētājsistēma",
|
||||||
"The version of %(brand)s": "%(brand)s versija",
|
"The version of %(brand)s": "%(brand)s versija",
|
||||||
"Your language of choice": "Izvēlētā valoda",
|
"Your language of choice": "Izvēlētā valoda",
|
||||||
|
@ -335,10 +335,10 @@
|
||||||
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s",
|
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s",
|
||||||
"Who would you like to add to this community?": "Kurus cilvēkus Tu vēlētos pievienot šai kopienai?",
|
"Who would you like to add to this community?": "Kurus cilvēkus Tu vēlētos pievienot šai kopienai?",
|
||||||
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Brīdinājums: ikviens, kurš tiek pievienots kopienai būs publiski redzams visiem, kuri zin kopienas Id",
|
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Brīdinājums: ikviens, kurš tiek pievienots kopienai būs publiski redzams visiem, kuri zin kopienas Id",
|
||||||
"Invite new community members": "Uzaicināt jaunus kopienas biedrus",
|
"Invite new community members": "Uzaicināt jaunus kopienas dalībniekus",
|
||||||
"Invite to Community": "Uzaicināt kopienā",
|
"Invite to Community": "Uzaicināt kopienā",
|
||||||
"Which rooms would you like to add to this community?": "Kuras istabas vēlies pievienot šai kopienai?",
|
"Which rooms would you like to add to this community?": "Kuras istabas vēlies pievienot šai kopienai?",
|
||||||
"Show these rooms to non-members on the community page and room list?": "Vai ne-biedriem rādīt kopienas lapā un istabu sarakstā šīs istabas?",
|
"Show these rooms to non-members on the community page and room list?": "Vai rādīt šis istabas kopienas lapā un istabu sarakstā tiem, kas nav dalībnieki?",
|
||||||
"Add rooms to the community": "Pievienot istabas kopienai",
|
"Add rooms to the community": "Pievienot istabas kopienai",
|
||||||
"Add to community": "Pievienot kopienai",
|
"Add to community": "Pievienot kopienai",
|
||||||
"Failed to invite the following users to %(groupId)s:": "Neizdevās uzaicināt sekojošus lietotājus grupā %(groupId)s:",
|
"Failed to invite the following users to %(groupId)s:": "Neizdevās uzaicināt sekojošus lietotājus grupā %(groupId)s:",
|
||||||
|
@ -384,10 +384,10 @@
|
||||||
"World readable": "Pieejama ikvienam un no visurienes",
|
"World readable": "Pieejama ikvienam un no visurienes",
|
||||||
"Failed to remove tag %(tagName)s from room": "Neizdevās istabai noņemt birku %(tagName)s",
|
"Failed to remove tag %(tagName)s from room": "Neizdevās istabai noņemt birku %(tagName)s",
|
||||||
"Failed to add tag %(tagName)s to room": "Neizdevās istabai pievienot birku %(tagName)s",
|
"Failed to add tag %(tagName)s to room": "Neizdevās istabai pievienot birku %(tagName)s",
|
||||||
"Banned by %(displayName)s": "%(displayName)s liedzis piekļuvi",
|
"Banned by %(displayName)s": "%(displayName)s liedzis pieeju",
|
||||||
"Members only (since the point in time of selecting this option)": "Tikai biedri (no šī parametra iestatīšanas brīža)",
|
"Members only (since the point in time of selecting this option)": "Tikai dalībnieki (no šī parametra iestatīšanas brīža)",
|
||||||
"Members only (since they were invited)": "Tikai biedri (no to uzaicināšanas brīža)",
|
"Members only (since they were invited)": "Tikai dalībnieki (no to uzaicināšanas brīža)",
|
||||||
"Members only (since they joined)": "Tikai biedri (kopš pievienošanās)",
|
"Members only (since they joined)": "Tikai dalībnieki (kopš pievienošanās)",
|
||||||
"Invalid community ID": "Nederīgs kopienas Id",
|
"Invalid community ID": "Nederīgs kopienas Id",
|
||||||
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' nav derīgs kopienas Id",
|
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' nav derīgs kopienas Id",
|
||||||
"Flair": "Noskaņa",
|
"Flair": "Noskaņa",
|
||||||
|
@ -400,11 +400,11 @@
|
||||||
"Failed to copy": "Nokopēt neizdevās",
|
"Failed to copy": "Nokopēt neizdevās",
|
||||||
"A text message has been sent to %(msisdn)s": "Teksta ziņa tika nosūtīta uz %(msisdn)s",
|
"A text message has been sent to %(msisdn)s": "Teksta ziņa tika nosūtīta uz %(msisdn)s",
|
||||||
"Remove from community": "Dzēst no kopienas",
|
"Remove from community": "Dzēst no kopienas",
|
||||||
"Disinvite this user from community?": "Atcelt šim lietotājam nosūtīto uzaicinājumu pievienoties kopienai?",
|
"Disinvite this user from community?": "Atsaukt šim lietotājam nosūtīto uzaicinājumu pievienoties kopienai?",
|
||||||
"Remove this user from community?": "Izdzēst šo lietotāju no kopienas?",
|
"Remove this user from community?": "Izdzēst šo lietotāju no kopienas?",
|
||||||
"Failed to withdraw invitation": "Neizdevās atcelt uzaicinājumu",
|
"Failed to withdraw invitation": "Neizdevās atcelt uzaicinājumu",
|
||||||
"Failed to remove user from community": "Neizdevās izdzēst lietotāju no kopienas",
|
"Failed to remove user from community": "Neizdevās izdzēst lietotāju no kopienas",
|
||||||
"Filter community members": "Kopienas biedru filtrs",
|
"Filter community members": "Kopienas dalībnieku filtrs",
|
||||||
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Vai tiešām vēlaties dzēst '%(roomName)s' no %(groupId)s?",
|
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Vai tiešām vēlaties dzēst '%(roomName)s' no %(groupId)s?",
|
||||||
"Removing a room from the community will also remove it from the community page.": "Dzēšot istabu no kopienas tā tiks dzēsta arī no kopienas lapas.",
|
"Removing a room from the community will also remove it from the community page.": "Dzēšot istabu no kopienas tā tiks dzēsta arī no kopienas lapas.",
|
||||||
"Failed to remove room from community": "Neizdevās dzēst istabu no kopienas",
|
"Failed to remove room from community": "Neizdevās dzēst istabu no kopienas",
|
||||||
|
@ -526,8 +526,8 @@
|
||||||
"Unable to reject invite": "Neizdevās noraidīt uzaicinājumu",
|
"Unable to reject invite": "Neizdevās noraidīt uzaicinājumu",
|
||||||
"Leave %(groupName)s?": "Pamest %(groupName)s?",
|
"Leave %(groupName)s?": "Pamest %(groupName)s?",
|
||||||
"%(inviter)s has invited you to join this community": "%(inviter)s uzaicināja jūs pievienoties šai kopienai",
|
"%(inviter)s has invited you to join this community": "%(inviter)s uzaicināja jūs pievienoties šai kopienai",
|
||||||
"You are an administrator of this community": "Tu esi šīs kopienas administrators",
|
"You are an administrator of this community": "Jūs esat šīs kopienas administrators",
|
||||||
"You are a member of this community": "Tu esi šīs kopienas biedrs",
|
"You are a member of this community": "Jūs esat šīs kopienas dalībnieks",
|
||||||
"Long Description (HTML)": "Garais apraksts (HTML)",
|
"Long Description (HTML)": "Garais apraksts (HTML)",
|
||||||
"Community %(groupId)s not found": "Kopiena %(groupId)s nav atrasta",
|
"Community %(groupId)s not found": "Kopiena %(groupId)s nav atrasta",
|
||||||
"Your Communities": "Jūsu kopienas",
|
"Your Communities": "Jūsu kopienas",
|
||||||
|
@ -546,7 +546,7 @@
|
||||||
"Update": "Atjaunināt",
|
"Update": "Atjaunināt",
|
||||||
"What's New": "Kas jauns",
|
"What's New": "Kas jauns",
|
||||||
"On": "Ieslēgt",
|
"On": "Ieslēgt",
|
||||||
"Changelog": "Izmaiņu saraksts (vēsture)",
|
"Changelog": "Izmaiņu vēsture",
|
||||||
"Waiting for response from server": "Tiek gaidīta atbilde no servera",
|
"Waiting for response from server": "Tiek gaidīta atbilde no servera",
|
||||||
"Send Custom Event": "Sūtīt individuālu notikumu",
|
"Send Custom Event": "Sūtīt individuālu notikumu",
|
||||||
"Failed to send logs: ": "Neizdevās nosūtīt logfailus: ",
|
"Failed to send logs: ": "Neizdevās nosūtīt logfailus: ",
|
||||||
|
@ -560,7 +560,7 @@
|
||||||
"Source URL": "Avota URL adrese",
|
"Source URL": "Avota URL adrese",
|
||||||
"Messages sent by bot": "Botu nosūtītās ziņas",
|
"Messages sent by bot": "Botu nosūtītās ziņas",
|
||||||
"Filter results": "Filtrēt rezultātus",
|
"Filter results": "Filtrēt rezultātus",
|
||||||
"Members": "Biedri",
|
"Members": "Dalībnieki",
|
||||||
"No update available.": "Nav atjauninājumu.",
|
"No update available.": "Nav atjauninājumu.",
|
||||||
"Resend": "Nosūtīt atkārtoti",
|
"Resend": "Nosūtīt atkārtoti",
|
||||||
"Collecting app version information": "Tiek iegūta programmas versijas informācija",
|
"Collecting app version information": "Tiek iegūta programmas versijas informācija",
|
||||||
|
@ -842,7 +842,7 @@
|
||||||
"Interactively verify by Emoji": "Abpusēji verificēt ar emocijzīmēm",
|
"Interactively verify by Emoji": "Abpusēji verificēt ar emocijzīmēm",
|
||||||
"Manually Verify by Text": "Manuāli verificēt ar tekstu",
|
"Manually Verify by Text": "Manuāli verificēt ar tekstu",
|
||||||
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s atsauca uzaicinājumu %(targetDisplayName)s pievienoties istabai.",
|
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s atsauca uzaicinājumu %(targetDisplayName)s pievienoties istabai.",
|
||||||
"%(senderName)s changed the addresses for this room.": "%(senderName)s izmainīja istabas adreses.",
|
"%(senderName)s changed the addresses for this room.": "%(senderName)s nomainīja istabas adreses.",
|
||||||
"%(senderName)s removed the main address for this room.": "%(senderName)s dzēsa galveno adresi šai istabai.",
|
"%(senderName)s removed the main address for this room.": "%(senderName)s dzēsa galveno adresi šai istabai.",
|
||||||
"%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s iestatīja istabas galveno adresi kā %(address)s.",
|
"%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s iestatīja istabas galveno adresi kā %(address)s.",
|
||||||
"Afghanistan": "Afganistāna",
|
"Afghanistan": "Afganistāna",
|
||||||
|
@ -920,7 +920,7 @@
|
||||||
"Phone numbers": "Tālruņa numuri",
|
"Phone numbers": "Tālruņa numuri",
|
||||||
"Email Address": "Epasta adrese",
|
"Email Address": "Epasta adrese",
|
||||||
"Email addresses": "Epasta adreses",
|
"Email addresses": "Epasta adreses",
|
||||||
"Change topic": "Mainīt tematu",
|
"Change topic": "Nomainīt tematu",
|
||||||
"Change room avatar": "Mainīt istabas avataru",
|
"Change room avatar": "Mainīt istabas avataru",
|
||||||
"Change main address for the room": "Mainīt istabas galveno adresi",
|
"Change main address for the room": "Mainīt istabas galveno adresi",
|
||||||
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s nomainīja istabas galveno un alternatīvo adresi.",
|
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s nomainīja istabas galveno un alternatīvo adresi.",
|
||||||
|
@ -932,7 +932,7 @@
|
||||||
"Invite users": "Uzaicināt lietotājus",
|
"Invite users": "Uzaicināt lietotājus",
|
||||||
"Send messages": "Sūtīt ziņas",
|
"Send messages": "Sūtīt ziņas",
|
||||||
"Default role": "Noklusējuma loma",
|
"Default role": "Noklusējuma loma",
|
||||||
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Izmaiņas attiecībā uz to, kas var lasīt vēsturi, attieksies tikai uz nākamajiem ziņojumiem šajā istabā. Esošās vēstures redzamība nemainīsies.",
|
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Izmaiņas attiecībā uz to, kas var lasīt vēsturi, attieksies tikai uz nākamajiem ziņām šajā istabā. Esošās vēstures redzamība nemainīsies.",
|
||||||
"Never send encrypted messages to unverified sessions in this room from this session": "Nesūtīt šifrētas ziņas no šīs sesijas neverificētām sesijām šajā istabā",
|
"Never send encrypted messages to unverified sessions in this room from this session": "Nesūtīt šifrētas ziņas no šīs sesijas neverificētām sesijām šajā istabā",
|
||||||
"Encrypted": "Šifrēts",
|
"Encrypted": "Šifrēts",
|
||||||
"Enable room encryption": "Iespējot istabas šifrēšanu",
|
"Enable room encryption": "Iespējot istabas šifrēšanu",
|
||||||
|
@ -1053,7 +1053,7 @@
|
||||||
"Reject & Ignore user": "Noraidīt un ignorēt lietotāju",
|
"Reject & Ignore user": "Noraidīt un ignorēt lietotāju",
|
||||||
"Do you want to chat with %(user)s?": "Vai vēlaties sarakstīties ar %(user)s?",
|
"Do you want to chat with %(user)s?": "Vai vēlaties sarakstīties ar %(user)s?",
|
||||||
"This homeserver doesn't offer any login flows which are supported by this client.": "Šis bāzes serveris neatbalsta nevienu pierakstīšanās metodi, kuru atbalstītu šis klients.",
|
"This homeserver doesn't offer any login flows which are supported by this client.": "Šis bāzes serveris neatbalsta nevienu pierakstīšanās metodi, kuru atbalstītu šis klients.",
|
||||||
"Explore rooms": "Pārlūkot telpas",
|
"Explore rooms": "Pārlūkot istabas",
|
||||||
"Confirm Security Phrase": "Apstipriniet slepeno frāzi",
|
"Confirm Security Phrase": "Apstipriniet slepeno frāzi",
|
||||||
"Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Nodrošinieties pret piekļuves zaudēšanu šifrētām ziņām un datiem, dublējot šifrēšanas atslēgas savā serverī.",
|
"Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Nodrošinieties pret piekļuves zaudēšanu šifrētām ziņām un datiem, dublējot šifrēšanas atslēgas savā serverī.",
|
||||||
"Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Izmantojiet tikai jums zināmu slepeno frāzi un pēc izvēles saglabājiet drošības atslēgu, lai to izmantotu dublēšanai.",
|
"Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Izmantojiet tikai jums zināmu slepeno frāzi un pēc izvēles saglabājiet drošības atslēgu, lai to izmantotu dublēšanai.",
|
||||||
|
@ -1113,7 +1113,7 @@
|
||||||
"The homeserver may be unavailable or overloaded.": "Iespējams, bāzes serveris nav pieejams vai ir pārslogots.",
|
"The homeserver may be unavailable or overloaded.": "Iespējams, bāzes serveris nav pieejams vai ir pārslogots.",
|
||||||
"%(brand)s failed to get the public room list.": "%(brand)s neizdevās iegūt publisko istabu sarakstu.",
|
"%(brand)s failed to get the public room list.": "%(brand)s neizdevās iegūt publisko istabu sarakstu.",
|
||||||
"%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s neizdevās iegūt protokolu sarakstu no bāzes servera. Iespējams, bāzes serveris ir pārāk vecs, lai atbalstītu trešo pušu tīklus.",
|
"%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s neizdevās iegūt protokolu sarakstu no bāzes servera. Iespējams, bāzes serveris ir pārāk vecs, lai atbalstītu trešo pušu tīklus.",
|
||||||
"Add a photo so people know it's you.": "Pievienot foto, lai cilvēki zina, ka tas esi tu.",
|
"Add a photo so people know it's you.": "Pievienot foto, lai cilvēki zina, ka tas esat jūs.",
|
||||||
"Great, that'll help people know it's you": "Lieliski, tas ļaus cilvēkiem tevi atpazīt",
|
"Great, that'll help people know it's you": "Lieliski, tas ļaus cilvēkiem tevi atpazīt",
|
||||||
"This homeserver does not support communities": "Šis bāzes serveris neatbalsta kopienas",
|
"This homeserver does not support communities": "Šis bāzes serveris neatbalsta kopienas",
|
||||||
"Everyone": "Jebkurš",
|
"Everyone": "Jebkurš",
|
||||||
|
@ -1148,7 +1148,7 @@
|
||||||
"Bulk options": "Lielapjoma opcijas",
|
"Bulk options": "Lielapjoma opcijas",
|
||||||
"Clear cache and reload": "Notīrīt kešatmiņu un pārlādēt",
|
"Clear cache and reload": "Notīrīt kešatmiņu un pārlādēt",
|
||||||
"Versions": "Versijas",
|
"Versions": "Versijas",
|
||||||
"Keyboard Shortcuts": "Klaviatūras saīsnes",
|
"Keyboard Shortcuts": "Īsinājumtaustiņi",
|
||||||
"FAQ": "BUJ",
|
"FAQ": "BUJ",
|
||||||
"For help with using %(brand)s, click <a>here</a>.": "Palīdzībai %(brand)s izmantošanā, spiediet <a>šeit</a>.",
|
"For help with using %(brand)s, click <a>here</a>.": "Palīdzībai %(brand)s izmantošanā, spiediet <a>šeit</a>.",
|
||||||
"Account management": "Konta pārvaldība",
|
"Account management": "Konta pārvaldība",
|
||||||
|
@ -1388,38 +1388,38 @@
|
||||||
"You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Jūs varat ierakstīties, taču dažas funkcijas nebūs pieejamas, kamēr nebūs pieejams identitāšu serveris. Ja arī turpmāk redzat šo brīdinājumu, lūdzu, pārbaudiet konfigurāciju vai sazinieties ar servera administratoru.",
|
"You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Jūs varat ierakstīties, taču dažas funkcijas nebūs pieejamas, kamēr nebūs pieejams identitāšu serveris. Ja arī turpmāk redzat šo brīdinājumu, lūdzu, pārbaudiet konfigurāciju vai sazinieties ar servera administratoru.",
|
||||||
"Cannot reach identity server": "Neizdodas sasniegt identitāšu serveri",
|
"Cannot reach identity server": "Neizdodas sasniegt identitāšu serveri",
|
||||||
"Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Paprasiet %(brand)s administratoram pārbaudīt, vai <a> jūsu konfigurācijas failā</a> nav nepareizu vai dublējošos ierakstu.",
|
"Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.": "Paprasiet %(brand)s administratoram pārbaudīt, vai <a> jūsu konfigurācijas failā</a> nav nepareizu vai dublējošos ierakstu.",
|
||||||
"See <b>%(msgtype)s</b> messages posted to your active room": "Redzēt jūsu aktīvajā telpā izliktās <b>%(msgtype)s</b> ziņas",
|
"See <b>%(msgtype)s</b> messages posted to your active room": "Apskatīt <b>%(msgtype)s</b> ziņas, kas publicētas jūsu aktīvajā istabā",
|
||||||
"See <b>%(msgtype)s</b> messages posted to this room": "Redzēt šajā telpā izliktās <b>%(msgtype)s</b> ziņas",
|
"See <b>%(msgtype)s</b> messages posted to this room": "Apskatīt <b>%(msgtype)s</b> ziņas, kas publicētas šajā istabā",
|
||||||
"Send <b>%(msgtype)s</b> messages as you in your active room": "Sūtīt <b>%(msgtype)s</b> ziņas savā vārdā savā aktīvajā telpā",
|
"Send <b>%(msgtype)s</b> messages as you in your active room": "Sūtīt <b>%(msgtype)s</b> ziņas savā vārdā savā aktīvajā telpā",
|
||||||
"Send <b>%(msgtype)s</b> messages as you in this room": "Sūtīt <b>%(msgtype)s</b> ziņas savā vārdā šajā telpā",
|
"Send <b>%(msgtype)s</b> messages as you in this room": "Sūtīt <b>%(msgtype)s</b> ziņas savā vārdā šajā telpā",
|
||||||
"See general files posted to your active room": "Redzēt jūsu aktīvajā telpā izliktos failus",
|
"See general files posted to your active room": "Redzēt jūsu aktīvajā telpā izliktos failus",
|
||||||
"See general files posted to this room": "Redzēt šajā telpā izliktos failus",
|
"See general files posted to this room": "Redzēt šajā telpā izliktos failus",
|
||||||
"Send general files as you in your active room": "Sūtīt failus savā vārdā jūsu aktīvajā telpā",
|
"Send general files as you in your active room": "Sūtīt failus savā vārdā jūsu aktīvajā istabā",
|
||||||
"Send general files as you in this room": "Sūtīt failus savā vārdā šajā telpā",
|
"Send general files as you in this room": "Sūtīt failus savā vārdā šajā istabā",
|
||||||
"See videos posted to your active room": "Redzēt video, kuri izlikti jūsu aktīvajā telpā",
|
"See videos posted to your active room": "Redzēt video, kuri izlikti jūsu aktīvajā telpā",
|
||||||
"See videos posted to this room": "Redzēt video, kuri izlikti šajā telpā",
|
"See videos posted to this room": "Redzēt video, kuri izlikti šajā telpā",
|
||||||
"Send videos as you in your active room": "Sūtīt video savā vārdā savā aktīvajā telpā",
|
"Send videos as you in your active room": "Sūtīt video savā vārdā savā aktīvajā istabā",
|
||||||
"Send videos as you in this room": "Sūtīt video savā vārdā šajā telpā",
|
"Send videos as you in this room": "Sūtīt video savā vārdā šajā istabā",
|
||||||
"See images posted to your active room": "Redzēt attēlus, kuri izlikti jūsu aktīvajā telpā",
|
"See images posted to your active room": "Redzēt attēlus, kuri izlikti jūsu aktīvajā telpā",
|
||||||
"See images posted to this room": "Redzēt attēlus, kuri izlikti šajā telpā",
|
"See images posted to this room": "Redzēt attēlus, kuri izlikti šajā telpā",
|
||||||
"Send images as you in your active room": "Sūtīt attēlus savā vārdā savā aktīvajā telpā",
|
"Send images as you in your active room": "Sūtīt attēlus savā vārdā savā aktīvajā istabā",
|
||||||
"Send images as you in this room": "Sūtīt attēlus savā vārdā šajā telpā",
|
"Send images as you in this room": "Sūtīt attēlus savā vārdā šajā istabā",
|
||||||
"See emotes posted to your active room": "Redzēt emocijas, kuras izvietotas jūsu aktīvajā telpā",
|
"See emotes posted to your active room": "Redzēt emocijas, kuras izvietotas jūsu aktīvajā telpā",
|
||||||
"See emotes posted to this room": "Redzēt emocijas, kuras izvietotas šajā telpā",
|
"See emotes posted to this room": "Redzēt emocijas, kuras izvietotas šajā telpā",
|
||||||
"Send emotes as you in your active room": "Nosūtīt emocijas savā vārdā uz savu aktīvo telpu",
|
"Send emotes as you in your active room": "Nosūtīt emocijas savā vārdā uz savu aktīvo istabu",
|
||||||
"Send emotes as you in this room": "Nosūtīt emocijas savā vārdā uz šo telpu",
|
"Send emotes as you in this room": "Nosūtīt emocijas savā vārdā uz šo istabu",
|
||||||
"See text messages posted to your active room": "Redzēt teksta ziņas, kuras izvietotas jūsu aktīvajā telpā",
|
"See text messages posted to your active room": "Redzēt teksta ziņas, kuras izvietotas jūsu aktīvajā telpā",
|
||||||
"See text messages posted to this room": "Redzēt teksta ziņas, kas izvietotas šajā telpā",
|
"See text messages posted to this room": "Redzēt teksta ziņas, kas izvietotas šajā telpā",
|
||||||
"Send text messages as you in your active room": "Sūtīt teksta ziņas savā vārdā jūsu aktīvajā telpā",
|
"Send text messages as you in your active room": "Sūtīt teksta ziņas savā vārdā jūsu aktīvajā istabā",
|
||||||
"Send text messages as you in this room": "Sūtīt teksta ziņas savā vārdā šajā telpā",
|
"Send text messages as you in this room": "Sūtīt teksta ziņas savā vārdā šajā istabā",
|
||||||
"See messages posted to your active room": "Redzēt ziņas, kas izvietotas jūsu aktīvajā telpā",
|
"See messages posted to your active room": "Redzēt ziņas, kas izvietotas jūsu aktīvajā telpā",
|
||||||
"See messages posted to this room": "Redzēt ziņas, kas izvietotas šajā telpā",
|
"See messages posted to this room": "Redzēt ziņas, kas izvietotas šajā telpā",
|
||||||
"Send messages as you in your active room": "Sūtiet ziņas savā vārdā jūsu aktīvajā telpā",
|
"Send messages as you in your active room": "Sūtiet ziņas savā vārdā jūsu aktīvajā istabā",
|
||||||
"Send messages as you in this room": "Sūtīt ziņas savā vārdā šajā telpā",
|
"Send messages as you in this room": "Sūtīt ziņas savā vārdā šajā istabā",
|
||||||
"The <b>%(capability)s</b> capability": "<b>%(capability)s</b> iespējas",
|
"The <b>%(capability)s</b> capability": "<b>%(capability)s</b> iespējas",
|
||||||
"See <b>%(eventType)s</b> events posted to your active room": "Redzēt, kad <b>%(eventType)s</b> notikumi izvietoti jūsu aktīvajā telpā",
|
"See <b>%(eventType)s</b> events posted to your active room": "Apskatīt <b>%(eventType)s</b> notikumus jūsu aktīvajā istabā",
|
||||||
"Send <b>%(eventType)s</b> events as you in your active room": "Sūtīt <b>%(eventType)s</b> notikumus savā vārdā savā aktīvajā telpā",
|
"Send <b>%(eventType)s</b> events as you in your active room": "Sūtīt <b>%(eventType)s</b> notikumus savā vārdā savā aktīvajā telpā",
|
||||||
"See <b>%(eventType)s</b> events posted to this room": "Redzēt <b>%(eventType)s</b> notikumus, kas izvietoti šajā telpā",
|
"See <b>%(eventType)s</b> events posted to this room": "Apskatīt <b>%(eventType)s</b> notikumus šajā istabā",
|
||||||
"Send <b>%(eventType)s</b> events as you in this room": "Sūtiet <b>%(eventType)s</b> notikumus jūsu vārdā šajā telpā",
|
"Send <b>%(eventType)s</b> events as you in this room": "Sūtiet <b>%(eventType)s</b> notikumus jūsu vārdā šajā telpā",
|
||||||
"with state key %(stateKey)s": "ar stāvokļa/statusa atslēgu %(stateKey)s",
|
"with state key %(stateKey)s": "ar stāvokļa/statusa atslēgu %(stateKey)s",
|
||||||
"with an empty state key": "ar tukšu stāvokļa/statusa atslēgu",
|
"with an empty state key": "ar tukšu stāvokļa/statusa atslēgu",
|
||||||
|
@ -1428,23 +1428,23 @@
|
||||||
"See when a sticker is posted in this room": "Redzēt, kad šajā telpā parādās stikers",
|
"See when a sticker is posted in this room": "Redzēt, kad šajā telpā parādās stikers",
|
||||||
"Send stickers to this room as you": "Nosūtīt stikerus savā vārdā uz šo telpu",
|
"Send stickers to this room as you": "Nosūtīt stikerus savā vārdā uz šo telpu",
|
||||||
"See when people join, leave, or are invited to your active room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz jūsu aktīvo telpu",
|
"See when people join, leave, or are invited to your active room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz jūsu aktīvo telpu",
|
||||||
"Kick, ban, or invite people to this room, and make you leave": "Izspert, liegt vai uzaicināt cilvēkus uz šo telpu un likt jums aiziet",
|
"Kick, ban, or invite people to this room, and make you leave": "Padzīt, liegt pieeju vai uzaicināt cilvēkus uz šo istabu un likt jums aiziet",
|
||||||
"Kick, ban, or invite people to your active room, and make you leave": "Izspert, liegt vai uzaicināt cilvēkus uz jūsu aktīvo telpu un likt jums aiziet",
|
"Kick, ban, or invite people to your active room, and make you leave": "Padzīt, liegt pieeju vai uzaicināt cilvēkus uz jūsu aktīvo istabu un likt jums aiziet",
|
||||||
"See when people join, leave, or are invited to this room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz šo telpu",
|
"See when people join, leave, or are invited to this room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz šo telpu",
|
||||||
"See when the avatar changes in your active room": "Redzēt, kad notiek jūsu aktīvās istabas avatara izmaiņas",
|
"See when the avatar changes in your active room": "Redzēt, kad notiek jūsu aktīvās istabas avatara izmaiņas",
|
||||||
"Change the avatar of your active room": "Mainīt jūsu aktīvās telpas avataru",
|
"Change the avatar of your active room": "Nomainīt jūsu aktīvās istabas avataru",
|
||||||
"See when the avatar changes in this room": "Redzēt, kad notiek šīs istabas avatara izmaiņas",
|
"See when the avatar changes in this room": "Redzēt, kad notiek šīs istabas avatara izmaiņas",
|
||||||
"Change the avatar of this room": "Mainīt šīs istabas avataru",
|
"Change the avatar of this room": "Nomainīt šīs istabas avataru",
|
||||||
"See when the name changes in your active room": "Redzēt, kad notiek aktīvās telpas nosaukuma izmaiņas",
|
"See when the name changes in your active room": "Redzēt, kad notiek aktīvās telpas nosaukuma izmaiņas",
|
||||||
"Change the name of your active room": "Mainīt jūsu aktīvās telpas nosaukumu",
|
"Change the name of your active room": "Nomainīt jūsu aktīvās istabas nosaukumu",
|
||||||
"See when the name changes in this room": "Redzēt, kad mainās šīs telpas nosaukums",
|
"See when the name changes in this room": "Redzēt, kad mainās šīs telpas nosaukums",
|
||||||
"Change the name of this room": "Mainīt šīs telpas nosaukumu",
|
"Change the name of this room": "Nomainīt šīs istabas nosaukumu",
|
||||||
"See when the topic changes in this room": "Redzēt, kad mainās šīs telpas temats",
|
"See when the topic changes in this room": "Redzēt, kad mainās šīs telpas temats",
|
||||||
"See when the topic changes in your active room": "Redzēt, kad mainās pašreizējā tērziņa temats",
|
"See when the topic changes in your active room": "Redzēt, kad mainās pašreizējā tērziņa temats",
|
||||||
"Change the topic of your active room": "Nomainīt jūsu aktīvās istabas tematu",
|
"Change the topic of your active room": "Nomainīt jūsu aktīvās istabas tematu",
|
||||||
"Change the topic of this room": "Nomainīt šīs telpas tematu",
|
"Change the topic of this room": "Nomainīt šīs istabas tematu",
|
||||||
"Change which room, message, or user you're viewing": "Nomainīt telpu, ziņu vai lietotāju, kurš ir fokusā (kuru jūs skatiet)",
|
"Change which room, message, or user you're viewing": "Nomainīt istabu, ziņu vai lietotāju, kuru jūs skatiet",
|
||||||
"Change which room you're viewing": "Nomainīt telpu, kuru jūs skatiet",
|
"Change which room you're viewing": "Nomainīt istabu, kuru jūs skatiet",
|
||||||
"Send stickers into your active room": "Iesūtīt stikerus jūsu aktīvajā telpā",
|
"Send stickers into your active room": "Iesūtīt stikerus jūsu aktīvajā telpā",
|
||||||
"Send stickers into this room": "Šajā telpā iesūtīt stikerus",
|
"Send stickers into this room": "Šajā telpā iesūtīt stikerus",
|
||||||
"Remain on your screen while running": "Darbības laikā paliek uz ekrāna",
|
"Remain on your screen while running": "Darbības laikā paliek uz ekrāna",
|
||||||
|
@ -1452,21 +1452,21 @@
|
||||||
"Dark": "Tumša",
|
"Dark": "Tumša",
|
||||||
"Light": "Gaiša",
|
"Light": "Gaiša",
|
||||||
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s pārjaunoja lieguma noteikumu šablonu %(oldGlob)s uz šablonu %(newGlob)s dēļ %(reason)s",
|
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s pārjaunoja lieguma noteikumu šablonu %(oldGlob)s uz šablonu %(newGlob)s dēļ %(reason)s",
|
||||||
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kas piekļuvi liedza serveriem, kas atbilst pazīmei %(oldGlob)s, ar atbilstošu pazīmei %(newGlob)s dēļ %(reason)s",
|
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kas liedza pieeju serveriem, kas atbilst pazīmei %(oldGlob)s, ar atbilstošu pazīmei %(newGlob)s dēļ %(reason)s",
|
||||||
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš liedza %(oldGlob)s pazīmei atbilstošas telpas ar jaunu noteikumu, kurš liedz %(newGlob)s dēļ %(reason)s",
|
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s izmainīja noteikumu, kurš liedz pieeju istabām, kas atbilst %(oldGlob)s pazīmei pret %(newGlob)s dēļ %(reason)s",
|
||||||
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš aizliedza lietotājus %(oldGlob)s ar jaunu noteikumu, kurš aizliedz %(newGlob)s dēļ %(reason)s",
|
"%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš liedza pieeju lietotājiem %(oldGlob)s ar jaunu noteikumu, kurš aizliedz %(newGlob)s dēļ %(reason)s",
|
||||||
"%(senderName)s has updated the widget layout": "%(senderName)s ir aktualizējis vidžeta/logrīka izkārtojumu",
|
"%(senderName)s has updated the widget layout": "%(senderName)s ir aktualizējis vidžeta/logrīka izkārtojumu",
|
||||||
"%(senderName)s changed the <a>pinned messages</a> for the room.": "%(senderName)s mainīja telpas <a>piekabinātās ziņas</a>.",
|
"%(senderName)s changed the <a>pinned messages</a> for the room.": "%(senderName)s nomainīja <a>piespraustās ziņas</a> šai istabai.",
|
||||||
"%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s modernizēja šo telpu.",
|
"%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s atjaunināja šo istabu.",
|
||||||
"%(senderName)s kicked %(targetName)s": "%(senderName)s izspēra %(targetName)s",
|
"%(senderName)s kicked %(targetName)s": "%(senderName)s padzina %(targetName)s",
|
||||||
"%(senderName)s kicked %(targetName)s: %(reason)s": "%(senderName)s izspēra %(targetName)s: %(reason)s",
|
"%(senderName)s kicked %(targetName)s: %(reason)s": "%(senderName)s padzina %(targetName)s: %(reason)s",
|
||||||
"%(senderName)s withdrew %(targetName)s's invitation": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu",
|
"%(senderName)s withdrew %(targetName)s's invitation": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu",
|
||||||
"%(senderName)s withdrew %(targetName)s's invitation: %(reason)s": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu: %(reason)s",
|
"%(senderName)s withdrew %(targetName)s's invitation: %(reason)s": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu: %(reason)s",
|
||||||
"%(senderName)s unbanned %(targetName)s": "%(senderName)s noņēma liegumu/atbanoja %(targetName)s",
|
"%(senderName)s unbanned %(targetName)s": "%(senderName)s noņēma liegumu/atbanoja %(targetName)s",
|
||||||
"%(targetName)s left the room": "%(targetName)s pameta/atvienojās no telpas",
|
"%(targetName)s left the room": "%(targetName)s pameta istabu",
|
||||||
"%(targetName)s left the room: %(reason)s": "%(targetName)s pameta/atvienojās no telpas: %(reason)s",
|
"%(targetName)s left the room: %(reason)s": "%(targetName)s pameta istabu: %(reason)s",
|
||||||
"%(targetName)s rejected the invitation": "%(targetName)s noraidīja uzaicinājumu",
|
"%(targetName)s rejected the invitation": "%(targetName)s noraidīja uzaicinājumu",
|
||||||
"%(targetName)s joined the room": "%(targetName)s ienāca (pievienojās) telpā",
|
"%(targetName)s joined the room": "%(targetName)s pievienojās istabai",
|
||||||
"%(senderName)s made no change": "%(senderName)s neizdarīja izmaiņas",
|
"%(senderName)s made no change": "%(senderName)s neizdarīja izmaiņas",
|
||||||
"%(senderName)s set a profile picture": "%(senderName)s iestatīja profila attēlu",
|
"%(senderName)s set a profile picture": "%(senderName)s iestatīja profila attēlu",
|
||||||
"%(senderName)s changed their profile picture": "%(senderName)s nomainīja savu profila attēlu",
|
"%(senderName)s changed their profile picture": "%(senderName)s nomainīja savu profila attēlu",
|
||||||
|
@ -1474,13 +1474,13 @@
|
||||||
"%(senderName)s removed their display name (%(oldDisplayName)s)": "%(senderName)s dzēsa savu redzamo vārdu (%(oldDisplayName)s)",
|
"%(senderName)s removed their display name (%(oldDisplayName)s)": "%(senderName)s dzēsa savu redzamo vārdu (%(oldDisplayName)s)",
|
||||||
"%(senderName)s set their display name to %(displayName)s": "%(senderName)s iestatīja %(displayName)s kā savu redzamo vārdu",
|
"%(senderName)s set their display name to %(displayName)s": "%(senderName)s iestatīja %(displayName)s kā savu redzamo vārdu",
|
||||||
"%(oldDisplayName)s changed their display name to %(displayName)s": "%(oldDisplayName)s nomainīja savu redzamo vārdu uz %(displayName)s",
|
"%(oldDisplayName)s changed their display name to %(displayName)s": "%(oldDisplayName)s nomainīja savu redzamo vārdu uz %(displayName)s",
|
||||||
"%(senderName)s banned %(targetName)s": "%(senderName)s aizliedza/nobanoja %(targetName)s",
|
"%(senderName)s banned %(targetName)s": "%(senderName)s liedza pieeju %(targetName)s",
|
||||||
"%(senderName)s banned %(targetName)s: %(reason)s": "%(senderName)s aizliedza/nobanoja %(targetName)s: %(reason)s",
|
"%(senderName)s banned %(targetName)s: %(reason)s": "%(senderName)s liedza pieeju %(targetName)s: %(reason)s",
|
||||||
"%(senderName)s invited %(targetName)s": "%(senderName)s uzaicināja %(targetName)s",
|
"%(senderName)s invited %(targetName)s": "%(senderName)s uzaicināja %(targetName)s",
|
||||||
"%(targetName)s accepted an invitation": "%(targetName)s pieņēma uzaicinājumu",
|
"%(targetName)s accepted an invitation": "%(targetName)s pieņēma uzaicinājumu",
|
||||||
"%(targetName)s accepted the invitation for %(displayName)s": "%(targetName)s pieņēma uzaicinājumu uz %(displayName)s",
|
"%(targetName)s accepted the invitation for %(displayName)s": "%(targetName)s pieņēma uzaicinājumu uz %(displayName)s",
|
||||||
"Converts the DM to a room": "Pārvērst DM par telpu",
|
"Converts the DM to a room": "Pārveido DM par istabu",
|
||||||
"Converts the room to a DM": "Pārvērst telpu par DM",
|
"Converts the room to a DM": "Pārveido istabu par DM",
|
||||||
"Places the call in the current room on hold": "Iepauzē sarunu šajā telpā",
|
"Places the call in the current room on hold": "Iepauzē sarunu šajā telpā",
|
||||||
"Takes the call in the current room off hold": "Šajā telpā iepauzētās sarunas atpauzēšana",
|
"Takes the call in the current room off hold": "Šajā telpā iepauzētās sarunas atpauzēšana",
|
||||||
"Sends a message to the given user": "Nosūtīt ziņu dotajam lietotājam",
|
"Sends a message to the given user": "Nosūtīt ziņu dotajam lietotājam",
|
||||||
|
@ -1490,28 +1490,28 @@
|
||||||
"Displays list of commands with usages and descriptions": "Parāda komandu sarakstu ar pielietojumiem un aprakstiem",
|
"Displays list of commands with usages and descriptions": "Parāda komandu sarakstu ar pielietojumiem un aprakstiem",
|
||||||
"Sends the given emote coloured as a rainbow": "Nosūta šo emociju iekrāsotu varavīksnes krāsās",
|
"Sends the given emote coloured as a rainbow": "Nosūta šo emociju iekrāsotu varavīksnes krāsās",
|
||||||
"Sends the given message coloured as a rainbow": "Nosūta šo ziņu iekrāsotu varavīksnes krāsās",
|
"Sends the given message coloured as a rainbow": "Nosūta šo ziņu iekrāsotu varavīksnes krāsās",
|
||||||
"Forces the current outbound group session in an encrypted room to be discarded": "Piespiedu kārtā atmet/izbeidz pašreizējo izejošo grupas sesiju šifrētajā telpā",
|
"Forces the current outbound group session in an encrypted room to be discarded": "Piespiedu kārtā pārtrauc pašreizējo izejošo grupas sesiju šifrētajā istabā",
|
||||||
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Jūsu iesniegtā parakstīšanas atslēga atbilst parakstīšanas atslēgai, kuru saņēmāt no %(userId)s sesijas %(deviceId)s. Sesija atzīmēta kā verificēta.",
|
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Jūsu iesniegtā parakstīšanas atslēga atbilst parakstīšanas atslēgai, kuru saņēmāt no %(userId)s sesijas %(deviceId)s. Sesija atzīmēta kā verificēta.",
|
||||||
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "BRĪDINĀJUMS: ATSLĒGU VERIFIKĀCIJA NEIZDEVĀS! Parakstīšanas atslēga lietotājam %(userId)s un sesijai %(deviceId)s ir \"%(fprint)s\", kura neatbilst norādītajai atslēgai \"%(fingerprint)s\". Tas var nozīmēt, ka jūsu saziņa tiek pārtverta!",
|
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "BRĪDINĀJUMS: ATSLĒGU VERIFIKĀCIJA NEIZDEVĀS! Parakstīšanas atslēga lietotājam %(userId)s un sesijai %(deviceId)s ir \"%(fprint)s\", kura neatbilst norādītajai atslēgai \"%(fingerprint)s\". Tas var nozīmēt, ka jūsu saziņa tiek pārtverta!",
|
||||||
"Verifies a user, session, and pubkey tuple": "Verificē lietotāju, sesiju un publiskās atslēgas",
|
"Verifies a user, session, and pubkey tuple": "Verificē lietotāju, sesiju un publiskās atslēgas",
|
||||||
"WARNING: Session already verified, but keys do NOT MATCH!": "BRĪDINĀJUMS: Sesija jau ir verificēta, bet atslēgas NESAKRĪT!",
|
"WARNING: Session already verified, but keys do NOT MATCH!": "BRĪDINĀJUMS: Sesija jau ir verificēta, bet atslēgas NESAKRĪT!",
|
||||||
"Unknown (user, session) pair:": "Nezināms (lietotājs, sesija) pāris:",
|
"Unknown (user, session) pair:": "Nezināms (lietotājs, sesija) pāris:",
|
||||||
"You cannot modify widgets in this room.": "Jūs šajā telpā nevarat mainīt vidžetus/logrīkus.",
|
"You cannot modify widgets in this room.": "Jūs nevarat mainīt vidžetus/logrīkus šajā istabā.",
|
||||||
"Please supply a https:// or http:// widget URL": "Lūdzu ievadiet logrīka URL https:// vai http:// formā",
|
"Please supply a https:// or http:// widget URL": "Lūdzu ievadiet logrīka URL https:// vai http:// formā",
|
||||||
"Please supply a widget URL or embed code": "Ievadiet vidžeta/logrīka URL vai ievietojiet kodu",
|
"Please supply a widget URL or embed code": "Ievadiet vidžeta/logrīka URL vai ievietojiet kodu",
|
||||||
"Adds a custom widget by URL to the room": "Pievieno telpai individuālu/pielāgotu logrīku/vidžetu ar URL-adresi",
|
"Adds a custom widget by URL to the room": "Pievieno istabai pielāgotu logrīku/vidžetu ar URL-adresi",
|
||||||
"Command failed": "Neizdevās izpildīt komandu",
|
"Command failed": "Neizdevās izpildīt komandu",
|
||||||
"Joins room with given address": "Pievienojas telpai ar šādu adresi",
|
"Joins room with given address": "Pievienojas istabai ar šādu adresi",
|
||||||
"Use an identity server to invite by email. Manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Pārvaldība pieejama Iestatījumos.",
|
"Use an identity server to invite by email. Manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Pārvaldība pieejama Iestatījumos.",
|
||||||
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Noklikšķiniet uz Turpināt, lai izmantotu noklusējuma identitātes serveri (%(defaultIdentityServerName)s) vai nomainītu to Iestatījumos.",
|
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Noklikšķiniet uz Turpināt, lai izmantotu noklusējuma identitātes serveri (%(defaultIdentityServerName)s) vai nomainītu to Iestatījumos.",
|
||||||
"Use an identity server": "Izmantot identitāšu serveri",
|
"Use an identity server": "Izmantot identitāšu serveri",
|
||||||
"Sets the room name": "Iestata telpas nosaukumu",
|
"Sets the room name": "Iestata istabas nosaukumu",
|
||||||
"Gets or sets the room topic": "Nolasa vai iestata telpas tematu",
|
"Gets or sets the room topic": "Nolasa vai iestata istabas tematu",
|
||||||
"Changes your avatar in all rooms": "Maina jūsu avataru visām telpām",
|
"Changes your avatar in all rooms": "Maina jūsu avataru visās istabās",
|
||||||
"Changes your avatar in this current room only": "Maina jūsu avataru tikai šajā telpā",
|
"Changes your avatar in this current room only": "Maina jūsu avataru tikai šajā istabā",
|
||||||
"Changes the avatar of the current room": "Maina šīs telpas avataru",
|
"Changes the avatar of the current room": "Maina šīs istabas avataru",
|
||||||
"Changes your display nickname in the current room only": "Maina rādāmo pseidonīmu/segvārdu tikai šai telpai",
|
"Changes your display nickname in the current room only": "Maina jūsu parādāmo vārdu tikai šajā istabā",
|
||||||
"Upgrades a room to a new version": "Modernizē telpu uz Jauno versiju",
|
"Upgrades a room to a new version": "Atjaunina istabu uz jaunu versiju",
|
||||||
"Sends a message as html, without interpreting it as markdown": "Nosūta ziņu kā HTML, to neinterpretējot kā Markdown",
|
"Sends a message as html, without interpreting it as markdown": "Nosūta ziņu kā HTML, to neinterpretējot kā Markdown",
|
||||||
"Sends a message as plain text, without interpreting it as markdown": "Nosūta ziņu kā vienkāršu tekstu, to neinterpretējot kā Markdown",
|
"Sends a message as plain text, without interpreting it as markdown": "Nosūta ziņu kā vienkāršu tekstu, to neinterpretējot kā Markdown",
|
||||||
"Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Pievieno ( ͡° ͜ʖ ͡°) pirms vienkārša teksta ziņas",
|
"Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Pievieno ( ͡° ͜ʖ ͡°) pirms vienkārša teksta ziņas",
|
||||||
|
@ -1783,17 +1783,141 @@
|
||||||
"The call could not be established": "Savienojums nevarēja tikt izveidots",
|
"The call could not be established": "Savienojums nevarēja tikt izveidots",
|
||||||
"The user you called is busy.": "Lietotājs, kuram zvanāt, ir aizņemts.",
|
"The user you called is busy.": "Lietotājs, kuram zvanāt, ir aizņemts.",
|
||||||
"User Busy": "Lietotājs aizņemts",
|
"User Busy": "Lietotājs aizņemts",
|
||||||
"Your user agent": "Jūsu lietotāja-aģents",
|
"Your user agent": "Jūsu lietotāja aģents",
|
||||||
"Whether you're using %(brand)s as an installed Progressive Web App": "Vai izmantojiet %(brand)s kā instalētu progresīvo tīmekļa lietotni",
|
"Whether you're using %(brand)s as an installed Progressive Web App": "Vai izmantojiet %(brand)s kā instalētu progresīvo tīmekļa lietotni",
|
||||||
"Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Vai izmantojat %(brand)s ierīcē, kurā skārnienjūtīgs ekrāns ir galvenais ievades mehānisms",
|
"Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Vai izmantojat %(brand)s ierīcē, kurā skārnienjūtīgs ekrāns ir galvenais ievades mehānisms",
|
||||||
"This room is used for important messages from the Homeserver, so you cannot leave it.": "Šī telpa tiek izmantota svarīgiem ziņojumiem no bāzes servera, tāpēc jūs nevarat to atstāt.",
|
"This room is used for important messages from the Homeserver, so you cannot leave it.": "Šī istaba tiek izmantota svarīgiem ziņojumiem no bāzes servera, tāpēc jūs nevarat to pamest.",
|
||||||
"Can't leave Server Notices room": "Nevar iziet no servera Paziņojumu telpas",
|
"Can't leave Server Notices room": "Nevar pamest Server Notices istabu",
|
||||||
"Unexpected server error trying to leave the room": "Mēģinot atstāt telpu radās negaidīta servera kļūme",
|
"Unexpected server error trying to leave the room": "Mēģinot pamest istabu radās negaidīta servera kļūme",
|
||||||
"Unable to connect to Homeserver. Retrying...": "Nevar izveidot savienojumu ar bāzes/mājas serveri. Mēģinam vēlreiz ...",
|
"Unable to connect to Homeserver. Retrying...": "Nevar izveidot savienojumu ar bāzes/mājas serveri. Mēģinam vēlreiz ...",
|
||||||
"Please <a>contact your service administrator</a> to continue using the service.": "Lūdzu <a>sazinieties ar savu administratoru</a>, lai turpinātu izmantot pakalpojumu.",
|
"Please <a>contact your service administrator</a> to continue using the service.": "Lūdzu <a>sazinieties ar savu administratoru</a>, lai turpinātu izmantot pakalpojumu.",
|
||||||
"This homeserver has exceeded one of its resource limits.": "Šis bāzes/mājas serveris ir pārsniedzis vienu no tā resursu ierobežojumiem.",
|
"This homeserver has exceeded one of its resource limits.": "Šis bāzes/mājas serveris ir pārsniedzis vienu no tā resursu ierobežojumiem.",
|
||||||
"This homeserver has been blocked by its administrator.": "Šo bāzes/mājas serveri ir bloķējis tā administrators.",
|
"This homeserver has been blocked by its administrator.": "Šo bāzes/mājas serveri ir bloķējis tā administrators.",
|
||||||
"This homeserver has hit its Monthly Active User limit.": "Šis bāzes/mājas serveris ir sasniedzis ikmēneša aktīvo lietotāju ierobežojumu.",
|
"This homeserver has hit its Monthly Active User limit.": "Šis bāzes/mājas serveris ir sasniedzis ikmēneša aktīvo lietotāju ierobežojumu.",
|
||||||
"Unexpected error resolving identity server configuration": "Negaidīta kļūda identitātes servera konfigurācijā",
|
"Unexpected error resolving identity server configuration": "Negaidīta kļūda identitātes servera konfigurācijā",
|
||||||
"Unexpected error resolving homeserver configuration": "Negaidīta kļūme mājas servera konfigurācijā"
|
"Unexpected error resolving homeserver configuration": "Negaidīta kļūme mājas servera konfigurācijā",
|
||||||
|
"Cancel All": "Atcelt visu",
|
||||||
|
"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.": "Iesniedzot ziņojumu par konkrēto ziņu, tās unikālais notikuma ID tiks nosūtīts jūsu bāzes servera administratoram. Ja ziņas šajā istabā ir šifrētas, jūsu bāzes servera administrators nevarēs lasīt ziņas tekstu vai skatīt failus un attēlus.",
|
||||||
|
"Sending": "Sūta",
|
||||||
|
"Adding...": "Pievienošana…",
|
||||||
|
"Can't load this message": "Nevar ielādēt šo ziņu",
|
||||||
|
"Send voice message": "Sūtīt balss ziņu",
|
||||||
|
"Sending your message...": "Sūta jūsu ziņu…",
|
||||||
|
"Address": "Adrese",
|
||||||
|
"%(sharerName)s is presenting": "%(sharerName)s prezentē",
|
||||||
|
"Group & filter rooms by custom tags (refresh to apply changes)": "Grupēt un filtrēt istabas pēc pielāgotiem tagiem (atsvaidzināt, lai piemērotu izmaiņas)",
|
||||||
|
"Hey you. You're the best!": "Sveiks! Tu esi labākais!",
|
||||||
|
"Inviting...": "Uzaicina…",
|
||||||
|
"Share %(name)s": "Dalīties ar %(name)s",
|
||||||
|
"Try different words or check for typos. Some results may not be visible as they're private and you need an invite to join them.": "Izmēģiniet citus vārdus vai pārbaudiet drukas kļūdas. Daži rezultāti var nebūt redzami, jo tie ir privāti un ir nepieciešams uzaicinājums, lai pievienotos.",
|
||||||
|
"No results for \"%(query)s\"": "Meklējumam \"%(query)s\" nav rezultātu",
|
||||||
|
"Explore Public Rooms": "Pārlūkot publiskas istabas",
|
||||||
|
"Show preview": "Rādīt priekšskatījumu",
|
||||||
|
"View source": "Skatīt pirmkodu",
|
||||||
|
"Forward": "Pārsūtīt",
|
||||||
|
"Forgotten or lost all recovery methods? <a>Reset all</a>": "Aizmirsāt vai pazaudējāt visas atkopšanās iespējas? <a>Atiestatiet visu</a>",
|
||||||
|
"Share Community": "Dalīties ar kopienu",
|
||||||
|
"Link to most recent message": "Saite uz jaunāko ziņu",
|
||||||
|
"Share Room": "Dalīties ar istabu",
|
||||||
|
"Report Content to Your Homeserver Administrator": "Ziņojums par saturu bāzes servera administratoram",
|
||||||
|
"Send report": "Nosūtīt ziņojumu",
|
||||||
|
"Report the entire room": "Ziņot par visu istabu",
|
||||||
|
"Leave all rooms": "Pamest visas istabas",
|
||||||
|
"Invited people will be able to read old messages.": "Uzaicinātie cilvēki varēs lasīt vecās ziņas.",
|
||||||
|
"Or send invite link": "Vai nosūtiet uzaicinājuma saiti",
|
||||||
|
"If you can't see who you’re looking for, send them your invite link below.": "Ja neredzat meklēto, nosūtiet savu uzaicinājuma saiti zemāk.",
|
||||||
|
"Some suggestions may be hidden for privacy.": "Daži ieteikumi var būt slēpti dēļ privātuma.",
|
||||||
|
"Search for rooms or people": "Meklēt istabas vai cilvēkus",
|
||||||
|
"Message preview": "Ziņas priekšskatījums",
|
||||||
|
"Forward message": "Pārsūtīt ziņu",
|
||||||
|
"Public room": "Publiska istaba",
|
||||||
|
"Private room (invite only)": "Privāta istaba (tikai ar ielūgumiem)",
|
||||||
|
"Only people invited will be able to find and join this room.": "Tikai uzaicinātās cilvēki varēs atrast un pievienoties šai istabai.",
|
||||||
|
"Anyone will be able to find and join this room.": "Ikviens varēs atrast un pievienoties šai istabai.",
|
||||||
|
"You can change this at any time from room settings.": "Jūs to varat mainīt istabas iestatījumos jebkurā laikā.",
|
||||||
|
"Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Privātas istabas var atrast un tām pievienoties tikai pēc uzaicinājuma. Publiskas istabas atrast un tām pievienoties var ikviens no šis kopienas.",
|
||||||
|
"Show": "Rādīt",
|
||||||
|
"Search for rooms": "Meklēt istabas",
|
||||||
|
"Server name": "Servera nosaukums",
|
||||||
|
"Enter the name of a new server you want to explore.": "Ievadiet nosaukumu jaunam serverim, kuru vēlaties pārlūkot.",
|
||||||
|
"%(severalUsers)schanged the <a>pinned messages</a> for the room %(count)s times.|other": "%(severalUsers)smainīja <a>piespraustās ziņas</a> istabā %(count)s reizes.",
|
||||||
|
"Zoom in": "Pietuvināt",
|
||||||
|
"Zoom out": "Attālināt",
|
||||||
|
"Join": "Pievienoties",
|
||||||
|
"Share content": "Dalīties ar saturu",
|
||||||
|
"Your theme": "Jūsu tēma",
|
||||||
|
"Your user ID": "Jūsu lietotāja ID",
|
||||||
|
"Show all": "Rādīt visu",
|
||||||
|
"Show image": "Rādīt attēlu",
|
||||||
|
"Call back": "Atzvanīt",
|
||||||
|
"Call declined": "Zvans noraidīts",
|
||||||
|
"Copy Room Link": "Kopēt istabas saiti",
|
||||||
|
"Invite People": "Uzaicināt cilvēkus",
|
||||||
|
"Forget Room": "Aizmirst istabu",
|
||||||
|
"Join the discussion": "Pievienoties diskusijai",
|
||||||
|
"Forget this room": "Aizmirst šo istabu",
|
||||||
|
"Joining room …": "Pievienošanās istabai…",
|
||||||
|
"Explore %(spaceName)s": "Pālūkot %(spaceName)s",
|
||||||
|
"Explore public rooms": "Pārlūkot publiskas istabas",
|
||||||
|
"Explore community rooms": "Pārlūkot kopienas istabas",
|
||||||
|
"Enable encryption in settings.": "Iespējot šifrēšanu iestatījumos.",
|
||||||
|
"%(seconds)ss left": "%(seconds)s sekundes atlikušas",
|
||||||
|
"Show %(count)s other previews|one": "Rādīt %(count)s citu priekšskatījumu",
|
||||||
|
"Show %(count)s other previews|other": "Rādīt %(count)s citus priekšskatījumus",
|
||||||
|
"Share": "Dalīties",
|
||||||
|
"Access": "Piekļuve",
|
||||||
|
"People with supported clients will be able to join the room without having a registered account.": "Cilvēki ar atbalstītām lietotnēm varēs pievienoties istabai bez reģistrēta konta.",
|
||||||
|
"Decide who can join %(roomName)s.": "Nosakiet, kas var pievienoties %(roomName)s.",
|
||||||
|
"Select the roles required to change various parts of the room": "Izvēlieties lomas, kas nepieciešamas, lai mainītu dažādus istabas parametrus",
|
||||||
|
"Timeline": "Laika skala",
|
||||||
|
"Code blocks": "Koda bloki",
|
||||||
|
"Displaying time": "Laika attēlošana",
|
||||||
|
"To view all keyboard shortcuts, click here.": "Lai apskatītu visus īsinājumtaustiņus, noklikšķiniet šeit.",
|
||||||
|
"Keyboard shortcuts": "Īsinājumtaustiņi",
|
||||||
|
"Theme": "Tēma",
|
||||||
|
"Custom theme URL": "Pielāgotas tēmas URL",
|
||||||
|
"Theme added!": "Tēma pievienota!",
|
||||||
|
"Enter a new identity server": "Ievadiet jaunu identitāšu serveri",
|
||||||
|
"Mentions & keywords": "Pieminēšana un atslēgvārdi",
|
||||||
|
"New keyword": "Jauns atslēgvārds",
|
||||||
|
"Keyword": "Atslēgvārds",
|
||||||
|
"Enable for this account": "Iespējot šim kontam",
|
||||||
|
"Messages containing keywords": "Ziņas, kas satur atslēgvārdus",
|
||||||
|
"Anyone can find and join.": "Ikviens var atrast un pievienoties.",
|
||||||
|
"Only invited people can join.": "Tikai uzaicināti cilvēki var pievienoties.",
|
||||||
|
"Private (invite only)": "Privāta (tikai ar ielūgumiem)",
|
||||||
|
"Expand": "Izvērst",
|
||||||
|
"Decide who can view and join %(spaceName)s.": "Nosakiet, kas var skatīt un pievienoties %(spaceName)s.",
|
||||||
|
"Enable guest access": "Iespējot piekļuvi viesiem",
|
||||||
|
"Invite people": "Uzaicināt cilvēkus",
|
||||||
|
"Show all rooms": "Rādīt visas istabas",
|
||||||
|
"Creating...": "Izveidošana…",
|
||||||
|
"Public": "Publiska",
|
||||||
|
"Corn": "Kukurūza",
|
||||||
|
"Show previews/thumbnails for images": "Rādīt attēlu priekšskatījumus/sīktēlus",
|
||||||
|
"Show hidden events in timeline": "Rādīt slēptos notikumus laika skalā",
|
||||||
|
"Show developer tools": "Rādīt izstrādātāja rīkus",
|
||||||
|
"Match system theme": "Pielāgoties sistēmas tēmai",
|
||||||
|
"Surround selected text when typing special characters": "Iekļaut iezīmēto tekstu, rakstot speciālās rakstzīmes",
|
||||||
|
"Use Ctrl + Enter to send a message": "Lietot Ctrl + Enter ziņas nosūtīšanai",
|
||||||
|
"Use Command + Enter to send a message": "Lietot Command + Enter ziņas nosūtīšanai",
|
||||||
|
"Use Ctrl + F to search timeline": "Lietot Ctrl + F meklēšanai laika skalā",
|
||||||
|
"Use Command + F to search timeline": "Lietot Command + F meklēšanai laika skalā",
|
||||||
|
"Enable big emoji in chat": "Iespējot lielas emocijzīmes čatā",
|
||||||
|
"Jump to the bottom of the timeline when you send a message": "Nosūtot ziņu, pāriet uz laika skalas beigām",
|
||||||
|
"Show line numbers in code blocks": "Rādīt rindu numurus koda blokos",
|
||||||
|
"Expand code blocks by default": "Izvērst koda blokus pēc noklusējuma",
|
||||||
|
"Autoplay videos": "Automātski atskaņot videoklipus",
|
||||||
|
"Autoplay GIFs": "Automātiski atskaņot GIF",
|
||||||
|
"Show read receipts sent by other users": "Rādīt izlasīšanas apliecinājumus no citiem lietotājiem",
|
||||||
|
"Show a placeholder for removed messages": "Rādīt dzēstu ziņu vietturus",
|
||||||
|
"Use custom size": "Izmantot pielāgotu izmēru",
|
||||||
|
"Font size": "Šrifta izmērs",
|
||||||
|
"Call ended": "Zvans beidzās",
|
||||||
|
"Guest": "Viesis",
|
||||||
|
"Dates are often easy to guess": "Datumi bieži vien ir viegli uzminami",
|
||||||
|
"%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s noņēma piespraustu ziņu šajā istabā. Skatīt visas piespraustās ziņas.",
|
||||||
|
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s noņēma piespraustu <a>ziņu</a> šajā istabā. Skatīt visas <b>piespraustās ziņas</b>.",
|
||||||
|
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s piesprauda ziņu šajā istabā. Skatīt visas piespraustās ziņas.",
|
||||||
|
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s piesprauda <a>ziņu</a> šajā istabā. Skatīt visas <b>piespraustās ziņas</b>."
|
||||||
}
|
}
|
||||||
|
|
|
@ -902,7 +902,7 @@
|
||||||
"Select the roles required to change various parts of the room": "Selecteer de vereiste rollen om verschillende delen van het gesprek te wijzigen",
|
"Select the roles required to change various parts of the room": "Selecteer de vereiste rollen om verschillende delen van het gesprek te wijzigen",
|
||||||
"Enable encryption?": "Versleuteling inschakelen?",
|
"Enable encryption?": "Versleuteling inschakelen?",
|
||||||
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Kamerversleuteling is onomkeerbaar. Berichten in versleutelde kamers zijn niet leesbaar voor de server; enkel voor de deelnemers. Veel robots en bruggen werken niet correct in versleutelde kamers. <a>Lees meer over versleuteling.</a>",
|
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Kamerversleuteling is onomkeerbaar. Berichten in versleutelde kamers zijn niet leesbaar voor de server; enkel voor de deelnemers. Veel robots en bruggen werken niet correct in versleutelde kamers. <a>Lees meer over versleuteling.</a>",
|
||||||
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Wijzigingen aan wie de geschiedenis kan lezen gelden enkel voor toekomstige berichten in dit gesprek. De zichtbaarheid van de bestaande geschiedenis blijft ongewijzigd.",
|
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Wijzigingen aan de leesregels van de geschiedenis gelden alleen voor toekomstige berichten in deze kamer. De zichtbaarheid van de bestaande geschiedenis blijft ongewijzigd.",
|
||||||
"Encryption": "Versleuteling",
|
"Encryption": "Versleuteling",
|
||||||
"Once enabled, encryption cannot be disabled.": "Eenmaal ingeschakeld kan versleuteling niet meer worden uitgeschakeld.",
|
"Once enabled, encryption cannot be disabled.": "Eenmaal ingeschakeld kan versleuteling niet meer worden uitgeschakeld.",
|
||||||
"Encrypted": "Versleuteld",
|
"Encrypted": "Versleuteld",
|
||||||
|
@ -1271,7 +1271,7 @@
|
||||||
"Find a room…": "Zoek een gesprek…",
|
"Find a room…": "Zoek een gesprek…",
|
||||||
"Find a room… (e.g. %(exampleRoom)s)": "Zoek een gesprek… (bv. %(exampleRoom)s)",
|
"Find a room… (e.g. %(exampleRoom)s)": "Zoek een gesprek… (bv. %(exampleRoom)s)",
|
||||||
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Als u de kamer niet kunt vinden is het mogelijk privé, vraag dan om een uitnodiging of <a>maak een nieuwe kamer aan</a>.",
|
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Als u de kamer niet kunt vinden is het mogelijk privé, vraag dan om een uitnodiging of <a>maak een nieuwe kamer aan</a>.",
|
||||||
"Explore rooms": "Ontdek kamers",
|
"Explore rooms": "Kamers ontdekken",
|
||||||
"Show previews/thumbnails for images": "Miniaturen voor afbeeldingen tonen",
|
"Show previews/thumbnails for images": "Miniaturen voor afbeeldingen tonen",
|
||||||
"Clear cache and reload": "Cache wissen en herladen",
|
"Clear cache and reload": "Cache wissen en herladen",
|
||||||
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "U staat op het punt 1 bericht door %(user)s te verwijderen. Dit kan niet ongedaan gemaakt worden. Wilt u doorgaan?",
|
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "U staat op het punt 1 bericht door %(user)s te verwijderen. Dit kan niet ongedaan gemaakt worden. Wilt u doorgaan?",
|
||||||
|
@ -2345,7 +2345,7 @@
|
||||||
"Page Down": "Page Down",
|
"Page Down": "Page Down",
|
||||||
"Esc": "Esc",
|
"Esc": "Esc",
|
||||||
"Enter": "Enter",
|
"Enter": "Enter",
|
||||||
"Space": "Spatie",
|
"Space": "Ruimte",
|
||||||
"Ctrl": "Ctrl",
|
"Ctrl": "Ctrl",
|
||||||
"Super": "Super",
|
"Super": "Super",
|
||||||
"Shift": "Shift",
|
"Shift": "Shift",
|
||||||
|
@ -2977,7 +2977,7 @@
|
||||||
"Connection failed": "Verbinding mislukt",
|
"Connection failed": "Verbinding mislukt",
|
||||||
"Could not connect media": "Mediaverbinding mislukt",
|
"Could not connect media": "Mediaverbinding mislukt",
|
||||||
"Spaces with access": "Ruimtes met toegang",
|
"Spaces with access": "Ruimtes met toegang",
|
||||||
"Anyone in a space can find and join. <a>Edit which spaces can access here.</a>": "Iedereen in een ruimte kan zoeken en deelnemen. <a>Wijzig hier welke ruimtes toegang hebben.</a>",
|
"Anyone in a space can find and join. <a>Edit which spaces can access here.</a>": "Iedereen in een ruimte kan hem vinden en deelnemen. <a>Wijzig hier welke ruimtes toegang hebben.</a>",
|
||||||
"Currently, %(count)s spaces have access|other": "Momenteel hebben %(count)s ruimtes toegang",
|
"Currently, %(count)s spaces have access|other": "Momenteel hebben %(count)s ruimtes toegang",
|
||||||
"& %(count)s more|other": "& %(count)s meer",
|
"& %(count)s more|other": "& %(count)s meer",
|
||||||
"Upgrade required": "Upgrade noodzakelijk",
|
"Upgrade required": "Upgrade noodzakelijk",
|
||||||
|
@ -2997,7 +2997,7 @@
|
||||||
"People with supported clients will be able to join the room without having a registered account.": "Personen met geschikte apps zullen aan de kamer kunnen deelnemen zonder een account te hebben.",
|
"People with supported clients will be able to join the room without having a registered account.": "Personen met geschikte apps zullen aan de kamer kunnen deelnemen zonder een account te hebben.",
|
||||||
"Decide who can join %(roomName)s.": "Kies wie kan deelnemen aan %(roomName)s.",
|
"Decide who can join %(roomName)s.": "Kies wie kan deelnemen aan %(roomName)s.",
|
||||||
"Space members": "Ruimte leden",
|
"Space members": "Ruimte leden",
|
||||||
"Anyone in a space can find and join. You can select multiple spaces.": "Iedereen in een ruimte kan zoeken en deelnemen. U kunt meerdere ruimtes selecteren.",
|
"Anyone in a space can find and join. You can select multiple spaces.": "Iedereen in een ruimte kan hem vinden en deelnemen. U kunt meerdere ruimtes selecteren.",
|
||||||
"Visible to space members": "Zichtbaar voor ruimte leden",
|
"Visible to space members": "Zichtbaar voor ruimte leden",
|
||||||
"Public room": "Openbaar gesprek",
|
"Public room": "Openbaar gesprek",
|
||||||
"Private room (invite only)": "Privégesprek (alleen op uitnodiging)",
|
"Private room (invite only)": "Privégesprek (alleen op uitnodiging)",
|
||||||
|
@ -3035,7 +3035,7 @@
|
||||||
"Search for rooms or spaces": "Kamers of ruimtes zoeken",
|
"Search for rooms or spaces": "Kamers of ruimtes zoeken",
|
||||||
"Add space": "Ruimte toevoegen",
|
"Add space": "Ruimte toevoegen",
|
||||||
"Leave %(spaceName)s": "%(spaceName)s verlaten",
|
"Leave %(spaceName)s": "%(spaceName)s verlaten",
|
||||||
"You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "U bent de enige beheerder van sommige kamers of spaces die u wilt verlaten. Door deze te verlaten hebben ze geen beheerder meer.",
|
"You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "U bent de enige beheerder van sommige kamers of ruimtes die u wilt verlaten. Door deze te verlaten hebben ze geen beheerder meer.",
|
||||||
"You're the only admin of this space. Leaving it will mean no one has control over it.": "U bent de enige beheerder van deze ruimte. Door het te verlaten zal er niemand meer controle over hebben.",
|
"You're the only admin of this space. Leaving it will mean no one has control over it.": "U bent de enige beheerder van deze ruimte. Door het te verlaten zal er niemand meer controle over hebben.",
|
||||||
"You won't be able to rejoin unless you are re-invited.": "U kunt niet opnieuw deelnemen behalve als u opnieuw wordt uitgenodigd.",
|
"You won't be able to rejoin unless you are re-invited.": "U kunt niet opnieuw deelnemen behalve als u opnieuw wordt uitgenodigd.",
|
||||||
"Search %(spaceName)s": "Zoek %(spaceName)s",
|
"Search %(spaceName)s": "Zoek %(spaceName)s",
|
||||||
|
@ -3094,7 +3094,7 @@
|
||||||
"A link to the Space will be put in your community description.": "In de gemeenschapsomschrijving zal een link naar deze ruimte worden geplaatst.",
|
"A link to the Space will be put in your community description.": "In de gemeenschapsomschrijving zal een link naar deze ruimte worden geplaatst.",
|
||||||
"Create Space from community": "Ruimte van gemeenschap maken",
|
"Create Space from community": "Ruimte van gemeenschap maken",
|
||||||
"Failed to migrate community": "Omzetten van de gemeenschap is mislukt",
|
"Failed to migrate community": "Omzetten van de gemeenschap is mislukt",
|
||||||
"To create a Space from another community, just pick the community in Preferences.": "Om een Space te maken van een gemeenschap kiest u de gemeenschap in Instellingen.",
|
"To create a Space from another community, just pick the community in Preferences.": "Om een ruimte te maken van een gemeenschap kiest u de gemeenschap in Instellingen.",
|
||||||
"<SpaceName/> has been made and everyone who was a part of the community has been invited to it.": "<SpaceName/> is gemaakt en iedereen die lid was van de gemeenschap is ervoor uitgenodigd.",
|
"<SpaceName/> has been made and everyone who was a part of the community has been invited to it.": "<SpaceName/> is gemaakt en iedereen die lid was van de gemeenschap is ervoor uitgenodigd.",
|
||||||
"Space created": "Ruimte aangemaakt",
|
"Space created": "Ruimte aangemaakt",
|
||||||
"To view Spaces, hide communities in <a>Preferences</a>": "Om ruimtes te zien, verberg gemeenschappen in uw <a>Instellingen</a>",
|
"To view Spaces, hide communities in <a>Preferences</a>": "Om ruimtes te zien, verberg gemeenschappen in uw <a>Instellingen</a>",
|
||||||
|
@ -3142,7 +3142,7 @@
|
||||||
"Change main address for the space": "Hoofdadres van ruimte wijzigen",
|
"Change main address for the space": "Hoofdadres van ruimte wijzigen",
|
||||||
"Change space name": "Ruimtenaam wijzigen",
|
"Change space name": "Ruimtenaam wijzigen",
|
||||||
"Change space avatar": "Ruimte-afbeelding wijzigen",
|
"Change space avatar": "Ruimte-afbeelding wijzigen",
|
||||||
"Anyone in <spaceName/> can find and join. You can select other spaces too.": "Iedereen in <spaceName/> kan zoeken en deelnemen. U kunt ook andere ruimtes selecteren.",
|
"Anyone in <spaceName/> can find and join. You can select other spaces too.": "Iedereen in <spaceName/> kan hem vinden en deelnemen. U kunt ook andere ruimtes selecteren.",
|
||||||
"Message didn't send. Click for info.": "Bericht is niet verstuur. Klik voor meer info.",
|
"Message didn't send. Click for info.": "Bericht is niet verstuur. Klik voor meer info.",
|
||||||
"To join %(communityName)s, swap to communities in your <a>preferences</a>": "Om aan %(communityName)s deel te nemen, wissel naar gemeenschappen in uw <a>instellingen</a>",
|
"To join %(communityName)s, swap to communities in your <a>preferences</a>": "Om aan %(communityName)s deel te nemen, wissel naar gemeenschappen in uw <a>instellingen</a>",
|
||||||
"To view %(communityName)s, swap to communities in your <a>preferences</a>": "Om %(communityName)s te bekijken, wissel naar gemeenschappen in uw <a>instellingen</a>",
|
"To view %(communityName)s, swap to communities in your <a>preferences</a>": "Om %(communityName)s te bekijken, wissel naar gemeenschappen in uw <a>instellingen</a>",
|
||||||
|
@ -3164,5 +3164,42 @@
|
||||||
"You are about to leave <spaceName/>.": "U staat op het punt <spaceName/> te verlaten.",
|
"You are about to leave <spaceName/>.": "U staat op het punt <spaceName/> te verlaten.",
|
||||||
"Leave some rooms": "Sommige kamers verlaten",
|
"Leave some rooms": "Sommige kamers verlaten",
|
||||||
"Leave all rooms": "Alle kamers verlaten",
|
"Leave all rooms": "Alle kamers verlaten",
|
||||||
"Don't leave any rooms": "Geen kamers verlaten"
|
"Don't leave any rooms": "Geen kamers verlaten",
|
||||||
|
"Expand quotes │ ⇧+click": "Quotes uitvouwen │ ⇧+click",
|
||||||
|
"Collapse quotes │ ⇧+click": "Quotes invouwen │ ⇧+click",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s Verstuurde een sticker.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s veranderde de kamerafbeelding.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s om %(time)s",
|
||||||
|
"Include Attachments": "Bijlages toevoegen",
|
||||||
|
"Size Limit": "Bestandsgrootte",
|
||||||
|
"Format": "Formaat",
|
||||||
|
"Select from the options below to export chats from your timeline": "Selecteer met welke opties u uw chats wilt exporteren van uw tijdlijn",
|
||||||
|
"Export Chat": "Chat exporteren",
|
||||||
|
"Exporting your data": "Uw data aan het exporteren",
|
||||||
|
"Stop": "Stop",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Weet u zeker dat u wilt stoppen terwijl u uw data exporteert? Als u dit doet moet u later opnieuw beginnen.",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "Uw export was succesvol. U vindt hem in uw Downloads-map.",
|
||||||
|
"The export was cancelled successfully": "De export was succesvol geannulleerd",
|
||||||
|
"Export Successful": "Export succesvol",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "Berichten aantal",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "Aantal berichten moet een getal zijn tussen %(min)s en %(max)s",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "Bestand moet een grootte hebben tussen %(min)s MB en %(max)s MB",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "Voer een nummer tussen %(min)s en %(max)s in",
|
||||||
|
"In reply to <a>this message</a>": "In antwoord op <a>dit bericht</a>",
|
||||||
|
"Export chat": "Chat exporteren",
|
||||||
|
"File Attached": "Bijgevoegd bestand",
|
||||||
|
"Error fetching file": "Fout bij bestand opvragen",
|
||||||
|
"Topic: %(topic)s": "Onderwerp: %(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "Dit is de start van de export van <roomName/>. Geëxporteerd door <exporterDetails/> op %(exportDate)s.",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s heeft deze kamer gemaakt.",
|
||||||
|
"Media omitted - file size limit exceeded": "Media weggelaten - limiet bestandsgrootte overschreden",
|
||||||
|
"Media omitted": "Media weglaten",
|
||||||
|
"Current Timeline": "Huidige tijdlijn",
|
||||||
|
"Specify a number of messages": "Kies het aantal berichten",
|
||||||
|
"From the beginning": "Van het begin",
|
||||||
|
"Plain Text": "Platte tekst",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "Weet u zeker dat u wilt afsluiten tijdens een export?"
|
||||||
}
|
}
|
||||||
|
|
|
@ -933,7 +933,7 @@
|
||||||
"Show hidden events in timeline": "Pokaż ukryte wydarzenia na linii czasowej",
|
"Show hidden events in timeline": "Pokaż ukryte wydarzenia na linii czasowej",
|
||||||
"Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Pozwól na awaryjny serwer wspomagania połączeń turn.matrix.org, gdy Twój serwer domowy takiego nie oferuje (Twój adres IP będzie udostępniony podczas połączenia)",
|
"Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Pozwól na awaryjny serwer wspomagania połączeń turn.matrix.org, gdy Twój serwer domowy takiego nie oferuje (Twój adres IP będzie udostępniony podczas połączenia)",
|
||||||
"Messages containing my username": "Wiadomości zawierające moją nazwę użytkownika",
|
"Messages containing my username": "Wiadomości zawierające moją nazwę użytkownika",
|
||||||
"Encrypted messages in one-to-one chats": "Zaszyforwane wiadomości w rozmowach jeden-do-jednego",
|
"Encrypted messages in one-to-one chats": "Zaszyfrowane wiadomości w rozmowach jeden-do-jednego",
|
||||||
"Encrypted messages in group chats": "Zaszyfrowane wiadomości w rozmowach grupowych",
|
"Encrypted messages in group chats": "Zaszyfrowane wiadomości w rozmowach grupowych",
|
||||||
"When rooms are upgraded": "Kiedy pokoje są uaktualniane",
|
"When rooms are upgraded": "Kiedy pokoje są uaktualniane",
|
||||||
"The other party cancelled the verification.": "Druga strona anulowała weryfikację.",
|
"The other party cancelled the verification.": "Druga strona anulowała weryfikację.",
|
||||||
|
@ -1068,7 +1068,7 @@
|
||||||
"Find a room… (e.g. %(exampleRoom)s)": "Znajdź pokój… (np. %(exampleRoom)s)",
|
"Find a room… (e.g. %(exampleRoom)s)": "Znajdź pokój… (np. %(exampleRoom)s)",
|
||||||
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Jeżeli nie możesz znaleźć szukanego pokoju, poproś o zaproszenie albo <a>stwórz nowy pokój</a>.",
|
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Jeżeli nie możesz znaleźć szukanego pokoju, poproś o zaproszenie albo <a>stwórz nowy pokój</a>.",
|
||||||
"Show typing notifications": "Pokazuj powiadomienia o pisaniu",
|
"Show typing notifications": "Pokazuj powiadomienia o pisaniu",
|
||||||
"Match system theme": "Dopasuj do motywu systemego",
|
"Match system theme": "Dopasuj do motywu systemowego",
|
||||||
"They match": "Pasują do siebie",
|
"They match": "Pasują do siebie",
|
||||||
"They don't match": "Nie pasują do siebie",
|
"They don't match": "Nie pasują do siebie",
|
||||||
"Upload": "Prześlij",
|
"Upload": "Prześlij",
|
||||||
|
|
|
@ -3138,5 +3138,62 @@
|
||||||
"%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s открепляет сообщение из этой комнаты. Просмотрите все прикрепленые сообщения.",
|
"%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s открепляет сообщение из этой комнаты. Просмотрите все прикрепленые сообщения.",
|
||||||
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s открепляет <a>сообщение</a> из этой комнаты. Просмотрите все <b>прикрепленые сообщения</b>.",
|
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s открепляет <a>сообщение</a> из этой комнаты. Просмотрите все <b>прикрепленые сообщения</b>.",
|
||||||
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикрепляет сообщение в этой комнате. Просмотрите все прикрепленные сообщения.",
|
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикрепляет сообщение в этой комнате. Просмотрите все прикрепленные сообщения.",
|
||||||
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s прикрепляет <a>сообщение</a> в этой комнате. Просмотрите все <b>прикрепленые сообщения</b>."
|
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s прикрепляет <a>сообщение</a> в этой комнате. Просмотрите все <b>прикрепленые сообщения</b>.",
|
||||||
|
"To join this Space, hide communities in your <a>preferences</a>": "Чтобы присоединиться к этому пространству, скройте сообщества в ваших <a>настройках</a>",
|
||||||
|
"To view this Space, hide communities in your <a>preferences</a>": "Чтобы просмотреть это пространство, скройте сообщества в ваших <a>настройках</a>",
|
||||||
|
"To join %(communityName)s, swap to communities in your <a>preferences</a>": "Чтобы присоединиться к %(communityName)s, переключитесь на сообщества в ваших <a>настройках</a>",
|
||||||
|
"To view %(communityName)s, swap to communities in your <a>preferences</a>": "Для просмотра %(communityName)s, переключитесь на сообщества в ваших <a>настройках</a>",
|
||||||
|
"Private community": "Приватное сообщество",
|
||||||
|
"Public community": "Публичное сообщество",
|
||||||
|
"Leave some rooms": "Покинуть несколько комнат",
|
||||||
|
"Leave all rooms": "Покинуть все комнаты",
|
||||||
|
"Don't leave any rooms": "Не покидать ни одну комнату",
|
||||||
|
"Would you like to leave the rooms in this space?": "Хотите ли вы покинуть комнаты в этом пространстве?",
|
||||||
|
"You are about to leave <spaceName/>.": "Вы собираетесь покинуть <spaceName/>.",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s отреагировали %(content)s",
|
||||||
|
"Expand quotes │ ⇧+click": "Развернуть цитаты │ ⇧+нажатие",
|
||||||
|
"Collapse quotes │ ⇧+click": "Свернуть цитаты │ ⇧+нажатие",
|
||||||
|
"Message": "Сообщение",
|
||||||
|
"Joining space …": "Присоединение к пространству…",
|
||||||
|
"Message didn't send. Click for info.": "Сообщение не отправлено. Нажмите для получения информации.",
|
||||||
|
"Upgrade anyway": "Обновить в любом случае",
|
||||||
|
"This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Эта комната находится в некоторых пространствах, администратором которых вы не являетесь. В этих пространствах старая комната будет по-прежнему отображаться, но людям будет предложено присоединиться к новой.",
|
||||||
|
"Before you upgrade": "Перед обновлением",
|
||||||
|
"To join a space you'll need an invite.": "Чтобы присоединиться к пространству, вам нужно получить приглашение.",
|
||||||
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Временно показывать сообщества вместо пространств для этой сессии. Поддержка этого будет удалена в ближайшем будущем. Это перезагрузит Element.",
|
||||||
|
"Display Communities instead of Spaces": "Показывать сообщества вместо пространств",
|
||||||
|
"You can also make Spaces from <a>communities</a>.": "Вы также можете создать пространство из <a>сообщества</a>.",
|
||||||
|
"Include Attachments": "Включить вложения",
|
||||||
|
"Size Limit": "Ограничение по размеру",
|
||||||
|
"Format": "Формат",
|
||||||
|
"Export Chat": "Экспорт чата",
|
||||||
|
"Exporting your data": "Экспорт ваших данных",
|
||||||
|
"Stop": "Стоп",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Вы уверены, что хотите прекратить экспорт данных? Если да, то вам придется начать все сначала.",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "Ваш экспорт звершен. Найдите его в папке \"Загрузки\".",
|
||||||
|
"The export was cancelled successfully": "Экспорт был отменен",
|
||||||
|
"Export Successful": "Экспорт завершен",
|
||||||
|
"MB": "Мб",
|
||||||
|
"Number of messages": "Количество сообщений",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "Количество сообщений может быть только числом между %(min)s и %(max)s",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "Размер может быть только числом между %(min)s Мб и %(max)s Мб",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "Введите число между %(min)s и %(max)s",
|
||||||
|
"In reply to <a>this message</a>": "В ответ на <a>это сообщение</a>",
|
||||||
|
"Export chat": "Экспорт чата",
|
||||||
|
"File Attached": "Файл прикреплен",
|
||||||
|
"Error fetching file": "Ошибка при получении файла",
|
||||||
|
"Topic: %(topic)s": "Тема: %(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "Это начало экспорта <roomName/>. Экспортировано <exporterDetails/> в %(exportDate)s.",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s создал(а) эту комнату.",
|
||||||
|
"Media omitted - file size limit exceeded": "Медиа пропущены - превышен лимит размера файла",
|
||||||
|
"Media omitted": "Медиа пропущены",
|
||||||
|
"Specify a number of messages": "Укажите количество сообщений",
|
||||||
|
"From the beginning": "С начала",
|
||||||
|
"Plain Text": "Текст",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "Вы уверены, что хотите выйти во время экспорта?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s отправил(а) стикер.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s сменил(а) аватар комнаты.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s в %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3161,5 +3161,42 @@
|
||||||
"You are about to leave <spaceName/>.": "Ju ndan një hap nga braktisja e <spaceName/>.",
|
"You are about to leave <spaceName/>.": "Ju ndan një hap nga braktisja e <spaceName/>.",
|
||||||
"Leave some rooms": "Braktis disa dhoma",
|
"Leave some rooms": "Braktis disa dhoma",
|
||||||
"Leave all rooms": "Braktisi krejt dhomat",
|
"Leave all rooms": "Braktisi krejt dhomat",
|
||||||
"Don't leave any rooms": "Mos braktis ndonjë dhomë"
|
"Don't leave any rooms": "Mos braktis ndonjë dhomë",
|
||||||
|
"Expand quotes │ ⇧+click": "Hapi citimet │ ⇧+klikim",
|
||||||
|
"Collapse quotes │ ⇧+click": "Tkurri citimet │ ⇧+klikim",
|
||||||
|
"Format": "Format",
|
||||||
|
"MB": "MB",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Include Attachments": "Përfshi Bashkëngjitje",
|
||||||
|
"Size Limit": "Kufi Madhësie",
|
||||||
|
"Select from the options below to export chats from your timeline": "Që të eksportohen fjalosje prej rrjedhës tuaj kohore, përzgjidhni prej mundësive më poshtë",
|
||||||
|
"Export Chat": "Eksportoni Fjalosje",
|
||||||
|
"Exporting your data": "Eksportim i të dhënave tuaja",
|
||||||
|
"Stop": "Ndale",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Jeni i sigurt se doni të ndalet eksportimi i të dhënave tuaja? Nëse po, do t’ju duhet t’ia filloni nga e para.",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "Eksportimi juaj qe i suksesshëm. E keni te dosja juaj Shkarkime.",
|
||||||
|
"The export was cancelled successfully": "Eksportimi u anulua me sukses",
|
||||||
|
"Export Successful": "Eksportim i Suksesshëm",
|
||||||
|
"Number of messages": "Numër mesazhesh",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "Numri i mesazheve mund të jetë vetëm një numër mes %(min)s dhe %(max)s",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "Madhësia mund të jetë vetëm një numër mes %(min)s MB dhe %(max)s MB",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "Jepni një numër mes %(min)s dhe %(max)s",
|
||||||
|
"In reply to <a>this message</a>": "Në përgjigje të <a>këtij mesazhi</a>",
|
||||||
|
"Export chat": "Eksportoni fjalosje",
|
||||||
|
"File Attached": "Kartelë Bashkëngjitur",
|
||||||
|
"Error fetching file": "Gabim në sjellje kartele",
|
||||||
|
"Topic: %(topic)s": "Temë: %(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "Ky është fillimi i eksportimit të <roomName/>. Eksportuar nga <exporterDetails/> më %(exportDate)s.",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s krijoi këtë dhomë.",
|
||||||
|
"Media omitted - file size limit exceeded": "U la jashtë media - u tejkalua kufi madhësie kartele",
|
||||||
|
"Media omitted": "U la jashtë media",
|
||||||
|
"Current Timeline": "Rrjedhë Kohore e Tanishme",
|
||||||
|
"Specify a number of messages": "Përcaktoni një numër mesazhesh",
|
||||||
|
"From the beginning": "Që nga fillimi",
|
||||||
|
"Plain Text": "Tekst i Thjeshtë",
|
||||||
|
"Are you sure you want to exit during this export?": "Jeni i sigurt se doni të dilet gjatë këtij eksportimi?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s dërgoi një ngjitës.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s ndryshoi avatarin e dhomës.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s më %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3159,5 +3159,10 @@
|
||||||
"To join a space you'll need an invite.": "För att gå med i ett utrymme så behöver du en inbjudan.",
|
"To join a space you'll need an invite.": "För att gå med i ett utrymme så behöver du en inbjudan.",
|
||||||
"You can also make Spaces from <a>communities</a>.": "Du kan också göra utrymmen av <a>gemenskaper</a>.",
|
"You can also make Spaces from <a>communities</a>.": "Du kan också göra utrymmen av <a>gemenskaper</a>.",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Visa tillfälligt gemenskaper istället för utrymmen för den här sessionen. Stöd för detta kommer snart att tas bort. Detta kommer att ladda om Element.",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Visa tillfälligt gemenskaper istället för utrymmen för den här sessionen. Stöd för detta kommer snart att tas bort. Detta kommer att ladda om Element.",
|
||||||
"Display Communities instead of Spaces": "Visa gemenskaper istället för utrymmen"
|
"Display Communities instead of Spaces": "Visa gemenskaper istället för utrymmen",
|
||||||
|
"Would you like to leave the rooms in this space?": "Vill du lämna rummen i det här utrymmet?",
|
||||||
|
"You are about to leave <spaceName/>.": "Du kommer att lämna <spaceName/>.",
|
||||||
|
"Leave some rooms": "Lämna vissa rum",
|
||||||
|
"Leave all rooms": "Lämna alla rum",
|
||||||
|
"Don't leave any rooms": "Lämna inga rum"
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
"Anyone": "Кожний",
|
"Anyone": "Кожний",
|
||||||
"Are you sure?": "Ви впевнені?",
|
"Are you sure?": "Ви впевнені?",
|
||||||
"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»?",
|
||||||
"Are you sure you want to reject the invitation?": "Ви впевнені, що ви хочете відхилити запрошення?",
|
"Are you sure you want to reject the invitation?": "Ви впевнені, що хочете відхилити запрошення?",
|
||||||
"Attachment": "Прикріплення",
|
"Attachment": "Прикріплення",
|
||||||
"Ban": "Заблокувати",
|
"Ban": "Заблокувати",
|
||||||
"Banned users": "Заблоковані користувачі",
|
"Banned users": "Заблоковані користувачі",
|
||||||
|
@ -511,12 +511,12 @@
|
||||||
"Command failed": "Не вдалося виконати команду",
|
"Command failed": "Не вдалося виконати команду",
|
||||||
"Could not find user in room": "Не вдалося знайти користувача в кімнаті",
|
"Could not find user in room": "Не вдалося знайти користувача в кімнаті",
|
||||||
"Please supply a widget URL or embed code": "Вкажіть URL або код вбудовування розширення",
|
"Please supply a widget URL or embed code": "Вкажіть URL або код вбудовування розширення",
|
||||||
"Verifies a user, session, and pubkey tuple": "Звіряє користувача, сеанс та кортеж відкритого ключа",
|
"Verifies a user, session, and pubkey tuple": "Звіряє користувача, сеанс та супровід відкритого ключа",
|
||||||
"Unknown (user, session) pair:": "Невідома пара (користувача, сеансу):",
|
"Unknown (user, session) pair:": "Невідома пара (користувача, сеансу):",
|
||||||
"Session already verified!": "Сеанс вже підтверджений!",
|
"Session already verified!": "Сеанс вже звірено!",
|
||||||
"WARNING: Session already verified, but keys do NOT MATCH!": "УВАГА: Сеанс вже підтверджений, проте ключі НЕ ЗБІГАЮТЬСЯ!",
|
"WARNING: Session already verified, but keys do NOT MATCH!": "УВАГА: Сеанс вже звірено, проте ключі НЕ ЗБІГАЮТЬСЯ!",
|
||||||
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "УВАГА: НЕ ВДАЛОСЯ ЗДІЙСНИТИ ЗВІРЯННЯ КЛЮЧА! Ключем для %(userId)s та сеансу %(deviceId)s є \"%(fprint)s\", що не відповідає наданому ключу \"%(fingerprint)s\". Це може означати, що ваші повідомлення перехоплюють!",
|
"WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "УВАГА: НЕ ВДАЛОСЯ ЗВІРИТИ КЛЮЧ! Ключем для %(userId)s та сеансу %(deviceId)s є «%(fprint)s», що не збігається з наданим ключем «%(fingerprint)s». Це може означати, що ваші повідомлення перехоплюють!",
|
||||||
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Наданий вами ключ підпису збігається з ключем підпису, що ви отримали від сеансу %(deviceId)s %(userId)s. Сеанс позначено як звірений.",
|
"The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Наданий вами ключ підпису збігається з ключем підпису, що ви отримали від сеансу %(deviceId)s %(userId)s. Сеанс позначено звіреним.",
|
||||||
"Sends the given emote coloured as a rainbow": "Надсилає вказаний смайлик, розфарбований веселкою",
|
"Sends the given emote coloured as a rainbow": "Надсилає вказаний смайлик, розфарбований веселкою",
|
||||||
"Displays list of commands with usages and descriptions": "Відбиває перелік команд із прикладами вжитку та описом",
|
"Displays list of commands with usages and descriptions": "Відбиває перелік команд із прикладами вжитку та описом",
|
||||||
"Displays information about a user": "Показує відомості про користувача",
|
"Displays information about a user": "Показує відомості про користувача",
|
||||||
|
@ -559,10 +559,10 @@
|
||||||
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування серверів зі збігом з %(glob)s через %(reason)s",
|
"%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування серверів зі збігом з %(glob)s через %(reason)s",
|
||||||
"Light": "Світла",
|
"Light": "Світла",
|
||||||
"Dark": "Темна",
|
"Dark": "Темна",
|
||||||
"You signed in to a new session without verifying it:": "Ви увійшли в новий сеанс, не підтвердивши його:",
|
"You signed in to a new session without verifying it:": "Ви увійшли в новий сеанс, не звіривши його:",
|
||||||
"Verify your other session using one of the options below.": "Перевірте інший сеанс за допомогою одного із варіантів знизу.",
|
"Verify your other session using one of the options below.": "Звірте інший сеанс за допомогою одного з варіантів знизу.",
|
||||||
"%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) починає новий сеанс без його підтвердження:",
|
"%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) починає новий сеанс без його звірення:",
|
||||||
"Ask this user to verify their session, or manually verify it below.": "Попросіть цього користувача підтвердити сеанс, або підтвердьте його власноруч унизу.",
|
"Ask this user to verify their session, or manually verify it below.": "Попросіть цього користувача звірити сеанс, або звірте його власноруч унизу.",
|
||||||
"Not Trusted": "Не довірений",
|
"Not Trusted": "Не довірений",
|
||||||
"Manually Verify by Text": "Ручна перевірка за допомогою тексту",
|
"Manually Verify by Text": "Ручна перевірка за допомогою тексту",
|
||||||
"Interactively verify by Emoji": "Інтерактивно звірити за допомогою емодзі",
|
"Interactively verify by Emoji": "Інтерактивно звірити за допомогою емодзі",
|
||||||
|
@ -907,7 +907,7 @@
|
||||||
"Upgrade public room": "Поліпшити відкриту кімнату",
|
"Upgrade public room": "Поліпшити відкриту кімнату",
|
||||||
"Restore your key backup to upgrade your encryption": "Відновіть резервну копію вашого ключа, щоб поліпшити шифрування",
|
"Restore your key backup to upgrade your encryption": "Відновіть резервну копію вашого ключа, щоб поліпшити шифрування",
|
||||||
"You'll need to authenticate with the server to confirm the upgrade.": "Ви матимете пройти розпізнання на сервері щоб підтвердити поліпшування.",
|
"You'll need to authenticate with the server to confirm the upgrade.": "Ви матимете пройти розпізнання на сервері щоб підтвердити поліпшування.",
|
||||||
"Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Поліпште цей сеанс щоб уможливити звіряння інших сеансів, надаючи їм доступ до зашифрованих повідомлень та позначуючи їх довіреними для інших користувачів.",
|
"Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Оновіть цей сеанс, щоб уможливити звірення інших сеансів, надаючи їм доступ до зашифрованих повідомлень та позначаючи їх довіреними для інших користувачів.",
|
||||||
"Upgrade your encryption": "Поліпшити ваше шифрування",
|
"Upgrade your encryption": "Поліпшити ваше шифрування",
|
||||||
"Show a placeholder for removed messages": "Показувати замісну позначку замість видалених повідомлень",
|
"Show a placeholder for removed messages": "Показувати замісну позначку замість видалених повідомлень",
|
||||||
"Show join/leave messages (invites/kicks/bans unaffected)": "Показувати повідомлення про приєднання/вихід (не впливає на запрошення/викидання/блокування)",
|
"Show join/leave messages (invites/kicks/bans unaffected)": "Показувати повідомлення про приєднання/вихід (не впливає на запрошення/викидання/блокування)",
|
||||||
|
@ -971,11 +971,11 @@
|
||||||
"Verify this user by confirming the following emoji appear on their screen.": "Звірте цього користувача підтвердженням того, що наступні емодзі з'являються на його екрані.",
|
"Verify this user by confirming the following emoji appear on their screen.": "Звірте цього користувача підтвердженням того, що наступні емодзі з'являються на його екрані.",
|
||||||
"Emoji picker": "Обирач емодзі",
|
"Emoji picker": "Обирач емодзі",
|
||||||
"The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "Сеанс, який ви намагаєтесь звірити, не підтримує сканування QR-коду або звіряння за допомогою емодзі, що є підтримувані %(brand)s. Спробуйте використати інший клієнт.",
|
"The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "Сеанс, який ви намагаєтесь звірити, не підтримує сканування QR-коду або звіряння за допомогою емодзі, що є підтримувані %(brand)s. Спробуйте використати інший клієнт.",
|
||||||
"If you can't scan the code above, verify by comparing unique emoji.": "Якщо ви не можете відсканувати вищезазначений код, звірте порівнянням унікальних емодзі.",
|
"If you can't scan the code above, verify by comparing unique emoji.": "Якщо ви не можете сканувати зазначений код, звірте порівнянням унікальних емодзі.",
|
||||||
"Verify by comparing unique emoji.": "Звірити порівнянням унікальних емодзі.",
|
"Verify by comparing unique emoji.": "Звірити порівнянням унікальних емодзі.",
|
||||||
"Verify by emoji": "Звірити за допомогою емодзі",
|
"Verify by emoji": "Звірити за допомогою емодзі",
|
||||||
"Compare emoji": "Порівняти емодзі",
|
"Compare emoji": "Порівняти емодзі",
|
||||||
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс тепер є звірений. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його як довірений.",
|
"Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс звірено. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його довіреним.",
|
||||||
"Emoji": "Емодзі",
|
"Emoji": "Емодзі",
|
||||||
"Emoji Autocomplete": "Самодоповнення емодзі",
|
"Emoji Autocomplete": "Самодоповнення емодзі",
|
||||||
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування зі збігом з %(glob)s через %(reason)s",
|
"%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування зі збігом з %(glob)s через %(reason)s",
|
||||||
|
@ -1355,11 +1355,11 @@
|
||||||
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sприєдналися %(count)s разів",
|
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sприєдналися %(count)s разів",
|
||||||
"Members only (since they joined)": "Лише учасники (від часу приєднання)",
|
"Members only (since they joined)": "Лише учасники (від часу приєднання)",
|
||||||
"This room is not accessible by remote Matrix servers": "Ця кімната недоступна для віддалених серверів Matrix",
|
"This room is not accessible by remote Matrix servers": "Ця кімната недоступна для віддалених серверів Matrix",
|
||||||
"Manually verify all remote sessions": "Перевірити всі сеанси власноруч",
|
"Manually verify all remote sessions": "Звірити всі сеанси власноруч",
|
||||||
"Explore rooms": "Каталог кімнат",
|
"Explore rooms": "Каталог кімнат",
|
||||||
"Session key:": "Ключ сеансу:",
|
"Session key:": "Ключ сеансу:",
|
||||||
"Hide sessions": "Сховати сеанси",
|
"Hide sessions": "Сховати сеанси",
|
||||||
"Hide verified sessions": "Сховати підтверджені сеанси",
|
"Hide verified sessions": "Сховати звірені сеанси",
|
||||||
"Session ID:": "ID сеансу:",
|
"Session ID:": "ID сеансу:",
|
||||||
"Click the button below to confirm setting up encryption.": "Клацніть на кнопку внизу, щоб підтвердити налаштування шифрування.",
|
"Click the button below to confirm setting up encryption.": "Клацніть на кнопку внизу, щоб підтвердити налаштування шифрування.",
|
||||||
"Confirm encryption setup": "Підтвердити налаштування шифрування",
|
"Confirm encryption setup": "Підтвердити налаштування шифрування",
|
||||||
|
@ -1377,7 +1377,7 @@
|
||||||
"Try again": "Спробувати ще раз",
|
"Try again": "Спробувати ще раз",
|
||||||
"%(creator)s created this DM.": "%(creator)s створює цю приватну розмову.",
|
"%(creator)s created this DM.": "%(creator)s створює цю приватну розмову.",
|
||||||
"Share Link to User": "Поділитися посиланням на користувача",
|
"Share Link to User": "Поділитися посиланням на користувача",
|
||||||
"Messages here are end-to-end encrypted. Verify %(displayName)s in their profile - tap on their avatar.": "Повідомлення тут захищено наскрізним шифруванням. Підтвердьте %(displayName)s у їхньому профілі — натиснувши на їх аватар.",
|
"Messages here are end-to-end encrypted. Verify %(displayName)s in their profile - tap on their avatar.": "Повідомлення тут захищено наскрізним шифруванням. Звірте %(displayName)s у їхньому профілі — натиснувши на їх аватар.",
|
||||||
"<a>In reply to</a> <pill>": "<a>У відповідь на</a> <pill>",
|
"<a>In reply to</a> <pill>": "<a>У відповідь на</a> <pill>",
|
||||||
"The user you called is busy.": "Користувач, якого ви викликаєте, зайнятий.",
|
"The user you called is busy.": "Користувач, якого ви викликаєте, зайнятий.",
|
||||||
"User Busy": "Користувач зайнятий",
|
"User Busy": "Користувач зайнятий",
|
||||||
|
@ -1419,7 +1419,7 @@
|
||||||
"Not trusted": "Не довірений",
|
"Not trusted": "Не довірений",
|
||||||
"Trusted": "Довірений",
|
"Trusted": "Довірений",
|
||||||
"This backup is trusted because it has been restored on this session": "Ця резервна копія довірена, оскільки її було відновлено у цьому сеансі",
|
"This backup is trusted because it has been restored on this session": "Ця резервна копія довірена, оскільки її було відновлено у цьому сеансі",
|
||||||
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Індивідуально перевіряйте кожен сеанс, який використовується користувачем, щоб позначити його довіреним, не довіряючи пристроям перехресного підписування.",
|
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Індивідуально звіряйте кожен сеанс, який використовується користувачем, щоб позначити його довіреним, не довіряючи пристроям перехресного підписування.",
|
||||||
"To be secure, do this in person or use a trusted way to communicate.": "Для забезпечення безпеки зробіть це особисто або скористайтесь надійним способом зв'язку.",
|
"To be secure, do this in person or use a trusted way to communicate.": "Для забезпечення безпеки зробіть це особисто або скористайтесь надійним способом зв'язку.",
|
||||||
"You can change this at any time from room settings.": "Ви завжди можете змінити це у налаштуваннях кімнати.",
|
"You can change this at any time from room settings.": "Ви завжди можете змінити це у налаштуваннях кімнати.",
|
||||||
"Room settings": "Налаштування кімнати",
|
"Room settings": "Налаштування кімнати",
|
||||||
|
@ -1623,12 +1623,12 @@
|
||||||
"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.": "Ваш домашній сервер намагався відхилити спробу вашого входу. Це може бути пов'язано з занадто тривалим часом входу. Повторіть спробу. Якщо це триватиме й далі, зверніться до адміністратора домашнього сервера.",
|
"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.": "Ваш домашній сервер намагався відхилити спробу вашого входу. Це може бути пов'язано з занадто тривалим часом входу. Повторіть спробу. Якщо це триватиме й далі, зверніться до адміністратора домашнього сервера.",
|
||||||
"Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Ваш домашній сервер був недоступний і вхід не виконано. Повторіть спробу. Якщо це триватиме й далі, зверніться до адміністратора свого домашнього сервера.",
|
"Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Ваш домашній сервер був недоступний і вхід не виконано. Повторіть спробу. Якщо це триватиме й далі, зверніться до адміністратора свого домашнього сервера.",
|
||||||
"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.": "Ми попросили переглядач запам’ятати, який домашній сервер ви використовуєте, щоб дозволити вам увійти, але, на жаль, ваш переглядач забув його. Перейдіть на сторінку входу та повторіть спробу.",
|
"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.": "Ми попросили переглядач запам’ятати, який домашній сервер ви використовуєте, щоб дозволити вам увійти, але, на жаль, ваш переглядач забув його. Перейдіть на сторінку входу та повторіть спробу.",
|
||||||
"You've successfully verified %(deviceName)s (%(deviceId)s)!": "Ви успішно підтвердили %(deviceName)s (%(deviceId)s)!",
|
"You've successfully verified %(deviceName)s (%(deviceId)s)!": "Ви успішно звірили %(deviceName)s (%(deviceId)s)!",
|
||||||
"You've successfully verified your device!": "Ви успішно підтвердили свій пристрій!",
|
"You've successfully verified your device!": "Ви успішно звірили свій пристрій!",
|
||||||
"You've successfully verified %(displayName)s!": "Ви успішно підтвердили %(displayName)s!",
|
"You've successfully verified %(displayName)s!": "Ви успішно звірили %(displayName)s!",
|
||||||
"Almost there! Is %(displayName)s showing the same shield?": "Майже готово! Ваш %(displayName)s показує той самий щит?",
|
"Almost there! Is %(displayName)s showing the same shield?": "Майже готово! Ваш %(displayName)s показує той самий щит?",
|
||||||
"Almost there! Is your other session showing the same shield?": "Майже готово! Ваш інший сеанс показує той самий щит?",
|
"Almost there! Is your other session showing the same shield?": "Майже готово! Ваш інший сеанс показує той самий щит?",
|
||||||
"Verify by scanning": "Підтвердити скануванням",
|
"Verify by scanning": "Звірити скануванням",
|
||||||
"Remove recent messages by %(user)s": "Вилучити останні повідомлення від %(user)s",
|
"Remove recent messages by %(user)s": "Вилучити останні повідомлення від %(user)s",
|
||||||
"Remove recent messages": "Видалити останні повідомлення",
|
"Remove recent messages": "Видалити останні повідомлення",
|
||||||
"Edit devices": "Керувати пристроями",
|
"Edit devices": "Керувати пристроями",
|
||||||
|
@ -1638,11 +1638,11 @@
|
||||||
"Server Options": "Опції сервера",
|
"Server Options": "Опції сервера",
|
||||||
"Verify your identity to access encrypted messages and prove your identity to others.": "Підтвердьте свою особу, щоб отримати доступ до зашифрованих повідомлень і довести свою справжність іншим.",
|
"Verify your identity to access encrypted messages and prove your identity to others.": "Підтвердьте свою особу, щоб отримати доступ до зашифрованих повідомлень і довести свою справжність іншим.",
|
||||||
"Allow this widget to verify your identity": "Дозволити цьому розширенню перевіряти вашу особу",
|
"Allow this widget to verify your identity": "Дозволити цьому розширенню перевіряти вашу особу",
|
||||||
"Verify this login": "Підтвердити цей вхід",
|
"Verify this login": "Звірити цей вхід",
|
||||||
"Verify other login": "Підтвердити інший вхід",
|
"Verify other login": "Звірити інший вхід",
|
||||||
"Use another login": "Інший обліковий запис",
|
"Use another login": "Інший обліковий запис",
|
||||||
"Use Security Key": "Використати ключ безпеки",
|
"Use Security Key": "Використати ключ безпеки",
|
||||||
"Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Без підтвердження ви не матимете доступу до всіх своїх повідомлень, а інші бачитимуть вас ненадійними.",
|
"Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Без звірки ви не матимете доступу до всіх своїх повідомлень, а інші бачитимуть вас недовіреними.",
|
||||||
"New? <a>Create account</a>": "Вперше тут? <a>Створіть обліковий запис</a>",
|
"New? <a>Create account</a>": "Вперше тут? <a>Створіть обліковий запис</a>",
|
||||||
"Forgotten your password?": "Забули свій пароль?",
|
"Forgotten your password?": "Забули свій пароль?",
|
||||||
"Forgot password?": "Забули пароль?",
|
"Forgot password?": "Забули пароль?",
|
||||||
|
@ -1659,8 +1659,8 @@
|
||||||
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s відкріплює <a>повідомлення</a> з цієї кімнати. Перегляньте всі <b>прикріплені повідомлення</b>.",
|
"%(senderName)s unpinned <a>a message</a> from this room. See all <b>pinned messages</b>.": "%(senderName)s відкріплює <a>повідомлення</a> з цієї кімнати. Перегляньте всі <b>прикріплені повідомлення</b>.",
|
||||||
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикріплює повідомлення до цієї кімнати. Перегляньте всі прикріплені повідомлення.",
|
"%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикріплює повідомлення до цієї кімнати. Перегляньте всі прикріплені повідомлення.",
|
||||||
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s прикріплює <a>повідомлення</a> до цієї кімнати. Перегляньте всі <b>прикріплені повідомлення</b>.",
|
"%(senderName)s pinned <a>a message</a> to this room. See all <b>pinned messages</b>.": "%(senderName)s прикріплює <a>повідомлення</a> до цієї кімнати. Перегляньте всі <b>прикріплені повідомлення</b>.",
|
||||||
"Verify this user by confirming the following number appears on their screen.": "Перевірте цього користувача, підтвердивши, що на екрані з'явилося таке число.",
|
"Verify this user by confirming the following number appears on their screen.": "Звірте справжність цього користувача, підтвердивши, що на екрані з'явилося таке число.",
|
||||||
"Verify this session by confirming the following number appears on its screen.": "Перевірте цей сеанс, підтвердивши, що на екрані з'явилося це число.",
|
"Verify this session by confirming the following number appears on its screen.": "Звірте цей сеанс, підтвердивши, що на екрані з'явилося це число.",
|
||||||
"They don't match": "Вони не збігаються",
|
"They don't match": "Вони не збігаються",
|
||||||
"They match": "Вони збігаються",
|
"They match": "Вони збігаються",
|
||||||
"Return to call": "Повернутися до виклику",
|
"Return to call": "Повернутися до виклику",
|
||||||
|
@ -1692,7 +1692,7 @@
|
||||||
"Enable desktop notifications": "Увімкнути сповіщення стільниці",
|
"Enable desktop notifications": "Увімкнути сповіщення стільниці",
|
||||||
"Don't miss a reply": "Не пропустіть відповідей",
|
"Don't miss a reply": "Не пропустіть відповідей",
|
||||||
"Review to ensure your account is safe": "Перевірте, щоб переконатися, що ваш обліковий запис у безпеці",
|
"Review to ensure your account is safe": "Перевірте, щоб переконатися, що ваш обліковий запис у безпеці",
|
||||||
"You have unverified logins": "У вас є не підтверджені сеанси",
|
"You have unverified logins": "У вас є незвірені сеанси",
|
||||||
"Error leaving room": "Помилка під час виходу з кімнати",
|
"Error leaving room": "Помилка під час виходу з кімнати",
|
||||||
"This homeserver has been blocked by its administrator.": "Цей домашній сервер заблокований адміністратором.",
|
"This homeserver has been blocked by its administrator.": "Цей домашній сервер заблокований адміністратором.",
|
||||||
"See when the name changes in your active room": "Бачити, коли зміниться назва активної кімнати",
|
"See when the name changes in your active room": "Бачити, коли зміниться назва активної кімнати",
|
||||||
|
@ -1726,7 +1726,7 @@
|
||||||
"Start sharing your screen": "Почати показ екрана",
|
"Start sharing your screen": "Почати показ екрана",
|
||||||
"Start the camera": "Запустити камеру",
|
"Start the camera": "Запустити камеру",
|
||||||
"Scan this unique code": "Скануйте цей унікальний код",
|
"Scan this unique code": "Скануйте цей унікальний код",
|
||||||
"Verify this session by completing one of the following:": "Підтвердьте цей сеанс одним із запропонованих способів:",
|
"Verify this session by completing one of the following:": "Звірте цей сеанс одним із запропонованих способів:",
|
||||||
"Leave %(groupName)s?": "Вийти з %(groupName)s?",
|
"Leave %(groupName)s?": "Вийти з %(groupName)s?",
|
||||||
"Leave Community": "Вийти зі спільноти",
|
"Leave Community": "Вийти зі спільноти",
|
||||||
"Add a User": "Додати користувача",
|
"Add a User": "Додати користувача",
|
||||||
|
@ -1900,7 +1900,7 @@
|
||||||
"Community Autocomplete": "Автозаповнення спільноти",
|
"Community Autocomplete": "Автозаповнення спільноти",
|
||||||
"Command Autocomplete": "Команда автозаповнення",
|
"Command Autocomplete": "Команда автозаповнення",
|
||||||
"Commands": "Команди",
|
"Commands": "Команди",
|
||||||
"Your new session is now verified. Other users will see it as trusted.": "Тепер ваша новий сеанс тепер підтверджено. Інші користувачі побачать її довіреною.",
|
"Your new session is now verified. Other users will see it as trusted.": "Ваш новий сеанс звірено. Інші користувачі побачать його довіреним.",
|
||||||
"Registration Successful": "Реєстрацію успішно виконано",
|
"Registration Successful": "Реєстрацію успішно виконано",
|
||||||
"You can now close this window or <a>log in</a> to your new account.": "Тепер можете закрити це вікно або <a>увійти</a> до свого нового облікового запису.",
|
"You can now close this window or <a>log in</a> to your new account.": "Тепер можете закрити це вікно або <a>увійти</a> до свого нового облікового запису.",
|
||||||
"<a>Log in</a> to your new account.": "<a>Увійти</a> до нового облікового запису.",
|
"<a>Log in</a> to your new account.": "<a>Увійти</a> до нового облікового запису.",
|
||||||
|
@ -1908,7 +1908,7 @@
|
||||||
"Set a new password": "Установити новий пароль",
|
"Set a new password": "Установити новий пароль",
|
||||||
"Return to login screen": "Повернутися на сторінку входу",
|
"Return to login screen": "Повернутися на сторінку входу",
|
||||||
"Send Reset Email": "Надіслати електронного листа скидання пароля",
|
"Send Reset Email": "Надіслати електронного листа скидання пароля",
|
||||||
"Session verified": "Сеанс підтверджено",
|
"Session verified": "Сеанс звірено",
|
||||||
"User settings": "Користувацькі налаштування",
|
"User settings": "Користувацькі налаштування",
|
||||||
"Community settings": "Налаштування спільноти",
|
"Community settings": "Налаштування спільноти",
|
||||||
"Switch theme": "Змінити тему",
|
"Switch theme": "Змінити тему",
|
||||||
|
@ -2110,5 +2110,31 @@
|
||||||
"There was an error finding this widget.": "Сталася помилка під час пошуку розширення.",
|
"There was an error finding this widget.": "Сталася помилка під час пошуку розширення.",
|
||||||
"Active Widgets": "Активні розширення",
|
"Active Widgets": "Активні розширення",
|
||||||
"Verification Requests": "Запит перевірки",
|
"Verification Requests": "Запит перевірки",
|
||||||
"There was a problem communicating with the server. Please try again.": "Виникла проблема зв'язку з сервером. Повторіть спробу."
|
"There was a problem communicating with the server. Please try again.": "Виникла проблема зв'язку з сервером. Повторіть спробу.",
|
||||||
|
"You're not currently a member of any communities.": "Ви не приєдналися до жодної групи.",
|
||||||
|
"Loading...": "Завантаження...",
|
||||||
|
"Failed to load group members": "Не вдалося завантажити учасників групи",
|
||||||
|
"Can't load this message": "Не вдалося завантажити це повідомлення",
|
||||||
|
"Click here to see older messages.": "Клацніть тут, щоб переглянути давніші повідомлення.",
|
||||||
|
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s вилучає аватар кімнати.",
|
||||||
|
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>реагує на %(shortName)s</reactedWith>",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s реагує на %(content)s",
|
||||||
|
"Reactions": "Реакції",
|
||||||
|
"Add reaction": "Додати реакцію",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s надсилає наліпку.",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s змінює аватар кімнати.",
|
||||||
|
"%(date)s at %(time)s": "%(date)s о %(time)s",
|
||||||
|
"Manually export keys": "Експорт ключів власноруч",
|
||||||
|
"Don't leave any rooms": "Не виходити з будь-якої кімнати",
|
||||||
|
"Updating %(brand)s": "Оновлення %(brand)s",
|
||||||
|
"Clear cache and resync": "Очистити кеш і повторно синхронізувати",
|
||||||
|
"Incompatible local cache": "Несумісний локальний кеш",
|
||||||
|
"Signature upload failed": "Не вдалося вивантажити підпис",
|
||||||
|
"Signature upload success": "Підпис успішно вивантажено",
|
||||||
|
"Unable to upload": "Не вдалося вивантажити",
|
||||||
|
"Cancelled signature upload": "Вивантаження підпису скасовано",
|
||||||
|
"Upload completed": "Вивантаження виконано",
|
||||||
|
"Search %(spaceName)s": "Пошук %(spaceName)s",
|
||||||
|
"Leave some rooms": "Вийте з кількох кімнат",
|
||||||
|
"Leave all rooms": "Вийти з кімнати"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3164,5 +3164,42 @@
|
||||||
"You are about to leave <spaceName/>.": "你即将离开 <spaceName/>。",
|
"You are about to leave <spaceName/>.": "你即将离开 <spaceName/>。",
|
||||||
"Leave some rooms": "离开一些聊天室",
|
"Leave some rooms": "离开一些聊天室",
|
||||||
"Leave all rooms": "离开所有聊天室",
|
"Leave all rooms": "离开所有聊天室",
|
||||||
"Don't leave any rooms": "不离开任何聊天室"
|
"Don't leave any rooms": "不离开任何聊天室",
|
||||||
|
"Collapse quotes │ ⇧+click": "折叠引号│ ⇧+click",
|
||||||
|
"Expand quotes │ ⇧+click": "展开引号│ ⇧+click",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "消息数只能是一个介于 %(min)s 和 %(max)s 之间的整数",
|
||||||
|
"Include Attachments": "包括附件",
|
||||||
|
"Size Limit": "大小限制",
|
||||||
|
"Format": "格式",
|
||||||
|
"Select from the options below to export chats from your timeline": "从下面的选项中选择以从时间轴导出聊天记录",
|
||||||
|
"Export Chat": "导出聊天",
|
||||||
|
"Exporting your data": "导出你的数据",
|
||||||
|
"Stop": "停止",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "您确定要停止导出数据吗?如果你这样做了,你需要重新开始。",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "导出成功了。你可以在下载文件夹中找到导出文件。",
|
||||||
|
"The export was cancelled successfully": "成功取消了导出",
|
||||||
|
"Export Successful": "成功导出",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "消息数",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "大小只能是 %(min)sMB 和 %(max)sMB 之间的一个数字",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "输入一个 %(min)s 和 %(max)s 之间的数字",
|
||||||
|
"In reply to <a>this message</a>": "回复<a>此消息</a>",
|
||||||
|
"Export chat": "导出聊天",
|
||||||
|
"File Attached": "已附加文件",
|
||||||
|
"Error fetching file": "获取文件出错",
|
||||||
|
"Topic: %(topic)s": "话题:%(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "这是 <roomName/> 导出的开始。导出人 <exporterDetails/>,导出日期 %(exportDate)s。",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s 创建了此聊天室。",
|
||||||
|
"Media omitted - file size limit exceeded": "省略了媒体文件 - 超出了文件大小限制",
|
||||||
|
"Media omitted": "省略了媒体文件",
|
||||||
|
"Current Timeline": "当前时间线",
|
||||||
|
"Specify a number of messages": "指定消息数",
|
||||||
|
"From the beginning": "从开头",
|
||||||
|
"Plain Text": "纯文本",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "您确定要在导出未完成时退出吗?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s 发送了一张贴纸。",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s 更改了聊天室头像。",
|
||||||
|
"%(date)s at %(time)s": "%(date)s 的 %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3160,5 +3160,49 @@
|
||||||
"To join a space you'll need an invite.": "若要加入空間,您必須被邀請。",
|
"To join a space you'll need an invite.": "若要加入空間,您必須被邀請。",
|
||||||
"You can also make Spaces from <a>communities</a>.": "您也可以從<a>社群</a>建立空間。",
|
"You can also make Spaces from <a>communities</a>.": "您也可以從<a>社群</a>建立空間。",
|
||||||
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "為此工作階段暫時顯示社群而非空間。對此功能的支援將在不久的將來移除。這將會重新載入 Element。",
|
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "為此工作階段暫時顯示社群而非空間。對此功能的支援將在不久的將來移除。這將會重新載入 Element。",
|
||||||
"Display Communities instead of Spaces": "顯示社群而非空間"
|
"Display Communities instead of Spaces": "顯示社群而非空間",
|
||||||
|
"Would you like to leave the rooms in this space?": "您想要離開此空間中的聊天室嗎?",
|
||||||
|
"You are about to leave <spaceName/>.": "您將要離開 <spaceName/>。",
|
||||||
|
"Leave some rooms": "離開部份聊天室",
|
||||||
|
"Leave all rooms": "離開所有聊天室",
|
||||||
|
"Don't leave any rooms": "不要離開任何聊天室",
|
||||||
|
"%(reactors)s reacted with %(content)s": "%(reactors)s 使用了 %(content)s 反應",
|
||||||
|
"Joining space …": "正在加入空間……",
|
||||||
|
"Expand quotes │ ⇧+click": "展開引用 │ ⇧+點擊",
|
||||||
|
"Collapse quotes │ ⇧+click": "折疊引用 │ ⇧+點擊",
|
||||||
|
"Include Attachments": "包含附件",
|
||||||
|
"Size Limit": "大小限制",
|
||||||
|
"Format": "格式",
|
||||||
|
"Select from the options below to export chats from your timeline": "從下面的選項中選擇以從您的時間軸匯出聊天",
|
||||||
|
"Export Chat": "匯出聊天",
|
||||||
|
"Exporting your data": "正在匯出您的資料",
|
||||||
|
"Stop": "停止",
|
||||||
|
"Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "您確定您要停止匯出您的資料嗎?若您這麼做,您就必須重新開始。",
|
||||||
|
"Your export was successful. Find it in your Downloads folder.": "您匯出成功。請在您的下載資料夾中尋找它。",
|
||||||
|
"The export was cancelled successfully": "匯出已成功取消",
|
||||||
|
"Export Successful": "匯出成功",
|
||||||
|
"MB": "MB",
|
||||||
|
"Number of messages": "訊息數",
|
||||||
|
"Number of messages can only be a number between %(min)s and %(max)s": "訊息數只能是 %(min)s MB 至 %(max)s MB 間的數字",
|
||||||
|
"Size can only be a number between %(min)s MB and %(max)s MB": "大小只能是 %(min)s MB 至 %(max)s MB 間的數字",
|
||||||
|
"Enter a number between %(min)s and %(max)s": "輸入介於 %(min)s 至 %(max)s 間的數字",
|
||||||
|
"In reply to <a>this message</a>": "回覆<a>此訊息</a>",
|
||||||
|
"Export chat": "匯出聊天",
|
||||||
|
"File Attached": "已附加檔案",
|
||||||
|
"Error fetching file": "擷取檔案錯誤",
|
||||||
|
"Topic: %(topic)s": "主題:%(topic)s",
|
||||||
|
"This is the start of export of <roomName/>. Exported by <exporterDetails/> at %(exportDate)s.": "這是 <roomName/> 匯出的開始。由 <exporterDetails/> 於 %(exportDate)s 匯出。",
|
||||||
|
"%(creatorName)s created this room.": "%(creatorName)s 建立了此聊天室。",
|
||||||
|
"Media omitted - file size limit exceeded": "媒體省略 - 超過檔案大小限制",
|
||||||
|
"Media omitted": "媒體省略",
|
||||||
|
"Current Timeline": "目前時間軸",
|
||||||
|
"Specify a number of messages": "指定訊息數量",
|
||||||
|
"From the beginning": "從一開始",
|
||||||
|
"Plain Text": "純文字",
|
||||||
|
"JSON": "JSON",
|
||||||
|
"HTML": "HTML",
|
||||||
|
"Are you sure you want to exit during this export?": "您確定您要從此匯出流程中退出嗎?",
|
||||||
|
"%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s 傳送了貼圖。",
|
||||||
|
"%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s 變更了聊天室大頭照。",
|
||||||
|
"%(date)s at %(time)s": "%(date)s 於 %(time)s"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import { IState } from "./components/structures/RoomView";
|
import { IRoomState } from "./components/structures/RoomView";
|
||||||
|
|
||||||
interface IDiff {
|
interface IDiff {
|
||||||
isMemberEvent: boolean;
|
isMemberEvent: boolean;
|
||||||
|
@ -54,7 +54,7 @@ function memberEventDiff(ev: MatrixEvent): IDiff {
|
||||||
* @param ctx An optional RoomContext to pull cached settings values from to avoid
|
* @param ctx An optional RoomContext to pull cached settings values from to avoid
|
||||||
* hitting the settings store
|
* hitting the settings store
|
||||||
*/
|
*/
|
||||||
export default function shouldHideEvent(ev: MatrixEvent, ctx?: IState): boolean {
|
export default function shouldHideEvent(ev: MatrixEvent, ctx?: IRoomState): boolean {
|
||||||
// Accessing the settings store directly can be expensive if done frequently,
|
// Accessing the settings store directly can be expensive if done frequently,
|
||||||
// so we should prefer using cached values if a RoomContext is available
|
// so we should prefer using cached values if a RoomContext is available
|
||||||
const isEnabled = ctx ?
|
const isEnabled = ctx ?
|
||||||
|
|
|
@ -22,6 +22,9 @@ import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verific
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||||
import { accessSecretStorage, AccessCancelledError } from '../SecurityManager';
|
import { accessSecretStorage, AccessCancelledError } from '../SecurityManager';
|
||||||
|
import Modal from '../Modal';
|
||||||
|
import InteractiveAuthDialog from '../components/views/dialogs/InteractiveAuthDialog';
|
||||||
|
import { _t } from '../languageHandler';
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -32,6 +35,7 @@ export enum Phase {
|
||||||
Done = 3, // final done stage, but still showing UX
|
Done = 3, // final done stage, but still showing UX
|
||||||
ConfirmSkip = 4,
|
ConfirmSkip = 4,
|
||||||
Finished = 5, // UX can be closed
|
Finished = 5, // UX can be closed
|
||||||
|
ConfirmReset = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SetupEncryptionStore extends EventEmitter {
|
export class SetupEncryptionStore extends EventEmitter {
|
||||||
|
@ -103,20 +107,23 @@ export class SetupEncryptionStore extends EventEmitter {
|
||||||
this.keyInfo = keys[this.keyId];
|
this.keyInfo = keys[this.keyId];
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we have any other devices which are E2EE which we can verify against?
|
// do we have any other verified devices which are E2EE which we can verify against?
|
||||||
const dehydratedDevice = await cli.getDehydratedDevice();
|
const dehydratedDevice = await cli.getDehydratedDevice();
|
||||||
this.hasDevicesToVerifyAgainst = cli.getStoredDevicesForUser(cli.getUserId()).some(
|
const ownUserId = cli.getUserId();
|
||||||
|
const crossSigningInfo = cli.getStoredCrossSigningForUser(ownUserId);
|
||||||
|
this.hasDevicesToVerifyAgainst = cli.getStoredDevicesForUser(ownUserId).some(
|
||||||
device =>
|
device =>
|
||||||
device.getIdentityKey() &&
|
device.getIdentityKey() &&
|
||||||
(!dehydratedDevice || (device.deviceId != dehydratedDevice.device_id)),
|
(!dehydratedDevice || (device.deviceId != dehydratedDevice.device_id)) &&
|
||||||
|
crossSigningInfo.checkDeviceTrust(
|
||||||
|
crossSigningInfo,
|
||||||
|
device,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
).isCrossSigningVerified(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!this.hasDevicesToVerifyAgainst && !this.keyInfo) {
|
this.phase = Phase.Intro;
|
||||||
// skip before we can even render anything.
|
|
||||||
this.phase = Phase.Finished;
|
|
||||||
} else {
|
|
||||||
this.phase = Phase.Intro;
|
|
||||||
}
|
|
||||||
this.emit("update");
|
this.emit("update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +215,50 @@ export class SetupEncryptionStore extends EventEmitter {
|
||||||
this.emit("update");
|
this.emit("update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public reset(): void {
|
||||||
|
this.phase = Phase.ConfirmReset;
|
||||||
|
this.emit("update");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async resetConfirm(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// If we've gotten here, the user presumably lost their
|
||||||
|
// secret storage key if they had one. Start by resetting
|
||||||
|
// secret storage and setting up a new recovery key, then
|
||||||
|
// create new cross-signing keys once that succeeds.
|
||||||
|
await accessSecretStorage(async () => {
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
await cli.bootstrapCrossSigning({
|
||||||
|
authUploadDeviceSigningKeys: async (makeRequest) => {
|
||||||
|
const { finished } = Modal.createTrackedDialog(
|
||||||
|
'Cross-signing keys dialog', '', InteractiveAuthDialog,
|
||||||
|
{
|
||||||
|
title: _t("Setting up keys"),
|
||||||
|
matrixClient: cli,
|
||||||
|
makeRequest,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const [confirmed] = await finished;
|
||||||
|
if (!confirmed) {
|
||||||
|
throw new Error("Cross-signing key upload auth canceled");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setupNewCrossSigning: true,
|
||||||
|
});
|
||||||
|
this.phase = Phase.Finished;
|
||||||
|
}, true);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error resetting cross-signing", e);
|
||||||
|
this.phase = Phase.Intro;
|
||||||
|
}
|
||||||
|
this.emit("update");
|
||||||
|
}
|
||||||
|
|
||||||
|
public returnAfterReset(): void {
|
||||||
|
this.phase = Phase.Intro;
|
||||||
|
this.emit("update");
|
||||||
|
}
|
||||||
|
|
||||||
public done(): void {
|
public done(): void {
|
||||||
this.phase = Phase.Finished;
|
this.phase = Phase.Finished;
|
||||||
this.emit("update");
|
this.emit("update");
|
||||||
|
@ -226,4 +277,8 @@ export class SetupEncryptionStore extends EventEmitter {
|
||||||
request.on("change", this.onVerificationRequestChange);
|
request.on("change", this.onVerificationRequestChange);
|
||||||
this.emit("update");
|
this.emit("update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public lostKeys(): boolean {
|
||||||
|
return !this.hasDevicesToVerifyAgainst && !this.keyInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,6 +608,9 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
if (membership === "join" && room.roomId === RoomViewStore.getRoomId()) {
|
if (membership === "join" && room.roomId === RoomViewStore.getRoomId()) {
|
||||||
// if the user was looking at the space and then joined: select that space
|
// if the user was looking at the space and then joined: select that space
|
||||||
this.setActiveSpace(room, false);
|
this.setActiveSpace(room, false);
|
||||||
|
} else if (membership === "leave" && room.roomId === this.activeSpace?.roomId) {
|
||||||
|
// user's active space has gone away, go back to home
|
||||||
|
this.setActiveSpace(null, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -790,7 +793,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
// 1 is Home, 2-9 are the spaces after Home
|
// 1 is Home, 2-9 are the spaces after Home
|
||||||
if (payload.num === 1) {
|
if (payload.num === 1) {
|
||||||
this.setActiveSpace(null);
|
this.setActiveSpace(null);
|
||||||
} else if (this.spacePanelSpaces.length >= payload.num) {
|
} else if (payload.num > 0 && this.spacePanelSpaces.length > payload.num - 2) {
|
||||||
this.setActiveSpace(this.spacePanelSpaces[payload.num - 2]);
|
this.setActiveSpace(this.spacePanelSpaces[payload.num - 2]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -176,7 +176,7 @@ export function getCustomTheme(themeName: string): ICustomTheme {
|
||||||
*
|
*
|
||||||
* @param {string} theme new theme
|
* @param {string} theme new theme
|
||||||
*/
|
*/
|
||||||
export async function setTheme(theme: string): Promise<void> {
|
export async function setTheme(theme?: string): Promise<void> {
|
||||||
if (!theme) {
|
if (!theme) {
|
||||||
const themeWatcher = new ThemeWatcher();
|
const themeWatcher = new ThemeWatcher();
|
||||||
theme = themeWatcher.getEffectiveTheme();
|
theme = themeWatcher.getEffectiveTheme();
|
||||||
|
|
|
@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
|
||||||
import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event';
|
import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event';
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||||
|
@ -73,9 +72,15 @@ export function canEditOwnEvent(mxEvent: MatrixEvent): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_JUMP_DISTANCE = 100;
|
const MAX_JUMP_DISTANCE = 100;
|
||||||
export function findEditableEvent(room: Room, isForward: boolean, fromEventId: string = undefined): MatrixEvent {
|
export function findEditableEvent({
|
||||||
const liveTimeline = room.getLiveTimeline();
|
events,
|
||||||
const events = liveTimeline.getEvents().concat(room.getPendingEvents());
|
isForward,
|
||||||
|
fromEventId,
|
||||||
|
}: {
|
||||||
|
events: MatrixEvent[];
|
||||||
|
isForward: boolean;
|
||||||
|
fromEventId?: string;
|
||||||
|
}): MatrixEvent {
|
||||||
const maxIdx = events.length - 1;
|
const maxIdx = events.length - 1;
|
||||||
const inc = isForward ? 1 : -1;
|
const inc = isForward ? 1 : -1;
|
||||||
const beginIdx = isForward ? 0 : maxIdx;
|
const beginIdx = isForward ? 0 : maxIdx;
|
||||||
|
|
|
@ -62,8 +62,9 @@ export default class MultiInviter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} targetId The ID of the room or group to invite to
|
* @param {string} targetId The ID of the room or group to invite to
|
||||||
|
* @param {function} progressCallback optional callback, fired after each invite.
|
||||||
*/
|
*/
|
||||||
constructor(targetId: string) {
|
constructor(targetId: string, private readonly progressCallback?: () => void) {
|
||||||
if (targetId[0] === '+') {
|
if (targetId[0] === '+') {
|
||||||
this.roomId = null;
|
this.roomId = null;
|
||||||
this.groupId = targetId;
|
this.groupId = targetId;
|
||||||
|
@ -181,6 +182,7 @@ export default class MultiInviter {
|
||||||
delete this.errors[address];
|
delete this.errors[address];
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
|
this.progressCallback?.();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (this.canceled) {
|
if (this.canceled) {
|
||||||
return;
|
return;
|
||||||
|
|
251
test/components/views/rooms/RoomHeader-test.tsx
Normal file
251
test/components/views/rooms/RoomHeader-test.tsx
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
import "../../../skinned-sdk";
|
||||||
|
|
||||||
|
import * as TestUtils from '../../../test-utils';
|
||||||
|
|
||||||
|
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
|
||||||
|
|
||||||
|
import DMRoomMap from '../../../../src/utils/DMRoomMap';
|
||||||
|
import RoomHeader from '../../../../src/components/views/rooms/RoomHeader';
|
||||||
|
|
||||||
|
import { Room, PendingEventOrdering, MatrixEvent, MatrixClient } from 'matrix-js-sdk';
|
||||||
|
import { SearchScope } from '../../../../src/components/views/rooms/SearchBar';
|
||||||
|
import { E2EStatus } from '../../../../src/utils/ShieldUtils';
|
||||||
|
import { PlaceCallType } from '../../../../src/CallHandler';
|
||||||
|
import { mkEvent } from '../../../test-utils';
|
||||||
|
|
||||||
|
describe('RoomHeader', () => {
|
||||||
|
it('shows the room avatar in a room with only ourselves', () => {
|
||||||
|
// When we render a non-DM room with 1 person in it
|
||||||
|
const room = createRoom({ name: "X Room", isDm: false, userIds: [] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then the room's avatar is the initial of its name
|
||||||
|
const initial = findSpan(rendered, ".mx_BaseAvatar_initial");
|
||||||
|
expect(initial.innerHTML).toEqual("X");
|
||||||
|
|
||||||
|
// And there is no image avatar (because it's not set on this room)
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual("data:image/png;base64,00");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the room avatar in a room with 2 people', () => {
|
||||||
|
// When we render a non-DM room with 2 people in it
|
||||||
|
const room = createRoom(
|
||||||
|
{ name: "Y Room", isDm: false, userIds: ["other"] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then the room's avatar is the initial of its name
|
||||||
|
const initial = findSpan(rendered, ".mx_BaseAvatar_initial");
|
||||||
|
expect(initial.innerHTML).toEqual("Y");
|
||||||
|
|
||||||
|
// And there is no image avatar (because it's not set on this room)
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual("data:image/png;base64,00");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the room avatar in a room with >2 people', () => {
|
||||||
|
// When we render a non-DM room with 3 people in it
|
||||||
|
const room = createRoom(
|
||||||
|
{ name: "Z Room", isDm: false, userIds: ["other1", "other2"] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then the room's avatar is the initial of its name
|
||||||
|
const initial = findSpan(rendered, ".mx_BaseAvatar_initial");
|
||||||
|
expect(initial.innerHTML).toEqual("Z");
|
||||||
|
|
||||||
|
// And there is no image avatar (because it's not set on this room)
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual("data:image/png;base64,00");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the room avatar in a DM with only ourselves', () => {
|
||||||
|
// When we render a non-DM room with 1 person in it
|
||||||
|
const room = createRoom({ name: "Z Room", isDm: true, userIds: [] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then the room's avatar is the initial of its name
|
||||||
|
const initial = findSpan(rendered, ".mx_BaseAvatar_initial");
|
||||||
|
expect(initial.innerHTML).toEqual("Z");
|
||||||
|
|
||||||
|
// And there is no image avatar (because it's not set on this room)
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual("data:image/png;base64,00");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the user avatar in a DM with 2 people', () => {
|
||||||
|
// Note: this is the interesting case - this is the ONLY
|
||||||
|
// time we should use the user's avatar.
|
||||||
|
|
||||||
|
// When we render a DM room with only 2 people in it
|
||||||
|
const room = createRoom({ name: "Y Room", isDm: true, userIds: ["other"] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then we use the other user's avatar as our room's image avatar
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual(
|
||||||
|
"http://this.is.a.url/example.org/other");
|
||||||
|
|
||||||
|
// And there is no initial avatar
|
||||||
|
expect(
|
||||||
|
rendered.querySelectorAll(".mx_BaseAvatar_initial"),
|
||||||
|
).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the room avatar in a DM with >2 people', () => {
|
||||||
|
// When we render a DM room with 3 people in it
|
||||||
|
const room = createRoom({
|
||||||
|
name: "Z Room", isDm: true, userIds: ["other1", "other2"] });
|
||||||
|
const rendered = render(room);
|
||||||
|
|
||||||
|
// Then the room's avatar is the initial of its name
|
||||||
|
const initial = findSpan(rendered, ".mx_BaseAvatar_initial");
|
||||||
|
expect(initial.innerHTML).toEqual("Z");
|
||||||
|
|
||||||
|
// And there is no image avatar (because it's not set on this room)
|
||||||
|
const image = findImg(rendered, ".mx_BaseAvatar_image");
|
||||||
|
expect(image.src).toEqual("data:image/png;base64,00");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
interface IRoomCreationInfo {
|
||||||
|
name: string;
|
||||||
|
isDm: boolean;
|
||||||
|
userIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRoom(info: IRoomCreationInfo) {
|
||||||
|
TestUtils.stubClient();
|
||||||
|
const client: MatrixClient = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
const roomId = '!1234567890:domain';
|
||||||
|
const userId = client.getUserId();
|
||||||
|
if (info.isDm) {
|
||||||
|
client.getAccountData = (eventType) => {
|
||||||
|
expect(eventType).toEqual("m.direct");
|
||||||
|
return mkDirectEvent(roomId, userId, info.userIds);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DMRoomMap.makeShared().start();
|
||||||
|
|
||||||
|
const room = new Room(roomId, client, userId, {
|
||||||
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
|
});
|
||||||
|
|
||||||
|
const otherJoinEvents = [];
|
||||||
|
for (const otherUserId of info.userIds) {
|
||||||
|
otherJoinEvents.push(mkJoinEvent(roomId, otherUserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
room.currentState.setStateEvents([
|
||||||
|
mkCreationEvent(roomId, userId),
|
||||||
|
mkNameEvent(roomId, userId, info.name),
|
||||||
|
mkJoinEvent(roomId, userId),
|
||||||
|
...otherJoinEvents,
|
||||||
|
]);
|
||||||
|
room.recalculate();
|
||||||
|
|
||||||
|
return room;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(room: Room): HTMLDivElement {
|
||||||
|
const parentDiv = document.createElement('div');
|
||||||
|
document.body.appendChild(parentDiv);
|
||||||
|
ReactDOM.render(
|
||||||
|
(
|
||||||
|
<RoomHeader
|
||||||
|
room={room}
|
||||||
|
inRoom={true}
|
||||||
|
onSettingsClick={() => {}}
|
||||||
|
onSearchClick={() => {}}
|
||||||
|
onForgetClick={() => {}}
|
||||||
|
onCallPlaced={(_type: PlaceCallType) => {}}
|
||||||
|
onAppsClick={() => {}}
|
||||||
|
e2eStatus={E2EStatus.Normal}
|
||||||
|
appsShown={true}
|
||||||
|
searchInfo={{
|
||||||
|
searchTerm: "",
|
||||||
|
searchScope: SearchScope.Room,
|
||||||
|
searchCount: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
parentDiv,
|
||||||
|
);
|
||||||
|
return parentDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkCreationEvent(roomId: string, userId: string): MatrixEvent {
|
||||||
|
return mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.room.create",
|
||||||
|
room: roomId,
|
||||||
|
user: userId,
|
||||||
|
content: {
|
||||||
|
creator: userId,
|
||||||
|
room_version: "5",
|
||||||
|
predecessor: {
|
||||||
|
room_id: "!prevroom",
|
||||||
|
event_id: "$someevent",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkNameEvent(
|
||||||
|
roomId: string, userId: string, name: string,
|
||||||
|
): MatrixEvent {
|
||||||
|
return mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.room.name",
|
||||||
|
room: roomId,
|
||||||
|
user: userId,
|
||||||
|
content: { name },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkJoinEvent(roomId: string, userId: string) {
|
||||||
|
const ret = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.room.member",
|
||||||
|
room: roomId,
|
||||||
|
user: userId,
|
||||||
|
content: {
|
||||||
|
"membership": "join",
|
||||||
|
"avatar_url": "mxc://example.org/" + userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
ret.event.state_key = userId;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkDirectEvent(
|
||||||
|
roomId: string, userId: string, otherUsers: string[],
|
||||||
|
): MatrixEvent {
|
||||||
|
const content = {};
|
||||||
|
for (const otherUserId of otherUsers) {
|
||||||
|
content[otherUserId] = [roomId];
|
||||||
|
}
|
||||||
|
return mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.direct",
|
||||||
|
room: roomId,
|
||||||
|
user: userId,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSpan(parent: HTMLElement, selector: string): HTMLSpanElement {
|
||||||
|
const els = parent.querySelectorAll(selector);
|
||||||
|
expect(els.length).toEqual(1);
|
||||||
|
return els[0] as HTMLSpanElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findImg(parent: HTMLElement, selector: string): HTMLImageElement {
|
||||||
|
const els = parent.querySelectorAll(selector);
|
||||||
|
expect(els.length).toEqual(1);
|
||||||
|
return els[0] as HTMLImageElement;
|
||||||
|
}
|
|
@ -24,8 +24,10 @@ import { sleep } from "matrix-js-sdk/src/utils";
|
||||||
import SendMessageComposer, {
|
import SendMessageComposer, {
|
||||||
createMessageContent,
|
createMessageContent,
|
||||||
isQuickReaction,
|
isQuickReaction,
|
||||||
|
SendMessageComposer as SendMessageComposerClass,
|
||||||
} from "../../../../src/components/views/rooms/SendMessageComposer";
|
} from "../../../../src/components/views/rooms/SendMessageComposer";
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
|
import RoomContext, { TimelineRenderingType } from "../../../../src/contexts/RoomContext";
|
||||||
import EditorModel from "../../../../src/editor/model";
|
import EditorModel from "../../../../src/editor/model";
|
||||||
import { createPartCreator, createRenderer } from "../../../editor/mock";
|
import { createPartCreator, createRenderer } from "../../../editor/mock";
|
||||||
import { createTestClient, mkEvent, mkStubRoom } from "../../../test-utils";
|
import { createTestClient, mkEvent, mkStubRoom } from "../../../test-utils";
|
||||||
|
@ -33,18 +35,58 @@ import BasicMessageComposer from "../../../../src/components/views/rooms/BasicMe
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor";
|
import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor";
|
||||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||||
|
import DocumentOffset from '../../../../src/editor/offset';
|
||||||
|
import { Layout } from '../../../../src/settings/Layout';
|
||||||
|
|
||||||
jest.mock("../../../../src/stores/RoomViewStore");
|
jest.mock("../../../../src/stores/RoomViewStore");
|
||||||
|
|
||||||
configure({ adapter: new Adapter() });
|
configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
describe('<SendMessageComposer/>', () => {
|
describe('<SendMessageComposer/>', () => {
|
||||||
|
const roomContext = {
|
||||||
|
roomLoading: true,
|
||||||
|
peekLoading: false,
|
||||||
|
shouldPeek: true,
|
||||||
|
membersLoaded: false,
|
||||||
|
numUnreadMessages: 0,
|
||||||
|
draggingFile: false,
|
||||||
|
searching: false,
|
||||||
|
guestsCanJoin: false,
|
||||||
|
canPeek: false,
|
||||||
|
showApps: false,
|
||||||
|
isPeeking: false,
|
||||||
|
showRightPanel: true,
|
||||||
|
joining: false,
|
||||||
|
atEndOfLiveTimeline: true,
|
||||||
|
atEndOfLiveTimelineInit: false,
|
||||||
|
showTopUnreadMessagesBar: false,
|
||||||
|
statusBarVisible: false,
|
||||||
|
canReact: false,
|
||||||
|
canReply: false,
|
||||||
|
layout: Layout.Group,
|
||||||
|
lowBandwidth: false,
|
||||||
|
alwaysShowTimestamps: false,
|
||||||
|
showTwelveHourTimestamps: false,
|
||||||
|
readMarkerInViewThresholdMs: 3000,
|
||||||
|
readMarkerOutOfViewThresholdMs: 30000,
|
||||||
|
showHiddenEventsInTimeline: false,
|
||||||
|
showReadReceipts: true,
|
||||||
|
showRedactions: true,
|
||||||
|
showJoinLeaves: true,
|
||||||
|
showAvatarChanges: true,
|
||||||
|
showDisplaynameChanges: true,
|
||||||
|
matrixClientIsReady: false,
|
||||||
|
dragCounter: 0,
|
||||||
|
timelineRenderingType: TimelineRenderingType.Room,
|
||||||
|
liveTimeline: undefined,
|
||||||
|
};
|
||||||
describe("createMessageContent", () => {
|
describe("createMessageContent", () => {
|
||||||
const permalinkCreator = jest.fn();
|
const permalinkCreator = jest.fn() as any;
|
||||||
|
|
||||||
it("sends plaintext messages correctly", () => {
|
it("sends plaintext messages correctly", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("hello world", "insertText", { offset: 11, atNodeEnd: true });
|
const documentOffset = new DocumentOffset(11, true);
|
||||||
|
model.update("hello world", "insertText", documentOffset);
|
||||||
|
|
||||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||||
|
|
||||||
|
@ -56,7 +98,8 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("sends markdown messages correctly", () => {
|
it("sends markdown messages correctly", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("hello *world*", "insertText", { offset: 13, atNodeEnd: true });
|
const documentOffset = new DocumentOffset(13, true);
|
||||||
|
model.update("hello *world*", "insertText", documentOffset);
|
||||||
|
|
||||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||||
|
|
||||||
|
@ -70,7 +113,8 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("strips /me from messages and marks them as m.emote accordingly", () => {
|
it("strips /me from messages and marks them as m.emote accordingly", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("/me blinks __quickly__", "insertText", { offset: 22, atNodeEnd: true });
|
const documentOffset = new DocumentOffset(22, true);
|
||||||
|
model.update("/me blinks __quickly__", "insertText", documentOffset);
|
||||||
|
|
||||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||||
|
|
||||||
|
@ -84,7 +128,9 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("allows sending double-slash escaped slash commands correctly", () => {
|
it("allows sending double-slash escaped slash commands correctly", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("//dev/null is my favourite place", "insertText", { offset: 32, atNodeEnd: true });
|
const documentOffset = new DocumentOffset(32, true);
|
||||||
|
|
||||||
|
model.update("//dev/null is my favourite place", "insertText", documentOffset);
|
||||||
|
|
||||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||||
|
|
||||||
|
@ -97,9 +143,11 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
describe("functions correctly mounted", () => {
|
describe("functions correctly mounted", () => {
|
||||||
const mockClient = MatrixClientPeg.matrixClient = createTestClient();
|
const mockClient = MatrixClientPeg.matrixClient = createTestClient();
|
||||||
const mockRoom = mkStubRoom();
|
const mockRoom = mkStubRoom('myfakeroom') as any;
|
||||||
const mockEvent = mkEvent({
|
const mockEvent = mkEvent({
|
||||||
type: "m.room.message",
|
type: "m.room.message",
|
||||||
|
room: 'myfakeroom',
|
||||||
|
user: 'myfakeuser',
|
||||||
content: "Replying to this",
|
content: "Replying to this",
|
||||||
event: true,
|
event: true,
|
||||||
});
|
});
|
||||||
|
@ -116,11 +164,13 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("renders text and placeholder correctly", () => {
|
it("renders text and placeholder correctly", () => {
|
||||||
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
||||||
<SendMessageComposer
|
<RoomContext.Provider value={roomContext}>
|
||||||
room={mockRoom}
|
<SendMessageComposer
|
||||||
placeholder="placeholder string"
|
room={mockRoom as any}
|
||||||
permalinkCreator={new SpecPermalinkConstructor()}
|
placeholder="placeholder string"
|
||||||
/>
|
permalinkCreator={new SpecPermalinkConstructor() as any}
|
||||||
|
/>
|
||||||
|
</RoomContext.Provider>
|
||||||
</MatrixClientContext.Provider>);
|
</MatrixClientContext.Provider>);
|
||||||
|
|
||||||
expect(wrapper.find('[aria-label="placeholder string"]')).toHaveLength(1);
|
expect(wrapper.find('[aria-label="placeholder string"]')).toHaveLength(1);
|
||||||
|
@ -135,12 +185,15 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("correctly persists state to and from localStorage", () => {
|
it("correctly persists state to and from localStorage", () => {
|
||||||
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
||||||
<SendMessageComposer
|
<RoomContext.Provider value={roomContext}>
|
||||||
room={mockRoom}
|
|
||||||
placeholder=""
|
<SendMessageComposer
|
||||||
permalinkCreator={new SpecPermalinkConstructor()}
|
room={mockRoom as any}
|
||||||
replyToEvent={mockEvent}
|
placeholder=""
|
||||||
/>
|
permalinkCreator={new SpecPermalinkConstructor() as any}
|
||||||
|
replyToEvent={mockEvent}
|
||||||
|
/>
|
||||||
|
</RoomContext.Provider>
|
||||||
</MatrixClientContext.Provider>);
|
</MatrixClientContext.Provider>);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
@ -148,7 +201,7 @@ describe('<SendMessageComposer/>', () => {
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = wrapper.find(SendMessageComposer).instance().editorStateKey;
|
const key = wrapper.find(SendMessageComposerClass).instance().editorStateKey;
|
||||||
|
|
||||||
expect(wrapper.text()).toBe("Test Text");
|
expect(wrapper.text()).toBe("Test Text");
|
||||||
expect(localStorage.getItem(key)).toBeNull();
|
expect(localStorage.getItem(key)).toBeNull();
|
||||||
|
@ -177,11 +230,14 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("persists state correctly without replyToEvent onbeforeunload", () => {
|
it("persists state correctly without replyToEvent onbeforeunload", () => {
|
||||||
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
||||||
<SendMessageComposer
|
<RoomContext.Provider value={roomContext}>
|
||||||
room={mockRoom}
|
|
||||||
placeholder=""
|
<SendMessageComposer
|
||||||
permalinkCreator={new SpecPermalinkConstructor()}
|
room={mockRoom as any}
|
||||||
/>
|
placeholder=""
|
||||||
|
permalinkCreator={new SpecPermalinkConstructor() as any}
|
||||||
|
/>
|
||||||
|
</RoomContext.Provider>
|
||||||
</MatrixClientContext.Provider>);
|
</MatrixClientContext.Provider>);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
@ -189,7 +245,7 @@ describe('<SendMessageComposer/>', () => {
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = wrapper.find(SendMessageComposer).instance().editorStateKey;
|
const key = wrapper.find(SendMessageComposerClass).instance().editorStateKey;
|
||||||
|
|
||||||
expect(wrapper.text()).toBe("Hello World");
|
expect(wrapper.text()).toBe("Hello World");
|
||||||
expect(localStorage.getItem(key)).toBeNull();
|
expect(localStorage.getItem(key)).toBeNull();
|
||||||
|
@ -203,12 +259,15 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("persists to session history upon sending", async () => {
|
it("persists to session history upon sending", async () => {
|
||||||
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
||||||
<SendMessageComposer
|
<RoomContext.Provider value={roomContext}>
|
||||||
room={mockRoom}
|
|
||||||
placeholder="placeholder"
|
<SendMessageComposer
|
||||||
permalinkCreator={new SpecPermalinkConstructor()}
|
room={mockRoom as any}
|
||||||
replyToEvent={mockEvent}
|
placeholder="placeholder"
|
||||||
/>
|
permalinkCreator={new SpecPermalinkConstructor() as any}
|
||||||
|
replyToEvent={mockEvent}
|
||||||
|
/>
|
||||||
|
</RoomContext.Provider>
|
||||||
</MatrixClientContext.Provider>);
|
</MatrixClientContext.Provider>);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
@ -230,12 +289,38 @@ describe('<SendMessageComposer/>', () => {
|
||||||
replyEventId: mockEvent.getId(),
|
replyEventId: mockEvent.getId(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('correctly sets the editorStateKey for threads', () => {
|
||||||
|
const mockThread ={
|
||||||
|
getThread: () => {
|
||||||
|
return {
|
||||||
|
id: 'myFakeThreadId',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
const wrapper = mount(<MatrixClientContext.Provider value={mockClient}>
|
||||||
|
<RoomContext.Provider value={roomContext}>
|
||||||
|
|
||||||
|
<SendMessageComposer
|
||||||
|
room={mockRoom as any}
|
||||||
|
placeholder=""
|
||||||
|
permalinkCreator={new SpecPermalinkConstructor() as any}
|
||||||
|
replyToEvent={mockThread}
|
||||||
|
/>
|
||||||
|
</RoomContext.Provider>
|
||||||
|
</MatrixClientContext.Provider>);
|
||||||
|
|
||||||
|
const instance = wrapper.find(SendMessageComposerClass).instance();
|
||||||
|
const key = instance.editorStateKey;
|
||||||
|
|
||||||
|
expect(key).toEqual('mx_cider_state_myfakeroom_myFakeThreadId');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("isQuickReaction", () => {
|
describe("isQuickReaction", () => {
|
||||||
it("correctly detects quick reaction", () => {
|
it("correctly detects quick reaction", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("+😊", "insertText", { offset: 3, atNodeEnd: true });
|
model.update("+😊", "insertText", new DocumentOffset(3, true));
|
||||||
|
|
||||||
const isReaction = isQuickReaction(model);
|
const isReaction = isQuickReaction(model);
|
||||||
|
|
||||||
|
@ -244,7 +329,7 @@ describe('<SendMessageComposer/>', () => {
|
||||||
|
|
||||||
it("correctly detects quick reaction with space", () => {
|
it("correctly detects quick reaction with space", () => {
|
||||||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("+ 😊", "insertText", { offset: 4, atNodeEnd: true });
|
model.update("+ 😊", "insertText", new DocumentOffset(4, true));
|
||||||
|
|
||||||
const isReaction = isQuickReaction(model);
|
const isReaction = isQuickReaction(model);
|
||||||
|
|
||||||
|
@ -256,10 +341,10 @@ describe('<SendMessageComposer/>', () => {
|
||||||
const model2 = new EditorModel([], createPartCreator(), createRenderer());
|
const model2 = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
const model3 = new EditorModel([], createPartCreator(), createRenderer());
|
const model3 = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
const model4 = new EditorModel([], createPartCreator(), createRenderer());
|
const model4 = new EditorModel([], createPartCreator(), createRenderer());
|
||||||
model.update("+😊hello", "insertText", { offset: 8, atNodeEnd: true });
|
model.update("+😊hello", "insertText", new DocumentOffset( 8, true));
|
||||||
model2.update(" +😊", "insertText", { offset: 4, atNodeEnd: true });
|
model2.update(" +😊", "insertText", new DocumentOffset( 4, true));
|
||||||
model3.update("+ 😊😊", "insertText", { offset: 6, atNodeEnd: true });
|
model3.update("+ 😊😊", "insertText", new DocumentOffset( 6, true));
|
||||||
model4.update("+smiley", "insertText", { offset: 7, atNodeEnd: true });
|
model4.update("+smiley", "insertText", new DocumentOffset( 7, true));
|
||||||
|
|
||||||
expect(isQuickReaction(model)).toBeFalsy();
|
expect(isQuickReaction(model)).toBeFalsy();
|
||||||
expect(isQuickReaction(model2)).toBeFalsy();
|
expect(isQuickReaction(model2)).toBeFalsy();
|
|
@ -47,6 +47,8 @@ export function createTestClient() {
|
||||||
getIdentityServerUrl: jest.fn(),
|
getIdentityServerUrl: jest.fn(),
|
||||||
getDomain: jest.fn().mockReturnValue("matrix.rog"),
|
getDomain: jest.fn().mockReturnValue("matrix.rog"),
|
||||||
getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"),
|
getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"),
|
||||||
|
getUser: jest.fn().mockReturnValue({ on: jest.fn() }),
|
||||||
|
credentials: { userId: "@userId:matrix.rog" },
|
||||||
|
|
||||||
getPushActionsForEvent: jest.fn(),
|
getPushActionsForEvent: jest.fn(),
|
||||||
getRoom: jest.fn().mockImplementation(mkStubRoom),
|
getRoom: jest.fn().mockImplementation(mkStubRoom),
|
||||||
|
@ -76,7 +78,7 @@ export function createTestClient() {
|
||||||
content: {},
|
content: {},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mxcUrlToHttp: (mxc) => 'http://this.is.a.url/',
|
mxcUrlToHttp: (mxc) => `http://this.is.a.url/${mxc.substring(6)}`,
|
||||||
setAccountData: jest.fn(),
|
setAccountData: jest.fn(),
|
||||||
setRoomAccountData: jest.fn(),
|
setRoomAccountData: jest.fn(),
|
||||||
sendTyping: jest.fn().mockResolvedValue({}),
|
sendTyping: jest.fn().mockResolvedValue({}),
|
||||||
|
@ -93,12 +95,14 @@ export function createTestClient() {
|
||||||
sessionStore: {
|
sessionStore: {
|
||||||
store: {
|
store: {
|
||||||
getItem: jest.fn(),
|
getItem: jest.fn(),
|
||||||
|
setItem: jest.fn(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pushRules: {},
|
pushRules: {},
|
||||||
decryptEventIfNeeded: () => Promise.resolve(),
|
decryptEventIfNeeded: () => Promise.resolve(),
|
||||||
isUserIgnored: jest.fn().mockReturnValue(false),
|
isUserIgnored: jest.fn().mockReturnValue(false),
|
||||||
getCapabilities: jest.fn().mockResolvedValue({}),
|
getCapabilities: jest.fn().mockResolvedValue({}),
|
||||||
|
supportsExperimentalThreads: () => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +134,11 @@ export function mkEvent(opts) {
|
||||||
};
|
};
|
||||||
if (opts.skey) {
|
if (opts.skey) {
|
||||||
event.state_key = opts.skey;
|
event.state_key = opts.skey;
|
||||||
} else if (["m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules",
|
} else if ([
|
||||||
"m.room.power_levels", "m.room.topic", "m.room.history_visibility", "m.room.encryption",
|
"m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules",
|
||||||
"com.example.state"].indexOf(opts.type) !== -1) {
|
"m.room.power_levels", "m.room.topic", "m.room.history_visibility",
|
||||||
|
"m.room.encryption", "m.room.member", "com.example.state",
|
||||||
|
].indexOf(opts.type) !== -1) {
|
||||||
event.state_key = "";
|
event.state_key = "";
|
||||||
}
|
}
|
||||||
return opts.event ? new MatrixEvent(event) : event;
|
return opts.event ? new MatrixEvent(event) : event;
|
||||||
|
|
Loading…
Reference in a new issue