Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into joriks/font-scaling-slider

This commit is contained in:
Jorik Schellekens 2020-05-07 18:01:20 +01:00
commit 33a5b5142d
62 changed files with 2367 additions and 728 deletions

View file

@ -1,3 +1,348 @@
Changes in [2.5.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0) (2020-05-05)
===================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.6...v2.5.0)
* Upgrade to JS SDK 6.0.0
* EventIndex: Reduce the logging the event index is producing.
[\#4551](https://github.com/matrix-org/matrix-react-sdk/pull/4551)
* Differentiate copy for own untrusted device dialog
[\#4550](https://github.com/matrix-org/matrix-react-sdk/pull/4550)
* More detailed progress for key backup progress
[\#4545](https://github.com/matrix-org/matrix-react-sdk/pull/4545)
* Increase rageshake size limit to 5mb
[\#4544](https://github.com/matrix-org/matrix-react-sdk/pull/4544)
Changes in [2.5.0-rc.6](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.6) (2020-05-01)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.5...v2.5.0-rc.6)
* Upgrade to JS SDK 6.0.0-rc.2
* Wait for user to be verified in e2e setup
[\#4538](https://github.com/matrix-org/matrix-react-sdk/pull/4538)
* Add device name to unverified session toast
[\#4536](https://github.com/matrix-org/matrix-react-sdk/pull/4536)
Changes in [2.5.0-rc.5](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.5) (2020-04-30)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.4...v2.5.0-rc.5)
* Upgrade to JS SDK 6.0.0-rc.1
* Fix device verification toasts not disappearing
[\#4533](https://github.com/matrix-org/matrix-react-sdk/pull/4533)
* Allow resetting storage from the access dialog
[\#4526](https://github.com/matrix-org/matrix-react-sdk/pull/4526)
* Update toast copy again
[\#4530](https://github.com/matrix-org/matrix-react-sdk/pull/4530)
* Reduce maximum width of toasts & allow multiple lines
[\#4528](https://github.com/matrix-org/matrix-react-sdk/pull/4528)
* Treat sessions that are there when we log in as old
[\#4527](https://github.com/matrix-org/matrix-react-sdk/pull/4527)
* Update (bulk) unverified device toast copy
[\#4523](https://github.com/matrix-org/matrix-react-sdk/pull/4523)
* Make new device toasts appear above review toasts
[\#4520](https://github.com/matrix-org/matrix-react-sdk/pull/4520)
* Separate toasts for existing & new device verification
[\#4517](https://github.com/matrix-org/matrix-react-sdk/pull/4517)
* Aggregate device verify toasts
[\#4516](https://github.com/matrix-org/matrix-react-sdk/pull/4516)
* Fix set up encryption toast to use "set up" as action
[\#4515](https://github.com/matrix-org/matrix-react-sdk/pull/4515)
* Fix internal link styling in Security Settings
[\#4512](https://github.com/matrix-org/matrix-react-sdk/pull/4512)
* Don't enable e2ee when inviting a 3pid
[\#4513](https://github.com/matrix-org/matrix-react-sdk/pull/4513)
* only clear on continuations where the clear isn't done by SenderProfile
[\#4505](https://github.com/matrix-org/matrix-react-sdk/pull/4505)
* cap width of editable item list item to leave space for its X button
[\#4504](https://github.com/matrix-org/matrix-react-sdk/pull/4504)
* Add a link from settings / devices to your user profile
[\#4499](https://github.com/matrix-org/matrix-react-sdk/pull/4499)
* Make icon change in SetupEncryptionDialog
[\#4490](https://github.com/matrix-org/matrix-react-sdk/pull/4490)
* Remove invite only padlocks feature flag for release
[\#4488](https://github.com/matrix-org/matrix-react-sdk/pull/4488)
* Fix incorrect toast if security setup skipped
[\#4489](https://github.com/matrix-org/matrix-react-sdk/pull/4489)
* Revert "Update emojibase for fixed emoji codepoints and Emoji 13 support"
[\#4483](https://github.com/matrix-org/matrix-react-sdk/pull/4483)
* Fix recovery link on login verification flow
[\#4480](https://github.com/matrix-org/matrix-react-sdk/pull/4480)
Changes in [2.5.0-rc.4](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.4) (2020-04-23)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.3...v2.5.0-rc.4)
* Upgrade to JS SDK 5.3.1-rc.4
* Take encrypted message search out of labs for release
[\#4468](https://github.com/matrix-org/matrix-react-sdk/pull/4468)
* Update login security copy and design to match Figma [to release]
[\#4474](https://github.com/matrix-org/matrix-react-sdk/pull/4474)
* Fix i18n of SSO UIA copy in Deactivate Account Dialog on release
[\#4473](https://github.com/matrix-org/matrix-react-sdk/pull/4473)
* Skip auth flow test for signing upload when password present
[\#4465](https://github.com/matrix-org/matrix-react-sdk/pull/4465)
* Fix: wait until cross-signing keys are fetched to show verify button
[\#4457](https://github.com/matrix-org/matrix-react-sdk/pull/4457)
* Handle load error in create secret storage dialog
[\#4454](https://github.com/matrix-org/matrix-react-sdk/pull/4454)
* Don't recheck DeviceListener until after initial sync is finished
[\#4450](https://github.com/matrix-org/matrix-react-sdk/pull/4450)
* EventIndex: Filter out events that don't have a propper content value.
[\#4447](https://github.com/matrix-org/matrix-react-sdk/pull/4447)
Changes in [2.5.0-rc.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.3) (2020-04-17)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.2...v2.5.0-rc.3)
* Upgrade to JS SDK 5.3.1-rc.3
Changes in [2.5.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.2) (2020-04-16)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.5.0-rc.1...v2.5.0-rc.2)
* Upgrade to JS SDK 5.3.1-rc.2
* [Release] Convert cross-signing flag to a setting
[\#4429](https://github.com/matrix-org/matrix-react-sdk/pull/4429)
* Iterate cross-signing copy
[\#4426](https://github.com/matrix-org/matrix-react-sdk/pull/4426)
* Fix: ensure twemoji font is loaded when showing SAS emojis
[\#4423](https://github.com/matrix-org/matrix-react-sdk/pull/4423)
Changes in [2.5.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.5.0-rc.1) (2020-04-15)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.4.0-rc.1...v2.5.0-rc.1)
* Upgrade to JS SDK 5.3.1-rc.1
* null-guard MatrixClientPeg in RoomViewStore
[\#4415](https://github.com/matrix-org/matrix-react-sdk/pull/4415)
* Fix: prevent spurious notifications from indexer
[\#4414](https://github.com/matrix-org/matrix-react-sdk/pull/4414)
* Login block on initialSync with spinners
[\#4413](https://github.com/matrix-org/matrix-react-sdk/pull/4413)
* Allow network dropdown to be scrollable and fix context menu padding calc
[\#4408](https://github.com/matrix-org/matrix-react-sdk/pull/4408)
* Remove end-to-end message info option when cross-signing is used
[\#4412](https://github.com/matrix-org/matrix-react-sdk/pull/4412)
* Minimize widgets by default
[\#4378](https://github.com/matrix-org/matrix-react-sdk/pull/4378)
* Add comments to highlight where we'll need m.widget support
[\#4380](https://github.com/matrix-org/matrix-react-sdk/pull/4380)
* Fix: dont try to enable 4S if cross-signing is disabled
[\#4407](https://github.com/matrix-org/matrix-react-sdk/pull/4407)
* Fix: don't confuse user with spinner during complete security step
[\#4406](https://github.com/matrix-org/matrix-react-sdk/pull/4406)
* Fix: avoid potential crash during certain verification paths
[\#4405](https://github.com/matrix-org/matrix-react-sdk/pull/4405)
* Add riot-desktop shortcuts for forward/back matching browsers&slack
[\#4392](https://github.com/matrix-org/matrix-react-sdk/pull/4392)
* Convert LoggedInView to an ES6 PureComponent Class & TypeScript
[\#4398](https://github.com/matrix-org/matrix-react-sdk/pull/4398)
* Fix width of MVideoBody in FilePanel
[\#4396](https://github.com/matrix-org/matrix-react-sdk/pull/4396)
* Remove unused react-addons-css-transition-group
[\#4397](https://github.com/matrix-org/matrix-react-sdk/pull/4397)
* Fix emoji tooltip flickering
[\#4395](https://github.com/matrix-org/matrix-react-sdk/pull/4395)
* Pass along key backup for bootstrap
[\#4374](https://github.com/matrix-org/matrix-react-sdk/pull/4374)
* Fix create room dialog e2ee private room setting
[\#4403](https://github.com/matrix-org/matrix-react-sdk/pull/4403)
* Sort emoji by shortcodes for autocomplete primarily for :-1 and :+1
[\#4391](https://github.com/matrix-org/matrix-react-sdk/pull/4391)
* Fix invalid commands when figuring out whether to set isTyping
[\#4390](https://github.com/matrix-org/matrix-react-sdk/pull/4390)
* op/deop return error if trying to affect an unknown user
[\#4389](https://github.com/matrix-org/matrix-react-sdk/pull/4389)
* Composer pills respect showPillAvatar setting
[\#4384](https://github.com/matrix-org/matrix-react-sdk/pull/4384)
* Only send typing notification when composing commands which send messages
[\#4385](https://github.com/matrix-org/matrix-react-sdk/pull/4385)
* Reverse order of they match/they don't match buttons
[\#4386](https://github.com/matrix-org/matrix-react-sdk/pull/4386)
* Use singular text on 'delete sessions' button for SSO
[\#4383](https://github.com/matrix-org/matrix-react-sdk/pull/4383)
* Pass widget data through from sticker picker
[\#4377](https://github.com/matrix-org/matrix-react-sdk/pull/4377)
* Obliterate widgets when they are minimized
[\#4376](https://github.com/matrix-org/matrix-react-sdk/pull/4376)
* Fix image thumbnail width when read receipts are hidden
[\#4370](https://github.com/matrix-org/matrix-react-sdk/pull/4370)
* Add toggle for e2ee when creating private room
[\#4362](https://github.com/matrix-org/matrix-react-sdk/pull/4362)
* Fix logging for failed searches
[\#4372](https://github.com/matrix-org/matrix-react-sdk/pull/4372)
* Ensure UI is updated when cross-signing gets disabled
[\#4369](https://github.com/matrix-org/matrix-react-sdk/pull/4369)
* Retry the request for the master key from SSSS on login
[\#4371](https://github.com/matrix-org/matrix-react-sdk/pull/4371)
* Upgrade deps
[\#4365](https://github.com/matrix-org/matrix-react-sdk/pull/4365)
* App load tweaks, i18n and localStorage
[\#4367](https://github.com/matrix-org/matrix-react-sdk/pull/4367)
* Fix encoding of widget arguments
[\#4366](https://github.com/matrix-org/matrix-react-sdk/pull/4366)
Changes in [2.4.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.4.0-rc.1) (2020-04-08)
=============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.1...v2.4.0-rc.1)
* Upgrade to JS SDK to 5.3.0-rc.1
* EventIndex: Log if we had all events in a checkpoint but are continuing.
[\#4363](https://github.com/matrix-org/matrix-react-sdk/pull/4363)
* Update from Weblate
[\#4364](https://github.com/matrix-org/matrix-react-sdk/pull/4364)
* Support deactivating your account with SSO
[\#4356](https://github.com/matrix-org/matrix-react-sdk/pull/4356)
* Add debug status for cached backup key format
[\#4359](https://github.com/matrix-org/matrix-react-sdk/pull/4359)
* Fix composer placeholder not updating
[\#4361](https://github.com/matrix-org/matrix-react-sdk/pull/4361)
* Fix sas verification buttons to match figma
[\#4358](https://github.com/matrix-org/matrix-react-sdk/pull/4358)
* Don't show fallback text for verification requests
[\#4345](https://github.com/matrix-org/matrix-react-sdk/pull/4345)
* Fix share dialog correctly
[\#4360](https://github.com/matrix-org/matrix-react-sdk/pull/4360)
* Use singular copy when only deleting one device
[\#4357](https://github.com/matrix-org/matrix-react-sdk/pull/4357)
* Deem m.sticker events as actionable for reacting
[\#4288](https://github.com/matrix-org/matrix-react-sdk/pull/4288)
* Don't show spinner over encryption setup dialogs
[\#4354](https://github.com/matrix-org/matrix-react-sdk/pull/4354)
* Support Jitsi information from client .well-known
[\#4348](https://github.com/matrix-org/matrix-react-sdk/pull/4348)
* Add new default home page fallback
[\#4350](https://github.com/matrix-org/matrix-react-sdk/pull/4350)
* Check more account data in toast listener
[\#4351](https://github.com/matrix-org/matrix-react-sdk/pull/4351)
* Don't try to send presence updates until the client is started
[\#4353](https://github.com/matrix-org/matrix-react-sdk/pull/4353)
* Fix copy button on code blocks when there is no code tag just pre
[\#4352](https://github.com/matrix-org/matrix-react-sdk/pull/4352)
* Clear sessionStorage on sign out
[\#4346](https://github.com/matrix-org/matrix-react-sdk/pull/4346)
* Re-request room keys after auth
[\#4341](https://github.com/matrix-org/matrix-react-sdk/pull/4341)
* Update emojibase for fixed emoji codepoints and Emoji 13 support
[\#4344](https://github.com/matrix-org/matrix-react-sdk/pull/4344)
* App load order tweaks for code splitting
[\#4343](https://github.com/matrix-org/matrix-react-sdk/pull/4343)
* Fix alignment of e2e icon in userinfo and expose full displayname in title
[\#4312](https://github.com/matrix-org/matrix-react-sdk/pull/4312)
* Adjust copy & UX for self-verification
[\#4342](https://github.com/matrix-org/matrix-react-sdk/pull/4342)
* QR code reciprocation
[\#4334](https://github.com/matrix-org/matrix-react-sdk/pull/4334)
* Fix Hangul typing does not work properly
[\#4339](https://github.com/matrix-org/matrix-react-sdk/pull/4339)
* Fix: dismiss setup encryption toast if cross-signing is ready
[\#4336](https://github.com/matrix-org/matrix-react-sdk/pull/4336)
* Fix read marker visibility for grouped events
[\#4340](https://github.com/matrix-org/matrix-react-sdk/pull/4340)
* Make all 'font-size's and 'line-height's rem
[\#4305](https://github.com/matrix-org/matrix-react-sdk/pull/4305)
* Fix spurious extra devices on registration
[\#4337](https://github.com/matrix-org/matrix-react-sdk/pull/4337)
* Fix the edit messager composer
[\#4333](https://github.com/matrix-org/matrix-react-sdk/pull/4333)
* Fix Room Settings Dialog Notifications tab icon
[\#4321](https://github.com/matrix-org/matrix-react-sdk/pull/4321)
* Fix various cases of React warnings by silencing them
[\#4331](https://github.com/matrix-org/matrix-react-sdk/pull/4331)
* Only apply padding to standard textual buttons (kind buttons)
[\#4332](https://github.com/matrix-org/matrix-react-sdk/pull/4332)
* Use console.log in place of console.warn for less warnings
[\#4330](https://github.com/matrix-org/matrix-react-sdk/pull/4330)
* Revert componentDidMount changes on breadcrumbs
[\#4329](https://github.com/matrix-org/matrix-react-sdk/pull/4329)
* Use new method for checking secret storage key
[\#4309](https://github.com/matrix-org/matrix-react-sdk/pull/4309)
* Label and use UNSAFE_componentWillMount to minimize warnings
[\#4315](https://github.com/matrix-org/matrix-react-sdk/pull/4315)
* Fix a number of minor code quality issues
[\#4314](https://github.com/matrix-org/matrix-react-sdk/pull/4314)
* Use componentDidMount in place of componentWillMount where possible
[\#4313](https://github.com/matrix-org/matrix-react-sdk/pull/4313)
* EventIndex: Mark the initial checkpoints for a full crawl.
[\#4325](https://github.com/matrix-org/matrix-react-sdk/pull/4325)
* Fix UserInfo e2e buttons to match Figma
[\#4320](https://github.com/matrix-org/matrix-react-sdk/pull/4320)
* Only auto-scroll to RoomTile when clicking on RoomTile or via shortcuts
[\#4316](https://github.com/matrix-org/matrix-react-sdk/pull/4316)
* Support SSO for interactive authentication
[\#4292](https://github.com/matrix-org/matrix-react-sdk/pull/4292)
* Fix /invite Slash Command
[\#4328](https://github.com/matrix-org/matrix-react-sdk/pull/4328)
* Fix jitsi popout URL
[\#4326](https://github.com/matrix-org/matrix-react-sdk/pull/4326)
* Use our own jitsi widget for the popout URL
[\#4323](https://github.com/matrix-org/matrix-react-sdk/pull/4323)
* Fix popout support for jitsi widgets
[\#4319](https://github.com/matrix-org/matrix-react-sdk/pull/4319)
* Fix: legacy verify user throwing error
[\#4318](https://github.com/matrix-org/matrix-react-sdk/pull/4318)
* Document settingDefaults
[\#3046](https://github.com/matrix-org/matrix-react-sdk/pull/3046)
* Fix Ctrl+/ for Finnish keyboard where it includes Shift
[\#4317](https://github.com/matrix-org/matrix-react-sdk/pull/4317)
* Rework SlashCommands to better expose aliases
[\#4302](https://github.com/matrix-org/matrix-react-sdk/pull/4302)
* Fix EventListSummary when RR rendering is disabled
[\#4311](https://github.com/matrix-org/matrix-react-sdk/pull/4311)
* Update link to css location.
[\#4299](https://github.com/matrix-org/matrix-react-sdk/pull/4299)
* Fix peeking keeping two timeline update mechanisms in play
[\#4310](https://github.com/matrix-org/matrix-react-sdk/pull/4310)
* Pass new secret storage key to bootstrap path
[\#4308](https://github.com/matrix-org/matrix-react-sdk/pull/4308)
* Show red shield for users that become unverified
[\#4303](https://github.com/matrix-org/matrix-react-sdk/pull/4303)
* Accessibility fixed for Event List Summary and Composer Format Bar
[\#4295](https://github.com/matrix-org/matrix-react-sdk/pull/4295)
* Support $riot: Templates for SSO/CAS urls in the welcome.html page
[\#4279](https://github.com/matrix-org/matrix-react-sdk/pull/4279)
* Added the /html command
[\#4296](https://github.com/matrix-org/matrix-react-sdk/pull/4296)
* EventIndex: Better logging on how many events are added.
[\#4301](https://github.com/matrix-org/matrix-react-sdk/pull/4301)
* Field: mark id as optional in propTypes
[\#4307](https://github.com/matrix-org/matrix-react-sdk/pull/4307)
* Fix view community link icon contrast
[\#4254](https://github.com/matrix-org/matrix-react-sdk/pull/4254)
* Remove underscore from Jitsi conference names
[\#4304](https://github.com/matrix-org/matrix-react-sdk/pull/4304)
* Refactor shield display logic; changed rules for DMs
[\#4290](https://github.com/matrix-org/matrix-react-sdk/pull/4290)
* Fix: bring back global thin scrollbars
[\#4300](https://github.com/matrix-org/matrix-react-sdk/pull/4300)
* Keyboard shortcuts: Escape cancel reply and fix Ctrl+K
[\#4297](https://github.com/matrix-org/matrix-react-sdk/pull/4297)
* Field: make id optional, generate one if not provided
[\#4298](https://github.com/matrix-org/matrix-react-sdk/pull/4298)
* Fix ugly scrollbars in TabbedView (settings), emojipicker and widgets
[\#4293](https://github.com/matrix-org/matrix-react-sdk/pull/4293)
* Rename secret storage force-reset variable to avoid confusion
[\#4274](https://github.com/matrix-org/matrix-react-sdk/pull/4274)
* Fix: can't dismiss unverified session toast when encryption hasn't been
upgraded
[\#4291](https://github.com/matrix-org/matrix-react-sdk/pull/4291)
* Blank out UserInfo avatar when changing between members
[\#4289](https://github.com/matrix-org/matrix-react-sdk/pull/4289)
* Add cancel button to verification panel
[\#4283](https://github.com/matrix-org/matrix-react-sdk/pull/4283)
* Show ongoing verification request straight away when navigating to member
[\#4284](https://github.com/matrix-org/matrix-react-sdk/pull/4284)
* Fix: allow scrolling while window is not focused & remove scrollbar hack
[\#4276](https://github.com/matrix-org/matrix-react-sdk/pull/4276)
* Show whether backup key is cached
[\#4287](https://github.com/matrix-org/matrix-react-sdk/pull/4287)
* Rename unverified session toast
[\#4285](https://github.com/matrix-org/matrix-react-sdk/pull/4285)
* Fix: pick last active DM for verification request
[\#4286](https://github.com/matrix-org/matrix-react-sdk/pull/4286)
* Fix formatBar not hidden after highlight and backspacing some text
[\#4269](https://github.com/matrix-org/matrix-react-sdk/pull/4269)
Changes in [2.3.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.3.1) (2020-04-01)
===================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.3.0...v2.3.1)

View file

@ -1,6 +1,6 @@
{
"name": "matrix-react-sdk",
"version": "2.3.1",
"version": "2.5.0",
"description": "SDK for matrix.org using React",
"author": "matrix.org",
"repository": {

View file

@ -34,7 +34,7 @@ $font-16px: 1.067rem;
$font-17px: 1.133rem;
$font-18px: 1.200rem;
$font-19px: 1.267rem;
$font-20px: 1.333rem;
$font-20px: 1.3333333rem;
$font-21px: 1.400rem;
$font-22px: 1.467rem;
$font-23px: 1.533rem;

View file

@ -91,9 +91,8 @@ limitations under the License.
}
.mx_Toast_description {
max-width: 400px;
max-width: 272px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin: 4px 0 11px 0;
font-size: $font-12px;

View file

@ -32,3 +32,9 @@ limitations under the License.
padding: 10px;
}
.mx_RestoreKeyBackupDialog_content > div {
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 110px; /* Empirically measured */
}

View file

@ -18,13 +18,14 @@ a.mx_Pill {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
vertical-align: text-bottom;
max-width: calc(100% - 1ch);
}
.mx_Pill {
padding: $font-1px;
padding-right: 0.4em;
vertical-align: text-top;
line-height: $font-17px;
}
/* More specific to override `.markdown-body a` color */

View file

@ -24,11 +24,6 @@ limitations under the License.
background-color: $togglesw-off-color;
opacity: 0.5;
display: flex;
flex-direction: row;
flex: 0 0 auto;
align-items: center;
}
.mx_ToggleSwitch_enabled {
@ -38,16 +33,18 @@ limitations under the License.
.mx_ToggleSwitch.mx_ToggleSwitch_on {
background-color: $togglesw-on-color;
> .mx_ToggleSwitch_ball {
left: calc(100% - $font-20px);
}
}
.mx_ToggleSwitch_ball {
transition: left 0.15s ease-out 0.1s;
position: relative;
width: $font-20px;
height: $font-20px;
border-radius: $font-20px;
background-color: $togglesw-ball-color;
}
.mx_ToggleSwitch_on {
flex-direction: row-reverse;
transition: left 0.15s ease-out 0.1s;
left: 0;
}

View file

@ -126,7 +126,7 @@ limitations under the License.
.mx_RoomView_timeline_rr_enabled,
// on ELS we need the margin to allow interaction with the expand/collapse button which is normally in the RR gutter
.mx_EventListSummary {
.mx_EventTile_line, .mx_EventTile_reply {
.mx_EventTile_line {
/* ideally should be 100px, but 95px gives us a max thumbnail size of 800x600, which is nice */
margin-right: 110px;
}

View file

@ -33,11 +33,6 @@ limitations under the License.
margin-bottom: 1em;
}
.mx_RoomRecoveryReminder_button {
@mixin mx_DialogButton;
margin: 0 10px;
}
.mx_RoomRecoveryReminder_secondary {
font-size: 90%;
margin-top: 1em;

View file

@ -22,6 +22,12 @@ limitations under the License.
margin-top: 0;
}
.mx_GeneralUserSettingsTab_accountSection .mx_Spinner,
.mx_GeneralUserSettingsTab_discovery .mx_Spinner {
// Move the spinner to the left side of the container (default center)
justify-content: left;
}
.mx_GeneralUserSettingsTab_accountSection .mx_EmailAddresses,
.mx_GeneralUserSettingsTab_accountSection .mx_PhoneNumbers,
.mx_GeneralUserSettingsTab_discovery .mx_ExistingEmailAddress,

View file

@ -55,3 +55,12 @@ limitations under the License.
.mx_SecurityUserSettingsTab_ignoredUser .mx_AccessibleButton {
margin-right: 10px;
}
.mx_SecurityUserSettingsTab {
.mx_SettingsTab_section {
.mx_AccessibleButton_kind_link {
padding: 0;
font-size: inherit;
}
}
}

View file

@ -147,6 +147,9 @@ $button-danger-disabled-bg-color: #f5b6bb; // TODO: Verify color
$button-link-fg-color: $accent-color;
$button-link-bg-color: transparent;
// Toggle switch
$togglesw-off-color: $room-highlight-color;
$visual-bell-bg-color: #800;
$room-warning-bg-color: $header-panel-bg-color;

View file

@ -53,7 +53,6 @@ $tooltip-timeline-bg-color: var(--sidebar-color);
$dialog-backdrop-color: var(--sidebar-color-50pct);
//
// --roomlist-background-color
$event-selected-color: var(--roomlist-background-color);
$header-panel-bg-color: var(--roomlist-background-color);
$reaction-row-button-bg-color: var(--roomlist-background-color);
$panel-gradient: var(--roomlist-background-color-0pct), var(--roomlist-background-color);
@ -134,3 +133,6 @@ $username-variant5-color: var(--username-colors_5, $username-variant5-color);
$username-variant6-color: var(--username-colors_6, $username-variant6-color);
$username-variant7-color: var(--username-colors_7, $username-variant7-color);
$username-variant8-color: var(--username-colors_8, $username-variant8-color);
$event-selected-color: var(--timeline-highlights-color);
$event-highlight-bg-color: var(--timeline-highlights-color);

View file

@ -37,4 +37,17 @@ declare global {
interface StorageEstimate {
usageDetails?: {[key: string]: number};
}
export interface ISettledFulfilled<T> {
status: "fulfilled";
value: T;
}
export interface ISettledRejected {
status: "rejected";
reason: any;
}
interface PromiseConstructor {
allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFulfilled<T> | ISettledRejected>>;
}
}

View file

@ -24,6 +24,10 @@ const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
const THIS_DEVICE_TOAST_KEY = 'setupencryption';
const OTHER_DEVICES_TOAST_KEY = 'reviewsessions';
function toastKey(deviceId) {
return "unverified_session_" + deviceId;
}
export default class DeviceListener {
static sharedInstance() {
if (!global.mx_DeviceListener) global.mx_DeviceListener = new DeviceListener();
@ -39,9 +43,18 @@ export default class DeviceListener {
// cache of the key backup info
this._keyBackupInfo = null;
this._keyBackupFetchedAt = null;
// We keep a list of our own device IDs so we can batch ones that were already
// there the last time the app launched into a single toast, but display new
// ones in their own toasts.
this._ourDeviceIdsAtStart = null;
// The set of device IDs we're currently displaying toasts for
this._displayingToastsForDeviceIds = new Set();
}
start() {
MatrixClientPeg.get().on('crypto.willUpdateDevices', this._onWillUpdateDevices);
MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated);
MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged);
MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged);
@ -53,6 +66,7 @@ export default class DeviceListener {
stop() {
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this._onWillUpdateDevices);
MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated);
MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged);
MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged);
@ -64,12 +78,19 @@ export default class DeviceListener {
this._dismissedThisDeviceToast = false;
this._keyBackupInfo = null;
this._keyBackupFetchedAt = null;
this._ourDeviceIdsAtStart = null;
this._displayingToastsForDeviceIds = new Set();
}
async dismissVerifications() {
const cli = MatrixClientPeg.get();
const devices = await cli.getStoredDevicesForUser(cli.getUserId());
this._dismissed = new Set(devices.filter(d => d.deviceId !== cli.deviceId).map(d => d.deviceId));
/**
* Dismiss notifications about our own unverified devices
*
* @param {String[]} deviceIds List of device IDs to dismiss notifications for
*/
async dismissUnverifiedSessions(deviceIds) {
for (const d of deviceIds) {
this._dismissed.add(d);
}
this._recheck();
}
@ -79,6 +100,28 @@ export default class DeviceListener {
this._recheck();
}
_ensureDeviceIdsAtStartPopulated() {
if (this._ourDeviceIdsAtStart === null) {
const cli = MatrixClientPeg.get();
this._ourDeviceIdsAtStart = new Set(
cli.getStoredDevicesForUser(cli.getUserId()).map(d => d.deviceId),
);
}
}
_onWillUpdateDevices = async (users, initialFetch) => {
// If we didn't know about *any* devices before (ie. it's fresh login),
// then they are all pre-existing devices, so ignore this and set the
// devicesAtStart list to the devices that we see after the fetch.
if (initialFetch) return;
const myUserId = MatrixClientPeg.get().getUserId();
if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated();
// No need to do a recheck here: we just need to get a snapshot of our devices
// before we download any new ones.
}
_onDevicesUpdated = (users) => {
if (!users.includes(MatrixClientPeg.get().getUserId())) return;
this._recheck();
@ -182,7 +225,6 @@ export default class DeviceListener {
});
}
}
return;
} else if (await cli.secretStorageKeyNeedsUpgrade()) {
ToastStore.sharedInstance().addOrReplaceToast({
key: THIS_DEVICE_TOAST_KEY,
@ -197,32 +239,70 @@ export default class DeviceListener {
}
}
// This needs to be done after awaiting on downloadKeys() above, so
// we make sure we get the devices after the fetch is done.
this._ensureDeviceIdsAtStartPopulated();
// Unverified devices that were there last time the app ran
// (technically could just be a boolean: we don't actually
// need to remember the device IDs, but for the sake of
// symmetry...).
const oldUnverifiedDeviceIds = new Set();
// Unverified devices that have appeared since then
const newUnverifiedDeviceIds = new Set();
// as long as cross-signing isn't ready,
// you can't see or dismiss any device toasts
if (crossSigningReady) {
let haveUnverifiedDevices = false;
const devices = await cli.getStoredDevicesForUser(cli.getUserId());
const devices = cli.getStoredDevicesForUser(cli.getUserId());
for (const device of devices) {
if (device.deviceId == cli.deviceId) continue;
const deviceTrust = await cli.checkDeviceTrust(cli.getUserId(), device.deviceId);
if (!deviceTrust.isCrossSigningVerified() && !this._dismissed.has(device.deviceId)) {
haveUnverifiedDevices = true;
break;
if (this._ourDeviceIdsAtStart.has(device.deviceId)) {
oldUnverifiedDeviceIds.add(device.deviceId);
} else {
newUnverifiedDeviceIds.add(device.deviceId);
}
}
}
}
if (haveUnverifiedDevices) {
// Display or hide the batch toast for old unverified sessions
if (oldUnverifiedDeviceIds.size > 0) {
ToastStore.sharedInstance().addOrReplaceToast({
key: OTHER_DEVICES_TOAST_KEY,
title: _t("Review where youre logged in"),
icon: "verification_warning",
component: sdk.getComponent("toasts.UnverifiedSessionToast"),
priority: ToastStore.PRIORITY_LOW,
props: {
deviceIds: oldUnverifiedDeviceIds,
},
component: sdk.getComponent("toasts.BulkUnverifiedSessionsToast"),
});
} else {
ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY);
}
// Show toasts for new unverified devices if they aren't already there
for (const deviceId of newUnverifiedDeviceIds) {
ToastStore.sharedInstance().addOrReplaceToast({
key: toastKey(deviceId),
title: _t("New login. Was this you?"),
icon: "verification_warning",
props: { deviceId },
component: sdk.getComponent("toasts.UnverifiedSessionToast"),
});
}
// ...and hide any we don't need any more
for (const deviceId of this._displayingToastsForDeviceIds) {
if (!newUnverifiedDeviceIds.has(deviceId)) {
ToastStore.sharedInstance().dismissToast(toastKey(deviceId));
}
}
this._displayingToastsForDeviceIds = newUnverifiedDeviceIds;
}
}

View file

@ -836,7 +836,7 @@ export const Commands = [
const fingerprint = matches[3];
return success((async () => {
const device = await cli.getStoredDevice(userId, deviceId);
const device = cli.getStoredDevice(userId, deviceId);
if (!device) {
throw new Error(_t('Unknown (user, session) pair:') + ` (${userId}, ${deviceId})`);
}

View file

@ -227,7 +227,7 @@ export default class RightPanel extends React.Component {
if (this.props.user) {
// If we have a user prop then we're displaying a user from the 'user' page type
// in LoggedInView, so need to change the page type to close the panel (we switch
// to the home page which is not obviosuly the correct thing to do, but I'm not sure
// to the home page which is not obviously the correct thing to do, but I'm not sure
// anything else is - we could hide the close button altogether?)
dis.dispatch({
action: "view_home_page",

View file

@ -37,6 +37,42 @@ import {toRem} from "../../utils/rem";
// turn this on for drop & drag console debugging galore
const debug = false;
class RoomTileErrorBoundary extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
error: null,
};
}
static getDerivedStateFromError(error) {
// Side effects are not permitted here, so we only update the state so
// that the next render shows an error message.
return { error };
}
componentDidCatch(error, { componentStack }) {
// Browser consoles are better at formatting output when native errors are passed
// in their own `console.error` invocation.
console.error(error);
console.error(
"The above error occured while React was rendering the following components:",
componentStack,
);
}
render() {
if (this.state.error) {
return (<div className="mx_RoomTile mx_RoomTileError">
{this.props.roomId}
</div>);
} else {
return this.props.children;
}
}
}
export default class RoomSubList extends React.PureComponent {
static displayName = 'RoomSubList';
static debug = debug;
@ -208,7 +244,7 @@ export default class RoomSubList extends React.PureComponent {
};
makeRoomTile = (room) => {
return <RoomTile
return <RoomTileErrorBoundary roomId={room.roomId}><RoomTile
room={room}
roomSubList={this}
tagName={this.props.tagName}
@ -221,7 +257,7 @@ export default class RoomSubList extends React.PureComponent {
refreshSubList={this._updateSubListCount}
incomingCall={null}
onClick={this.onRoomTileClick}
/>;
/></RoomTileErrorBoundary>;
};
_onNotifBadgeClick = (e) => {

View file

@ -425,7 +425,7 @@ export default createReactClass({
}
this.onResize();
document.addEventListener("keydown", this.onKeyDown);
document.addEventListener("keydown", this.onNativeKeyDown);
},
shouldComponentUpdate: function(nextProps, nextState) {
@ -508,7 +508,7 @@ export default createReactClass({
this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize);
}
document.removeEventListener("keydown", this.onKeyDown);
document.removeEventListener("keydown", this.onNativeKeyDown);
// Remove RoomStore listener
if (this._roomStoreToken) {
@ -550,7 +550,8 @@ export default createReactClass({
}
},
onKeyDown: function(ev) {
// we register global shortcuts here, they *must not conflict* with local shortcuts elsewhere or both will fire
onNativeKeyDown: function(ev) {
let handled = false;
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
@ -576,6 +577,25 @@ export default createReactClass({
}
},
onReactKeyDown: function(ev) {
let handled = false;
switch (ev.key) {
case Key.ESCAPE:
if (!ev.altKey && !ev.ctrlKey && !ev.shiftKey && !ev.metaKey) {
this._messagePanel.forgetReadMarker();
this.jumpToLiveTimeline();
handled = true;
}
break;
}
if (handled) {
ev.stopPropagation();
ev.preventDefault();
}
},
onAction: function(payload) {
switch (payload.action) {
case 'message_send_failed':
@ -1768,7 +1788,7 @@ export default createReactClass({
const showRoomRecoveryReminder = (
SettingsStore.getValue("showRoomRecoveryReminder") &&
this.context.isRoomEncrypted(this.state.room.roomId) &&
!this.context.getKeyBackupEnabled()
this.context.getKeyBackupEnabled() === false
);
const hiddenHighlightCount = this._getHiddenHighlightCount();
@ -2008,9 +2028,13 @@ export default createReactClass({
mx_RoomView_timeline_rr_enabled: this.state.showReadReceipts,
});
const mainClasses = classNames("mx_RoomView", {
mx_RoomView_inCall: inCall,
});
return (
<RoomContext.Provider value={this.state}>
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref={this._roomView}>
<main className={mainClasses} ref={this._roomView} onKeyDown={this.onReactKeyDown}>
<ErrorBoundary>
<RoomHeader
room={this.state.room}

View file

@ -42,7 +42,10 @@ export default class UserView extends React.Component {
}
componentDidUpdate(prevProps) {
if (prevProps.userId !== this.props.userId) {
// XXX: We shouldn't need to null check the userId here, but we declare
// it as optional and MatrixChat sometimes fires in a way which results
// in an NPE when we try to update the profile info.
if (prevProps.userId !== this.props.userId && this.props.userId) {
this._loadProfileInfo();
}
}

View file

@ -76,7 +76,7 @@ export default createReactClass({
email: this.props.defaultEmail || "",
phoneNumber: this.props.defaultPhoneNumber || "",
password: this.props.defaultPassword || "",
passwordConfirm: "",
passwordConfirm: this.props.defaultPassword || "",
passwordComplexity: null,
passwordSafe: false,
};

View file

@ -577,12 +577,15 @@ export default class InviteDialog extends React.PureComponent {
if (SettingsStore.getValue("feature_cross_signing")) {
// Check whether all users have uploaded device keys before.
// If so, enable encryption in the new room.
const has3PidMembers = targets.some(t => t instanceof ThreepidMember);
if (!has3PidMembers) {
const client = MatrixClientPeg.get();
const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds);
if (allHaveDeviceKeys) {
createRoomOptions.encryption = true;
}
}
}
// Check if it's a traditional DM and create the room if required.
// TODO: [Canonical DMs] Remove this check and instead just create the multi-person DM
@ -1067,9 +1070,8 @@ export default class InviteDialog extends React.PureComponent {
let buttonText;
let goButtonFn;
if (this.props.kind === KIND_DM) {
const userId = MatrixClientPeg.get().getUserId();
if (this.props.kind === KIND_DM) {
title = _t("Direct Messages");
helpText = _t(
"Start a conversation with someone using their name, username (like <userId/>) or email address.",
@ -1083,9 +1085,11 @@ export default class InviteDialog extends React.PureComponent {
} else { // KIND_INVITE
title = _t("Invite to this room");
helpText = _t(
"If you can't find someone, ask them for their username (e.g. @user:server.com) or " +
"<a>share this room</a>.", {},
"Invite someone using their name, username (like <userId/>), email address or <a>share this room</a>.",
{},
{
userId: () =>
<a href={makeUserPermalink(userId)} rel="noreferrer noopener" target="_blank">{userId}</a>,
a: (sub) =>
<a href={makeRoomPermalink(this.props.roomId)} rel="noreferrer noopener" target="_blank">{sub}</a>,
},

View file

@ -59,6 +59,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
forceRecoveryKey: false,
passPhrase: '',
restoreType: null,
progress: { stage: "prefetch" },
};
}
@ -80,6 +81,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
});
}
_progressCallback = (data) => {
this.setState({
progress: data,
});
}
_onResetRecoveryClick = () => {
this.props.onFinished(false);
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
@ -110,6 +117,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
// is the right one and restoring it is currently the only way we can do this.
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword(
this.state.passPhrase, undefined, undefined, this.state.backupInfo,
{ progressCallback: this._progressCallback },
);
if (this.props.keyCallback) {
const key = await MatrixClientPeg.get().keyBackupKeyFromPassword(
@ -146,6 +154,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
try {
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey(
this.state.recoveryKey, undefined, undefined, this.state.backupInfo,
{ progressCallback: this._progressCallback },
);
if (this.props.keyCallback) {
const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey);
@ -185,6 +194,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
const recoverInfo = await accessSecretStorage(async () => {
return MatrixClientPeg.get().restoreKeyBackupWithSecretStorage(
this.state.backupInfo,
{ progressCallback: this._progressCallback },
);
});
this.setState({
@ -207,6 +217,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
undefined, /* targetRoomId */
undefined, /* targetSessionId */
backupInfo,
{ progressCallback: this._progressCallback },
);
this.setState({
recoverInfo,
@ -272,8 +283,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
let content;
let title;
if (this.state.loading) {
title = _t("Loading...");
content = <Spinner />;
title = _t("Restoring keys from backup");
let details;
if (this.state.progress.stage === "fetch") {
details = _t("Fetching keys from server...");
} else if (this.state.progress.stage === "load_keys") {
const { total, successes, failures } = this.state.progress;
details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures });
} else if (this.state.progress.stage === "prefetch") {
details = _t("Fetching keys from server...");
}
content = <div>
<div>{details}</div>
<Spinner />
</div>;
} else if (this.state.loadError) {
title = _t("Error");
content = _t("Unable to load backup status");
@ -305,7 +328,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
content = _t("No backup found!");
} else if (this.state.recoverInfo) {
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
title = _t("Backup restored");
title = _t("Keys restored");
let failedToDecrypt;
if (this.state.recoverInfo.total > this.state.recoverInfo.imported) {
failedToDecrypt = <p>{_t(
@ -314,7 +337,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
)}</p>;
}
content = <div>
<p>{_t("Restored %(sessionCount)s session keys", {sessionCount: this.state.recoverInfo.imported})}</p>
<p>{_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}</p>
{failedToDecrypt}
<DialogButtons primaryButton={_t('OK')}
onPrimaryButtonClick={this._onDone}
@ -435,7 +458,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
onFinished={this.props.onFinished}
title={title}
>
<div>
<div className='mx_RestoreKeyBackupDialog_content'>
{content}
</div>
</BaseDialog>

View file

@ -21,6 +21,7 @@ import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../CrossSigningManager';
/*
* Access Secure Secret Storage by requesting the user's passphrase.
@ -55,8 +56,9 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
}
_onResetRecoveryClick = () => {
// Re-enter the access flow, but resetting storage this time around.
this.props.onFinished(false);
throw new Error("Resetting secret storage unimplemented");
accessSecretStorage(() => {}, /* forceReset = */ true);
}
_onRecoveryKeyChange = (e) => {

View file

@ -19,8 +19,22 @@ import TagTile from './TagTile';
import React from 'react';
import { Draggable } from 'react-beautiful-dnd';
import { ContextMenu, toRightOf, useContextMenu } from "../../structures/ContextMenu";
import * as sdk from '../../../index';
export default function DNDTagTile(props) {
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu();
let contextMenu = null;
if (menuDisplayed && handle.current) {
const elementRect = handle.current.getBoundingClientRect();
const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu');
contextMenu = (
<ContextMenu {...toRightOf(elementRect)} onFinished={closeMenu}>
<TagTileContextMenu tag={props.tag} onFinished={closeMenu} />
</ContextMenu>
);
}
return <div>
<Draggable
key={props.tag}
@ -29,17 +43,20 @@ export default function DNDTagTile(props) {
type="draggable-TagTile"
>
{(provided, snapshot) => (
<div>
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<TagTile {...props} />
</div>
{ provided.placeholder }
<TagTile
{...props}
contextMenuButtonRef={handle}
menuDisplayed={menuDisplayed}
openMenu={openMenu}
/>
</div>
)}
</Draggable>
{contextMenu}
</div>;
}

View file

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {createRef} from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import classNames from 'classnames';
@ -28,7 +28,6 @@ import * as FormattingUtils from '../../../utils/FormattingUtils';
import FlairStore from '../../../stores/FlairStore';
import GroupStore from '../../../stores/GroupStore';
import TagOrderStore from '../../../stores/TagOrderStore';
import {ContextMenu, toRightOf} from "../../structures/ContextMenu";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents
@ -43,6 +42,9 @@ export default createReactClass({
// A string tag such as "m.favourite" or a group ID such as "+groupid:domain.bla"
// For now, only group IDs are handled.
tag: PropTypes.string,
contextMenuButtonRef: PropTypes.object,
openMenu: PropTypes.func,
menuDisplayed: PropTypes.bool,
},
statics: {
@ -55,14 +57,10 @@ export default createReactClass({
hover: false,
// The profile data of the group if this.props.tag is a group ID
profile: null,
// Whether or not the context menu is open
menuDisplayed: false,
};
},
componentDidMount() {
this._contextMenuButton = createRef();
this.unmounted = false;
if (this.props.tag[0] === '+') {
FlairStore.addListener('updateGroupProfile', this._onFlairStoreUpdated);
@ -124,17 +122,8 @@ export default createReactClass({
// Prevent the TagTile onClick event firing as well
e.stopPropagation();
e.preventDefault();
this.setState({
menuDisplayed: true,
hover: false,
});
},
closeMenu: function() {
this.setState({
menuDisplayed: false,
});
this.setState({ hover: false });
this.props.openMenu();
},
render: function() {
@ -154,7 +143,7 @@ export default createReactClass({
const badge = TagOrderStore.getGroupBadge(this.props.tag);
let badgeElement;
if (badge && !this.state.hover) {
if (badge && !this.state.hover && !this.props.menuDisplayed) {
const badgeClasses = classNames({
"mx_TagTile_badge": true,
"mx_TagTile_badgeHighlight": badge.highlight,
@ -163,26 +152,24 @@ export default createReactClass({
}
// FIXME: this ought to use AccessibleButton for a11y but that causes onMouseOut/onMouseOver to fire too much
const contextButton = this.state.hover || this.state.menuDisplayed ?
<div className="mx_TagTile_context_button" onClick={this.openMenu} ref={this._contextMenuButton}>
const contextButton = this.state.hover || this.props.menuDisplayed ?
<div className="mx_TagTile_context_button" onClick={this.openMenu} ref={this.props.contextMenuButtonRef}>
{"\u00B7\u00B7\u00B7"}
</div> : <div ref={this._contextMenuButton} />;
let contextMenu;
if (this.state.menuDisplayed) {
const elementRect = this._contextMenuButton.current.getBoundingClientRect();
const TagTileContextMenu = sdk.getComponent('context_menus.TagTileContextMenu');
contextMenu = (
<ContextMenu {...toRightOf(elementRect)} onFinished={this.closeMenu}>
<TagTileContextMenu tag={this.props.tag} onFinished={this.closeMenu} />
</ContextMenu>
);
}
</div> : <div ref={this.props.contextMenuButtonRef} />;
const AccessibleTooltipButton = sdk.getComponent("elements.AccessibleTooltipButton");
return <React.Fragment>
<AccessibleTooltipButton className={className} onClick={this.onClick} onContextMenu={this.openMenu} title={name}>
<div className="mx_TagTile_avatar" onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut}>
return <AccessibleTooltipButton
className={className}
onClick={this.onClick}
onContextMenu={this.openMenu}
title={name}
>
<div
className="mx_TagTile_avatar"
onMouseOver={this.onMouseOver}
onMouseOut={this.onMouseOut}
>
<BaseAvatar
name={name}
idName={this.props.tag}
@ -193,9 +180,6 @@ export default createReactClass({
{contextButton}
{badgeElement}
</div>
</AccessibleTooltipButton>
{ contextMenu }
</React.Fragment>;
</AccessibleTooltipButton>;
},
});

View file

@ -22,7 +22,6 @@ import VerificationPanel from "./VerificationPanel";
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import {ensureDMExists} from "../../../createRoom";
import {useEventEmitter} from "../../../hooks/useEventEmitter";
import {useAsyncMemo} from "../../../hooks/useAsyncMemo";
import Modal from "../../../Modal";
import {PHASE_REQUESTED, PHASE_UNSENT} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
import * as sdk from "../../../index";
@ -47,10 +46,7 @@ const EncryptionPanel = (props) => {
}, [verificationRequest]);
const deviceId = request && request.channel.deviceId;
const device = useAsyncMemo(() => {
const cli = MatrixClientPeg.get();
return cli.getStoredDevice(cli.getUserId(), deviceId);
}, [deviceId]);
const device = MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId);
useEffect(() => {
async function awaitPromise() {

View file

@ -1110,7 +1110,7 @@ export const useDevices = (userId) => {
async function _downloadDeviceList() {
try {
await cli.downloadKeys([userId], true);
const devices = await cli.getStoredDevicesForUser(userId);
const devices = cli.getStoredDevicesForUser(userId);
if (cancelled) {
// we got cancelled - presumably a different user now
@ -1135,7 +1135,7 @@ export const useDevices = (userId) => {
useEffect(() => {
let cancel = false;
const updateDevices = async () => {
const newDevices = await cli.getStoredDevicesForUser(userId);
const newDevices = cli.getStoredDevicesForUser(userId);
if (cancel) return;
setDevices(newDevices);
};

View file

@ -160,14 +160,11 @@ export default createReactClass({
// no need to re-download the whole thing; just update our copy of
// the list.
// Promise.resolve to handle transition from static result to promise; can be removed
// in future
Promise.resolve(this.context.getStoredDevicesForUser(userId)).then((devices) => {
const devices = this.context.getStoredDevicesForUser(userId);
this.setState({
devices: devices,
e2eStatus: this._getE2EStatus(devices),
});
});
}
},

View file

@ -129,7 +129,7 @@ export default createReactClass({
return;
}
const devices = await cli.getStoredDevicesForUser(userId);
const devices = cli.getStoredDevicesForUser(userId);
const anyDeviceUnverified = devices.some(device => {
const { deviceId } = device;
// For your own devices, we use the stricter check of cross-signing

View file

@ -150,7 +150,7 @@ export default class RoomRecoveryReminder extends React.PureComponent {
)}</p>
</div>
<div className="mx_RoomRecoveryReminder_buttons">
<AccessibleButton className="mx_RoomRecoveryReminder_button"
<AccessibleButton kind="primary"
onClick={this.onSetupClick}>
{setupCaption}
</AccessibleButton>

View file

@ -432,10 +432,9 @@ export default createReactClass({
});
let name = this.state.roomName;
if (name == undefined || name == null) name = '';
if (typeof name !== 'string') name = '';
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
let badge;
if (badges) {
const limitedCount = FormattingUtils.formatCount(notificationCount);

View file

@ -36,6 +36,7 @@ import {SERVICE_TYPES} from "matrix-js-sdk";
import IdentityAuthClient from "../../../../../IdentityAuthClient";
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
import Spinner from "../../../elements/Spinner";
export default class GeneralUserSettingsTab extends React.Component {
static propTypes = {
@ -58,6 +59,10 @@ export default class GeneralUserSettingsTab extends React.Component {
},
emails: [],
msisdns: [],
loading3pids: true, // whether or not the emails and msisdns have been loaded
...this._calculateThemeState(),
customThemeUrl: "",
customThemeMessage: {isError: false, text: ""},
};
this.dispatcherRef = dis.register(this._onAction);
@ -120,8 +125,11 @@ export default class GeneralUserSettingsTab extends React.Component {
);
console.warn(e);
}
this.setState({ emails: threepids.filter((a) => a.medium === 'email') });
this.setState({ msisdns: threepids.filter((a) => a.medium === 'msisdn') });
this.setState({
emails: threepids.filter((a) => a.medium === 'email'),
msisdns: threepids.filter((a) => a.medium === 'msisdn'),
loading3pids: false,
});
}
async _checkTerms() {
@ -225,7 +233,6 @@ export default class GeneralUserSettingsTab extends React.Component {
const ChangePassword = sdk.getComponent("views.settings.ChangePassword");
const EmailAddresses = sdk.getComponent("views.settings.account.EmailAddresses");
const PhoneNumbers = sdk.getComponent("views.settings.account.PhoneNumbers");
const Spinner = sdk.getComponent("views.elements.Spinner");
let passwordChangeForm = (
<ChangePassword
@ -244,18 +251,24 @@ export default class GeneralUserSettingsTab extends React.Component {
// For newer homeservers with separate 3PID add and bind methods (MSC2290),
// there is no such concern, so we can always show the HS account 3PIDs.
if (this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true) {
threepidSection = <div>
<span className="mx_SettingsTab_subheading">{_t("Email addresses")}</span>
<EmailAddresses
const emails = this.state.loading3pids || true
? <Spinner />
: <EmailAddresses
emails={this.state.emails}
onEmailsChange={this._onEmailsChange}
/>
<span className="mx_SettingsTab_subheading">{_t("Phone numbers")}</span>
<PhoneNumbers
/>;
const msisdns = this.state.loading3pids
? <Spinner />
: <PhoneNumbers
msisdns={this.state.msisdns}
onMsisdnsChange={this._onMsisdnsChange}
/>
/>;
threepidSection = <div>
<span className="mx_SettingsTab_subheading">{_t("Email addresses")}</span>
{emails}
<span className="mx_SettingsTab_subheading">{_t("Phone numbers")}</span>
{msisdns}
</div>;
} else if (this.state.serverSupportsSeparateAddAndBind === null) {
threepidSection = <Spinner />;
@ -320,12 +333,15 @@ export default class GeneralUserSettingsTab extends React.Component {
const EmailAddresses = sdk.getComponent("views.settings.discovery.EmailAddresses");
const PhoneNumbers = sdk.getComponent("views.settings.discovery.PhoneNumbers");
const emails = this.state.loading3pids ? <Spinner /> : <EmailAddresses emails={this.state.emails} />;
const msisdns = this.state.loading3pids ? <Spinner /> : <PhoneNumbers msisdns={this.state.msisdns} />;
const threepidSection = this.state.haveIdServer ? <div className='mx_GeneralUserSettingsTab_discovery'>
<span className="mx_SettingsTab_subheading">{_t("Email addresses")}</span>
<EmailAddresses emails={this.state.emails} />
{emails}
<span className="mx_SettingsTab_subheading">{_t("Phone numbers")}</span>
<PhoneNumbers msisdns={this.state.msisdns} />
{msisdns}
</div> : null;
return (

View file

@ -112,7 +112,10 @@ export default class SecurityUserSettingsTab extends React.Component {
};
_onGoToUserProfileClick = () => {
// close the settings dialog & let the default action run (ie. navigate to the link)
dis.dispatch({
action: 'view_user_info',
userId: MatrixClientPeg.get().getUserId(),
});
this.props.closeSettingsFn();
}
@ -327,9 +330,9 @@ export default class SecurityUserSettingsTab extends React.Component {
"Manage the names of and sign out of your sessions below or " +
"<a>verify them in your User Profile</a>.", {},
{
a: sub => <a href={"#/user/" + MatrixClientPeg.get().getUserId()}
onClick={this._onGoToUserProfileClick}
>{sub}</a>,
a: sub => <AccessibleButton kind="link" onClick={this._onGoToUserProfileClick}>
{sub}
</AccessibleButton>,
},
)}
</span>

View file

@ -0,0 +1,56 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import dis from "../../../dispatcher";
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import DeviceListener from '../../../DeviceListener';
import FormButton from '../elements/FormButton';
import { replaceableComponent } from '../../../utils/replaceableComponent';
@replaceableComponent("views.toasts.BulkUnverifiedSessionsToast")
export default class BulkUnverifiedSessionsToast extends React.PureComponent {
static propTypes = {
deviceIds: PropTypes.array,
}
_onLaterClick = () => {
DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds);
};
_onReviewClick = async () => {
DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds);
dis.dispatch({
action: 'view_user_info',
userId: MatrixClientPeg.get().getUserId(),
});
};
render() {
return (<div>
<div className="mx_Toast_description">
{_t("Verify all your sessions to ensure your account & messages are safe")}
</div>
<div className="mx_Toast_buttons" aria-live="off">
<FormButton label={_t("Later")} kind="danger" onClick={this._onLaterClick} />
<FormButton label={_t("Review")} onClick={this._onReviewClick} />
</div>
</div>);
}
}

View file

@ -90,6 +90,7 @@ export default class SetupEncryptionToast extends React.PureComponent {
getSetupCaption() {
switch (this.props.kind) {
case 'set_up_encryption':
return _t('Set up');
case 'upgrade_encryption':
case 'upgrade_ssss':
return _t('Upgrade');

View file

@ -15,36 +15,51 @@ limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import dis from "../../../dispatcher";
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import DeviceListener from '../../../DeviceListener';
import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog';
import FormButton from '../elements/FormButton';
import { replaceableComponent } from '../../../utils/replaceableComponent';
@replaceableComponent("views.toasts.UnverifiedSessionToast")
export default class UnverifiedSessionToast extends React.PureComponent {
static propTypes = {
deviceId: PropTypes.string,
}
_onLaterClick = () => {
DeviceListener.sharedInstance().dismissVerifications();
DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]);
};
_onReviewClick = async () => {
DeviceListener.sharedInstance().dismissVerifications();
dis.dispatch({
action: 'view_user_info',
userId: MatrixClientPeg.get().getUserId(),
});
const cli = MatrixClientPeg.get();
Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, {
userId: cli.getUserId(),
device: cli.getStoredDevice(cli.getUserId(), this.props.deviceId),
onFinished: (r) => {
if (!r) {
/* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */
DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]);
}
},
}, null, /* priority = */ false, /* static = */ true);
};
render() {
const cli = MatrixClientPeg.get();
const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId);
return (<div>
<div className="mx_Toast_description">
{_t("Verify your other sessions")}
{_t(
"Verify the new login accessing your account: %(name)s", { name: device.getDisplayName()})}
</div>
<div className="mx_Toast_buttons" aria-live="off">
<FormButton label={_t("Later")} kind="danger" onClick={this._onLaterClick} />
<FormButton label={_t("Review")} onClick={this._onReviewClick} />
<FormButton label={_t("Verify")} onClick={this._onReviewClick} />
</div>
</div>);
}

View file

@ -51,7 +51,7 @@ export default class VerificationRequestToast extends React.PureComponent {
if (request.isSelfVerification) {
const cli = MatrixClientPeg.get();
this.setState({device: await cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)});
this.setState({device: cli.getStoredDevice(cli.getUserId(), request.channel.deviceId)});
}
}

View file

@ -259,7 +259,7 @@ class RoomPillPart extends PillPart {
"crop");
if (!avatarUrl) {
initialLetter = Avatar.getInitialLetter(this._room ? this._room.name : this.resourceId);
avatarUrl = `../../${Avatar.defaultAvatarUrlForString(this._room ? this._room.roomId : this.resourceId)}`;
avatarUrl = Avatar.defaultAvatarUrlForString(this._room ? this._room.roomId : this.resourceId);
}
this._setAvatarVars(node, avatarUrl, initialLetter);
}
@ -291,18 +291,13 @@ class UserPillPart extends PillPart {
}
const name = this._member.name || this._member.userId;
const defaultAvatarUrl = Avatar.defaultAvatarUrlForString(this._member.userId);
let avatarUrl = Avatar.avatarUrlForMember(
const avatarUrl = Avatar.avatarUrlForMember(
this._member,
16 * window.devicePixelRatio,
16 * window.devicePixelRatio,
"crop");
let initialLetter = "";
if (avatarUrl === defaultAvatarUrl) {
// the url from defaultAvatarUrlForString is meant to go in an img element,
// which has the base of the document. we're using it in css,
// which has the base of the theme css file, two levels deeper than the document,
// so go up to the level of the document.
avatarUrl = `../../${avatarUrl}`;
initialLetter = Avatar.getInitialLetter(name);
}
this._setAvatarVars(node, avatarUrl, initialLetter);

View file

@ -1961,5 +1961,221 @@
"Enable message search in encrypted rooms": "Включи търсенето на съобщения в шифровани стаи",
"Keep secret storage passphrase in memory for this session": "Съхрани паролата за секретното складиране в паметта за тази сесия",
"How fast should messages be downloaded.": "Колко бързо да се изтеглят съобщенията.",
"Manually verify all remote sessions": "Ръчно потвърждаване на всички отдалечени сесии"
"Manually verify all remote sessions": "Ръчно потвърждаване на всички отдалечени сесии",
"If you cancel now, you won't complete your operation.": "Ако се откажете сега, няма да завършите операцията.",
"Review where youre logged in": "Прегледайте откъде сте влезли в профила си",
"New login. Was this you?": "Нов вход. Вие ли бяхте това?",
"%(name)s is requesting verification": "%(name)s изпрати запитване за верификация",
"Failed to set topic": "Неуспешно задаване на тема",
"Command failed": "Командата не се изпълни",
"Could not find user in room": "Неуспешно намиране на потребител в стаята",
"Please supply a widget URL or embed code": "Укажете URL адрес на приспособление или код за вграждане",
"Send a bug report with logs": "Изпратете доклад за грешка с логове",
"Enable cross-signing to verify per-user instead of per-session": "Включи кръстосано-подписване за верифициране на ниво потребител, вместо на ниво сесия",
"Keep recovery passphrase in memory for this session": "Запази паролата за възстановяване в паметта за тази сесия",
"Verify this session by completing one of the following:": "Верифицирайте тази сесия чрез едно от следните действия:",
"Scan this unique code": "Сканирайте този уникален код",
"or": "или",
"Compare unique emoji": "Сравнете уникални емоджи",
"Compare a unique set of emoji if you don't have a camera on either device": "Сравнете уникални емоджи, ако нямате камера на някое от устройствата",
"Start": "Започни",
"Confirm the emoji below are displayed on both sessions, in the same order:": "Потвърдете, че емоджитата по-долу са показани и на двете сесии в един и същи ред:",
"Verify this session by confirming the following number appears on its screen.": "Потвърдете тази сесия, като потвърдите, че следното число се появява на екрана й.",
"Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Изчакване на другата сесия, %(deviceName)s (%(deviceId)s) да потвърди…",
"Waiting for %(displayName)s to verify…": "Изчакване на %(displayName)s да потвърди…",
"Cancelling…": "Отказване…",
"They match": "Съвпадат",
"They don't match": "Не съвпадат",
"To be secure, do this in person or use a trusted way to communicate.": "За да е по-сигурно, направете го на живо или използвайте доверен начин за комуникация.",
"Lock": "Заключи",
"Unverified sessions currently have access to your account & messages": "Непотвърдени сесии в момента имат достъп до профила и съобщенията ви",
"Later": "По-късно",
"Review": "Прегледай",
"Verify yourself & others to keep your chats safe": "Потвърдете себе си и останалите за да запазите чатовете си сигурни",
"Other users may not trust it": "Други потребители може да не се доверят",
"Update your secure storage": "Обновете защитеното складиране",
"Verify the identity of the new login accessing your account & messages": "Потвърдете самоличността на новия вход достъпващ профила и съобщенията ви",
"From %(deviceName)s (%(deviceId)s)": "От %(deviceName)s (%(deviceId)s)",
"This bridge was provisioned by <user />.": "Мостът е настроен от <user />.",
"Workspace: %(networkName)s": "Работна област: %(networkName)s",
"Channel: %(channelName)s": "Канал: %(channelName)s",
"Show less": "Покажи по-малко",
"Changing password will currently reset any end-to-end encryption keys on all sessions, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Промяната на паролата в момента би нулирало всички ключове за шифроване-от-край-до-край, правейки историята на чата нечетима, освен ако първо не експортирате ключовете, а след промяната на паролата ги импортирате. В бъдеще, това ще бъде подобрено.",
"Your homeserver does not support cross-signing.": "Сървърът ви не поддържа кръстосано-подписване.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Профилът ви има самоличност за кръстосано подписване в секретно складиране, но все още не е доверено от тази сесия.",
"Reset cross-signing and secret storage": "Нулирай кръстосаното-подписване и секретното складиране",
"well formed": "коректен",
"unexpected type": "непознат тип",
"in memory": "в паметта",
"Self signing private key:": "Частен ключ за самоподписване:",
"cached locally": "кеширан локално",
"not found locally": "ненамерен локално",
"User signing private key:": "Частен ключ за подписване на потребители:",
"Session backup key:": "Ключ за резервно копие на сесията:",
"Homeserver feature support:": "Поддържани функции от сървъра:",
"exists": "съществува",
"Secret Storage key format:": "Формат на ключа за секретно складиране:",
"outdated": "остарял",
"up to date": "обновен",
"Your homeserver does not support session management.": "Сървърът ви не поддържа управление на сесии.",
"Unable to load session list": "Неуспешно зареждане на списъка със сесии",
"Confirm deleting these sessions by using Single Sign On to prove your identity.|other": "Потвърдете изтриването на тези сесии използвайки Single Sign On, за да докажете самоличността си.",
"Confirm deleting these sessions by using Single Sign On to prove your identity.|one": "Потвърдете изтриването на тази сесия използвайки Single Sign On, за да докажете самоличността си.",
"Confirm deleting these sessions": "Потвърдете изтриването на тези сесии",
"Click the button below to confirm deleting these sessions.|other": "Кликнете бутона по-долу за да потвърдите изтриването на тези сесии.",
"Click the button below to confirm deleting these sessions.|one": "Кликнете бутона по-долу за да потвърдите изтриването на тази сесия.",
"Delete sessions|other": "Изтрий сесиите",
"Delete sessions|one": "Изтрий сесията",
"Delete %(count)s sessions|other": "Изтрий %(count)s сесии",
"Delete %(count)s sessions|one": "Изтрий %(count)s сесия",
"Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Потвърждавай индивидуално всяка сесия на потребителите, маркирайки я като доверена и недоверявайки се на кръстосано-подписваните устройства.",
"Securely cache encrypted messages locally for them to appear in search results, using ": "Кеширай шифровани съобщения по сигурен начин, за да могат да се появяват в резултати от търсения, използвайки ",
" to store messages from ": " за складиране на съобщения от ",
"rooms.": "стаи.",
"Manage": "Управление",
"Securely cache encrypted messages locally for them to appear in search results.": "Кеширай шифровани съобщения локално по сигурен начин за да се появяват в резултати от търсения.",
"Enable": "Включи",
"Riot is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom Riot Desktop with <nativeLink>search components added</nativeLink>.": "Липсват задължителни компоненти в Riot, за да могат да бъдат складирани локално и по сигурен начин шифровани съобщения. Ако искате да експериментирате с тази функция, \"компилирайте\" версия на Riot Desktop с <nativeLink>добавени компоненти за търсене</nativeLink>.",
"Riot can't securely cache encrypted messages locally while running in a web browser. Use <riotLink>Riot Desktop</riotLink> for encrypted messages to appear in search results.": "Riot работещ в браузър не може да складира шифровани съобщения локално по сигурен начин. Използвайте <riotLink>Riot Desktop</riotLink> за да може шифровани съобщения да се появяват в резултати от търсения.",
"This session is backing up your keys. ": "Тази сесия прави резервни копия на ключовете ви. ",
"This session is <b>not backing up your keys</b>, but you do have an existing backup you can restore from and add to going forward.": "Тази сесия <b>не прави резервни копия на ключовете</b>, но имате съществуващо резервно копие, което да възстановите и към което да добавяте от тук нататък.",
"Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Свържете тази сесия с резервно копие на ключове преди да се отпишете от нея, за да не загубите ключове, които може би съществуват единствено в тази сесия.",
"Connect this session to Key Backup": "Свържи тази сесия с резервно копие на ключовете",
"Backup has a signature from <verify>unknown</verify> session with ID %(deviceId)s": "Резервното копие има подпис от <verify>непозната</verify> сесия с идентификатор %(deviceId)s",
"Backup has a <validity>valid</validity> signature from this session": "Резервното копие има <validity>валиден</validity> подпис от тази сесия",
"Backup has an <validity>invalid</validity> signature from this session": "Резервното копие има <validity>невалиден</validity> подпис от тази сесия",
"Verify all your sessions to ensure your account & messages are safe": "Верифицирайте всички свой сесии за да подсигурите, че профила и съобщенията ви са защитени",
"Verify the new login accessing your account: %(name)s": "Верифицирайте новия вход достъпващ профила ви: %(name)s",
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> session <device></device>": "Резервното копие има <validity>валиден</validity> подпис от <verify>потвърдена</verify> сесия <device></device>",
"Backup has a <validity>valid</validity> signature from <verify>unverified</verify> session <device></device>": "Резервното копие има <validity>валиден</validity> подпис от <verify>непотвърдена</verify> сесия <device></device>",
"Backup has an <validity>invalid</validity> signature from <verify>verified</verify> session <device></device>": "Резервното копие има <validity>невалиден</validity> подпис от <verify>потвърдена</verify> сесия <device></device>",
"Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> session <device></device>": "Резервното копие има <validity>невалиден</validity> подпис от <verify>непотвърдена</verify> сесия <device></device>",
"Backup is not signed by any of your sessions": "Резервното копие не е подписано от нито една ваша сесия",
"This backup is trusted because it has been restored on this session": "Това резервно копие е доверено, защото е било възстановено в текущата сесия",
"Backup key stored in secret storage, but this feature is not enabled on this session. Please enable cross-signing in Labs to modify key backup state.": "Резервно копие на ключа е съхранено в секретно складиране, но тази функция не е включена в сегашната сесия. Включете кръстосано-подписване в Labs за да модифицирате състоянието на резервното копие на ключа.",
"Your keys are <b>not being backed up from this session</b>.": "На ключовете ви <b>не се прави резервно копие от тази сесия</b>.",
"Enable desktop notifications for this session": "Включи уведомления на работния плот за тази сесия",
"Enable audible notifications for this session": "Включи звукови уведомления за тази сесия",
"Your password was successfully changed. You will not receive push notifications on other sessions until you log back in to them": "Паролата ви беше променена. Няма да получавате push уведомления на другите ви сесии докато не влезете отново в тях",
"Invalid theme schema.": "Невалиден формат на темата.",
"Error downloading theme information.": "Неуспешно изтегляне на информацията за темата.",
"Theme added!": "Темата беше добавена!",
"Custom theme URL": "Собствен URL адрес на тема",
"Add theme": "Добави тема",
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "За да съобщените за проблем със сигурността свързан с Matrix, прочетете <a>Политиката за споделяне на проблеми със сигурността</a> на Matrix.org.",
"Keyboard Shortcuts": "Клавишни комбинации",
"Session ID:": "Сесиен идентификатор:",
"Session key:": "Сесиен ключ:",
"Message search": "Търсене на съобщения",
"Where youre logged in": "Когато сте вписани",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Управлявайте имената или входа в сесиите си по-долу или <a>ги верифицирайте от профила си</a>.",
"A session's public name is visible to people you communicate with": "Публичното име на сесията е видимо за хората, с които комуникирате",
"This room is bridging messages to the following platforms. <a>Learn more.</a>": "Тази стая препредава съобщения със следните платформи. <a>Научи повече.</a>",
"This room isnt bridging messages to any platforms. <a>Learn more.</a>": "Тази стая не препредава съобщения с други платформи. <a>Научи повече.</a>",
"Bridges": "Мостове",
"This user has not verified all of their sessions.": "Този потребител не е верифицирал всичките си сесии.",
"You have not verified this user.": "Не сте верифицирали този потребител.",
"You have verified this user. This user has verified all of their sessions.": "Верифицирали сте този потребител. Този потребител е верифицирал всичките си сесии.",
"Someone is using an unknown session": "Някой използва непозната сесия",
"This room is end-to-end encrypted": "Тази стая е шифрована от-край-до-край",
"Everyone in this room is verified": "Всички в тази стая са верифицирани",
"Some sessions for this user are not trusted": "Някои сесии на този потребител не са доверени",
"All sessions for this user are trusted": "Всички сесии на този потребител са доверени",
"Some sessions in this encrypted room are not trusted": "Някои сесии в тази шифрована стая не са доверени",
"All sessions in this encrypted room are trusted": "Всички сесии в тази шифрована стая са доверени",
"Mod": "Модератор",
"Your key share request has been sent - please check your other sessions for key share requests.": "Заявката ви за споделяне на ключ е изпратена - проверете останалите си сесии за заявки за споделяне на ключове.",
"Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Заявките за споделяне на ключове се изпращат до другите ви сесии автоматично. Ако сте отказали заявката от другите ви сесии, кликнете тук за да изпратите заявка за тази сесия отново.",
"If your other sessions do not have the key for this message you will not be able to decrypt them.": "Ако другите ви сесии нямат ключа за това съобщения, няма да можете да ги дешифровате.",
"<requestLink>Re-request encryption keys</requestLink> from your other sessions.": "<requestLink>Поискай отново ключове за шифроване</requestLink> от другите сесии.",
"Encrypted by an unverified session": "Шифровано от неверифицирана сесия",
"Encrypted by a deleted session": "Шифровано от изтрита сесия",
"Invite only": "Само с покани",
"Scroll to most recent messages": "Отиди до най-скорошните съобщения",
"No sessions with registered encryption keys": "Няма сесии с регистрирани ключове за шифроване",
"Sessions": "Сесии",
"Send a reply…": "Изпрати отговор…",
"Send a message…": "Изпрати съобщение…",
"Reject & Ignore user": "Откажи и игнорирай потребителя",
"Unknown Command": "Непозната команда",
"Unrecognised command: %(commandText)s": "Неразпозната команда: %(commandText)s",
"You can use <code>/help</code> to list available commands. Did you mean to send this as a message?": "Може да използвате <code>/help</code> за да видите наличните команди. Или пък искахте да изпратите това като съобщение?",
"Hint: Begin your message with <code>//</code> to start it with a slash.": "Съвет: Започнете съобщението си с <code>//</code> за да изпратите съобщение започващо с наклонена черта.",
"Send as message": "Изпрати като съобщение",
"Mark all as read": "Маркирай всичко като прочетено",
"There was an error updating the room's alternative addresses. It may not be allowed by the server or a temporary failure occurred.": "Възникна грешка при обновяване на алтернативните адреси на стаята. Или не е позволено от сървъра или се е случила временна грешка.",
"You don't have permission to delete the alias.": "Нямате привилегия да изтриете този алтернативен адрес.",
"Local address": "Локален адрес",
"Published Addresses": "Публикувани адреси",
"Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.": "Публикуваните адреси могат да бъдат използвани от всеки човек, на кой да е сървър, за присъединяване към стаята. За да публикувате адрес, първо трябва да е настроен като локален адрес.",
"Other published addresses:": "Други публикувани адреси:",
"No other published addresses yet, add one below": "Все още няма други публикувани адреси, добавете такъв по-долу",
"New published address (e.g. #alias:server)": "Нов публикуван адрес (напр. #alias:server)",
"Local Addresses": "Локални адреси",
"Set addresses for this room so users can find this room through your homeserver (%(localDomain)s)": "Настройте адреси за тази стая, така че потребителите да могат да намерят стаята през вашия сървър (%(localDomain)s)",
"Waiting for you to accept on your other session…": "Изчаква се да приемете от другата ви сесия…",
"Waiting for %(displayName)s to accept…": "Изчаква се %(displayName)s да приеме…",
"Accepting…": "Приемане…",
"Start Verification": "Започни верификация",
"Your messages are secured and only you and the recipient have the unique keys to unlock them.": "Съобщенията ви са защитени и само вие и получателят имате уникалните ключове за да ги отключите.",
"In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.": "В шифровани стаи, съобщенията ви са защитени и само вие и получателят имате уникалните ключове за да ги отключите.",
"Verify User": "Потвърди потребителя",
"For extra security, verify this user by checking a one-time code on both of your devices.": "За допълнителна сигурност, потвърдете този потребител като проверите еднократен код на устройствата ви.",
"Your messages are not secure": "Съобщенията ви не са защитени",
"One of the following may be compromised:": "Едно от следните неща може да е било компрометирано:",
"Your homeserver": "Сървърът ви",
"The homeserver the user youre verifying is connected to": "Сървърът на потребителя, който верифицирате",
"Yours, or the other users internet connection": "Интернет връзката ви или тази на другите потребители",
"Yours, or the other users session": "Сесията ви или тази на другите потребители",
"%(count)s sessions|other": "%(count)s сесии",
"%(count)s sessions|one": "%(count)s сесия",
"Hide sessions": "Скрий сесиите",
"The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what Riot supports. Try with a different client.": "Сесията, която се опитвате да верифицирате не поддържа сканиране на QR код или емоджи верификация (нещата които Riot поддържа). Пробвайте с друг клиент.",
"Verify by scanning": "Верифицирай чрез сканиране",
"Ask %(displayName)s to scan your code:": "Попитайте %(displayName)s да сканира вашия код:",
"If you can't scan the code above, verify by comparing unique emoji.": "Ако не можете да сканирате кода по-горе, верифицирайте сравнявайки уникални емоджита.",
"Verify by comparing unique emoji.": "Верифицирай чрез сравняване на уникални емоджита.",
"Verify by emoji": "Верифицирай чрез емоджи",
"Almost there! Is your other session showing the same shield?": "Почти е готово! Другата ви сесия показва ли същия щит?",
"Almost there! Is %(displayName)s showing the same shield?": "Почти е готово! Сесията %(displayName)s показва ли същия щит?",
"Verify all users in a room to ensure it's secure.": "Верифицирай всички потребители в стаята за да подсигурите безопасността.",
"In encrypted rooms, verify all users to ensure its secure.": "В шифровани стаи, верифицирайте всички потребители за да подсигурите безопасността.",
"You've successfully verified %(deviceName)s (%(deviceId)s)!": "Успешно верифицирахте %(deviceName)s (%(deviceId)s)!",
"You've successfully verified %(displayName)s!": "Успешно верифицирахте %(displayName)s!",
"Verified": "Потвърдено",
"Got it": "Разбрах",
"Start verification again from the notification.": "Започнете верифициране отново от уведомлението.",
"Start verification again from their profile.": "Започнете верифициране отново от профила им.",
"Verification timed out.": "Изтече времето за верификация.",
"You cancelled verification on your other session.": "Отказахте верификацията от другата сесия.",
"%(displayName)s cancelled verification.": "%(displayName)s отказа верификацията.",
"You cancelled verification.": "Отказахте верификацията.",
"Verification cancelled": "Верификацията беше отказана",
"Compare emoji": "Сравни емоджи",
"Encryption enabled": "Шифроването е включено",
"Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Съобщенията в тази стая са ширфовани от-край-до-край. Научете повече и верифицирайте този потребител от профила им.",
"Encryption not enabled": "Шифроването не е включено",
"The encryption used by this room isn't supported.": "Шифроването използвано от тази стая не се поддържа.",
"You declined": "Отказахте",
"%(name)s declined": "%(name)s отказа",
"Accepting …": "Приемане…",
"Declining …": "Отказване…",
"Can't load this message": "Съобщението не може да се зареди",
"Submit logs": "Изпрати логове",
"Enter a server name": "Въведете име на сървър",
"Looks good": "Изглежда добре",
"Can't find this server or its room list": "Сървърът или списъка със стаи не може да бъде намерен",
"All rooms": "Всички стаи",
"Your server": "Вашият сървър",
"Are you sure you want to remove <b>%(serverName)s</b>": "Сигурни ли сте, че искате да премахнете <b>%(serverName)s</b>",
"Remove server": "Премахни сървъра",
"Matrix": "Matrix",
"Add a new server": "Добави нов сървър",
"Enter the name of a new server you want to explore.": "Въведете името на новия сървър, който искате да прегледате.",
"Server name": "Име на сървър",
"Add a new server...": "Добави нов сървър...",
"%(networkName)s rooms": "%(networkName)s стаи",
"Matrix rooms": "Matrix стаи",
"Reminder: Your browser is unsupported, so your experience may be unpredictable.": "Напомняне: браузърът ви не се поддържа, така че не всичко може да работи правилно.",
"Destroy cross-signing keys?": "Унищожаване на ключовете за кръстосано-подписване?"
}

View file

@ -2107,7 +2107,7 @@
"Whether you're using Riot on a device where touch is the primary input mechanism": "Zda používáte Riot na dotykovém zařízení",
"Whether you're using Riot as an installed Progressive Web App": "Zda používáte Riot jako nainstalovanou Progresivní Webovou Aplikaci",
"Your user agent": "Identifikace vašeho prohlížeče",
"The information being sent to us to help make Riot better includes:": "Abychom mohli Riot zlepšovat, posíláme si následující informace:",
"The information being sent to us to help make Riot better includes:": "Abychom mohli Riot zlepšovat, posíláte nám následující informace:",
"Verify this session by completing one of the following:": "Ověřte tuto relaci dokončením jednoho z následujících:",
"Scan this unique code": "Naskenujte tento jedinečný kód",
"or": "nebo",

View file

@ -1855,5 +1855,12 @@
"Enter your recovery passphrase a second time to confirm it.": "Gib deine Wiederherstellungspassphrase zur Bestätigung erneut ein.",
"Confirm your recovery passphrase": "Bestätige deine Wiederherstellungspassphrase",
"Confirm recovery passphrase": "Bestätige die Wiederherstellungspassphrase",
"Please enter your recovery passphrase a second time to confirm.": "Bitte gib deine Wiederherstellungspassphrase ein zweites Mal ein um sie zu bestätigen."
"Please enter your recovery passphrase a second time to confirm.": "Bitte gib deine Wiederherstellungspassphrase ein zweites Mal ein um sie zu bestätigen.",
"Review where youre logged in": "Überprüfe, wo du eingeloggt bist",
"New login. Was this you?": "Neue Anmeldung. Warst du das?",
"Please supply a widget URL or embed code": "Bitte gib eine Widget-URL oder einen Einbettungscode an",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Gibt den per SMS an +%(msisdn)s gesendeten Bestätigungscode ein.",
"Someone is using an unknown session": "Jemand verwendet eine unbekannte Sitzung",
"This room is end-to-end encrypted": "Dieser Raum ist Ende-zu-Ende verschlüsselt",
"You are not subscribed to any lists": "Du hast keine Listen abonniert"
}

View file

@ -106,6 +106,7 @@
"Encryption upgrade available": "Encryption upgrade available",
"Set up encryption": "Set up encryption",
"Review where youre logged in": "Review where youre logged in",
"New login. Was this you?": "New login. Was this you?",
"Who would you like to add to this community?": "Who would you like to add to this community?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID",
"Invite new community members": "Invite new community members",
@ -309,9 +310,11 @@
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
"Light theme": "Light theme",
"Dark theme": "Dark theme",
"Not Trusted": "Not Trusted",
"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) signed in to a new session without verifying it:",
"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",
"Done": "Done",
@ -563,14 +566,16 @@
"Headphones": "Headphones",
"Folder": "Folder",
"Pin": "Pin",
"Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe",
"Later": "Later",
"Review": "Review",
"Verify yourself & others to keep your chats safe": "Verify yourself & others to keep your chats safe",
"Other users may not trust it": "Other users may not trust it",
"Update your secure storage": "Update your secure storage",
"Set up": "Set up",
"Upgrade": "Upgrade",
"Verify": "Verify",
"Later": "Later",
"Verify your other sessions": "Verify your other sessions",
"Review": "Review",
"Verify the new login accessing your account: %(name)s": "Verify the new login accessing your account: %(name)s",
"From %(deviceName)s (%(deviceId)s)": "From %(deviceName)s (%(deviceId)s)",
"Decline (%(counter)s)": "Decline (%(counter)s)",
"Accept <policyLink /> to continue:": "Accept <policyLink /> to continue:",
@ -1654,7 +1659,7 @@
"Recently Direct Messaged": "Recently Direct Messaged",
"Start a conversation with someone using their name, username (like <userId/>) or email address.": "Start a conversation with someone using their name, username (like <userId/>) or email address.",
"Go": "Go",
"If you can't find someone, ask them for their username (e.g. @user:server.com) or <a>share this room</a>.": "If you can't find someone, ask them for their username (e.g. @user:server.com) or <a>share this room</a>.",
"Invite someone using their name, username (like <userId/>), email address or <a>share this room</a>.": "Invite someone using their name, username (like <userId/>), email address or <a>share this room</a>.",
"You added a new session '%(displayName)s', which is requesting encryption keys.": "You added a new session '%(displayName)s', which is requesting encryption keys.",
"Your unverified session '%(displayName)s' is requesting encryption keys.": "Your unverified session '%(displayName)s' is requesting encryption keys.",
"Start verification": "Start verification",
@ -1803,6 +1808,9 @@
"Not a valid recovery key": "Not a valid recovery key",
"Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.": "Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery key.",
"If you've forgotten your recovery key you can <button>set up new recovery options</button>.": "If you've forgotten your recovery key you can <button>set up new recovery options</button>.",
"Restoring keys from backup": "Restoring keys from backup",
"Fetching keys from server...": "Fetching keys from server...",
"%(completed)s of %(total)s keys restored": "%(completed)s of %(total)s keys restored",
"Unable to load backup status": "Unable to load backup status",
"Recovery key mismatch": "Recovery key mismatch",
"Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.",
@ -1810,9 +1818,9 @@
"Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this recovery passphrase: please verify that you entered the correct recovery passphrase.",
"Unable to restore backup": "Unable to restore backup",
"No backup found!": "No backup found!",
"Backup restored": "Backup restored",
"Keys restored": "Keys restored",
"Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!",
"Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys",
"Successfully restored %(sessionCount)s keys": "Successfully restored %(sessionCount)s keys",
"<b>Warning</b>: you should only set up key backup from a trusted computer.": "<b>Warning</b>: you should only set up key backup from a trusted computer.",
"Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.",
"If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>": "If you've forgotten your recovery passphrase you can <button1>use your recovery key</button1> or <button2>set up new recovery options</button2>",
@ -2239,7 +2247,6 @@
"Unable to create key backup": "Unable to create key backup",
"Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.",
"If you don't want to set this up now, you can later in Settings.": "If you don't want to set this up now, you can later in Settings.",
"Set up": "Set up",
"Don't ask again": "Don't ask again",
"New Recovery Method": "New Recovery Method",
"A new recovery passphrase and key for Secure Messages have been detected.": "A new recovery passphrase and key for Secure Messages have been detected.",

View file

@ -47,7 +47,7 @@
"%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s",
"Verify this session": "Verifitseeri see sessioon",
"Which rooms would you like to add to this community?": "Milliseid jututubasid sooviksid lisada siia kogukonda?",
"Show these rooms to non-members on the community page and room list?": "Kas näitan neid jututubasid kogukonna lehel ja tubade loendis mitte-liikmetele?",
"Show these rooms to non-members on the community page and room list?": "Kas näitan neid jututubasid kogukonna lehel ja tubade loendis kogukonna mitte-liikmetele?",
"Add rooms to the community": "Lisa siia kogukonda jututubasid",
"Failed to add the following rooms to %(groupId)s:": "Järgnevate jututubade lisamine %(groupId)s kogukonda ebaõnnestus:",
"Changes your avatar in all rooms": "Muuda oma tunnuspilti kõikides jututubades",
@ -110,8 +110,8 @@
"Create new room": "Loo uus jututuba",
"Unblacklist": "Eemalda mustast nimekirjast",
"Blacklist": "Kanna musta nimekirja",
"Unverify": "Eemalda õigeks tunnistamine",
"Verify...": "Tunnista õigeks...",
"Unverify": "Tühista verifitseerimine",
"Verify...": "Verifitseeri...",
"Join": "Liitu",
"No results": "Tulemusi pole",
"Please <newIssueLink>create a new issue</newIssueLink> on GitHub so that we can investigate this bug.": "Selle vea uurimiseks palun <newIssueLink>loo uus veateade</newIssueLink> meie GitHub'is.",
@ -144,5 +144,671 @@
"Explore rooms": "Uuri jututubasid",
"If you've joined lots of rooms, this might take a while": "Kui oled liitunud paljude jututubadega, siis see võib natuke aega võtta",
"If disabled, messages from encrypted rooms won't appear in search results.": "Kui see seadistus pole kasutusel, siis krüptitud jututubade sõnumeid otsing ei vaata.",
"Indexed rooms:": "Indekseeritud jututoad:"
"Indexed rooms:": "Indekseeritud jututoad:",
"Remove": "Eemalda",
"You should <b>remove your personal data</b> from identity server <idserver /> before disconnecting. Unfortunately, identity server <idserver /> is currently offline or cannot be reached.": "Sa peaksid enne ühenduse katkestamisst <b>eemaldama isiklikud andmed</b> id-serverist <idserver />. Kahjuks id-server <idserver /> ei ole hetkel võrgus või pole kättesaadav.",
"We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Me soovitame, et eemaldad enne ühenduse katkestamist oma e-posti aadressi ja telefoninumbrid id-serverist.",
"Remove messages": "Kustuta sõnumid",
"Unable to remove contact information": "Kontaktiinfo eemaldamine ebaõnnestus",
"Remove %(email)s?": "Eemalda %(email)s?",
"Remove %(phone)s?": "Eemalda %(phone)s?",
"Remove recent messages by %(user)s": "Eemalda %(user)s hiljutised sõnumid",
"Replying With Files": "Vasta faili(de)ga",
"Invite new community members": "Kutsu uusi liikmeid kogukonda",
"rooms.": "jututoad.",
"Notify for all other messages/rooms": "Teavita kõikidest teistest sõnumitest/jututubadest",
"Members only (since the point in time of selecting this option)": "Ainult liikmetele (alates selle seadistuse kasutuselevõtmisest)",
"Members only (since they were invited)": "Ainult liikmetele (alates nende kutsumise ajast)",
"Members only (since they joined)": "Ainult liikmetele (alates liitumisest)",
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "Oled kustutamas %(user)s %(count)s sõnumit. Seda tegevust ei saa hiljem tagasi pöörata. Kas sa kindlasti soovid jätkata?",
"You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "Oled kustutamas ühte %(user)s sõnumit. Seda tegevust ei saa hiljem tagasi pöörata. Kas sa kindlasti soovid jätkata?",
"Remove %(count)s messages|other": "Eemalda %(count)s sõnumit",
"Remove %(count)s messages|one": "Eemalda 1 sõnum",
"Remove recent messages": "Eemalda hiljutised sõnumid",
"Filter room members": "Filtreeri jututoa liikmeid",
"Members": "Liikmed",
"Files": "Failid",
"Remove from community": "Eemalda kogukonnast",
"Remove this user from community?": "Kas eemaldan selle kasutaja kogukonnast?",
"Failed to remove user from community": "Kasutaja eemaldamine kogukonnast ebaõnnestus",
"Failed to load group members": "Grupi liikmete laadimine ebaõnnestus",
"Filter community members": "Filtreeri kogukonna liikmeid",
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Kas sa soovid eemaldada %(roomName)s jututoa %(groupId)s kogukonnast?",
"Removing a room from the community will also remove it from the community page.": "Eemaldades jututoa kogukonnast eemaldad selle ka kogukonna lehelt.",
"Failed to remove room from community": "Jututoa eemaldamine kogukonnast ebaõnnestus",
"Failed to remove '%(roomName)s' from %(groupId)s": "Jututoa %(roomName)s eemaldamine %(groupId)s kogukonnast ebaõnnestus",
"Only visible to community members": "Nähtav ainult kogukonna liikmetele",
"Filter community rooms": "Filtreeri kogukonna jututubasid",
"Failed to remove widget": "Vidina eemaldamine ebaõnnestus",
"An error ocurred whilst trying to remove the widget from the room": "Vidina eemaldamisel jututoast tekkis viga",
"Are you sure you want to remove <b>%(serverName)s</b>": "Kas sa oled kindel et soovid eemadlada <b>%(serverName)s</b>",
"Remove server": "Eemalda server",
"%(networkName)s rooms": "%(networkName)s jututoad",
"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.": "Kas sa oled kindel et soovid eemaldada (kustutada) seda sündmust? Pane tähele, et see muutus võib tagasi pöörduda, kui muudad hiljem jututoa nime või teemanime.",
"Sign out and remove encryption keys?": "Logi välja ja eemalda krüptimisvõtmed?",
"Upload files (%(current)s of %(total)s)": "Lae failid üles (%(current)s / %(total)s)",
"Upload files": "Lae failid üles",
"These files are <b>too large</b> to upload. The file size limit is %(limit)s.": "Need failid on üleslaadimiseks <b>liiga suured</b>. Failisuuruse piir on %(limit)s.",
"Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.": "Mõned failid on üleslaadimiseks <b>liiga suured</b>. Failisuuruse piir on %(limit)s.",
"Upload %(count)s other files|other": "Lae üles %(count)s muud faili",
"Unable to reject invite": "Ei õnnestu kutset tagasi lükata",
"Resend": "Saada uuesti",
"Resend edit": "Saada muudetud sõnum uuesti",
"Resend %(unsentCount)s reaction(s)": "Saada uuesti %(unsentCount)s reaktsioon(i)",
"Resend removal": "Saada eemaldamine uuesti",
"Cancel Sending": "Tühista saatmine",
"Forward Message": "Edasta sõnum",
"Pin Message": "Klammerda sõnum",
"View Decrypted Source": "Vaata dekrüptitud lähtekoodi",
"Unhide Preview": "Näita eelvaadet",
"Share Permalink": "Jaga püsiviidet",
"Share Message": "Jaga sõnumit",
"Source URL": "Lähteaadress",
"Collapse Reply Thread": "Ahenda vastuste jutulõnga",
"End-to-end encryption information": "Läbiva krüptimise teave",
"Notification settings": "Teavituste seadistused",
"All messages (noisy)": "Kõik sõnumid (lärmakas)",
"All messages": "Kõik sõnumid",
"Mentions only": "Ainult mainimised",
"Leave": "Lahku",
"Forget": "Unusta",
"Favourite": "Lemmik",
"Low Priority": "Madal prioriteet",
"Direct Chat": "Otsevestlus",
"Clear status": "Eemalda olek",
"Update status": "Uuenda olek",
"Set status": "Määra olek",
"Set a new status...": "Määra uus olek...",
"View Community": "Näita kogukonda",
"Hide": "Peida",
"Home": "Avaleht",
"Sign in": "Logi sisse",
"Help": "Abiteave",
"Reload": "Lae uuesti",
"Take picture": "Tee foto",
"Remove for everyone": "Eemalda kõigilt",
"Remove for me": "Eemalda minult",
"User Status": "Kasutaja olek",
"You must join the room to see its files": "Failide nägemiseks pead jututoaga liituma",
"There are no visible files in this room": "Jututoas pole nähtavaid faile",
"Failed to remove the room from the summary of %(groupId)s": "Jututoa eemaldamine %(groupId)s kogukonna ülevaatelehelt ebaõnnestus",
"Failed to remove a user from the summary of %(groupId)s": "Kasutaja eemaldamine %(groupId)s kogukonna ülevaatelehelt ebaõnnestus",
"Create a Group Chat": "Loo rühmavestlus",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Kas kustutame jututoa aliase %(alias)s ja eemaldame %(name)s kataloogist?",
"Remove %(name)s from the directory?": "Eemalda %(name)s kataloogist?",
"Remove from Directory": "Eemalda kataloogist",
"remove %(name)s from the directory.": "eemalda %(name)s kataloogist.",
"You seem to be uploading files, are you sure you want to quit?": "Tundub, et sa parasjagu laed faile üles, kas sa kindlasti soovid väljuda?",
"Failed to set direct chat tag": "Otsevestluse sildi lisamine ei õnnestunud",
"Failed to remove tag %(tagName)s from room": "Sildi %(tagName)s eemaldamine jututoast ebaõnnestus",
"Calls": "Kõned",
"Room List": "Jututubade loend",
"Alt": "Alt",
"Alt Gr": "Alt Gr",
"Shift": "Shift",
"Super": "Super",
"Ctrl": "Ctrl",
"Toggle Bold": "Lülita paks kiri sisse/välja",
"Toggle Italics": "Lülita kaldkiri sisse/välja",
"Toggle Quote": "Lülita tsiteerimine sisse/välja",
"New line": "Reavahetus",
"Cancel replying to a message": "Tühista sõnumile vastamine",
"Toggle microphone mute": "Lülita mikrofoni summutamine sisse/välja",
"Toggle video on/off": "Lülita video kasutamine sisse/välja",
"Jump to room search": "Suundu jututoa otsingusse",
"Navigate up/down in the room list": "Suundu jututubade loendis üles/alla",
"Select room from the room list": "Vali tubade loendist jututuba",
"Collapse room list section": "Ahenda jututubade loendi valikut",
"Expand room list section": "Laienda jututubade loendi valikut",
"Create Account": "Loo konto",
"Sign In": "Logi sisse",
"Send a bug report with logs": "Saada veakirjeldus koos logidega",
"Group & filter rooms by custom tags (refresh to apply changes)": "Rühmita ja filtreeri jututubasid kohandatud siltide alusel (muudatuste rakendamiseks värskenda vaade)",
"Try out new ways to ignore people (experimental)": "Proovi uusi kasutajate eiramise viise (katseline)",
"Uploading report": "Laen üles veakirjeldust",
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Kui soovid teatada Matrix'iga seotud turvaveast, siis palun tutvu enne Matrix.org <a>Turvalisuse avalikustamise juhendiga</a>.",
"Add users and servers you want to ignore here. Use asterisks to have Riot match any characters. For example, <code>@bot:*</code> would ignore all users that have the name 'bot' on any server.": "Lisa siia kasutajad ja serverid keda soovid eirata. Kasuta tärne kõikide märkide tähistamiseks. Näiteks <code>@bot:*</code> eiraks kõiki kasutajaid kõikidest serveritest, kus nimi on \"bot\".",
"Server or user ID to ignore": "Serverid või kasutajate tunnused, mida soovid eirata",
"Ignore": "Eira",
"If this isn't what you want, please use a different tool to ignore users.": "Kui tulemus pole see mida soovisid, siis pruugi muud vahendit kasutajate eiramiseks.",
"Sessions": "Sessioonid",
"Mention": "Maini",
"Share Link to User": "Jaga viidet kasutaja kohta",
"User Options": "Kasutaja valikud",
"Direct chats": "Isiklikud sõnumid",
"Admin Tools": "Haldustoimingud",
"Online": "Võrgus",
"Reject & Ignore user": "Hülga ja eira kasutaja",
"%(count)s unread messages including mentions.|one": "1 lugemata mainimine.",
"Filter results": "Filtreeri tulemusi",
"Ignore request": "Eira taotlust",
"Report bugs & give feedback": "Teata vigadest ja anna tagasisidet",
"Report Content to Your Homeserver Administrator": "Teata sisust Sinu koduserveri haldurile",
"Send report": "Saada veateade",
"(HTTP status %(httpStatus)s)": "(HTTP staatuse kood %(httpStatus)s)",
"Please set a password!": "Palun määra salasõna!",
"This will allow you to return to your account after signing out, and sign in on other sessions.": "See võimaldab sul tagasi tulla oma kasutajakonto juurde ka peale väljalogimist ning logida sisse muudesse sessioonidesse.",
"Share Room": "Jaga jututuba",
"Link to most recent message": "Viide kõige viimasele sõnumile",
"Share User": "Jaga viidet kasutaja kohta",
"Share Community": "Jaga viidet kogukonna kohta",
"Share Room Message": "Jaga jututoa sõnumit",
"Link to selected message": "Viide valitud sõnumile",
"COPY": "KOPEERI",
"Command Help": "Abiteave käskude kohta",
"To help us prevent this in future, please <a>send us logs</a>.": "Tagamaks et sama ei juhtuks tulevikus, palun <a>saada meile salvestatud logid</a>.",
"Missing session data": "Sessiooni andmed on puudu",
"Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Osa sessiooniandmetest, sealhulgas sõnumi krüptovõtmed, on puudu. Vea parandamiseks logi välja ja sisse, vajadusel taasta võtmed varundusest.",
"Your browser likely removed this data when running low on disk space.": "On võimalik et sinu brauser kustutas need andmed, sest kõvakettaruumist jäi puudu.",
"Integration Manager": "Lõiminguhaldur",
"Find others by phone or email": "Leia teisi kasutajaid telefoninumbri või e-posti aadressi alsusel",
"Be found by phone or email": "Ole leitav telefoninumbri või e-posti aadressi alsusel",
"Terms of Service": "Kasutustingimused",
"To continue you need to accept the terms of this service.": "Jätkamaks pead nõustuma kasutustingimustega.",
"Service": "Teenus",
"Summary": "Kokkuvõte",
"Document": "Dokument",
"Next": "Järgmine",
"You are currently blacklisting unverified sessions; to send messages to these sessions you must verify them.": "Sa parasjagu oled kõik verifitseerimata sessioonid kandnud musta nimekirja. Sinna sõnumite saatmiseks sa pead nad enne verifitseerima.",
"Room contains unknown sessions": "Jututoas on tundmatuid sessioone",
"\"%(RoomName)s\" contains sessions that you haven't seen before.": "\"%(RoomName)s\" sisaldab sessioone, mida sa ei ole varem näinud.",
"Unknown sessions": "Tundmatud sessioonid",
"Report Content": "Teata sisust haldurile",
"powered by Matrix": "põhineb Matrix'il",
"Custom Server Options": "Serveri kohaldatud seadistused",
"Missing captcha public key in homeserver configuration. Please report this to your homeserver administrator.": "Robotilõksu avalik võti on puudu koduserveri seadistustes. Palun teata sellest oma koduserveri haldurile.",
"Filter": "Filtreeri",
"Clear filter": "Eemalda filter",
"Copy": "Kopeeri",
"Clear room list filter field": "Tühjenda jututubade filtriväli",
"Mute": "Summuta",
"Settings": "Seadistused",
"You're not currently a member of any communities.": "Sa ei ole hetkel ainsamagi kogukonna liige.",
"Create a new community": "Loo uus kogukond",
"Never send encrypted messages to unverified sessions from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse",
"Never send encrypted messages to unverified sessions in this room from this session": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse selles jututoas",
"Sign In or Create Account": "Logi sisse või loo uus konto",
"Use your account or create a new one to continue.": "Jätkamaks kasuta oma kontot või loo uus konto.",
"Anyone": "Kõik kasutajad",
"Encryption": "Krüptimine",
"Once enabled, encryption cannot be disabled.": "Kui krüptimine on juba kasutusele võetud, siis ei saa seda enam eemaldada.",
"Encrypted": "Krüptitud",
"Who can access this room?": "Kes pääsevad ligi siia jututuppa?",
"Who can read history?": "Kes võib lugeda ajalugu?",
"Encrypted by an unverified session": "Krüptitud verifitseerimata sessiooni poolt",
"Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Sõnumid selles jututoas on läbivalt krüptitud. Uuri lisaks ja verifitseeri see kasutaja tema kasutajaprofiilis.",
"Encryption not enabled": "Krüptimine ei ole kasutusel",
"The encryption used by this room isn't supported.": "Selles jututoas kasutatud krüptimine ei ole toetatud.",
"Error decrypting audio": "Viga helivoo dekrüptimisel",
"React": "Reageeri",
"Reply": "Vasta",
"Edit": "Muuda",
"Message Actions": "Tegevused sõnumitega",
"Attachment": "Manus",
"Error decrypting attachment": "Viga manuse dekrüptimisel",
"Decrypt %(text)s": "Dekrüpti %(text)s",
"Download %(text)s": "Lae alla %(text)s",
"Invalid file%(extra)s": "Vigane fail %(extra)s",
"Error decrypting image": "Viga pildi dekrüptimisel",
"Show image": "Näita pilti",
"You have ignored this user, so their message is hidden. <a>Show anyways.</a>": "Sa oled seda kasutajat eiranud ja seega tema sõnum on peidetud. <a>Näita seda ikkagi.</a>",
"You verified %(name)s": "Sa verifitseerisid %(name)s",
"You cancelled verifying %(name)s": "Sa tühistasid %(name)s verifitseerimise",
"%(name)s cancelled verifying": "%(name)s tühistas verifitseerimise",
"You accepted": "Sa nõustusid",
"%(name)s accepted": "%(name)s nõustus",
"You declined": "Sa keeldusid",
"You cancelled": "Sa tühistasid",
"%(name)s declined": "%(name)s keeldus",
"%(name)s cancelled": "%(name)s tühistas",
"Accepting …": "Nõustun …",
"Declining …": "Keeldun …",
"%(name)s wants to verify": "%(name)s soovib verifitseerida",
"You sent a verification request": "Sa saatsid verifitseerimispalve",
"Error decrypting video": "Viga videovoo dekrüptimisel",
"Show all": "Näita kõiki",
"Reactions": "Reageerimised",
"<reactors/><reactedWith> reacted with %(content)s</reactedWith>": "<reactors/><reactedWith> reageeris: %(content)s</reactedWith>",
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>": "<reactors/><reactedWith>reageeris(id) %(shortName)s</reactedWith>",
"%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s muutis %(roomName)s jututoa avatari",
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s eemaldas jututoa avatari.",
"%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s vahetas jututoa avatariks <img/>",
"This room is a continuation of another conversation.": "See jututuba on järg varasemale vestlusele.",
"Click here to see older messages.": "Vanemate sõnumite nägemiseks klõpsi siia.",
"Copied!": "Kopeeritud!",
"Failed to copy": "Kopeerimine ebaõnnestus",
"Edited at %(date)s. Click to view edits.": "Muudetud %(date)s. Klõpsi et näha varasemaid versioone.",
"edited": "muudetud",
"Can't load this message": "Selle sõnumi laadimine ei õnnestu",
"Submit logs": "Saada rakenduse logid",
"Removed or unknown message type": "Kustutatud või tundmatu sõnumi tüüp",
"Message removed by %(userId)s": "Kasutaja %(userId)s poolt kustutatud sõnum",
"Message removed": "Sõnum on kustutatud",
"Invite to this community": "Kutsu selle kogukonna liikmeks",
"Something went wrong!": "Midagi läks nüüd valesti!",
"The visibility of '%(roomName)s' in %(groupId)s could not be updated.": "Jututoa %(roomName)s nähtavust %(groupId)s kogukonnas ei õnnestunud värskendada.",
"Visibility in Room List": "Nähtavus jututubade loendis",
"Visible to everyone": "Nähtav kõigile",
"Something went wrong when trying to get your communities.": "Sinu kogukondade laadimisel läks midagi nüüd viltu.",
"Please help improve Riot.im by sending <UsageDataLink>anonymous usage data</UsageDataLink>. This will use a cookie (please see our <PolicyLink>Cookie Policy</PolicyLink>).": "Palun aita Riot'it paremaks teha saates arendajatele <UsageDataLink>anonüümset kasutusteavet</UsageDataLink>. See eeldab küpsise kasutamist (palun vaata meie <PolicyLink>küpsiste kasutuse reegleid</PolicyLink>).",
"Please help improve Riot.im by sending <UsageDataLink>anonymous usage data</UsageDataLink>. This will use a cookie.": "Palun aita Riot'it paremaks teha saates <UsageDataLink>anonüümset kasutusteavet</UsageDataLink>. See eeldab küpsise kasutamist.",
"Yes, I want to help!": "Jah, ma soovin aidata!",
"You are not receiving desktop notifications": "Sa hetkel ei saa oma arvuti töölauakeskkonna teavitusi",
"Enable them now": "Võta need nüüd kasutusele",
"What's New": "Meie uudised",
"Update": "Uuenda",
"What's new?": "Mida on meil uut?",
"A new version of Riot is available.": "Uus Riot'i versioon on saadaval.",
"Your server": "Sinu server",
"Matrix": "Matrix",
"Add a new server": "Lisa uus server",
"Server name": "Serveri nimi",
"Add a new server...": "Lisa uus server...",
"Matrix ID": "Matrix'i kasutajatunnus",
"Matrix Room ID": "Matrix'i jututoa tunnus",
"email address": "e-posti aadress",
"That doesn't look like a valid email address": "See ei tundu olema e-posti aadressi moodi",
"You have entered an invalid address.": "Sa oled sisestanud vigase e-posti aadressi.",
"Try using one of the following valid address types: %(validTypesList)s.": "Proovi mõnda nendest sobilikest aadressitüüpidest: %(validTypesList)s.",
"Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)": "Blokeeri teiste matrixi koduserverite kasutajate liitumine selle jututoaga (seda ei saa hiljem enam muuta!)",
"Create Room": "Loo jututuba",
"Sign out": "Logi välja",
"Incompatible Database": "Mitteühilduv andmebaas",
"Continue With Encryption Disabled": "Jätka ilma krüptimiseta",
"Your unverified session '%(displayName)s' is requesting encryption keys.": "Sinu verifitseerimata sessioon '%(displayName)s' soovib saada krüptimisvõtmeid.",
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "Kui sa ei leia otsitavat jututuba, siis palu sinna kutset või <a>loo uus jututuba</a>.",
"device id: ": "seadme tunnus: ",
"%(duration)ss": "%(duration)s sekund(it)",
"%(duration)sm": "%(duration)s minut(it)",
"%(duration)sh": "%(duration)s tund(i)",
"%(duration)sd": "%(duration)s päev(a)",
"Online for %(duration)s": "Võrgus %(duration)s",
"Idle for %(duration)s": "Jõude %(duration)s",
"Offline for %(duration)s": "Võrgust väljas %(duration)s",
"Unknown for %(duration)s": "Teadmata olek viimased %(duration)s",
"Idle": "Jõude",
"Offline": "Võrgust väljas",
"Unknown": "Teadmata olek",
"Seen by %(userName)s at %(dateTime)s": "Nähtud %(userName)s poolt %(dateTime)s",
"Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Nähtud %(displayName)s (%(userName)s) poolt %(dateTime)s",
"Replying": "Vastan",
"Room %(name)s": "Jututuba %(name)s",
"Unnamed room": "Nimeta jututuba",
"World readable": "Kogu maailmale avali",
"Guests can join": "Külalised võivad liituda",
"(~%(count)s results)|other": "(~%(count)s tulemust)",
"(~%(count)s results)|one": "(~%(count)s tulemus)",
"Join Room": "Liitu jututoaga",
"Forget room": "Unusta jututuba",
"Search": "Otsing",
"Share room": "Jaga jututuba",
"Community Invites": "Kutsed kogukonda",
"Invites": "Kutsed",
"Favourites": "Lemmikud",
"Low priority": "Vähetähtis",
"Historical": "Ammune",
"System Alerts": "Süsteemi teated",
"This room": "See jututuba",
"Joining room …": "Liitun jututoaga …",
"Loading …": "Laen …",
"Device ID": "Seadme tunnus",
"e.g. %(exampleValue)s": "näiteks %(exampleValue)s",
"Could not find user in room": "Jututoast ei leidnud kasutajat",
"Show timestamps in 12 hour format (e.g. 2:30pm)": "Näita ajatempleid 12-tunnises vomingus (näiteks 2:30pl)",
"New published address (e.g. #alias:server)": "Uus avaldatud aadess (näiteks #alias:server)",
"New community ID (e.g. +foo:%(localDomain)s)": "Uus kogukonna tunnus (näiteks +midagi:%(localDomain)s)",
"e.g. my-room": "näiteks minu-jututuba",
"Can't find this server or its room list": "Ei leia seda serverit ega tema jututubade loendit",
"If you can't find someone, ask them for their username (e.g. @user:server.com) or <a>share this room</a>.": "Kui sa ei leia kedagi, siis küsi tema kasutajanime (näiteks @kasutaja:server.ee) või <a>jaga seda jututuba</a>.",
"Couldn't find a matching Matrix room": "Ei leidnud vastavat Matrix'i jututuba",
"Find a room…": "Leia jututuba…",
"Find a room… (e.g. %(exampleRoom)s)": "Otsi jututuba… (näiteks %(exampleRoom)s)",
"Tried to load a specific point in this room's timeline, but was unable to find it.": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid ei suutnud seda leida.",
"Options": "Valikud",
"Searches DuckDuckGo for results": "Otsi DuckDuckGo abil",
"Securely cache encrypted messages locally for them to appear in search results, using ": "Turvaliselt puhverda krüptitud sõnumeid kohalikus arvutis selleks, et nad oleks otsitavad kasutades ",
"this room": "see jututuba",
"Quote": "Tsiteeri",
"This Room": "See jututuba",
"Sun": "Pühapäev",
"Mon": "Esmaspäev",
"Tue": "Teisipäev",
"Wed": "Kolmapäev",
"Thu": "Neljapäev",
"Fri": "Reede",
"Sat": "Laupäev",
"%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(time)s",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s %(time)s",
"Encryption upgrade available": "Krüptimise uuendus on saadaval",
"Set up encryption": "Seadista krüptimine",
"Review where youre logged in": "Vaata üle, kust sa oled Matrix'i võrku loginud",
"New login. Was this you?": "Uus sisselogimine. Kas see olid sina?",
"Who would you like to add to this community?": "Kas sa sooviksid seda lisada kogukonda?",
"Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Hoiatus: kõik kogukonda lisatud kasutajad on nähtavad kõigile, kes teavad kogukonna tunnust",
"Name or Matrix ID": "Nimi või Matrix'i tunnus",
"Invite to Community": "Kutsu kogukonda",
"Room name or alias": "Jututoa nimi või alias",
"Add to community": "Lisa kogukonda",
"Failed to invite the following users to %(groupId)s:": "Järgnevate kasutajate kutsumine %(groupId)s liikmeks ebaõnnestus:",
"Failed to invite users to community": "Kasutajate kutsumine kogukonda ebaõnnestus",
"Failed to invite users to %(groupId)s": "Kasutajate kutsumine %(groupId)s kogukonna liikmeks ebaõnnestus",
"Unnamed Room": "Ilma nimeta jututuba",
"Identity server has no terms of service": "Isikutuvastusserveril puuduvad kasutustingimused",
"This action requires accessing the default identity server <server /> to validate an email address or phone number, but the server does not have any terms of service.": "E-posti aadressi või telefoninumbri kontrolliks see tegevus eeldab päringut vaikimisi isikutuvastusserverisse <server />, aga sellel serveril puuduvad kasutustingimused.",
"Only continue if you trust the owner of the server.": "Jätka vaid siis, kui sa usaldad serveri omanikku.",
"Trust": "Usalda",
"%(name)s is requesting verification": "%(name)s soovib verifitseerimist",
"Securely cache encrypted messages locally for them to appear in search results.": "Turvaliselt puhverda krüptitud sõnumid kohalikku arvutisse ja võimalda kasutada neid otsingus.",
"Riot is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom Riot Desktop with <nativeLink>search components added</nativeLink>.": "Riot'is on puudu need komponendid, mis võimaldavad otsida kohalikest turvaliselt puhverdatud krüptitud sõnumitest. Kui sa tahaksid sellist funktsionaalsust katsetada, siis pead kompileerima Riot'i variandi, kus <nativeLink>need komponendid on lisatud</nativeLink>.",
"Riot can't securely cache encrypted messages locally while running in a web browser. Use <riotLink>Riot Desktop</riotLink> for encrypted messages to appear in search results.": "Riot ei saa veebibrauserist käivitades otsida turvaliselt kohalikult puhverdatud krüptitud sõnumite hulgast. Selliste sõnumite hulgast otsimiseks kasuta <riotLink>Riot'i töölauaversiooni</riotLink>.",
"Message search": "Otsing sõnumite seast",
"Search…": "Otsi…",
"Cancel search": "Tühista otsing",
"Search failed": "Otsing ebaõnnestus",
"Server may be unavailable, overloaded, or search timed out :(": "Server kas pole leitav, on üle koormatud või otsing aegus :(",
"No more results": "Rohkem otsingutulemusi pole",
"Riot is securely caching encrypted messages locally for them to appear in search results:": "Otsingus kasutamiseks Riot puhverdab turvaliselt kohalikku arvutisse krüptitud sõnumeid:",
"Riot does not have permission to send you notifications - please check your browser settings": "Riot'il puudub luba sulle teavituste kuvamiseks - palun kontrolli oma brauseri seadistusi",
"Riot was not given permission to send notifications - please try again": "Riot ei saanud luba teavituste kuvamiseks - palun proovi uuesti",
"Room Notification": "Jututoa teavitus",
"Displays information about a user": "Näitab teavet kasutaja kohta",
"This homeserver has hit its Monthly Active User limit.": "See koduserver on saavutanud igakuise aktiivsete kasutajate piiri.",
"about a minute ago": "umbes minut tagasi",
"about an hour ago": "umbes tund tagasi",
"%(num)s hours ago": "%(num)s tundi tagasi",
"about a day ago": "umbes päev tagasi",
"%(num)s days ago": "%(num)s päeva tagasi",
"about a minute from now": "umbes minuti pärast",
"about an hour from now": "umbes tunni pärast",
"%(num)s hours from now": "%(num)s tunni pärast",
"about a day from now": "umbes päeva pärast",
"%(num)s days from now": "%(num)s päeva pärast",
"Are you sure?": "Kas sa oled kindel?",
"No sessions with registered encryption keys": "Puuduvad registreeritud krüptimisvõtmetega sessioonid",
"Jump to read receipt": "Hüppa lugemisteatise juurde",
"Invite": "Kutsu",
"Unmute": "Eemalda summutamine",
"This homeserver has hit its Monthly Active User limit so <b>some users will not be able to log in</b>.": "See koduserver on saavutanud igakuise aktiivsete kasutajate piiri ja seega <b>osad kasutajad ei saa sisse logida</b>.",
"Create a public room": "Loo avalik jututuba",
"Create a private room": "Loo omavaheline jututuba",
"Name": "Nimi",
"Topic (optional)": "Teema (valikuline)",
"Make this room public": "Tee see jututuba avalikuks",
"Hide advanced": "Peida lisaseadistused",
"Show advanced": "Näita lisaseadistusi",
"Server did not require any authentication": "Server ei nõudnud mitte mingisugust autentimist",
"Recent Conversations": "Hiljutised vestlused",
"Suggestions": "Soovitused",
"Start a conversation with someone using their name, username (like <userId/>) or email address.": "Alusta vestlust kasutades teise osapoole nime, kasutajanime (näiteks <userId/>) või e-posti aadressi.",
"Go": "Mine",
"Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please <a>contact your service administrator</a> to continue using the service.": "Sinu sõnumit ei saadetud, kuna see koduserver on saavutanud igakuise aktiivsete kasutajate piiri. Teenuse kasutamiseks palun <a>võta ühendust serveri haldajaga</a>.",
"Add room": "LIsa jututuba",
"%(senderName)s invited %(targetName)s.": "%(senderName)s kutsus vestlema kasutajat %(targetName)s.",
"%(targetName)s joined the room.": "%(targetName)s liitus jututoaga.",
"%(senderName)s answered the call.": "%(senderName)s vastas kõnele.",
"%(senderName)s ended the call.": "%(senderName)s lõpetas kõne.",
"%(senderName)s placed a voice call.": "%(senderName)s alustas häälkõnet.",
"%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s alustas häälkõnet. (sellel brauseril puudub niisuguste kõnede tugi)",
"%(senderName)s placed a video call.": "%(senderName)s alustas videokõnet.",
"%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s alustas videokõnet. (sellel brauseril puudub niisuguste kõnede tugi)",
"%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s määras et jututuppa pääseb vaid kutsega.",
"%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s muutis liitumisreeglid järgnevaks - %(rule)s",
"%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s on lubanud külalistel jututoaga liituda.",
"%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s on määranud et külalised ei saa jututoaga liituda.",
"%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s muutis külaliste ligipääsureeglid alljärgnevaks - %(rule)s",
"%(senderDisplayName)s sent an image.": "%(senderDisplayName)s saatis pildi.",
"%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s muutis selle jututoa põhiaadressiks %(address)s.",
"%(senderName)s removed the main address for this room.": "%(senderName)s eemaldas põhiaadressi sellest jututoast.",
"%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s lisas sellele jututoale täiendava aadressi %(addresses)s.",
"%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s lisas sellele jututoale täiendava aadressi %(addresses)s.",
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s eemaldas täiendavad aadressid %(addresses)s sellelt jututoalt.",
"%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s eemaldas täiendava aadressi %(addresses)s sellelt jututoalt.",
"%(senderName)s changed the alternative addresses for this room.": "%(senderName)s muutis selle jututoa täiendavat aadressi.",
"%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s muutis selle jututoa põhiaadressi ja täiendavat aadressi.",
"%(senderName)s changed the addresses for this room.": "%(senderName)s muutis selle jututoa aadressid.",
"Someone": "Keegi",
"(not supported by this browser)": "(ei ole toetatud selles brauseris)",
"(could not connect media)": "(ühendus teise osapoolega ei õnnestunud)",
"(no answer)": "(ei ole vastust)",
"(unknown failure: %(reason)s)": "(teadmata viga: %(reason)s)",
"%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s võttis %(targetDisplayName)s'lt tagasi jututoaga liitumise kutse.",
"%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s saatis %(targetDisplayName)s'le kutse jututoaga liitumiseks.",
"%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele nende kutsumise hetkest.",
"%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele nende liitumise hetkest.",
"%(senderName)s made future room history visible to all room members.": "%(senderName)s määras, et jututoa tulevane ajalugu on nähtav kõikidele selle liikmetele.",
"%(senderName)s made future room history visible to anyone.": "%(senderName)s seadistas, et jututoa tulevane ajalugu on kõigile nähtav.",
"%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s seadistas, et jututoa tulevase ajaloo nähtavuse olek on (%(visibility)s).",
"%(widgetName)s widget modified by %(senderName)s": "%(senderName)s muutis vidinat %(widgetName)s",
"%(widgetName)s widget added by %(senderName)s": "%(senderName)s lisas vidina %(widgetName)s",
"%(widgetName)s widget removed by %(senderName)s": "%(senderName)s eemaldas vidina %(widgetName)s",
"Muted Users": "Summutatud kasutajad",
"This room is end-to-end encrypted": "See jututuba on läbivalt krüptitud",
"Everyone in this room is verified": "Kõik kasutajad siin nututoas on verifitseeritud",
"Some sessions for this user are not trusted": "Mõned selle kasutaja sessioonid ei ole usaldusväärsed",
"All sessions for this user are trusted": "Kõik selle kasutaja sessioonid on usaldusväärsed",
"Some sessions in this encrypted room are not trusted": "Mõned sessioonid selles krüptitud jututoas ei ole usaldusväärsed",
"All sessions in this encrypted room are trusted": "Kõik sessioonid selles krüptitud jututoas on usaldusväärsed",
"Edit message": "Muuda sõnumit",
"%(senderName)s sent an image": "%(senderName)s saatis pildi",
"%(senderName)s sent a video": "%(senderName)s saatis video",
"%(senderName)s uploaded a file": "%(senderName)s laadis üles faili",
"Your key share request has been sent - please check your other sessions for key share requests.": "Sinu krüptovõtme jagamise päring on saadetud - palun oma teisi sessioone krüptovõtme jagamise päringu osas.",
"This message cannot be decrypted": "Seda sõnumit ei sa dekrüptida",
"Unencrypted": "Krüptimata",
"Encrypted by a deleted session": "Krüptitud kustutatud sessiooni poolt",
"Please select the destination room for this message": "Palun vali jututuba, kuhu soovid seda sõnumit saata",
"Invite only": "Ainult kutse",
"Scroll to most recent messages": "Mine viimaste sõnumite juurde",
"Close preview": "Sulge eelvaade",
"Disinvite": "Eemalda kutse",
"Kick": "Müksa välja",
"Disinvite this user?": "Kas võtad selle kasutaja kutse tagasi?",
"Kick this user?": "Kas müksad selle kasutaja jututoast välja?",
"Failed to kick": "Jututoast väljamüksamine ei õnnestunud",
"No recent messages by %(user)s found": "Kasutajalt %(user)s ei leitud hiljutisi sõnumeid",
"Try scrolling up in the timeline to see if there are any earlier ones.": "Vaata kas ajajoonel ülespool leidub varasemaid sõnumeid.",
"For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "Kui sõnumeid on väga palju, siis võib nüüd aega kuluda. Oodates palun ära tee ühtegi päringut ega andmevärskendust.",
"Failed to mute user": "Kasutaja summutamine ebaõnnestus",
"%(creator)s created and configured the room.": "%(creator)s lõi ja seadistas jututoa.",
"Click to unmute video": "Klõpsi video heli taastamiseks",
"Click to mute video": "Klõpsi video heli summutamiseks",
"Click to unmute audio": "Klõpsi heli taastamiseks",
"Click to mute audio": "Klõpsi heli summutamiseks",
"Your profile": "Sinu profiil",
"How fast should messages be downloaded.": "Kui kiiresti peaksime sõnumeid alla laadima.",
"Error downloading theme information.": "Viga teema teabefaili allalaadimisel.",
"Close": "Sulge",
"Add a widget": "Lisa vidin",
"Drop File Here": "Lohista fail siia",
"Drop file here to upload": "Faili üleslaadimiseks lohista ta siia",
" (unsupported)": " (ei ole toetatud)",
"This user has not verified all of their sessions.": "See kasutaja ei ole verifitseerinud kõiki nende sessioone.",
"You have not verified this user.": "Sa ei ole seda kasutajat verifitseerinud.",
"You have verified this user. This user has verified all of their sessions.": "Sa oled selle kasutaja verifitseerinud. See kasutaja on verifitseerinud kõik nende sessioonid.",
"Someone is using an unknown session": "Keegi kasutab tundmatut sessiooni",
"This event could not be displayed": "Seda sündmust ei õnnestunud kuvada",
"Downloading update...": "Laen alla uuendust...",
"Download this file": "Lae see fail alla",
"You can now close this window or <a>log in</a> to your new account.": "Sa võid nüüd sulgeda selle akna või <a>logida sisse</a> oma uuele kontole.",
"Download": "Lae alla",
"Your recovery key is in your <b>Downloads</b> folder.": "Sinu taastevõti on sinu <b>Allalaadimised</b> kasutas.",
"Disable": "Lülita välja",
"Not currently indexing messages for any room.": "Mitte ainsamagi jututoa sõnumeid hetkel ei indekseerita.",
"Currently indexing: %(currentRoom)s": "Parasjagu indekseerin: %(currentRoom)s",
"Space used:": "Kasutatud andmeruum:",
"Indexed messages:": "Indekseeritud sõnumid:",
"Failed to add tag %(tagName)s to room": "Sildi %(tagName)s lisamine jututoale ebaõnnestus",
"Close dialog or context menu": "Sulge dialoogiaken või kontekstimenüü",
"Page Up": "Page Up",
"Page Down": "Page Down",
"Esc": "Esc",
"Enter": "Enter",
"Space": "Tühikuklahv",
"End": "End",
"Unable to add email address": "E-posti aadressi lisamine ebaõnnestus",
"Add": "Lisa",
"We've sent you an email to verify your address. Please follow the instructions there and then click the button below.": "Sinu aadressi kontrollimiseks saatsime sulle e-kirja. Palun järgi kirjas näidatud juhendit ja siis klõpsi alljärgnevat nuppu.",
"Email Address": "E-posti aadress",
"A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Saatsime tekstisõnumi numbrile +%(msisdn)s. Palun sisesta seal kuvatud kontrollkood.",
"Phone Number": "Telefoni number",
"Cannot add any more widgets": "Rohkem vidinaid ei õnnestu lisada",
"The maximum permitted number of widgets have already been added to this room.": "Suurim lubatud vidinate arv on siia jututuppa juba lisatud.",
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Liitu kas <voiceText>häälkõnega</voiceText> või <videoText>videokõnega</videoText>.",
"Ongoing conference call%(supportedText)s.": "Toimuv rühmavestlus %(supportedText)s.",
"Advanced": "Teave arendajatele",
"Gets or sets the room topic": "Otsib või määrab jututoa teema",
"Sets the room name": "Määrab jututoa nime",
"%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s eemaldas jututoa nime.",
"%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s muutis jututoa vana nime %(oldRoomName)s uueks nimeks %(newRoomName)s.",
"%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s muutis jututoa nimeks %(roomName)s.",
"Show info about bridges in room settings": "Näita jututoa seadistustes teavet võrgusildade kohta",
"Upload": "Lae üles",
"Save": "Salvesta",
"General": "Üldist",
"Notifications": "Teavitused",
"Security & Privacy": "Turvalisus ja privaatsus",
"No Audio Outputs detected": "Ei leidnud ühtegi heliväljundit",
"No Microphones detected": "Ei leidnud ühtegi mikrofoni",
"No Webcams detected": "Ei leidnud ühtegi veebikaamerat",
"Default Device": "Vaikimisi seade",
"Audio Output": "Heliväljund",
"Microphone": "Mikrofon",
"Camera": "Kaamera",
"Voice & Video": "Heli ja video",
"This room is not accessible by remote Matrix servers": "See jututuba ei ole leitav teiste Matrix'i serverite jaoks",
"Upgrade this room to the recommended room version": "Uuenda see jututoa versioon soovitatud versioonini",
"View older messages in %(roomName)s.": "Näita vanemat tüüpi sõnumeid jututoas %(roomName)s.",
"Room information": "Info jututoa kohta",
"Internal room ID:": "Jututoa sisemine tunnus:",
"Room version": "Jututoa versioon",
"Room version:": "Jututoa versioon:",
"Developer options": "Valikud arendajale",
"Open Devtools": "Ava arendusvahendid",
"Change room name": "Muuda jututoa nimi",
"Roles & Permissions": "Rollid ja õigused",
"Room Name": "Jututoa nimi",
"Room Topic": "Jututoa teema",
"Room Settings - %(roomName)s": "Jututoa seadistused - %(roomName)s",
"General failure": "Üldine viga",
"Where youre logged in": "Kus sa oled võrku loginud",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Halda alljärgnevas oma sessioonide nimesid, logi neist välja või <a>verifitseeri neid oma kasutajaprofiilis</a>.",
"A session's public name is visible to people you communicate with": "Sessiooni avalik nimi on nähtav neile, kellega sa suhtled",
"Riot collects anonymous analytics to allow us to improve the application.": "Võimaldamaks meil rakendust parandada kogub Riot anonüümset analüütikat.",
"Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privaatsus on meile oluline ning seega me ei kogu ei isiklikke ega isikustatavaid andmeid.",
"Learn more about how we use analytics.": "Loe lisaks kuidas me kasutama analüütikat.",
"No media permissions": "Meediaõigused puuduvad",
"You may need to manually permit Riot to access your microphone/webcam": "Sa võib-olla pead andma Riot'ile loa mikrofoni ja veebikaamera kasutamiseks",
"Missing media permissions, click the button below to request.": "Meediaga seotud õigused puuduvad. Nende nõutamiseks klõpsi järgnevat nuppu.",
"Request media permissions": "Nõuta meediaõigusi",
"Frequently Used": "Enamkasutatud",
"Smileys & People": "Vigurnäod ja inimesed",
"Animals & Nature": "Loomad ja loodus",
"Food & Drink": "Toit ja jook",
"Activities": "Tegevused",
"Travel & Places": "Reisimine ja kohad",
"Objects": "Esemed",
"Symbols": "Sümbolid",
"Flags": "Lipud",
"Quick Reactions": "Reageeri lennult",
"Unknown Address": "Teadmata aadress",
"Any of the following data may be shared:": "Järgnevaid andmeid võib jagada:",
"Your display name": "Sinu kuvatav nimi",
"Your avatar URL": "Sinu avatari aadress",
"Your user ID": "Sinu kasutajatunnus",
"Your theme": "Sinu teema",
"Riot URL": "Riot'i aadress",
"Room ID": "Jututoa tunnus",
"Widget ID": "Vidina tunnus",
"%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s muutis oma kuvatava nime %(displayName)s-ks.",
"%(senderName)s set their display name to %(displayName)s.": "%(senderName)s määras oma kuvatava nime %(displayName)s-ks.",
"%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s eemaldas oma kuvatava nime (%(oldDisplayName)s).",
"%(senderName)s removed their profile picture.": "%(senderName)s eemaldas om profiilipildi.",
"%(senderName)s changed their profile picture.": "%(senderName)s muutis oma profiilipilti.",
"%(senderName)s set a profile picture.": "%(senderName)s määras oma profiilipildi.",
"Light theme": "Hele teema",
"Dark theme": "Tume teema",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Your browser does not support the required cryptography extensions": "Sinu brauser ei toeta vajalikke krüptoteeke",
"Not a valid Riot keyfile": "See ei ole sobilik võtmefail Riot'i jaoks",
"Authentication check failed: incorrect password?": "Autentimine ebaõnnestus: kas salasõna pole õige?",
"Unrecognised address": "Tundmatu aadress",
"You do not have permission to invite people to this room.": "Sul pole õigusi siia jututuppa osalejate kutsumiseks.",
"User %(userId)s is already in the room": "Kasutaja %(userId)s on juba jututoas",
"User %(user_id)s does not exist": "Kasutajat %(user_id)s pole olemas",
"User %(user_id)s may or may not exist": "Kasutaja %(user_id)s võib olla olemas, aga võib ka mitte olla olemas",
"The user's homeserver does not support the version of the room.": "Kasutaja koduserver ei toeta selle jututoa versiooni.",
"Unknown server error": "Tundmatu serveriviga",
"This is a top-10 common password": "See on kümne levinuima salasõna seas",
"This is a top-100 common password": "See on saja levinuima salasõna seas",
"This is a very common password": "See on väga levinud salasõna",
"This is similar to a commonly used password": "See on sarnane tavaliselt kasutatavatele salasõnadele",
"Support adding custom themes": "Toeta kohandatud teemade lisamist",
"Show display name changes": "Näita kuvatava nime muutusi",
"Match system theme": "Kasuta süsteemset teemat",
"Messages containing my display name": "Sõnumid, mis sisaldavad minu kuvatavat nime",
"Failed to upload profile picture!": "Profiilipildi üleslaadimine ebaõnnestus!",
"No display name": "Kuvatav nimi puudub",
"New passwords don't match": "Uued salasõnad ei klapi",
"Passwords can't be empty": "Salasõna ei saa olla tühi",
"Current password": "Praegune salasõna",
"Password": "Salasõna",
"New Password": "Uus salasõna",
"Confirm password": "Korda uut salasõna",
"Change Password": "Muuda salasõna",
"Failed to set display name": "Kuvatava nime määramine ebaõnnestus",
"Display Name": "Kuvatav nimi",
"Profile picture": "Profiilipilt",
"Failed to change password. Is your password correct?": "Salasõna muutmine ebaõnnestus. Kas sinu salasõna on ikka õige?",
"Invalid theme schema.": "Vigane teemafail.",
"Theme added!": "Teema sai lisatud!",
"Profile": "Profiil",
"Email addresses": "E-posti aadressid",
"Phone numbers": "Telefoninumbrid",
"Set a new account password...": "Määra kontole uus salasõna...",
"Account": "Kasutajakonto",
"Language and region": "Keel ja piirkond",
"Custom theme URL": "Kohandatud teema URL",
"Add theme": "Lisa teema",
"Theme": "Teema",
"Start verification again from their profile.": "Alusta verifitseerimist uuesti nende profiilist.",
"To return to your account in future you need to <u>set a password</u>": "Selleks et hiljemgi oma kontot kasutada, sa pead <u>määrama salasõna</u>",
"Set Password": "Määra salasõna",
"Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "Allpool loetletud Matrix'i kasutajatunnustele ei leidunud profiile. Kas sa ikkagi tahaksid neile kutse saata?",
"To continue, please enter your password:": "Jätkamiseks palun sisesta oma salasõna:",
"Your password": "Sinu salasõna",
"We recommend you change your password and recovery key in Settings immediately": "Me soovitame et vaheta koheselt Seadistuste lehelt oma salasõna ja taastevõti",
"Could not load user profile": "Kasutajaprofiili laadimine ei õnnestunud",
"Set a display name:": "Määra kuvatav nimi:",
"Send typing notifications": "Anna märku teisele osapoolele, kui mina sõnumit kirjutan",
"Show typing notifications": "Anna märku, kui teine osapool sõnumit kirjutab",
"Automatically replace plain text Emoji": "Automaatelt asenda vormindamata tekst emotikoniga",
"Mirror local video feed": "Peegelda kohalikku videovoogu",
"Enable Community Filter Panel": "Kasuta kogukondade filtreerimispaneeli",
"Allow Peer-to-Peer for 1:1 calls": "Luba võrdõigusvõrgu loogikat kasutavad omavahelised kõned",
"Send analytics data": "Saada arendajatele analüütikat",
"Enable inline URL previews by default": "Luba URL'ide vaikimisi eelvaated",
"Enable URL previews for this room (only affects you)": "Luba URL'ide eelvaated selle jututoa jaoks (mõjutab vaid sind)",
"Enable URL previews by default for participants in this room": "Luba URL'ide vaikimisi eelvaated selles jututoas osalejate jaoks",
"Room Colour": "Jututoa värv",
"Enable widget screenshots on supported widgets": "Kui vidin seda toetab, siis luba tal teha ekraanitõmmiseid",
"Prompt before sending invites to potentially invalid matrix IDs": "Hoiata enne kutse saatmist võimalikule vigasele Matrix'i kasutajatunnusele",
"Show developer tools": "Näita arendaja tööriistu",
"Show hidden events in timeline": "Näita peidetud sündmusi ajajoonel",
"Low bandwidth mode": "Vähese ribalaiusega režiim",
"Composer": "Sõnumite kirjutamine",
"Jump to start/end of the composer": "Hüppa sõnumite kirjutamise algusesse või lõppu",
"Navigate composer history": "Vaata sõnumite kirjutamise ajalugu",
"Show previews/thumbnails for images": "Näita piltide eelvaateid või väikepilte",
"Collecting logs": "Kogun logisid",
"Waiting for response from server": "Ootan serverilt vastust",
"Messages containing my username": "Sõnumid, mis sisaldavad minu kasutajatunnust",
"Messages containing @room": "Sõnumid, mis sisaldavad sõna @room",
"Messages in one-to-one chats": "Kahepoolsete vestluste sõnumid",
"Encrypted messages in one-to-one chats": "Kahepoolsete vestluste krüptitud sõnumid",
"Messages in group chats": "Rühmavestluste sõnumid",
"Encrypted messages in group chats": "Rühmavestluste krüptitud sõnumid",
"When I'm invited to a room": "Kui mind kutsutakse jututuppa",
"Call invitation": "Kõnekutse",
"Messages sent by bot": "Robotite saadetud sõnumid"
}

View file

@ -39,7 +39,7 @@
"Banned users": "Utilisateurs bannis",
"Bans user with given id": "Bannit l'utilisateur à partir de son identifiant",
"Blacklisted": "Sur liste noire",
"Call Timeout": "Délai dappel expiré",
"Call Timeout": "Lappel a dépassé le délai d'attente maximal",
"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>.": "Impossible de se connecter au serveur d'accueil en HTTP si l'URL dans la barre de votre explorateur est en HTTPS. Utilisez HTTPS ou <a>activez le support des scripts non-vérifiés</a>.",
"Change Password": "Changer le mot de passe",
"%(senderName)s changed their profile picture.": "%(senderName)s a changé son image de profil.",
@ -88,7 +88,7 @@
"An error has occurred.": "Une erreur est survenue.",
"Email": "E-mail",
"Failed to unban": "Échec de la révocation du bannissement",
"Failed to verify email address: make sure you clicked the link in the email": "Échec de la vérification de ladresse e-mail : vérifiez que vous avez bien cliqué sur le lien dans le-mail",
"Failed to verify email address: make sure you clicked the link in the email": "La vérification de ladresse e-mail a échoué : vérifiez que vous avez bien cliqué sur le lien dans le-mail",
"Failure to create room": "Échec de la création du salon",
"Favourites": "Favoris",
"Fill screen": "Plein écran",
@ -215,7 +215,7 @@
"Unable to verify email address.": "Impossible de vérifier ladresse e-mail.",
"Unban": "Révoquer le bannissement",
"%(senderName)s unbanned %(targetName)s.": "%(senderName)s a révoqué le bannissement de %(targetName)s.",
"Unable to capture screen": "Impossible de capturer l'écran",
"Unable to capture screen": "Impossible de faire une capture d'écran",
"Unable to enable Notifications": "Impossible d'activer les notifications",
"unencrypted": "non chiffré",
"unknown device": "appareil inconnu",
@ -234,7 +234,7 @@
"Voice call": "Appel vocal",
"VoIP conference finished.": "Téléconférence VoIP terminée.",
"VoIP conference started.": "Téléconférence VoIP démarrée.",
"VoIP is unsupported": "VoIP (Appels par Internet) n'est pas supportée",
"VoIP is unsupported": "Voix sur IP non gérée",
"Warning!": "Attention !",
"Who can access this room?": "Qui peut accéder au salon ?",
"Who can read history?": "Qui peut lire l'historique ?",
@ -661,10 +661,10 @@
"Display your community flair in rooms configured to show it.": "Sélectionnez les badges dans les paramètres de chaque salon pour les afficher.",
"expand": "développer",
"collapse": "réduire",
"Call Failed": "Échec de l'appel",
"Call Failed": "L'appel a échoué",
"Review Devices": "Passer en revue les appareils",
"Call Anyway": "Appeler quand même",
"Answer Anyway": "Répondre quand même",
"Call Anyway": "Appeler malgré tout",
"Answer Anyway": "Répondre malgré tout",
"Call": "Appel",
"Answer": "Répondre",
"Send": "Envoyer",
@ -688,8 +688,8 @@
"The platform you're on": "La plateforme que vous utilisez",
"The version of Riot.im": "La version de Riot.im",
"Your language of choice": "La langue que vous avez choisie",
"Which officially provided instance you are using, if any": "Quelle instance officielle vous utilisez, si c'est le cas",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Si vous utilisez le mode de texte enrichi de l'éditeur de texte enrichi",
"Which officially provided instance you are using, if any": "L'instance officielle que vous utilisez, si vous en utilisez une",
"Whether or not you're using the Richtext mode of the Rich Text Editor": "Si vous utilisez le mode « texte enrichi » de l'éditeur de texte enrichi",
"Your homeserver's URL": "L'URL de votre serveur d'accueil",
"Your identity server's URL": "L'URL de votre serveur d'identité",
"%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s %(day)s %(monthName)s %(fullYear)s",
@ -1553,9 +1553,9 @@
"You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one below.": "Vous nutilisez actuellement aucun serveur didentité. Pour découvrir et être découvert par les contacts existants que vous connaissez, ajoutez-en un ci-dessous.",
"Disconnecting from your identity server will mean you won't be discoverable by other users and you won't be able to invite others by email or phone.": "La déconnexion de votre serveur didentité signifie que vous ne serez plus découvrable par dautres utilisateurs et que vous ne pourrez plus faire dinvitation par e-mail ou téléphone.",
"Integration Manager": "Gestionnaire dintégration",
"Call failed due to misconfigured server": "Échec de lappel à cause dun serveur mal configuré",
"Call failed due to misconfigured server": "Lappel a échoué à cause dun serveur mal configuré",
"Please ask the administrator of your homeserver (<code>%(homeserverDomain)s</code>) to configure a TURN server in order for calls to work reliably.": "Demandez à ladministrateur de votre serveur daccueil (<code>%(homeserverDomain)s</code>) de configurer un serveur TURN afin que les appels fonctionnent de manière fiable.",
"Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Sinon, vous pouvez essayer dutiliser le serveur public à <code>turn.matrix.org</code>, mais ça ne sera pas aussi fiable et ça partagera votre adresse IP avec ce serveur. Vous pouvez aussi gérer cela dans les paramètres.",
"Alternatively, you can try to use the public server at <code>turn.matrix.org</code>, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Vous pouvez sinon essayer dutiliser le serveur public <code>turn.matrix.org</code>, mais ça ne sera pas aussi fiable et votre adresse IP sera partagée avec ce serveur. Vous pouvez aussi gérer ce réglage dans les paramètres.",
"Try using turn.matrix.org": "Essayer dutiliser turn.matrix.org",
"Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Autoriser le repli sur le serveur dassistance dappel turn.matrix.org quand votre serveur nen fournit pas (votre adresse IP serait partagée lors dun appel)",
"Only continue if you trust the owner of the server.": "Continuez seulement si vous faites confiance au propriétaire du serveur.",
@ -2403,5 +2403,19 @@
"Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Confirmez votre identité en vérifiant cette connexion depuis une de vos autres sessions, cela lui permettra davoir accès aux messages chiffrés.",
"This requires the latest Riot on your other devices:": "Ceci nécessite la dernière version de Riot sur vos autres appareils :",
"or another cross-signing capable Matrix client": "ou un autre client Matrix compatible avec la signature croisée",
"Use Recovery Passphrase or Key": "Utiliser la phrase secrète ou la clé de récupération"
"Use Recovery Passphrase or Key": "Utiliser la phrase secrète ou la clé de récupération",
"Where youre logged in": "Où vous vous êtes connecté",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Gérez les noms et déconnectez-vous de vos sessions ci-dessous ou <a>vérifiez-les dans votre profil utilisateur</a>.",
"Review where youre logged in": "Vérifier où vous vous êtes connecté",
"Verify your other sessions": "Vérifier vos autres sessions",
"Unverified sessions currently have access to your account & messages": "Des sessions non vérifiées ont accès à votre compte et messages",
"Verify the identity of the new login accessing your account & messages": "Vérifiez l'identité de la nouvelle connexion accédant à votre compte et messages",
"New login. Was this you?": "Nouvelle connexion. Était-ce vous ?",
"Verify all your sessions to ensure your account & messages are safe": "Vérifiez toutes vos sessions pour vous assurer que votre compte et messages sont sécurisés",
"Verify the new login accessing your account: %(name)s": "Vérifiez la nouvelle connexion accédant à votre compte : %(name)s",
"Restoring keys from backup": "Restauration des clés depuis la sauvegarde",
"Fetching keys from server...": "Récupération des clés depuis le serveur…",
"%(completed)s of %(total)s keys restored": "%(completed)s clés sur %(total)s restaurées",
"Keys restored": "Clés restaurées",
"Successfully restored %(sessionCount)s keys": "%(sessionCount)s clés ont été restaurées avec succès"
}

View file

@ -1351,7 +1351,7 @@
"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>": "Ha egyszer engedélyezve lett, a szoba titkosítását nem lehet kikapcsolni. A titkosított szobákban küldött üzenetek a szerver számára nem, csak a szoba tagjai számára láthatók. A titkosítás bekapcsolása megakadályoz sok botot és hidat a megfelelő működésben. <a>Tudj meg többet a titkosításról.</a>",
"Power level": "Hozzáférési szint",
"Want more than a community? <a>Get your own server</a>": "Többet szeretnél, mint egy közösség? <a>Szerezz saját szervert</a>",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Kérlek telepíts <chromeLink>Chrome</chromeLink>ot, <firefoxLink>Firefox</firefoxLink>ot vagy <safariLink>Safari</safariLink>t a jegjobb élményhez.",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "A legjobb élmény eléréséhez kérlek telepíts <chromeLink>Chrome-ot</chromeLink>, <firefoxLink>Firefoxot</firefoxLink> vagy <safariLink>Safarit</safariLink>.",
"<b>Warning</b>: Upgrading a room will <i>not automatically migrate room members to the new version of the room.</i> We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "<b>Figyelmeztetés</b>: A szoba frissítése <i>nem fogja automatikusan átvinni a szoba résztvevőit az új verziójú szobába.</i> A régi szobába bekerül egy link az új szobához - a tagoknak rá kell kattintani a linkre az új szobába való belépéshez.",
"Adds a custom widget by URL to the room": "Egyedi kisalkalmazás hozzáadása a szobához URL-lel",
"Please supply a https:// or http:// widget URL": "Kérlek add meg a https:// vagy http:// kisalkalmazás URL-t",
@ -2395,5 +2395,16 @@
"This requires the latest Riot on your other devices:": "A Riot legújabb kliensére van ehhez szükséged a többi eszközödön:",
"or another cross-signing capable Matrix client": "vagy másik eszközök közötti hitelesítésre alkalmas Matrix kliensre",
"Use Recovery Passphrase or Key": "Használd a Visszaállítási Jelmondatot vagy Kulcsot",
"Unable to query secret storage status": "A biztonsági tároló állapotát nem lehet lekérdezni"
"Unable to query secret storage status": "A biztonsági tároló állapotát nem lehet lekérdezni",
"Review where youre logged in": "Tekintsd át hol vagy bejelentkezve",
"New login. Was this you?": "Új bejelentkezés. Te voltál?",
"Verify all your sessions to ensure your account & messages are safe": "Ellenőrizd minden munkamenetedet, hogy a fiókod és az üzeneteid biztonságban legyenek",
"Verify the new login accessing your account: %(name)s": "Ellenőrizd ezt az új bejelentkezést ami hozzáfér a fiókodhoz: %(name)s",
"Where youre logged in": "Ahol be vagy jelentkezve",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Állítsd be a munkameneteid neveit, jelentkezz ki vagy <a>ellenőrizd őket a Felhasználói Beállításokban</a>.",
"Restoring keys from backup": "Kulcsok visszaállítása mentésből",
"Fetching keys from server...": "Kulcsok lekérdezése a szerverről…",
"%(completed)s of %(total)s keys restored": "%(completed)s/%(total)s kulcs visszaállítva",
"Keys restored": "Kulcsok visszaállítva",
"Successfully restored %(sessionCount)s keys": "Kulcsok (%(sessionCount)s) sikeresen visszaállítva"
}

View file

@ -780,7 +780,7 @@
"Explore Account Data": "Esplora dati account",
"All messages (noisy)": "Tutti i messaggi (rumoroso)",
"Saturday": "Sabato",
"I understand the risks and wish to continue": "Sono consapevole dei rischi e vorrei continuare",
"I understand the risks and wish to continue": "Capisco i rischi e desidero continuare",
"Direct Chat": "Chat Diretta",
"The server may be unavailable or overloaded": "Il server potrebbe essere non disponibile o sovraccarico",
"Reject": "Rifiuta",
@ -1321,7 +1321,7 @@
"Premium hosting for organisations <a>Learn more</a>": "Hosting premium per organizzazioni <a>Maggior informazioni</a>",
"Other": "Altro",
"Find other public servers or use a custom server": "Trova altri server pubblici o usane uno personale",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Ti suggeriamo di installare <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> o <safariLink>Safari</safariLink> per la migliore esperienza.",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Installa <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, o <safariLink>Safari</safariLink> per una migliore esperienza.",
"Couldn't load page": "Caricamento pagina fallito",
"Want more than a community? <a>Get your own server</a>": "Vuoi più di una comunità? <a>Ottieni il tuo server personale</a>",
"This homeserver does not support communities": "Questo homeserver non supporta le comunità",
@ -2400,5 +2400,17 @@
"Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Conferma la tua identità verificando questo accesso da una delle tue altre sessioni, dandogli l'accesso ai messaggi cifrati.",
"This requires the latest Riot on your other devices:": "È richiesta l'ultima versione di Riot sui tuoi altri dispositivi:",
"or another cross-signing capable Matrix client": "o un altro client Matrix che supporti la firma incrociata",
"Use Recovery Passphrase or Key": "Usa la password di ripristino o la chiave"
"Use Recovery Passphrase or Key": "Usa la password di ripristino o la chiave",
"Review where youre logged in": "Controlla dove hai fatto l'accesso",
"Verify your other sessions": "Verifica le tue altre sessioni",
"Where youre logged in": "Dove hai fatto l'accesso",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Gestisci i nomi e disconnettiti dalle tue sessioni sotto o <a>verificale nel tuo profilo utente</a>.",
"New login. Was this you?": "Nuovo accesso. Eri tu?",
"Verify all your sessions to ensure your account & messages are safe": "Verifica tutte le tue sessioni per assicurarti che il tuo account e i messaggi siano protetti",
"Verify the new login accessing your account: %(name)s": "Verifica il nuovo accesso entrando nel tuo account: %(name)s",
"Restoring keys from backup": "Ripristino delle chiavi dal backup",
"Fetching keys from server...": "Ricezione delle chiavi dal server...",
"%(completed)s of %(total)s keys restored": "%(completed)s di %(total)s chiavi ripristinate",
"Keys restored": "Chiavi ripristinate",
"Successfully restored %(sessionCount)s keys": "Ripristinate %(sessionCount)s chiavi correttamente"
}

View file

@ -2165,5 +2165,8 @@
"To report a Matrix-related security issue, please read the Matrix.org <a>Security Disclosure Policy</a>.": "Bekijk eerst het <a>beveiligingsopenbaarmakingsbeleid</a> van Matrix.org als u een probleem met de beveiliging van Matrix wilt melden.",
"Not currently indexing messages for any room.": "Er worden momenteel voor geen enkel gesprek berichten geïndexeerd.",
"Currently indexing: %(currentRoom)s.": "Wordt geïndexeerd: %(currentRoom)s.",
"%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s van %(totalRooms)s"
"%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s van %(totalRooms)s",
"Unverified login. Was this you?": "Ongeverifieerde aanmelding. Was u dit?",
"Where youre logged in": "Waar u aangemeld bent",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Beheer hieronder de namen van uw sessies en meld ze af. <a>Of verifieer ze in uw gebruikersprofiel</a>."
}

View file

@ -1506,5 +1506,18 @@
"Something went wrong. Please try again or view your console for hints.": "Niečo sa nepodarilo. Prosím, skúste znovu neskôr alebo si prečítajte ďalšie usmernenia zobrazením konzoly.",
"Error subscribing to list": "Chyba pri prihlasovaní sa do zoznamu",
"Please verify the room ID or alias and try again.": "Prosím, overte platnosť ID miestnosti alebo alias a skúste znovu.\nPlease verify the room ID or alias and try again.",
"Error removing ignored user/server": "Chyba pri odstraňovaní ignorovaného používateľa / servera"
"Error removing ignored user/server": "Chyba pri odstraňovaní ignorovaného používateľa / servera",
"Use Single Sign On to continue": "Pokračovať pomocou Jednotného prihlásenia",
"Confirm adding this email address by using Single Sign On to prove your identity.": "Potvrďte pridanie tejto adresy pomocou Jednotného prihlásenia.",
"Single Sign On": "Jednotné prihlásenie",
"Confirm adding email": "Potvrdiť pridanie emailu",
"Click the button below to confirm adding this email address.": "Kliknutím na tlačítko potvrdíte pridanie emailovej adresy.",
"Confirm adding this phone number by using Single Sign On to prove your identity.": "Potvrďte pridanie telefónneho čísla pomocou Jednotného prihlásenia.",
"Confirm adding phone number": "Potvrdiť pridanie telefónneho čísla",
"Click the button below to confirm adding this phone number.": "Kliknutím na tlačítko potvrdíte pridanie telefónneho čísla.",
"The version of Riot": "Verzia Riotu",
"Whether you're using Riot on a device where touch is the primary input mechanism": "Či používate Riot na zariadení, ktorého hlavným vstupným mechanizmom je dotyk (mobil, tablet,...)",
"Whether you're using Riot as an installed Progressive Web App": "Či používate Riot ako nainštalovanú Progresívnu Webovú Aplikáciu",
"Your user agent": "Identifikátor vášho prehliadača",
"The information being sent to us to help make Riot better includes:": "Informácie, ktoré nám posielate, aby sme zlepšili Riot, zahŕňajú:"
}

View file

@ -722,7 +722,7 @@
"Everyone": "每個人",
"Fetching third party location failed": "抓取第三方位置失敗",
"A new version of Riot is available.": "Riot 釋出了新版本。",
"I understand the risks and wish to continue": "我了解這些風險並願意繼續",
"I understand the risks and wish to continue": "我了解風險並希望繼續",
"Send Account Data": "傳送帳號資料",
"Advanced notification settings": "進階通知設定",
"Uploading report": "上傳報告",
@ -1351,7 +1351,7 @@
"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>": "一旦啟用,聊天室的加密就不能停用了。在已加密的聊天室裡傳送的訊息無法被伺服器看見,僅能被聊天室的參與者看到。啟用加密可能會讓許多機器人與橋接運作不正常。<a>取得更多關於加密的資訊。</a>",
"Power level": "權力等級",
"Want more than a community? <a>Get your own server</a>": "想要的不只是社群?<a>架設您自己的伺服器</a>",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "請安裝 <chromeLink>Chrome</chromeLink>、<firefoxLink>Firefox</firefoxLink> 或 <safariLink>Safari</safariLink> 以得最佳體驗。",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "請安裝 <chromeLink>Chrome</chromeLink>、<firefoxLink>Firefox</firefoxLink> 或 <safariLink>Safari</safariLink> 以得最佳體驗。",
"<b>Warning</b>: Upgrading a room will <i>not automatically migrate room members to the new version of the room.</i> We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "<b>警告</b>:升級聊天室<i>不會自動將聊天室成員遷移到新版的聊天室<i>。我們會在舊版聊天室中貼出到新聊天室的連結,聊天室成員必須點選此連結以加入新聊天室。",
"Adds a custom widget by URL to the room": "透過 URL 新增自訂小工具到聊天室",
"Please supply a https:// or http:// widget URL": "請提供 https:// 或 http:// 小工具 URL",
@ -2402,5 +2402,19 @@
"Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "透過驗證這個從您的其他工作階段而來的登入來確認您的身份,並授予其對加密訊息的存取權限。",
"This requires the latest Riot on your other devices:": "這需要在您的其他裝置上使用最新的 Riot",
"or another cross-signing capable Matrix client": "或另一個有交叉簽章功能的 Matrix 客戶端",
"Use Recovery Passphrase or Key": "使用復原通關密語或金鑰"
"Use Recovery Passphrase or Key": "使用復原通關密語或金鑰",
"Where youre logged in": "您登入的地方",
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "在下方管理您工作階段的名稱與登入或<a>在您的使用者檔案中驗證它們</a>。",
"Review where youre logged in": "審閱您的登入位置",
"Verify your other sessions": "驗證您其他的工作階段",
"New login. Was this you?": "新登入。這是您嗎?",
"Unverified sessions currently have access to your account & messages": "未驗證的工作階段目前正在存取您的帳號與訊息",
"Verify the identity of the new login accessing your account & messages": "驗證存取您帳號與訊息的新登入身份",
"Verify all your sessions to ensure your account & messages are safe": "驗證您所有的工作階段以確保您的帳號與訊息是安全的",
"Verify the new login accessing your account: %(name)s": "驗證正在存取您帳號的新登入:%(name)s",
"Restoring keys from backup": "從備份還原金鑰",
"Fetching keys from server...": "正在從伺服器擷取金鑰……",
"%(completed)s of %(total)s keys restored": "%(total)s 中的 %(completed)s 金鑰已復原",
"Keys restored": "金鑰已復原",
"Successfully restored %(sessionCount)s keys": "成功復原 %(sessionCount)s 金鑰"
}

View file

@ -102,9 +102,6 @@ export default class EventIndex extends EventEmitter {
const timeline = room.getLiveTimeline();
const token = timeline.getPaginationToken("b");
console.log("EventIndex: Got token for indexer",
room.roomId, token);
const backCheckpoint = {
roomId: room.roomId,
token: token,
@ -161,7 +158,6 @@ export default class EventIndex extends EventEmitter {
if (prevState === "SYNCING" && state === "SYNCING") {
// A sync was done, presumably we queued up some live events,
// commit them now.
console.log("EventIndex: Committing events");
await indexManager.commitLiveEvents();
return;
}
@ -336,8 +332,6 @@ export default class EventIndex extends EventEmitter {
async crawlerFunc() {
let cancelled = false;
console.log("EventIndex: Started crawler function");
const client = MatrixClientPeg.get();
const indexManager = PlatformPeg.get().getEventIndexingManager();
@ -366,8 +360,6 @@ export default class EventIndex extends EventEmitter {
await sleep(sleepTime);
console.log("EventIndex: Running the crawler loop.");
if (cancelled) {
break;
}
@ -386,8 +378,6 @@ export default class EventIndex extends EventEmitter {
idle = false;
console.log("EventIndex: crawling using checkpoint", checkpoint);
// We have a checkpoint, let us fetch some messages, again, very
// conservatively to not bother our homeserver too much.
const eventMapper = client.getEventMapper({preventReEmit: true});
@ -477,9 +467,6 @@ export default class EventIndex extends EventEmitter {
// decryption keys, do we want to retry this checkpoint at a later
// stage?
const filteredEvents = matrixEvents.filter(this.isValidEvent);
const undecryptableEvents = matrixEvents.filter((ev) => {
return ev.isDecryptionFailure();
});
// Collect the redaction events so we can delete the redacted events
// from the index.
@ -511,15 +498,6 @@ export default class EventIndex extends EventEmitter {
direction: checkpoint.direction,
};
console.log(
"EventIndex: Crawled room",
client.getRoom(checkpoint.roomId).name,
"and fetched total", matrixEvents.length, "events of which",
events.length, "are being added,", redactionEvents.length,
"are redacted,", matrixEvents.length - events.length,
"are being skipped, undecryptable", undecryptableEvents.length,
);
try {
for (let i = 0; i < redactionEvents.length; i++) {
const ev = redactionEvents[i];
@ -552,8 +530,6 @@ export default class EventIndex extends EventEmitter {
}
this._crawler = null;
console.log("EventIndex: Stopping crawler function");
}
/**

View file

@ -41,7 +41,7 @@ limitations under the License.
const FLUSH_RATE_MS = 30 * 1000;
// the length of log data we keep in indexeddb (and include in the reports)
const MAX_LOG_SIZE = 1024 * 1024 * 1; // 1 MB
const MAX_LOG_SIZE = 1024 * 1024 * 5; // 5 MB
// A class which monkey-patches the global console and stores log lines.
class ConsoleLogger {

View file

@ -139,7 +139,7 @@ export default class RightPanelStore extends Store {
let targetPhase = payload.phase;
let refireParams = payload.refireParams;
// redirect to EncryptionPanel if there is an ongoing verification request
if (targetPhase === RIGHT_PANEL_PHASES.RoomMemberInfo) {
if (targetPhase === RIGHT_PANEL_PHASES.RoomMemberInfo && payload.refireParams) {
const {member} = payload.refireParams;
const pendingRequest = pendingVerificationRequestForUser(member);
if (pendingRequest) {

View file

@ -17,6 +17,7 @@ limitations under the License.
import EventEmitter from 'events';
import { MatrixClientPeg } from '../MatrixClientPeg';
import { accessSecretStorage, AccessCancelledError } from '../CrossSigningManager';
import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
export const PHASE_INTRO = 0;
export const PHASE_BUSY = 1;
@ -39,6 +40,7 @@ export class SetupEncryptionStore extends EventEmitter {
this.verificationRequest = null;
this.backupInfo = null;
MatrixClientPeg.get().on("crypto.verification.request", this.onVerificationRequest);
MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged);
}
stop() {
@ -51,6 +53,7 @@ export class SetupEncryptionStore extends EventEmitter {
}
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("crypto.verification.request", this.onVerificationRequest);
MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged);
}
}
@ -102,6 +105,15 @@ export class SetupEncryptionStore extends EventEmitter {
}
}
_onUserTrustStatusChanged = async (userId) => {
if (userId !== MatrixClientPeg.get().getUserId()) return;
const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady();
if (crossSigningReady) {
this.phase = PHASE_DONE;
this.emit("update");
}
}
onVerificationRequest = async (request) => {
if (request.otherUserId !== MatrixClientPeg.get().getUserId()) return;
@ -114,11 +126,20 @@ export class SetupEncryptionStore extends EventEmitter {
this.emit("update");
}
onVerificationRequestChange = () => {
onVerificationRequestChange = async () => {
if (this.verificationRequest.cancelled) {
this.verificationRequest.off("change", this.onVerificationRequestChange);
this.verificationRequest = null;
this.emit("update");
} else if (this.verificationRequest.phase === VERIF_PHASE_DONE) {
this.verificationRequest.off("change", this.onVerificationRequestChange);
this.verificationRequest = null;
// At this point, the verification has finished, we just need to wait for
// cross signing to be ready to use, so wait for the user trust status to
// change (or change to DONE if it's already ready).
const crossSigningReady = await MatrixClientPeg.get().isCrossSigningReady();
this.phase = crossSigningReady ? PHASE_DONE : PHASE_BUSY;
this.emit("update");
}
}

View file

@ -20,8 +20,9 @@ import EventEmitter from 'events';
* Holds the active toasts
*/
export default class ToastStore extends EventEmitter {
static PRIORITY_REALTIME = 1;
static PRIORITY_DEFAULT = 0;
static PRIORITY_REALTIME = 0;
static PRIORITY_DEFAULT = 1;
static PRIORITY_LOW = 2;
static sharedInstance() {
if (!global.mx_ToastStore) global.mx_ToastStore = new ToastStore();
@ -38,17 +39,23 @@ export default class ToastStore extends EventEmitter {
this._toasts = [];
}
/**
* Add or replace a toast
* If a toast with the same toastKey already exists, the given toast will replace it
* Toasts are always added underneath any toasts of the same priority, so existing
* toasts stay at the top unless a higher priority one arrives (better to not change the
* toast unless necessary).
*
* @param {boject} newToast The new toast
*/
addOrReplaceToast(newToast) {
if (newToast.priority === undefined) newToast.priority = ToastStore.PRIORITY_DEFAULT;
const oldIndex = this._toasts.findIndex(t => t.key === newToast.key);
if (oldIndex === -1) {
// we only have two priorities so just push realtime ones onto the front
if (newToast.priority) {
this._toasts.unshift(newToast);
} else {
this._toasts.push(newToast);
}
let newIndex = this._toasts.length;
while (newIndex > 0 && this._toasts[newIndex - 1].priority > newToast.priority) --newIndex;
this._toasts.splice(newIndex, 0, newToast);
} else {
this._toasts[oldIndex] = newToast;
}

View file

@ -242,6 +242,10 @@ export async function setTheme(theme) {
if (a == styleElements[stylesheetName]) return;
a.disabled = true;
});
const bodyStyles = global.getComputedStyle(document.getElementsByTagName("body")[0]);
if (bodyStyles.backgroundColor) {
document.querySelector('meta[name="theme-color"]').content = bodyStyles.backgroundColor;
}
Tinter.setTheme(theme);
resolve();
};

View file

@ -7,7 +7,7 @@ interface Client {
isCrossSigningVerified: () => boolean
wasCrossSigningVerified: () => boolean
};
getStoredDevicesForUser: (userId: string) => Promise<[{ deviceId: string }]>;
getStoredDevicesForUser: (userId: string) => [{ deviceId: string }];
checkDeviceTrust: (userId: string, deviceId: string) => {
isVerified: () => boolean
}
@ -45,7 +45,7 @@ export async function shieldStatusForRoom(client: Client, room: Room): Promise<s
(members.length === 1); // Do alarm for self if we're alone in a room
const targets = includeUser ? [...verified, client.getUserId()] : verified;
for (const userId of targets) {
const devices = await client.getStoredDevicesForUser(userId);
const devices = client.getStoredDevicesForUser(userId);
const anyDeviceNotVerified = devices.some(({deviceId}) => {
return !client.checkDeviceTrust(userId, deviceId).isVerified();
});

View file

@ -1,5 +1,5 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// @flow
// Returns a promise which resolves with a given value after the given number of ms
export const sleep = (ms: number, value: any): Promise => new Promise((resolve => { setTimeout(resolve, ms, value); }));
export function sleep<T>(ms: number, value: T): Promise<T> {
return new Promise((resolve => { setTimeout(resolve, ms, value); }));
}
// Returns a promise which resolves when the input promise resolves with its value
// or when the timeout of ms is reached with the value of given timeoutValue
export async function timeout(promise: Promise, timeoutValue: any, ms: number): Promise {
const timeoutPromise = new Promise((resolve) => {
export async function timeout<T>(promise: Promise<T>, timeoutValue: T, ms: number): Promise<T> {
const timeoutPromise = new Promise<T>((resolve) => {
const timeoutId = setTimeout(resolve, ms, timeoutValue);
promise.then(() => {
clearTimeout(timeoutId);
@ -32,12 +32,18 @@ export async function timeout(promise: Promise, timeoutValue: any, ms: number):
return Promise.race([promise, timeoutPromise]);
}
export interface IDeferred<T> {
resolve: (value: T) => void;
reject: (any) => void;
promise: Promise<T>;
}
// Returns a Deferred
export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise} {
export function defer<T>(): IDeferred<T> {
let resolve;
let reject;
const promise = new Promise((_resolve, _reject) => {
const promise = new Promise<T>((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
@ -46,11 +52,12 @@ export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise}
}
// Promise.allSettled polyfill until browser support is stable in Firefox
export function allSettled(promises: Promise[]): {status: string, value?: any, reason?: any}[] {
export function allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFulfilled<T> | ISettledRejected>> {
if (Promise.allSettled) {
return Promise.allSettled(promises);
return Promise.allSettled<T>(promises);
}
// @ts-ignore - typescript isn't smart enough to see the disjoint here
return Promise.all(promises.map((promise) => {
return promise.then(value => ({
status: "fulfilled",

View file

@ -23,7 +23,6 @@ import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases";
import {findDMForUser} from './createRoom';
import {accessSecretStorage} from './CrossSigningManager';
import SettingsStore from './settings/SettingsStore';
import NewSessionReviewDialog from './components/views/dialogs/NewSessionReviewDialog';
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
async function enable4SIfNeeded() {
@ -44,14 +43,26 @@ function UntrustedDeviceDialog(props) {
const {device, user, onFinished} = props;
const BaseDialog = sdk.getComponent("dialogs.BaseDialog");
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
let askToVerifyText;
let newSessionText;
if (MatrixClientPeg.get().getUserId() === user.userId) {
newSessionText = _t("You signed in to a new session without verifying it:");
askToVerifyText = _t("Verify your other session using one of the options below.");
} else {
newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:",
{name: user.displayName, userId: user.userId});
askToVerifyText = _t("Ask this user to verify their session, or manually verify it below.");
}
return <BaseDialog
onFinished={onFinished}
headerImage={require("../res/img/e2e/warning.svg")}
title={_t("Not Trusted")}>
<div className="mx_Dialog_content" id='mx_Dialog_content'>
<p>{_t("%(name)s (%(userId)s) signed in to a new session without verifying it:", {name: user.displayName, userId: user.userId})}</p>
<p>{newSessionText}</p>
<p>{device.getDisplayName()} ({device.deviceId})</p>
<p>{_t("Ask this user to verify their session, or manually verify it below.")}</p>
<p>{askToVerifyText}</p>
</div>
<div className='mx_Dialog_buttons'>
<AccessibleButton element="button" kind="secondary" onClick={() => onFinished("legacy")}>{_t("Manually Verify by Text")}</AccessibleButton>
@ -70,12 +81,6 @@ export async function verifyDevice(user, device) {
}
}
if (user.userId === cli.getUserId()) {
Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, {
userId: user.userId,
device,
});
} else {
Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, {
user,
device,
@ -105,7 +110,6 @@ export async function verifyDevice(user, device) {
},
});
}
}
export async function legacyVerifyUser(user) {
const cli = MatrixClientPeg.get();

View file

@ -11,7 +11,7 @@ function mkClient(selfTrust) {
checkDeviceTrust: (userId, deviceId) => ({
isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T",
}),
getStoredDevicesForUser: async (userId) => ["DEVICE"],
getStoredDevicesForUser: (userId) => ["DEVICE"],
};
}

View file

@ -5721,8 +5721,8 @@ mathml-tag-names@^2.0.1:
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
version "5.2.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/84637c6ebd442346623bce562b441e1093d40270"
version "6.0.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f120533fadb309ac5dc8b2bcb6882e784ba93f18"
dependencies:
"@babel/runtime" "^7.8.3"
another-json "^0.2.0"