From 09048a169363f2261716a1d5d6f1ac6a39047958 Mon Sep 17 00:00:00 2001 From: Peter Lewis Date: Sat, 20 Feb 2021 08:07:12 +0000 Subject: [PATCH 001/140] Update Vector.strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “and be” > “and be” --- Riot/Assets/en.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 2882eeb7b..f4d0ef697 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -655,7 +655,7 @@ Tap the + to start adding people."; "identity_server_settings_add" = "Add"; "identity_server_settings_change" = "Change"; -"identity_server_settings_disconnect_info" = "Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone."; +"identity_server_settings_disconnect_info" = "Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone."; "identity_server_settings_disconnect" = "Disconnect"; "identity_server_settings_alert_no_terms_title" = "Identity server has no terms of services"; From e10bfcd47bee41bc7209f3d0441d9ab52d500ba7 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Fri, 5 Mar 2021 19:43:14 +0100 Subject: [PATCH 002/140] EmojiStore: Include short name when searching for emojis This adds the "common" short name to the list of strings to match the search text against. Previously, only the "other" short names were included in the comparison. This causes an issue for certain emojis like, for instance, the "Hundred Points Symbol" where the term "100" is *only* included in the common short name. As a result, the emoji did not previously show up when searching for "100". Note that as a side effect, searching for "2" will now also return things such as the "dog2" emoji. This matches the behavior in the Element Android app and also in the emoji-mart Node.js package. Closes: #4063 Signed-off-by: Johannes Marbach --- CHANGES.rst | 2 +- .../EmojiPicker/Data/Store/EmojiStore.swift | 4 ++ RiotTests/EmojiStoreTests.swift | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 RiotTests/EmojiStoreTests.swift diff --git a/CHANGES.rst b/CHANGES.rst index 0f97eeeaa..ad86a43d7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,7 +8,7 @@ Changes to be released in next version * 🐛 Bugfix - * + * Emoji store: Include short name when searching emojis (#4063). ⚠️ API Changes * diff --git a/Riot/Modules/Room/EmojiPicker/Data/Store/EmojiStore.swift b/Riot/Modules/Room/EmojiPicker/Data/Store/EmojiStore.swift index be52d9c1d..26377417f 100644 --- a/Riot/Modules/Room/EmojiPicker/Data/Store/EmojiStore.swift +++ b/Riot/Modules/Room/EmojiPicker/Data/Store/EmojiStore.swift @@ -43,6 +43,10 @@ final class EmojiStore { // Do not use `String.localizedCaseInsensitiveContains` here as EmojiItem data is not localized for the moment + if emojiItem.shortName.vc_caseInsensitiveContains(searchText) { + return true + } + if emojiItem.name.vc_caseInsensitiveContains(searchText) { return true } diff --git a/RiotTests/EmojiStoreTests.swift b/RiotTests/EmojiStoreTests.swift new file mode 100644 index 000000000..56742ac98 --- /dev/null +++ b/RiotTests/EmojiStoreTests.swift @@ -0,0 +1,72 @@ +/* + Copyright 2021 New Vector Ltd + + 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 XCTest + +@testable import Riot + +class EmojiStoreTests: XCTestCase { + + private lazy var store = loadStore() + + // MARK: - Tests + + func testFinds💯WhenSearchingForHundred() { + find("hundred", expect: "💯") + } + + func testFinds💯WhenSearchingFor100() { + find("100", expect: "💯") + } + + func testFinds2️⃣WhenSearchingForTwo() { + find("two", expect: "2️⃣") + } + + func testFinds2️⃣WhenSearchingFor2() { + find("2", expect: "2️⃣") + } + + // MARK: - Helpers + + private func loadStore() -> EmojiStore { + let store = EmojiStore() + let emojiService = EmojiMartService() + let expectation = self.expectation(description: "The wai-ai-ting is the hardest part") + + emojiService.getEmojiCategories { response in + switch response { + case .success(let categories): + store.set(categories) + expectation.fulfill() + case .failure(let error): + XCTFail("Failed to load emojis: \(error)") + } + } + + waitForExpectations(timeout: 2) { error in + XCTAssertNil(error) + } + + return store + } + + private func find(_ searchText: String, expect emoji: String) { + let emojis = store.findEmojiItemsSortedByCategory(with: searchText).flatMap { $0.emojis.map { $0.value } } + XCTAssert(emojis.contains(emoji), "Search text \"\(searchText)\" should find \"\(emoji)\" but only found \(emojis)") + } + +} From 293520cb5df4c20043db1a0793de3c657f9a5ae4 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 15 Mar 2021 14:27:59 +0100 Subject: [PATCH 003/140] Composer Update - Typing and sending a message --- CHANGES.rst | 1 + Riot/Assets/Base.lproj/Main.storyboard | 24 +- .../Images.xcassets/Room/Input/Contents.json | 6 +- .../Contents.json | 23 + .../input_text_background.png | Bin 0 -> 1822 bytes .../input_text_background@2x.png | Bin 0 -> 2975 bytes .../input_text_background@3x.png | Bin 0 -> 2676 bytes .../Input/send_icon.imageset/Contents.json | 23 + .../Input/send_icon.imageset/send_icon.png | Bin 0 -> 960 bytes .../Input/send_icon.imageset/send_icon@2x.png | Bin 0 -> 1745 bytes .../Input/send_icon.imageset/send_icon@3x.png | Bin 0 -> 2561 bytes .../Input/upload_icon.imageset/Contents.json | 3 - .../upload_icon.imageset/upload_icon.png | Bin 332 -> 809 bytes .../upload_icon.imageset/upload_icon@2x.png | Bin 615 -> 1529 bytes .../upload_icon.imageset/upload_icon@3x.png | Bin 918 -> 2180 bytes .../Input/video_call.imageset/Contents.json | 23 + .../Input/video_call.imageset/video_call.png | Bin 0 -> 356 bytes .../video_call.imageset/video_call@2x.png | Bin 0 -> 512 bytes .../video_call.imageset/video_call@3x.png | Bin 0 -> 756 bytes Riot/Assets/en.lproj/Vector.strings | 3 + Riot/Generated/Images.swift | 3 + Riot/Generated/Strings.swift | 12 + .../Room/RoomInfo/RoomInfoCoordinator.swift | 45 +- .../RoomInfoCoordinatorBridgePresenter.swift | 10 + .../RoomInfoList/RoomInfoListViewAction.swift | 10 +- .../RoomInfoListViewController.swift | 14 +- Riot/Modules/Room/RoomViewController.h | 1 + Riot/Modules/Room/RoomViewController.m | 1651 ++++++++--------- Riot/Modules/Room/RoomViewController.xib | 32 +- .../Views/Activities/RoomActivitiesView.m | 3 + .../Views/Activities/RoomActivitiesView.xib | 2 +- .../InputToolbar/KeyboardGrowingTextView.m | 6 + .../Views/InputToolbar/RoomInputToolbarView.h | 19 +- .../Views/InputToolbar/RoomInputToolbarView.m | 159 +- .../InputToolbar/RoomInputToolbarView.xib | 120 +- Riot/Modules/Room/Views/Title/RoomTitleView.h | 11 +- Riot/Modules/Room/Views/Title/RoomTitleView.m | 36 +- .../Room/Views/Title/RoomTitleView.xib | 71 +- Riot/SupportingFiles/Riot-Bridging-Header.h | 2 + 39 files changed, 1103 insertions(+), 1210 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/send_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/send_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/send_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@3x.png diff --git a/CHANGES.rst b/CHANGES.rst index df35967f7..6f78f7429 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Changes to be released in next version ✨ Features * Improve the status of send messages (sending, sent, received, failed) (#4014) * Retrying & deleting failed messages (#4013) + * Composer Update - Typing and sending a message (#4085) 🙌 Improvements * diff --git a/Riot/Assets/Base.lproj/Main.storyboard b/Riot/Assets/Base.lproj/Main.storyboard index b4e354b0f..ff80d131e 100644 --- a/Riot/Assets/Base.lproj/Main.storyboard +++ b/Riot/Assets/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -34,14 +34,6 @@ - - - - - - - - @@ -96,7 +88,7 @@ - + @@ -320,7 +312,7 @@ - + @@ -589,11 +581,10 @@ - - + + - @@ -602,5 +593,8 @@ + + + diff --git a/Riot/Assets/Images.xcassets/Room/Input/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/Contents.json index da4a164c9..73c00596a 100644 --- a/Riot/Assets/Images.xcassets/Room/Input/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Input/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json new file mode 100644 index 000000000..30afe661d --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "input_text_background.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "input_text_background@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "input_text_background@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background.png b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background.png new file mode 100644 index 0000000000000000000000000000000000000000..45de94894ecb3e1e61dd69d643f538b35d2085fd GIT binary patch literal 1822 zcmeAS@N?(olHy`uVBq!ia0vp^azHG?!3HE}t?oSnq*&4&eH|GXHuiJ>Nn{1`6_P!I zd>I(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N#&bHNrE^*Ox&H$mU>R zV`O7s2C^6#n1F;3l+6faOEG{<2C^8!7^UItI7SVG`u0o)7O0vuAPoW@Kn&6Yp_vvi z!BxmDV1~0rKuU!#=4}H~oCO|{#S9GG!XV7ZFl&wk0|V2e%#etZ2wxwoh+i#(Mch>H3D2mX`VkM*2oZ zx=P7{9O-#x!EwNQn0$BtH5OxaJiqxD4m(1MMJg_e<4Q%wWN}y|W&d|cfNHeS2c-g}Q~^nHU{PS2v*WVSho@gVF1^~SS_TGYF;5rA z5D(t1VQ0NV0!8ef-?28fTCrH!cUc;%aqUin&M+s9t8U_Nm)I+<_{V(Lwcg3aNu-J8 zs*_d>N1)y+*KQ_Pp~OED`(^E)pRN5q@7(20N~Wb>4m`eBe&6zW`M&qg0{k5w{#ayR-^uO>W`{fm4~VwS3(57po&Y zT9cWMz4^rFD5@N(+O}pDhcEk_dF>%Ge6B~&Xrh&u@kI>sPNnomLn;cZSv0 zAFPsTn~x{2{o3&}{(0*<+cT?D%XBAhuiMO=SC;d8(XG9A8RSmulyN&O+P3OX6oZM4 zjf|(-1Epy_vpMFb%RPKebT>UNlcE6?W6|M9)n=b8|GDR)+iTi2p&>i8G zTq}h>+BkZ>G~#mn8^_B1RJq;zjfL(})(0s}tl8=5=^JD;Un-fOJ<}|GVA9v#uvaf$ z+z9p;OPaYqiC1vlq~bT0_fLx~%CX-h(mN@2`IfI|tF^e)zbnUZtT){`LnOTA6A%B* z=dXpnuiY8j@#t;}t23jPr*@l0l<4c!*Ivhsz1QyMls&fnOUXAA!+6!>lB=9zo(kOG zo*>`jcP7q)r{Qf$iqUD#opbVyl4ALO{&WlNuUT8sd>}Teb+>wY*zIk?HZNwjg!`Y< zjo)(QyUcFwYctlhZtOa^|C5#3BG}A7sOa4Bv>;?1h(9m z!?G-jah6l7cFvq>UnLgpTO+F4_+aw$r*iYH0xdO;e$98Roj0T7nu}NT+^4&vR;tZh znUK0=cfuay^*QW1>5a?}7i2uS?tZK(hVjh4k7rl>S+vLCfvxpqj~d|vYiGY__iRh> UIpfeU2UO~Ny85}Sb4q9e0L_4p!2kdN literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background@2x.png b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/input_text_background@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9994131230d6c9517e4b8b71b59a8d840d6707af GIT binary patch literal 2975 zcmZ`*c{r5o8~!XIJK0kGh$CB!rK60YER`8%(ws>{#KbVeY-Yw%)-0iHNyajgBE_*4 zWy_LKky6&NHQ|(ykfbcX89LSJI_JBt_j~T|dGGtV-{-xaKfYKy#9=XEMPUE{#Guwz zNKS-smWGf3=Y6dveT@_NJ3iv)l#oK)Cb0PxiV zfOoC{08Rq{c?z@oD7R1~77g`)!vQT076Jr#1OPq`;sJO$FX?ZXhl3RXZe^Rle_7gG-IiP8a2b%@k_~8UToF;VvE^ zgQ)-jysz;nG#w4M1-p@nx)^uzDXeY)k-}90kN_|T60vlQasZJ)qJaZURn{3`4(6so zD$45=y0@tc8g8d-Nv2|zjdb;N^;FD+m6eqtRCfXM#WR;crr`OOQ zQQ;bWe>ToZ$9w#6BGJCJ#c2@4-2v(A>Vf`Eh7G{~hm5wo^EFFP4Y|nSCt)(Oeb@$oQijYlIU0}$C8fW z7WrP_zZt*QIzq)`Iaj={{`A+p_PUM34;!O@*!;BdO$Y&Tr{Jfl*ciF>ENAA-gdw2s^J^xo8+;}h z00bFOD{~ZX(~#o;+3E1s?1AFm$(j=*FVY@H6^QxTr0^o~g@Y&_WVd~Rm0BeKGS2}? ziE$oHdzaIE$7H3Yc{OEV^T?c=Iynh9VaZR3&=<+!Sw@r2Gu^|clS37YOhfq)T94=b zva-wq(4^_(+4l6w#Z2<2%o&4}sSoY#?WHgCk8FY6x(g?HWN9LvVotrir@8ZGOVU>% zHA^Nf9KxE`lRU49joc*WsMx>z%T^e~OQ@9*oSFC{8MniBXt%eA#)4+fCQ+XVeZOYA z`Tyy^i>UUyBzX8xs`(wl-JxWBj_aKkg{Dque{wT({-9U8Camv{o7;-2bl&)!;%web zgsUxKHk=??|I%`+XV)skO{tlSjLoOic~+^lQGnGUgByf3MDbvd>X{+Bg{;{Dj1 zwC!P6(`Uab*ERdPTG3p2x|Q?FgNCpOqk)?&fqncJ_GCO^WD90w+s27KyuD-qWbD=O ze3PCtQ@peacj!cf)|Whb$iFkaD3=)G?L1+mFU5DthWw#x2psRbRn?vGM!Mf7_U-0L zf|rxSeB~U+*9# z@+v5o&EG`G6-r3DtauR0*Vx;`u633iV9ltv29`wa7*NZ~-s^nL6AROu#r>v&&}&gj zMzXS>JLFBc)L#6&pb48Ccw51&hjx(5)fym@i$88?lE=^+GWIFpDRHq*F)dn|S zIOH{-%@+H5&MkD9P9o_hKQi_Qjcf0R$rmu@n-@?w%0ETt4YE|zw9mAC)(~n4sYO-F zyUzbUlGbcH(d}-~Pu#}(62F+b!>3J|ICpV3Bl=R++@e97H~Fvg-nR(&m3y(5pR8Q1 zH~(s@3~6u(!TU6RRI?fw4QU}~+gl~Yd3L%#?yM~`IddRt{+V!O( zQlh}vS!L*7OqcMozLt(=i=5}4+B(O{fvHB`X%uFTZOB4&)n(S#^l_HSh5qjR-8~1a z)n0U1CN1o58$UjMWG-J-RaLgFzeu|HsopfK<7{JNvitD1Cy(l1>unzmhb%$sjHD?H zeVW%uAJE*t_0MH;f9LD*bfwgJx=Xf~DBYF?Op>1hb0UN_(yV zUu6-w@&hr$&)~3zJy7|pduxkiw|ZJ^$CkzHs}3bllw{(1)mx)W`h)8j_vU(zCEvdN z`pf$oSfSP^Jp-SY&{HIhZ{JTC6_Gcp$SKNNe7)G!g&M;7@o7y#45xs~#|iro@wnoV zyI~1CR84SGfl{Oh52mHs6f5!f&L+v1V<&H=BpySv!ph<7;TpSbDXlR#&5=#j*X}>B zISA5cm6)u~ofN#gW#vl#Z|$w%1BcTpjL#18+e@4&zyH2+OM&wf_+Yf=V~Ga-=FOtB zaU(wMZ)SZ4@<%@z>iL!_5Illk80-Z^?@~SJu8Dps(I?WCaE?WrveFhI5;u@d(|0y2 zsL2u3NqD&cgs5oLxeJeOMC!9yGH;HxVmz2NNvJ}(6PKC}X>~9M6 z^i_(2_n@H6M^3v;WGRV)hf5cjqeAD#t*AY21XMYjcj7?T`HMVos3>}ez?f2Fcvvx3 z+)ud&knW225&HAw)Y!p7$CKeQsuXfi#UDI|suJv}sx4-PlXj(jBN)k^vRg`;au@ir z1kPZwc_T@W80@&|#=xk@l~-shU%KDF?_(F-Xa$Q=o?@d%XNv_ff}XjZGi5c==d@VQ z8Lm)@)`Y}ubS#30SS50LIR&-KD7T-XwMd`M?4is&D^}kh({f7vSmP2RA1JPzaxXUt zd4O{~XY;8$*#DCnZ!@2Mciho;r-e#29d{p#le|6h$i!;V6}16I+W+-d|eA< zZ)Qd+J&X2%y{fDA@VD^6`jfUMf%abcFE3k~jXyiOGeK2uZP)d8c{T49#huZawYK@a z61nr;y%%IP8Pvk#A41&j_>sp9gqS+ATAp*w)e(|y`=yQsEjJZ)Hpyx15i-_2?xJlU zl+}J28B3Tzsjx*W%JFRkqs(dZps93J4zUvedj}%S!?H**KvRWfw9TC}yu)cMe-C?Yr z9+FdVzilxw!T!X=puoOAnVE*OWx?Y!(umOE-ht5P^G?ep>UN=0f}c-(pzAhQ*UXig z^BVF$*lCfbkm@*uX>CwTSUcx7cXeuJAiFoBz2pnC0(PFJN2#r(1q!gA$ zb|{VnVlnKdBYq{Xa-#0oEKKe>OEEL!x?r_9)zG}KN!_>_5CAv4h zUO?R5<9ddg?Sj(oWh}94U2LMDC0LVsUSGyv)iBO!UU9h7gpvjFl0RkW)fS((I06y+b>RSxr#u`8HBs?In z&H(@v_XGfb7U&0)#rHky&Eo$a^Spr3h1385;CqdC_oR9{?n4BT2)Y4SQXo#3Mu^}M z03;2;4GB1E0F*`uCsGhJGv###f*bQ-m@;&oLOpDz?CIzNwIY#mP-9&^T|H$K7z%|V z$=F~725s|A&V4dd4y95f5HMI&RFrO%p)QFW0@H`X;V?Y|n1O)~m!U&BMx+MNbchs{ zjUs>7LE|VvWPAh_Pa;BjbprxPkyJBfWuDRZYokvpKKO?dk@9UU?tm~}2Bxp82m3b} zj)wma885RTTc2yg4#_Kqup$v6$T$jx+ZIY6xo+?e>_>YWd<>343XkMX;X%YxQ3l^6 zzreq$oXL0`_qFh3-(7yje&xG_lBgu^CnDp6?1)qxncLzw_1}j7&G@MnZ*GJOo`wte zMB@oK;`)?uJtXX36Tb?rNZ};1TSPz*j@R?LZm%H25>7zz8nzbJ6i)n4vW3th8ATe{Ogv)M7^Eqf)CLV|bd-O{vOyYNabJVmii zS=bg!j!$m`DUyL=nB=e`6sK$Picf$Hq)S+M9RwVV>y0y#u?3s%XcHy}8acE_e#6n8 zlI?~bJxiUrk5=<5CQA(O_35AL>xSpA2j0y~)3Ij2>r2i4TGH8^uWJlpi|WF3ng^A~#XcWKeP)0ooz4{sFA%-prPkxp8Q34oNM6kIumyXFW28)TxY)*eo9pJJbfNDs$7QiS@|2ZSkTxbpu-N1L-pHmmBENb2 z-XrwN7AnTU2R47mIIz=Ai)lLhL^PlqpE}l}xb5>*9SPZ%Ut~6}Thocy&0wHKt|M(oxF{b-dn5!9mG9&Y*blrs^ql zyYgyf6rae)`dVxo3zsdG5iy9n5H|t=73E$~?qxkj;y*dK8=nlts)(Teyke0;wbl$u zAhuQRFv+VOU6s9+o))9R8gEXO(c%mL=;Xef=wiDB85VNw^?zxt5Nh{vVPVTWD=jBK z6umf^z+r7qsRt`9`7a}8mCCI2J?l>@X&=fPJ$Y0^NQ>5W@=Zz!OZ2U!sm#f(NOt}E z$RV@Pq`=|?VKdKKr^mvxE@J!jvNDJ*&Mmn|;G83K0{#8vl!YN7(|kqtg$tJ|QZ$e2 ze^rNHy3sng?0)R^xS7bNQhH3`R;{;9N}Fbw#<@jIy<1E+-q=TwJEAG5aH&DX%0o)r ze@$`Pl%p;G+p2Ku(vcGa*a@*Rmvj+Lrb1l@+_xgETQ5)$TW{VoB|$FR{W-^0G~nE_ z#}-SSVf69xNT<(=TjyQV1eUf{PZTr+%}<>ePCF0FUihwO;AuUahsyb1l0y5mMP|Ux|8>=YV}2hK@q56TcKVF_Zm3a*%U1X`A~B^JSFp~ z8fUA0V@m~SWzhLE_EOhN2qkCR;SLCbQLlhFTkD)TB3vDhf)MFdp7qL&9HOd?s?@+h z1+09Q*`$%qq`Jx1(ay!O;FMUS6FG7F3jIq?Z-1o35mp|V?<hjlf%AC{K( z4$@o+*WYS185q*PN6~m(-f?EL`RtR;fA|6;hLgJftsUTw*U$cdmKHzI4{vX(ACeiP zvX3Q*NT;Vw4V8^cC8#Z7}V;k9&7LnO4*XTEUc?zy<5s?VB(rj z%{Ft6L~;Sx?`m<`YWWA6T#T9+Bj+;q#q^c^DYW2HRoU}$Rbe|7dYthn`2No1?et80 zIVS9thsh#2`%F7BMCv_CZtNy~ls^ZI;;g#ZuU9l0XtE=;T z(gz_nJxNu`ZzYb#?Fk=ccWV1jcJITyOoy1(J>MQ#;iEDoUsjhI&$#JZ(evJ(Q~Y#3 z)A;g)MrI618yYR71KxeK%e=;b0=8FoTRT?MmUmfj>^xLXM9+I}T1r9J_JSPfGk^zw`U@-Fx@$9zs&=nuem`5+dfvr92|& zd{=KgwF$sNK#PDXu0wmUY+8^27`LOkZ>|Aik(+r)047*v(wp^LrJXqadlT9<^Qwy5 z+|z*mVDUT5Uc@khh_0wg36btWia^3mr|y>7m3GJH(3y;(X}HUB=U_0f>JAk;%`fak zhFx@+f{RW?3fsu&OyI$nyJ~)73iOeTcRiR}O`DjZzAYD< zgm@d+=wp(`)A_p|i>rkA`dVOlYfAYtMxIjhus&J}c zKmtUm6vn9(Bg(6|Qh3bG48(+}^zPedn7J?k`e?>eEDA{#L-kFWpbtoV(nrpDS7S_v z)vH<1weJ7#ZgmfKc*S;u0)0Z}Dhct{rT_AizSHO&&o*a$3%9pTUqJV}`5QmaW5az?8`aLxQ+U#th$U-OIQ> z;yP)Wi0kknkZG^U{wL&HP)zS%8T6+DSG50000ar4IR4H|Z|AYu$_)w+52ZRa&-K5%+0{3NA?ZJ)mHuMn$+mI+E$TWS> z6un|G3Xq;{`sS;(Beg?<`Ct({0yT?L0=ooaU7KG63z!v13nOL`)NL?hDRJ->;Hs?3 zHIr6lMxbnkX(bS9Vr~HpkY1qma>;RU1zLh^4)Ey*yIGw`7u1sr#8%^oc|>hBxdjz2 zS8H;C+^zx%NG8yF*(0mj%AwUn;n%8aJV|U45EphS7at9fIE=^N+1V&h#r(f`0*TEp zX6b{rAp1a^gaTEg>tbU*R!HbsAhEePk06&}z(EvCd@em7-^)R4Il~}M7^UPLd3~Yl zIdv6C`z@I!3?WnojCU&oIt#?viUaas#++WLPb2>qsM6&yWqh9;0XaIipXXcGc?Bf{oT)?_~NCe_jdj{fW<#|=+TE9!&&We zcwpOPLDbWkHW8Rx#bL%SjB2aOxkVLPt*A*LRB8qc(8)^jE))u!4aXwq_{m0jhAQS6 zFu=i+3QWIprQp#sgrsCG zRKv}*i#eMM3M|1VY2pMka6MfUIox9w!c6vRM=u$z7c$6t=ahsW1o>L}Z{LBWu_%gu zx*lm$5}?on%cO}#QS?P9(ne6_SOm+MwxTdLh2kYS0{hf4ytTUlzQwp0iC2N>_Z44$ay$(sK938^T559t=#Gjk*BNcK>ZiZ%w3mFnv z$p~B_*J5ko_)&b}qJCaDW5&hOxEJF>u$t6^KEc^$^5PqCo!o{6u?3eE!O-LYQsDQ^ zg1C|YCWUE0b7d8m24n|lIaF)6N|A{= zVMCY(q|F{%kZ*fEIj3sV*c9d%(#DkzZaWgJ!PaAPjMNul>IlSL7oJiUbAjt|D=Ed4 z_4HGi20T|U>a&QuU;z`>!@|7(>l)p@?W;HxfwuWxr+KC1ed@uMz%Xg7Cku;d0&$fe zv_P_ktBwmsS9Bz`p3H@*qjwTPD1FhOl~yBBjTP~FXVDO&1m)=TWkr7)m}7rqSbJ$qI|Q#MmleFFyQWIfqsrQV=fjJ4+1 zA*2LeSe?3Y+^#{NcVQT|o@y0V!|yeZ!VFmvH|V+d%nX7s4Yc*NteHMJ2-Ew(@DZMl zCBVm!_3X=u`Bz)tKRJ%)B_F76!YPBS=T`go+rVQG>V+5y*nvGhdjmS7YtgwzZUByMm65B-n&N6QH;V^NL*o1^tLnW@`&m2p5-FmS`Q3owM4_U%(`6rP z*JdmGrb2lKh75u7ZtZ&cr*6kN&;#nborlgRB`OK91cQ$vuUM>3EPUC^!Lgdr;^+C> zsKg*|bWvW(T)Q$)jA)>y%Iy>3ky)Sy)`J+wyu(cY~@2t zlFf+G2T=)dbpVPZ2$On3j9pFvF6GUd*lKwAkln>iT5vbZWvOsFYoY3~ z<{nkY%SkV262|lemOR&mnGA$dywJd;Fb%BDIoG#W@fL>?*rC3%N^O&i-={dUW>T02 zb|>W-z0H$EN-vhG-&H8^?%EV3jD3MxpjcIsfW_c4fml?a3Ut;5MD#+3DZ=L`G}E$+ nQXWWwz9Zz$(NpwoixTF4dma5Cs>q1500000NkvXXu0mjft#&wQ literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/send_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Input/send_icon.imageset/send_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..4e3719595a010183f8d343d3165f2456fb2fee02 GIT binary patch literal 2561 zcmV+c3jXzpP)6+tb5^tvdM`{ z6^Ba&5(;+cvC8IDMM8>w1R*j8A(aE_h67m2&OCmNOY(U%hXfY3+aNA#p090mdG z)1P_p19u-v1cJ@nb@}A4HUzvS1+MUOI4MXT^e~VIg8+K`oJ8z{rPwDJi6k1hNx#@z z^r{WT(4#Z6<3E)TNIVZL!Vbag5GjdJyf?S*fCUsQm=a1{MUWqWo>G@59<_fx|7p-E z(sjiMM!~^xz@-zg31tLvrzqjf3Pz41p}M6NYMcUuGb32JO5d#XC15w$xZVK+=ojp+ z+jbnhP5)90s*Oh<$oB^uZVxn~PcU|sBeoEgs}=^7*d1KFehoCCM=%vC@csh0DhbaY z$aNiUn}D2g{`ldh)4)dyEEdz^b0GG%a<4AA3MTGtZ-ESUpnAb#9%yV++)(EvNAf9& z++Hn-8z|*vs5wa(|F7jSMwwkO606a``!XDutx15+&wdcLYnepLCRi=jOynWj{DReD z%|%wx<`b+ID-&5nn=2)9z^KKVA9Bg6L+23YU}nKMrq*dN2k0Em6ZvN$E{SSvuog=PO)|p$;ew;7q!LW* zZQoe%u|eIm8Z@(!=D_JCk>|4-%3U>@q4~7+Y4d4Q9i}E9Ym7iM*SDvY##04Tv9m6P zCTR%)r%uTvmqbIUu-P~RSHAfwTzUCbXfBz*;Xc@3FI-Wb=)9;>IEjak zV~0`LXhT8d<+3a7Hw=oz&LZ zCTxCVMg9GU|9e7T)@~FqiI)6P`zHLhccdIvWI2qZ%VlxO>bOQDT&1Q2lhO{sbhKqj zlufuGP&+Jyf?>F6i4~Y|S)8&67ikoQjy70=NteYbfpDrMB7EYmI)R#~v<4mhvRSdQ zAIDQJj`Mc=HOh@|gGK00jA^hjRSJXyL4m`{HS(t0vLtLOm84b6!Jo7*BcgSpvCEG9 z0le|GZ-EWi;5Zb*bHuyrSNZn=3whZ8CoDgA4pz@ipP4pAp~6Xd=s54J^CX!)XJm{$ zn&dqEZy#1jv}mD@4HO}qL_9)guk*MpYY%x12)8MGl2*>0ht_lUEcG{(Dm`@Wb-sX- zUgW^BpM_%~Sv-EuE=;qyM;9y_e`%u6f=Q?#ELwBv%g16aQwihOCX(KT&wiuLX$`0- z2mkq8J#wjv!;4n=OD8MOpVuZ>?pqhx4iA0lMrSyxti!kjuF@x6wR2n^zeJB;Ij_>D zZtnc!0Cd5EaUQKi=vY2`E_{Brxc?3Z4vi7N-+*uv{!$3Wkv@v{MGG?yw^?DVKLm~R z8;HCGs@?FVNZd&+GOj0KNGOG5!6ZnJMyagbB;})(izJqPzn)2-_B4S5gMMh@uSzq03$67HSCMPW1Fxu)xP1 zDvNV%9Gn#$ZC53P8lrBVI^@|XVt5U04+aNNP1#14w3&w6oJUX#LWsy43H^C5D+*Q5OcM?SG zjsNUK?<)wP>j=p8o>xhl0QuAD$4r6m1wuA8)|p;Z z=p1*a-FJmawS<%=INiE5>SI_6ucbLQ-I`x2je#$D0x*C@zn}K_^oz8^ zzFDeIK}~ub47StWolhMPGax_i?K|(ZsViW|3ahdcM)=MzXM4{aID76+(Ob@z9vSTT z7dta2@VTyA;ZYD7E`j(UgmO`g7*n-;C-xbz&#TzmI@h0Z*3n@i#8Kk z#bUAv#?+#vA`h{c?AKm$A8kN=G((e~r9{e|Jj7zMJ1j=yp6g1eNB3h$itgLf26Sg( zrheEof{%MWe0S{$0=`Bs?b$1@0C)t$k-^Uf7du_Zkz5^i%w4x79BS7V^p?UrHaIMS z9^{N3!G=(Y>{5v={4yqka0$FggXNt(+N()u6^tR#+JVH|Rd*Y^is!S^Op#K+ zK*DY-<-S%)a9c$}-6B_Yb-5~zF~JmkQ#rmVYBk0oC9iJsp9ViSAykA}!6M2nTqM-C zj!-d;Vg!pA3P)#P&GI%*^71p2r7wwM1&a~h;Z`}W4R$cx+NO9~FEDjAUvv??>EyMd~wIM&`@LQkyPW#CFU##W(puM=Vq8(vl#Xbmp7n$|jC=8#s2;F}&+42_rmylz#AcMCmR0*gGm9IAr1f X{+Ezuej0eF00000NkvXXu0mjfRp+Kt literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/Contents.json index b3ad81cfb..776550e12 100644 --- a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/Contents.json @@ -19,8 +19,5 @@ "info" : { "author" : "xcode", "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" } } diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon.png index 8364d79ce1cc1ae77194e534230882d3583ec8ca..3ff1aefaeb19ece92ffc993cb49f086ae865e6f7 100644 GIT binary patch delta 771 zcmV+e1N{8V0;vWeiBL{Q4GJ0x0000DNk~Le0000a0000a2nGNE0O0_bn2{kge*(Tq zL_t(|0nM0AZxTTm$De145D`K(p%y~JO*naQZys!WSMT*M`Vl;7_2fan0DJ(hP1^K| zXuOr0^hCK~4K$EgEQoeHJL5bc*ft>h!Y=$S4D5vcXP);#ut>SujE95%RnA2U5j4gy zBn5=&88T=K0dPcGluHnV@C zplY+Fp&>UBFa{1l#F`Zjrzy;{EI=}Vjqx=g;i_x=AO=MRTyZD972y^|stt_o5olYtqrAn?^--4oP19S5c=eEzbuwOd>Pn~*<|hM^z? z=EziqPkSr-2bCpoz~3qWjKbWld}9%f>Lk;Fufd!U4)|A@B8x_E)YaONGfs&LwX;522@pHVcD751b~n|CL_)UHLQex1e|h>GHu+!cC)=v= zo=MhLy;v==9C=LZVPcdLH(^E?+{g{qLqW;-Vu^-0@EFxC=97tk)9j_v(PcbKvp9GJ znX3DPXD|PDh2EgZ)okXnKarTu*@QunpfqsZ=g+94tbulSr3pIrzRv58A86M;Q9YPlk{gdwqavJDXFBlb1{;pB4_|Py>9R| zWll{iBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_>mzre*oc0 zL_t(|0lij<4TCTYJeYtHyh%rBHz6CqCUk{P5OsrY02?qu8mo>JwE_%{Iq8BF+2O8NvN^)dG^}O614VB9hV#Ic;Gm|6?V8(_#8;1bg1MTl=f3HUOG@MXi2BW2^e8_ zi)OB1f*oEQ;0ZfCc;Opl)gnp`euo1oZHK%Rb~1hJ7_MM|#lh1T5bv=82g8w>K+w+! orpF(D7p(~7RgJROW8GqYZQ>`zMku^UJG z_j~i+%)U1ShRDW7&b#3E1PSnne_CfDN=cA$ejbkzAi?HyIq-~lw?F_2obyd(hNkPl zHov;t#6KsPr;?D1wBE(CFEziBEU(@3!e{>aGG#F?%8#FY5aBv3u?>>wZ5q+@M1S+YOH^Ie#?q>Axm+M|; zbT`w-AlJQ2h-el@H>2C>yep0c7|r~CPms>ck}$YfQdN0`s*Hue#S)dX5EWB>*Mi!h zP!go*Yv5vu%K3Q_#kea_2Z&hz`5PpHv+^H*`F(lV^QqTfe+}i|d*`jK`FW2D66yQa zb2sik{MYBiWb^S>+IRQf13yScxV2#w4*>7#e!`YE3kl_DwNt< zh&|3Igr+I4e-Ot9!%?NK2n#BDDj7mypbF4Q2WyAuN+3|+3>>)!HR5QVb+{(2kUQXF zfYn(7A2oprP)&e~fwHO|TM)V#G)&4xEt)n_djF`9@CEb05Q`A(l5c`ktO@=+?*DbskP7~M)U_4mghnZ!sHFXpQs4!R@Ee~C9YL6=hiu8x{Dq1E8@pN49YP2}mRjAGz zkC@2*S;$utGKJBxeUmq|Dr}aKAeJUb!%{Zw6r~y41u}!J4>Od6u}E9EVfe5NnR`t| zFI@a^n?Mm}33AzF3+DtOiBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj#Pe*yeS zL_t(|0o9p-ae_b)MW3m_RFF*tv4oUh2UL9oW z-kbRY=*-<;cA15{0X7T^jSGzmy}9Gi$+LCZ6j~Qrx$E9gbF)IrLU~JRAd^Buhj`-| z?Tug4oDKpBVZ5pt0T9Y`=N&1&aKAHIDf}FVmV39dA$ye$4;u| z#dw08ODxAeX5qyR{z+V@`LEL-LcHfxu^xY^gAORmC&iutmjPJwswMPEf4qz}fD!RB z(f~e)7tsKOcsbnsrceKZ8=de$gyzjOYZHJFj>aAPh34!DN2|;>efOUeCJRG1cB2ev zvq=LP>Y|ZtwS@kNmqP$M;$;(i2G&}q`tW4f)5SCJ?oXE3zwTDC9{=!x@B6@t`1n4( z@MRQJ21Ez-8PM+fgDt0Be^sz$!Ij+|>nzNj@m3v{JMR89661+ND4~WfH!_+kL5K;Ndl5?Yb~Igy(8XzKdf=fxD*I2Rh3EEaMHa4#C@6B+1a@r z0+O-179aEXdS)olQJt|d4<-FNe}gdq7NGn!(;-lLJ)w}&b#}mCr3moXjBQauVtK}* zJzh_2A~X;Mi69^_tE=&V|9sCB$+K&OkSTuirz!=phzR2XYW#Sd%txlDLn#mx;RHjG z0_T0Ry2h^Yw=>`l5gqiE%&``ko(#o6AcPQ15RqzOh&MShybJ>1s$eM8e@DTdIqvG_ zY;tv$!Ci7p)Ag5`Y(DI!)wv>AJbpNu)${W_0Js4X!aw(lTf#XinBn?{eD`G)suDMZ zb3`ziTwk-`RDl63T^tF9!2xU+Y%QLcAsSmCKt`d1F~&H`zMTvOBVZ%835HhHH{_is zjLbn7!3bNrbYW-_Y{C}7e=w-XXxVV5TU9O4+76Dg_v{$kEEjBTd-sNi()*n@Ry7Nb zZTufLJU%kG1QuecVDGjQ^ZYOmic-Q>1|*gU)@k9o)fnM_GQVg=j(4Qu8e9m|xr2ZR(%jv|yNSVvH%VEXL!d z_pz|Z?DeJv!`xuErarygH^6(0_qx$_e+>o0#Ya#$f=4G08@a~1f??RHT%mKIYs6BDde_tx45LD=zk0ncwRiCQ zs)zY!vh`?PM_NvZI`U@uZ#U`t`Ppw*{@qRb@%=!5U-r)Jf7w^(hX=DDA%}_F^~#L? z84Huyx|VbYpfPAmI;O> zYHHpk4j3^8g1*_(bF};oodtzZ=wLiESEMKy1{)yW!*mL+NvT^b3YON6r5(FEol>_* zKfF-xP*h6Yf1)ASYTPh6yiM>df<`^&3QD_HE{}eF*Zf>5;cCw0`6c(`Rb-h z_DTY7H%RddD5StkNk7HG3=~p;8+lUP$rBV(z_?aqf8%}Pxm)FISc8E}__C}DkB^2@ zw{Bd2>sE~j?)^dCtUdhcmz7UtTEfTAik}%=0*9}b9+|a*=$m)_SR@0IfuDIj_TCRJ z;hJE5=Xy1el%w>K7hJ+M!6wE(&V+`8X^@P8{=Va>E0zd#`c=e(X64TV11a&s=G zFi$8n5H&I#JOM0K)3Ywcm`k1rMwk*zaIhgAe;!W+)5r@@2n{Kl6-;b2qE?(5zaQh)XVfbyErE5@=nu8lKiHBu&xmV-+zv57r)5 z8@meB6ioJrQC6_)dcAhSbxXA|Vq~gFf5$QSylb;jN7}lA8CJ%~0w^3o)7hg&*ED<> zVsb1P!FKJSuodpfmhfITy3W+oD`}b!E7xcr=n5~54lSCw)|6oA8vS11yowsF2cyD+ z-$o8Yz9wS zi3V$7sbI+Fc5;qU*7f}}`HkJze?b3!a%9+2&tth@2$mRR^4T!y(%numH;Cz`W-=J& zf3}UR@9aJ3vM%d9N6wz6llia}<5e|m6%1L6C1wa=3!QFlXjQnLWoC(_z2D;yM%Q%; zbDcJ};aJ5Zi>HT)+>%{ZRq^|r1IIROirOJPq8a}?e$6EFi%tktz)`^pe@HIeiBQ>m z*p8s05v~YUpdg&4>sJLI;}|Y9I_dgq;i_PzV29h&E`g#n?qR3L2nF&-Dv@1rQ>X&M z2vz{C4*PMsB%Y8Wl_H#ArC=Mu-a+q-hYNSwKg&u14RKCgU6jwC{$`B4$n58$qKQ?J delta 881 zcmV-%1CIQJ5taubiBL{Q4GJ0x0000DNk~Le0000;0000;2nGNE09Ea?N0A{ke*-H? zL_t(|0qvZNb=oi#hCgS5bb=}qBpXy4G#i8sl1_j-LD~({5xPK2H%J!1WPy+gaDBl# zalqnWkR{pCcg_#tameN8UcDj1FXxq1r7x8(Dt)eWRX?V-p1Y{@TI;D&QD4s(8Dh$9 zrN5Pyl}ZPa*ScZX)WOg+rR-V8f2=_u#!PXSDP2_5|636uA&s#a6%CqAP@#=!GfEQ> z$(noOGiF=&b*x@d#F;hwvPt0yO&o1aS4qs*^vo?#4qSKi#1tq;qA89UL+13BN!LI* zQfW>^G0X<}P%Sy3cayP00hA+G!I9&nAq)at>7I^^x!tiz(}4nl1{*>Je=VhU#x7IB zEE#;S^r_Z2{G&La>z5~qlfFN_w!rcLaY(PWx51tU2&%LMbsi{|oIMnQg0c}JmUmgy zY=b5YcoEzoV$Q_eXc}}w!tmAnk=56VO?ibPv)sS0{Q5?E(^r#0n#48}xiAK$^4eux zW+t^mrm_%YiOH7tg=CN>f6>PJ9Dx{gMZ$&_gA@rH>kPUiVPkEO_g%*Uap~G1vt*HV zl#Q;h)5}tct4UsO8*)dG(oheGy> z=A@ge_ftq4BnBzM660Jbgz-{<=FKi+;m&s9}aMi>gtVsabP0l+XkKWNVKU literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@2x.png b/Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5e4d6597c4a0c96d9284a98be255571894ee8f24 GIT binary patch literal 512 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=<_9rXP!T@G9U8a6DsK zu%NkwA*5llNJFrb)&`d;#S5AOn!Hcgrm1gM@e4>fV5GFWqmuo@Ddoz2<^R0?F?21` zIHlTbA6{AI+UCYF=Y&?H@F50mmlN0iz7&=@IlaNAcQHqNs_5bWL2JC<9W>Bgp!%fF z#`JxMvhw+9ciX20nE2=0n#KzXAC!nn5-2?KKwM={Ud*3KWlG(~<(@}`mCu$Ru=kv- zR8=RjaBJk&ZDPeu#*NRu8@Jqlw!f3NrEkuJV+rRDY@IChjc-Tgbm5}=GuX8coZUU+ z>)Q*Ql4}}fRjz-Um+af^3=MW z&x@ACnm(*{FjBUjQKni@y=Hfzopr0H21^vj6}9 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@3x.png b/Riot/Assets/Images.xcassets/Room/Input/video_call.imageset/video_call@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..adaaf0a70a3043b04e8b8be0a157b3b677d763a0 GIT binary patch literal 756 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!oCO|{#S9FJ79h;%I?XTvD9BhG zN}VonM|uBh!ht6@moU9h&}uBdko(Q$k%jO~VS`T|yZ)x-oHTmz zaDH-l@_R-n4#gG$ATe*&sl8U6iyzEKU03W=xf?LO*(+ete#Y8^)`ZfVu?mhXq`>ePEqos!fpU{M6mL~+64_qCVoZ;nr;_C1$sbaNhX~%>F z|9dq@-b|S4xib6sk8hRp<4s>^`JH*XV6nru{vWMrW_xrl%|893?e!&g5ss6$^|r0` ze%AB)()rl+pLd;If4+U2-rgsvTTcA8jrTXTear9x zhiPgyYrRk00+z^$e&!`-+eNcF4o6DvR$ZuaTklxwslG3Z(-c!5z9{;heP?^+Z;d?n zUn|XGd!HT4bJQrD-!^r(tk&#(>{Uw&7A?>+Ry!kW9vF3Abf#hX3`=lQ0TL#c^o7Ll VY8WN1wE-ql22WQ%mvv4FO#s|%P*MN@ literal 0 HcmV?d00001 diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 49354fd09..cdadc4fc8 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -389,6 +389,7 @@ Tap the + to start adding people."; "room_accessibility_integrations" = "Integrations"; "room_accessibility_upload" = "Upload"; "room_accessibility_call" = "Call"; +"room_accessibility_video_call" = "Video Call"; "room_accessibility_hangup" = "Hang up"; "room_place_voice_call" = "Voice call"; "room_open_dialpad" = "Dial pad"; @@ -684,6 +685,8 @@ Tap the + to start adding people."; "room_details_title_for_dm" = "Details"; "room_details_people" = "Members"; "room_details_files" = "Uploads"; +"room_details_search" = "Search room"; +"room_details_integrations" = "Integrations"; "room_details_settings" = "Settings"; "room_details_photo" = "Room Photo"; "room_details_photo_for_dm" = "Photo"; diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index 5793e9185..6690852cf 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -111,7 +111,10 @@ internal enum Asset { internal static let roomContextMenuMore = ImageAsset(name: "room_context_menu_more") internal static let roomContextMenuReply = ImageAsset(name: "room_context_menu_reply") internal static let roomContextMenuRetry = ImageAsset(name: "room_context_menu_retry") + internal static let inputTextBackground = ImageAsset(name: "input_text_background") + internal static let sendIcon = ImageAsset(name: "send_icon") internal static let uploadIcon = ImageAsset(name: "upload_icon") + internal static let videoCall = ImageAsset(name: "video_call") internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon") internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon") internal static let addMemberFloatingAction = ImageAsset(name: "add_member_floating_action") diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 218303eaf..2ef199678 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2294,6 +2294,10 @@ internal enum VectorL10n { internal static var roomAccessibilityUpload: String { return VectorL10n.tr("Vector", "room_accessibility_upload") } + /// Video Call + internal static var roomAccessibilityVideoCall: String { + return VectorL10n.tr("Vector", "room_accessibility_video_call") + } /// Scroll to bottom internal static var roomAccessiblityScrollToBottom: String { return VectorL10n.tr("Vector", "room_accessiblity_scroll_to_bottom") @@ -2614,6 +2618,10 @@ internal enum VectorL10n { internal static var roomDetailsHistorySectionPromptTitle: String { return VectorL10n.tr("Vector", "room_details_history_section_prompt_title") } + /// Integrations + internal static var roomDetailsIntegrations: String { + return VectorL10n.tr("Vector", "room_details_integrations") + } /// Low priority internal static var roomDetailsLowPriorityTag: String { return VectorL10n.tr("Vector", "room_details_low_priority_tag") @@ -2666,6 +2674,10 @@ internal enum VectorL10n { internal static var roomDetailsSaveChangesPrompt: String { return VectorL10n.tr("Vector", "room_details_save_changes_prompt") } + /// Search room + internal static var roomDetailsSearch: String { + return VectorL10n.tr("Vector", "room_details_search") + } /// Set as Main Address internal static var roomDetailsSetMainAddress: String { return VectorL10n.tr("Vector", "room_details_set_main_address") diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift index 3d9b179dc..f1efb7577 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift @@ -86,8 +86,13 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType { // MARK: - Setup - init(parameters: RoomInfoCoordinatorParameters) { - self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController()) + init(parameters: RoomInfoCoordinatorParameters, navigationRouter: NavigationRouterType? = nil) { + if let navigationRouter = navigationRouter { + self.navigationRouter = navigationRouter + } else { + self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController()) + } + self.session = parameters.session self.room = parameters.room self.initialSection = parameters.initialSection @@ -102,8 +107,12 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType { self.add(childCoordinator: rootCoordinator) - self.navigationRouter.setRootModule(rootCoordinator) - + if self.navigationRouter.modules.isEmpty == false { + self.navigationRouter.push(rootCoordinator.toPresentable(), animated: true, popCompletion: nil) + } else { + self.navigationRouter.setRootModule(rootCoordinator) + } + switch initialSection { case .addParticipants: self.showRoomDetails(with: .members, animated: false) @@ -129,13 +138,29 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType { } private func showRoomDetails(with target: RoomInfoListTarget, animated: Bool) { - segmentedViewController.selectedIndex = target.tabIndex - - if case .settings(let roomSettingsField) = target { - roomSettingsViewController?.selectedRoomSettingsField = roomSettingsField + switch target { + case .integrations: + if let modularVC = IntegrationManagerViewController(for: session, inRoom: room.roomId, screen: kIntegrationManagerMainScreen, widgetId: nil) { + navigationRouter.present(modularVC, animated: true) + } + case .search: + MXKRoomDataSourceManager.sharedManager(forMatrixSession: session)?.roomDataSource(forRoom: self.room.roomId, create: false, onComplete: { (roomDataSource) in + guard let dataSource = roomDataSource else { return } + let storyboard = UIStoryboard(name: "Main", bundle: nil) + if let search = storyboard.instantiateViewController(withIdentifier: "RoomSearch") as? RoomSearchViewController { + search.roomDataSource = dataSource + self.navigationRouter.push(search, animated: animated, popCompletion: nil) + } + }) + default: + segmentedViewController.selectedIndex = target.tabIndex + + if case .settings(let roomSettingsField) = target { + roomSettingsViewController?.selectedRoomSettingsField = roomSettingsField + } + + navigationRouter.push(segmentedViewController, animated: animated, popCompletion: nil) } - - navigationRouter.push(segmentedViewController, animated: animated, popCompletion: nil) } } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorBridgePresenter.swift b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorBridgePresenter.swift index 3503eb783..5348b9ab1 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorBridgePresenter.swift @@ -63,6 +63,16 @@ final class RoomInfoCoordinatorBridgePresenter: NSObject { self.coordinator = roomInfoCoordinator } + func push(from navigationController: UINavigationController, animated: Bool) { + let navigationRouter = NavigationRouter(navigationController: navigationController) + + let roomInfoCoordinator = RoomInfoCoordinator(parameters: self.coordinatorParameters, navigationRouter: navigationRouter) + roomInfoCoordinator.delegate = self + roomInfoCoordinator.start() + + self.coordinator = roomInfoCoordinator + } + func dismiss(animated: Bool, completion: (() -> Void)?) { guard let coordinator = self.coordinator else { return diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift index 6d50c1551..945d2844a 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift @@ -18,11 +18,13 @@ import Foundation -enum RoomInfoListTarget { +enum RoomInfoListTarget: Equatable { case settings(_ field: RoomSettingsViewControllerField = RoomSettingsViewControllerFieldNone) case members case uploads - + case integrations + case search + var tabIndex: UInt { let tabIndex: UInt @@ -33,6 +35,10 @@ enum RoomInfoListTarget { tabIndex = 1 case .settings: tabIndex = 2 + case .integrations: + tabIndex = 3 + case .search: + tabIndex = 4 } return tabIndex diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift index 0ce7f656d..67a75586a 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift @@ -157,11 +157,19 @@ final class RoomInfoListViewController: UIViewController { let rowUploads = Row(type: .default, icon: Asset.Images.scrollup.image, text: VectorL10n.roomDetailsFiles, accessoryType: .disclosureIndicator) { self.viewModel.process(viewAction: .navigate(target: .uploads)) } + let rowSearch = Row(type: .default, icon: Asset.Images.searchIcon.image, text: VectorL10n.roomDetailsSearch, accessoryType: .disclosureIndicator) { + self.viewModel.process(viewAction: .navigate(target: .search)) + } + let rowIntegrations = Row(type: .default, icon: Asset.Images.integrationsIcon.image, text: VectorL10n.roomDetailsIntegrations, accessoryType: .disclosureIndicator) { + self.viewModel.process(viewAction: .navigate(target: .integrations)) + } let sectionSettings = Section(header: VectorL10n.roomInfoListSectionOther, rows: [rowSettings, + rowIntegrations, rowMembers, - rowUploads], + rowUploads, + rowSearch], footer: nil) let leaveTitle = viewData.basicInfoViewData.isDirect ? @@ -205,7 +213,9 @@ final class RoomInfoListViewController: UIViewController { } private func setupViews() { - self.navigationItem.rightBarButtonItem = MXKBarButtonItem(customView: closeButton) + if navigationController?.viewControllers.count ?? 0 <= 1 { + self.navigationItem.rightBarButtonItem = MXKBarButtonItem(customView: closeButton) + } self.title = "" diff --git a/Riot/Modules/Room/RoomViewController.h b/Riot/Modules/Room/RoomViewController.h index 4e9864bfd..f8bbc484f 100644 --- a/Riot/Modules/Room/RoomViewController.h +++ b/Riot/Modules/Room/RoomViewController.h @@ -46,6 +46,7 @@ extern NSNotificationName const RoomCallTileTappedNotification; @property (weak, nonatomic) IBOutlet UILabel *jumpToLastUnreadLabel; @property (weak, nonatomic) IBOutlet UIButton *resetReadMarkerButton; @property (weak, nonatomic) IBOutlet UIView *jumpToLastUnreadBannerSeparatorView; +@property (weak, nonatomic) IBOutlet UIVisualEffectView *inputBackgroundView; /** Preview data for a room invitation received by email, or a link to a room. diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 611a64390..53ad7d9ba 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -157,8 +157,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo NSUInteger missedHighlightCount; UIBarButtonItem *missedDiscussionsButton; UILabel *missedDiscussionsBadgeLabel; - UIView *missedDiscussionsBadgeLabelBgView; - UIView *missedDiscussionsBarButtonCustomView; // Potential encryption details view. EncryptionInfoView *encryptionInfoView; @@ -194,9 +192,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Tell whether the view controller is appeared or not. BOOL isAppeared; - - // The right bar button items back up. - NSArray *rightBarButtonItems; // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. id kThemeServiceDidChangeThemeNotificationObserver; @@ -231,6 +226,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo @property (nonatomic, strong) RoomCreationModalCoordinatorBridgePresenter *roomCreationModalCoordinatorBridgePresenter; @property (nonatomic, strong) RoomInfoCoordinatorBridgePresenter *roomInfoCoordinatorBridgePresenter; @property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController; +@property (nonatomic, getter=isActivitiesViewExpanded) BOOL activitiesViewExpanded; @end @@ -371,7 +367,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // call cells [self.bubblesTableView registerClass:RoomDirectCallStatusBubbleCell.class forCellReuseIdentifier:RoomDirectCallStatusBubbleCell.defaultReuseIdentifier]; - [self.bubblesTableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier]; + [self.bubblesTableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier]; [self vc_removeBackTitle]; @@ -388,13 +384,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Custom the event details view [self setEventDetailsViewClass:EventDetailsView.class]; - // Update navigation bar items - for (UIBarButtonItem *barButtonItem in self.navigationItem.rightBarButtonItems) - { - barButtonItem.target = self; - barButtonItem.action = @selector(onButtonPressed:); - } - // Prepare missed dicussion badge (if any) self.showMissedDiscussionsBadge = _showMissedDiscussionsBadge; @@ -420,6 +409,15 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo }]; [self userInterfaceThemeDidChange]; + + if ([ThemeService.shared.themeId isEqualToString:@"light"]) + { + self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + } + else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"]) + { + self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; + } } - (void)userInterfaceThemeDidChange @@ -436,7 +434,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { [ThemeService.shared.theme applyStyleOnNavigationBar:mainNavigationController.navigationBar]; } - + // Keep navigation bar transparent in some cases if (!self.previewHeaderContainer.hidden) { @@ -469,7 +467,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { [self.bubblesTableView reloadData]; } - + [self setNeedsStatusBarAppearanceUpdate]; } @@ -487,7 +485,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - + // Screen tracking [[Analytics sharedInstance] trackScreen:@"ChatRoom"]; @@ -558,7 +556,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self removeWidgetNotificationsListeners]; [self removeTombstoneEventNotificationsListener]; [self removeMXSessionStateChangeNotificationsListener]; - + // Re-enable the read marker display, and disable its update. self.roomDataSource.showReadMarker = YES; self.updateRoomReadMarker = NO; @@ -589,9 +587,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Observe missed notifications mxRoomSummaryDidChangeObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXRoomSummaryDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { - + MXRoomSummary *roomSummary = notif.object; - + if ([roomSummary.roomId isEqualToString:self.roomDataSource.roomId]) { [self refreshMissedDiscussionsCount:NO]; @@ -622,7 +620,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [[NSNotificationCenter defaultCenter] removeObserver:mxRoomSummaryDidChangeObserver]; mxRoomSummaryDidChangeObserver = nil; } - + if (mxEventDidDecryptNotificationObserver) { [[NSNotificationCenter defaultCenter] removeObserver:mxEventDidDecryptNotificationObserver]; @@ -659,7 +657,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo eventDetailsView = nil; } } - + // Check whether the preview header is visible if (previewHeader) { @@ -675,17 +673,17 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo previewHeader.mainHeaderBackgroundHeightConstraint.constant = mainHeaderBackgroundHeight; // Force the layout of previewHeader to update the position of 'bottomBorderView' which - // is used to define the actual height of the preview container. + // is used to define the actual of the preview container. [previewHeader layoutIfNeeded]; } } - + self.edgesForExtendedLayout = UIRectEdgeAll; - + // Adjust the top constraint of the bubbles table CGRect frame = previewHeader.bottomBorderView.frame; self.previewHeaderContainerHeightConstraint.constant = frame.origin.y + frame.size.height; - + self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top; self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant; } @@ -694,7 +692,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // In non expanded header mode, the navigation bar is opaque // The table view must not display behind it self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight; - + self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; // no expanded } @@ -772,25 +770,25 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction { BOOL canScroll = YES; - + // Scroll by one page CGFloat tableViewHeight = self.bubblesTableView.frame.size.height; - + CGPoint offset = self.bubblesTableView.contentOffset; switch (direction) { case UIAccessibilityScrollDirectionUp: offset.y -= tableViewHeight; break; - + case UIAccessibilityScrollDirectionDown: offset.y += tableViewHeight; break; - + default: break; } - + if (offset.y < 0 && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionBackwards]) { // Can't paginate more. Let's stick on the first item @@ -810,9 +808,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { // Disable VoiceOver while scrolling self.bubblesTableView.accessibilityElementsHidden = YES; - + [self setBubbleTableViewContentOffset:offset animated:NO]; - + NSEnumerator *cells; if (direction == UIAccessibilityScrollDirectionUp) { @@ -823,13 +821,13 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo cells = self.bubblesTableView.visibleCells.reverseObjectEnumerator; } UIView *cell = [self firstCellWithAccessibilityDataInCells:cells]; - + self.bubblesTableView.accessibilityElementsHidden = NO; - + // Force VoiceOver to focus on a visible item UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, cell); } - + // If we cannot scroll, let VoiceOver indicates the border return canScroll; } @@ -837,7 +835,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (UIView*)firstCellWithAccessibilityDataInCells:(NSEnumerator*)cells { UIView *view; - + for (UITableViewCell *cell in cells) { if (![cell isKindOfClass:[RoomEmptyBubbleCell class]]) @@ -846,7 +844,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo break; } } - + return view; } @@ -894,7 +892,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (self.roomDataSource) { [self listenToServerNotices]; - + self.eventsAcknowledgementEnabled = YES; // Set room title view @@ -1000,7 +998,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo Class roomInputToolbarViewClass = RoomInputToolbarView.class; BOOL shouldDismissContextualMenu = NO; - + // Check the user has enough power to post message if (self.roomDataSource.roomState) { @@ -1022,7 +1020,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo shouldDismissContextualMenu = YES; } } - + // Do not show toolbar in case of preview if (self.isRoomPreview) { @@ -1047,7 +1045,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (CGFloat)inputToolbarHeight { CGFloat height = 0; - + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { height = ((RoomInputToolbarView*)self.inputToolbarView).mainToolbarHeightConstraint.constant; @@ -1056,7 +1054,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { height = ((DisabledRoomInputToolbarView*)self.inputToolbarView).mainToolbarMinHeightConstraint.constant; } - + return height; } @@ -1069,6 +1067,11 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } [super setRoomActivitiesViewClass:roomActivitiesViewClass]; + + if (!self.isActivitiesViewExpanded) + { + self.roomActivitiesContainerHeightConstraint.constant = 0; + } } - (BOOL)isIRCStyleCommand:(NSString*)string @@ -1176,9 +1179,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Let the datasource send it and manage the local echo [self.roomDataSource sendTextMessage:msgTxt success:nil failure:^(NSError *error) { - // Just log the error. The message will be displayed in red in the room history - NSLog(@"[MXKRoomViewController] sendTextMessage failed."); - }]; + // Just log the error. The message will be displayed in red in the room history + NSLog(@"[MXKRoomViewController] sendTextMessage failed."); + }]; } [self cancelEventSelection]; @@ -1186,19 +1189,22 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)setRoomTitleViewClass:(Class)roomTitleViewClass { - [super setRoomTitleViewClass:roomTitleViewClass]; + // Sanity check: accept only MXKRoomTitleView classes or sub-classes + NSParameterAssert([roomTitleViewClass isSubclassOfClass:MXKRoomTitleView.class]); + + MXKRoomTitleView *titleView = [roomTitleViewClass roomTitleView]; + [self setValue:titleView forKey:@"titleView"]; + titleView.delegate = self; + titleView.mxRoom = self.roomDataSource.room; + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:titleView]; + + [self updateViewControllerAppearanceOnRoomDataSourceState]; [self updateTitleViewEncryptionDecoration]; } - (void)destroy { - rightBarButtonItems = nil; - for (UIBarButtonItem *barButtonItem in self.navigationItem.rightBarButtonItems) - { - barButtonItem.enabled = NO; - } - if (currentAlert) { [currentAlert dismissViewControllerAnimated:NO completion:nil]; @@ -1244,7 +1250,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self removeTombstoneEventNotificationsListener]; [self removeMXSessionStateChangeNotificationsListener]; [self removeServerNoticesListener]; - + if (previewHeader) { // Here [destroy] is called before [viewWillDisappear:] @@ -1259,8 +1265,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo roomPreviewData = nil; - missedDiscussionsBarButtonCustomView = nil; - missedDiscussionsBadgeLabelBgView = nil; missedDiscussionsBadgeLabel = nil; [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXEventDidChangeSentStateNotification object:nil]; @@ -1271,58 +1275,23 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo #pragma mark - +-(void)setActivitiesViewExpanded:(BOOL)activitiesViewExpanded +{ + if (_activitiesViewExpanded != activitiesViewExpanded) + { + _activitiesViewExpanded = activitiesViewExpanded; + + self.roomActivitiesContainerHeightConstraint.constant = activitiesViewExpanded ? 53 : 0; + [super roomInputToolbarView:self.inputToolbarView heightDidChanged:[self inputToolbarHeight] completion:nil]; + } +} + - (void)setShowMissedDiscussionsBadge:(BOOL)showMissedDiscussionsBadge { - _showMissedDiscussionsBadge = showMissedDiscussionsBadge; - - if (_showMissedDiscussionsBadge && !missedDiscussionsBarButtonCustomView) - { - // Prepare missed dicussion badge - missedDiscussionsBarButtonCustomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 21)]; - missedDiscussionsBarButtonCustomView.backgroundColor = [UIColor clearColor]; - missedDiscussionsBarButtonCustomView.clipsToBounds = NO; - - NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:missedDiscussionsBarButtonCustomView - attribute:NSLayoutAttributeHeight - relatedBy:NSLayoutRelationEqual - toItem:nil - attribute:NSLayoutAttributeNotAnAttribute - multiplier:1.0 - constant:21]; - - missedDiscussionsBadgeLabelBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 21, 21)]; - [missedDiscussionsBadgeLabelBgView.layer setCornerRadius:10]; - - [missedDiscussionsBarButtonCustomView addSubview:missedDiscussionsBadgeLabelBgView]; - missedDiscussionsBarButtonCustomView.accessibilityIdentifier = @"RoomVCMissedDiscussionsBarButton"; - - missedDiscussionsBadgeLabel = [[UILabel alloc]initWithFrame:CGRectMake(2, 2, 17, 17)]; - missedDiscussionsBadgeLabel.translatesAutoresizingMaskIntoConstraints = NO; - [missedDiscussionsBadgeLabelBgView addSubview:missedDiscussionsBadgeLabel]; - - NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:missedDiscussionsBadgeLabel - attribute:NSLayoutAttributeCenterX - relatedBy:NSLayoutRelationEqual - toItem:missedDiscussionsBadgeLabelBgView - attribute:NSLayoutAttributeCenterX - multiplier:1.0 - constant:0]; - NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:missedDiscussionsBadgeLabel - attribute:NSLayoutAttributeCenterY - relatedBy:NSLayoutRelationEqual - toItem:missedDiscussionsBadgeLabelBgView - attribute:NSLayoutAttributeCenterY - multiplier:1.0 - constant:0]; - - [NSLayoutConstraint activateConstraints:@[heightConstraint, centerXConstraint, centerYConstraint]]; - } - else - { - missedDiscussionsBarButtonCustomView = nil; - missedDiscussionsBadgeLabelBgView = nil; - missedDiscussionsBadgeLabel = nil; - } + BOOL toto = [UIDevice currentDevice].userInterfaceIdiom != + UIUserInterfaceIdiomPhone || !showMissedDiscussionsBadge; + missedDiscussionsBadgeLabel.hidden = [UIDevice currentDevice].userInterfaceIdiom != + UIUserInterfaceIdiomPhone || !showMissedDiscussionsBadge; } #pragma mark - Internals @@ -1357,20 +1326,26 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo return self.roomDataSource.room.summary.isEncrypted && self.mainSession.crypto != nil; } +- (BOOL)supportCallOption +{ + return BuildSettings.allowVoIPUsage && self.roomDataSource.mxSession.callManager && self.roomDataSource.room.summary.membersCount.joined >= 2; +} + +- (BOOL)isCallActive +{ + MXCall *callInRoom = [self.roomDataSource.mxSession.callManager callInRoom:self.roomDataSource.roomId]; + + return (callInRoom && callInRoom.state != MXCallStateEnded) + || [[AppDelegate theDelegate].jitsiViewController.widget.roomId isEqualToString:self.roomDataSource.roomId]; +} + - (void)refreshRoomTitle { - if (rightBarButtonItems && !self.navigationItem.rightBarButtonItems) - { - // Restore by default the search bar button. - self.navigationItem.rightBarButtonItems = rightBarButtonItems; - } + NSMutableArray *rightBarButtonItems = nil; // Set the right room title view if (self.isRoomPreview) { - // Do not show the right buttons - self.navigationItem.rightBarButtonItems = nil; - [self showPreviewHeader:YES]; } else if (self.roomDataSource) @@ -1379,107 +1354,75 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (self.roomDataSource.isLive) { - // Enable the right buttons (Search and Integrations) - for (UIBarButtonItem *barButtonItem in self.navigationItem.rightBarButtonItems) + rightBarButtonItems = [NSMutableArray new]; + + UIEdgeInsets itemInsets = UIEdgeInsetsMake(0, -5, 0, 5); + if (self.supportCallOption) { - barButtonItem.enabled = YES; - } - - if (self.navigationItem.rightBarButtonItems.count == 2) - { - BOOL matrixAppsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"matrixApps"]; - if (!matrixAppsEnabled) - { - // If the setting is disabled, do not show the icon - self.navigationItem.rightBarButtonItems = @[self.navigationItem.rightBarButtonItem]; - } - else if ([self widgetsCount:NO]) - { - // Show there are widgets by changing the "apps" icon color - // Show it in red only for room widgets, not user's widgets - // TODO: Design must be reviewed - UIImage *icon = self.navigationItem.rightBarButtonItems[1].image; - icon = [MXKTools paintImage:icon withColor:ThemeService.shared.theme.warningColor]; - icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; - - self.navigationItem.rightBarButtonItems[1].image = icon; - self.navigationItem.rightBarButtonItems[1].accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil); - } - else - { - // Reset original icon - self.navigationItem.rightBarButtonItems[1].image = [UIImage imageNamed:@"integrations_icon"]; - self.navigationItem.rightBarButtonItems[1].accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil); - } + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangon_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(onVoiceCallPressed:)]; + item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_call", @"Vector", nil); + item.imageInsets = UIEdgeInsetsMake(0, -5, 0, 5); + [rightBarButtonItems addObject:item]; - self.navigationItem.rightBarButtonItems.firstObject.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_search", @"Vector", nil); + item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"video_call"] style:UIBarButtonItemStylePlain target:self action:@selector(onVideoCallPressed:)]; + item.imageInsets = UIEdgeInsetsMake(0, 10, 0, -10); + item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_video_call", @"Vector", nil); + [rightBarButtonItems addObject:item]; + itemInsets = UIEdgeInsetsMake(0, 20, 0, -20); } - + + if ([self widgetsCount:NO]) + { + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"integrations_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(onIntegrationsPressed:)]; + item.imageInsets = itemInsets; + item.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil); + [rightBarButtonItems addObject:item]; + } + // Do not change title view class here if the expanded header is visible. [self setRoomTitleViewClass:RoomTitleView.class]; ((RoomTitleView*)self.titleView).tapGestureDelegate = self; } - else + + MXKImageView *userPictureView = ((RoomTitleView*)self.titleView).pictureView; + + // Set user picture in input toolbar + if (userPictureView) { - // Remove the search button temporarily - rightBarButtonItems = self.navigationItem.rightBarButtonItems; - self.navigationItem.rightBarButtonItems = nil; - - [self setRoomTitleViewClass:SimpleRoomTitleView.class]; - self.titleView.editable = NO; + [self.roomDataSource.room.summary setRoomAvatarImageIn:userPictureView]; } + + missedDiscussionsBadgeLabel = ((RoomTitleView*)self.titleView).missedDiscussionsBadgeLabel; + + [self refreshMissedDiscussionsCount:YES]; } - else - { - self.navigationItem.rightBarButtonItem.enabled = NO; - } + + self.navigationItem.rightBarButtonItems = rightBarButtonItems; } - (void)refreshRoomInputToolbar { MXKImageView *userPictureView; - + // Check whether the input toolbar is ready before updating it. if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView; - // Check whether the call option is supported - roomInputToolbarView.supportCallOption = BuildSettings.allowVoIPUsage && self.roomDataSource.mxSession.callManager && self.roomDataSource.room.summary.membersCount.joined >= 2; - - // Get user picture view in input toolbar - userPictureView = roomInputToolbarView.pictureView; - - // Show the hangup button if there is an active call or an active jitsi - // conference call in the current room - MXCall *callInRoom = [self.roomDataSource.mxSession.callManager callInRoom:self.roomDataSource.roomId]; - if ((callInRoom && callInRoom.state != MXCallStateEnded) - || [[AppDelegate theDelegate].jitsiViewController.widget.roomId isEqualToString:self.roomDataSource.roomId]) - { - roomInputToolbarView.activeCall = YES; - } - else - { - roomInputToolbarView.activeCall = NO; - - // Hide the call button if there is an active call in another room - roomInputToolbarView.supportCallOption &= ([[AppDelegate theDelegate] callStatusBarWindow] == nil); - } - // Update encryption decoration if needed [self updateEncryptionDecorationForRoomInputToolbar:roomInputToolbarView]; } else if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:DisabledRoomInputToolbarView.class]) { DisabledRoomInputToolbarView *roomInputToolbarView = (DisabledRoomInputToolbarView*)self.inputToolbarView; - + // Get user picture view in input toolbar userPictureView = roomInputToolbarView.pictureView; - + // For the moment, there is only one reason to use `DisabledRoomInputToolbarView` [roomInputToolbarView setDisabledReason:NSLocalizedStringFromTable(@"room_do_not_have_permission_to_post", @"Vector", nil)]; } - + // Set user picture in input toolbar if (userPictureView) { @@ -1516,7 +1459,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView; sendMode = roomInputToolbarView.sendMode; } - + return sendMode; } @@ -1578,7 +1521,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)updateEncryptionDecorationForRoomInputToolbar:(RoomInputToolbarView*)roomInputToolbarView { roomInputToolbarView.isEncryptionEnabled = self.isEncryptionEnabled; - roomInputToolbarView.encryptedRoomIcon.image = self.roomEncryptionBadgeImage; } - (void)handleLongPressFromCell:(id)cell withTappedEvent:(MXEvent*)event @@ -1609,7 +1551,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo CameraPresenter *cameraPresenter = [CameraPresenter new]; cameraPresenter.delegate = self; [cameraPresenter presentCameraFrom:self with:@[MXKUTI.image, MXKUTI.movie] animated:YES]; - + self.cameraPresenter = cameraPresenter; } @@ -1631,7 +1573,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { sourceView = self.inputToolbarView; } - + [mediaPickerPresenter presentFrom:self sourceView:sourceView sourceRect:sourceView.bounds animated:YES]; self.mediaPickerPresenter = mediaPickerPresenter; @@ -1691,7 +1633,8 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo self.roomInfoCoordinatorBridgePresenter = [[RoomInfoCoordinatorBridgePresenter alloc] initWithParameters:parameters]; self.roomInfoCoordinatorBridgePresenter.delegate = self; - [self.roomInfoCoordinatorBridgePresenter presentFrom:self animated:YES]; +// [self.roomInfoCoordinatorBridgePresenter presentFrom:self animated:true]; + [self.roomInfoCoordinatorBridgePresenter pushFrom:self.navigationController animated:YES]; } #pragma mark - Dialpad @@ -1803,7 +1746,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } self.previewHeaderContainer.hidden = NO; - + // Finalize preview header display according to the screen orientation [self refreshPreviewHeader:UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])]; } @@ -1826,8 +1769,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Remove details icon RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView; - [roomTitleView.roomDetailsIconImageView removeFromSuperview]; - roomTitleView.roomDetailsIconImageView = nil; // Remove the shadow image used to hide the bottom border of the navigation bar when the preview header is displayed [mainNavigationController.navigationBar setShadowImage:nil]; @@ -1835,19 +1776,19 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - - self.bubblesTableViewTopConstraint.constant = 0; - self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; - - // Force to render the view - [self forceLayoutRefresh]; - - } + + self.bubblesTableViewTopConstraint.constant = 0; + self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; + + // Force to render the view + [self forceLayoutRefresh]; + + } completion:^(BOOL finished){ - }]; + }]; } } - + // Consider the main navigation controller if the current view controller is embedded inside a split view controller. UINavigationController *mainNavigationController = self.navigationController; if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) @@ -1875,8 +1816,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Remove details icon RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView; - [roomTitleView.roomDetailsIconImageView removeFromSuperview]; - roomTitleView.roomDetailsIconImageView = nil; // Set preview data to provide the room name roomTitleView.roomPreviewData = roomPreviewData; @@ -1885,17 +1824,17 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { previewHeader.mainHeaderContainer.hidden = NO; previewHeader.mainHeaderBackgroundHeightConstraint.constant = previewHeader.mainHeaderContainer.frame.size.height; - + if ([previewHeader isKindOfClass:PreviewRoomTitleView.class]) { // In case of preview, update the header height so that we can // display as much as possible the room topic in this header. // Note: the header height is handled by the previewHeader.mainHeaderBackgroundHeightConstraint. PreviewRoomTitleView *previewRoomTitleView = (PreviewRoomTitleView *)previewHeader; - + // Compute the height required to display all the room topic CGSize sizeThatFitsTextView = [previewRoomTitleView.roomTopic sizeThatFits:CGSizeMake(previewRoomTitleView.roomTopic.frame.size.width, MAXFLOAT)]; - + // Increase the preview header height according to the room topic height // but limit it in order to let room for room messages at the screen bottom. // This free space depends on the device. @@ -1904,13 +1843,13 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // apply a factor to give more priority to the display of more messages. CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height; CGFloat maxRoomTopicHeight = 50 + (screenHeight - 568) / 3; - + CGFloat additionalHeight = MIN(maxRoomTopicHeight, sizeThatFitsTextView.height) - - previewRoomTitleView.roomTopic.frame.size.height; - + - previewRoomTitleView.roomTopic.frame.size.height; + previewHeader.mainHeaderBackgroundHeightConstraint.constant += additionalHeight; } - + [self setRoomTitleViewClass:RoomAvatarTitleView.class]; // Note the avatar title view does not define tap gesture. @@ -1956,18 +1895,18 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - - self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top; - self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant; - - previewHeader.roomAvatar.alpha = 1; - - // Force to render the view - [self forceLayoutRefresh]; - - } + + self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top; + self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant; + + previewHeader.roomAvatar.alpha = 1; + + // Force to render the view + [self forceLayoutRefresh]; + + } completion:^(BOOL finished){ - }]; + }]; } } @@ -2288,7 +2227,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo RoomDataSource *roomDataSource = (RoomDataSource*)self.roomDataSource; [roomDataSource acceptVerificationRequestForEventId:eventId success:^{ - + } failure:^(NSError *error) { [[AppDelegate theDelegate] showErrorAsAlert:error]; }]; @@ -2388,7 +2327,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo MXEvent *callInviteEvent = userInfo[kMXKRoomBubbleCellEventKey]; MXCallInviteEventContent *eventContent = [MXCallInviteEventContent modelFromJSON:callInviteEvent.content]; - [self roomInputToolbarView:self.inputToolbarView placeCallWithVideo2:eventContent.isVideoCall]; + [self placeCallWithVideo2:eventContent.isVideoCall]; } else if ([actionIdentifier isEqualToString:RoomCreationIntroCell.tapOnAvatarView]) { @@ -2436,33 +2375,33 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"retry", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Let the datasource resend. It will manage local echo, etc. - [self.roomDataSource resendEventWithEventId:selectedEvent.eventId success:nil failure:nil]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + + [self cancelEventSelection]; + + // Let the datasource resend. It will manage local echo, etc. + [self.roomDataSource resendEventWithEventId:selectedEvent.eventId success:nil failure:nil]; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_delete", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + + [self cancelEventSelection]; + + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; + } + + }]]; } // Add actions for text message @@ -2480,7 +2419,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo selectedComponent = nil; } - + // Check status of the selected event if (selectedEvent.sentState == MXEventSentStatePreparing || selectedEvent.sentState == MXEventSentStateEncrypting || @@ -2490,41 +2429,41 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - - self->currentAlert = nil; - - // Cancel and remove the outgoing message - [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - - [self cancelEventSelection]; - } - - }]]; + if (weakSelf) + { + typeof(self) self = weakSelf; + + self->currentAlert = nil; + + // Cancel and remove the outgoing message + [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; + + [self cancelEventSelection]; + } + + }]]; } - + [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_quote", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Quote the message a la Markdown into the input toolbar composer - self.inputToolbarView.textMessage = [NSString stringWithFormat:@"%@\n>%@\n\n", self.inputToolbarView.textMessage, selectedComponent.textMessage]; - - // And display the keyboard - [self.inputToolbarView becomeFirstResponder]; - } - - }]]; - + + if (weakSelf) + { + typeof(self) self = weakSelf; + + [self cancelEventSelection]; + + // Quote the message a la Markdown into the input toolbar composer + self.inputToolbarView.textMessage = [NSString stringWithFormat:@"%@\n>%@\n\n", self.inputToolbarView.textMessage, selectedComponent.textMessage]; + + // And display the keyboard + [self.inputToolbarView becomeFirstResponder]; + } + + }]]; + if (BuildSettings.messageDetailsAllowShare) { [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_share", @"Vector", nil) @@ -2594,7 +2533,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo }]]; } } - + // Check status of the selected event if (selectedEvent.sentState == MXEventSentStatePreparing || selectedEvent.sentState == MXEventSentStateEncrypting || @@ -2608,37 +2547,37 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_cancel_send", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - // Get again the loader - MXMediaLoader *loader = [MXMediaManager existingUploaderWithId:uploadId]; - if (loader) - { - [loader cancel]; - } - // Hide the progress animation - roomBubbleTableViewCell.progressView.hidden = YES; - - if (weakSelf) - { - typeof(self) self = weakSelf; - - self->currentAlert = nil; - - // Remove the outgoing message and its related cached file. - [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.cacheFilePath error:nil]; - [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.thumbnailCachePath error:nil]; - - // Cancel and remove the outgoing message - [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - - [self cancelEventSelection]; - } - - }]]; + + // Get again the loader + MXMediaLoader *loader = [MXMediaManager existingUploaderWithId:uploadId]; + if (loader) + { + [loader cancel]; + } + // Hide the progress animation + roomBubbleTableViewCell.progressView.hidden = YES; + + if (weakSelf) + { + typeof(self) self = weakSelf; + + self->currentAlert = nil; + + // Remove the outgoing message and its related cached file. + [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.cacheFilePath error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.thumbnailCachePath error:nil]; + + // Cancel and remove the outgoing message + [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; + + [self cancelEventSelection]; + } + + }]]; } } - + if (attachment.type != MXKAttachmentTypeSticker) { if (BuildSettings.messageDetailsAllowShare) @@ -2695,24 +2634,24 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_cancel_download", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Get again the loader - MXMediaLoader *loader = [MXMediaManager existingDownloaderWithIdentifier:downloadId]; - if (loader) - { - [loader cancel]; - } - // Hide the progress animation - roomBubbleTableViewCell.progressView.hidden = YES; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + + [self cancelEventSelection]; + + // Get again the loader + MXMediaLoader *loader = [MXMediaManager existingDownloaderWithIdentifier:downloadId]; + if (loader) + { + [loader cancel]; + } + // Hide the progress animation + roomBubbleTableViewCell.progressView.hidden = YES; + } + + }]]; } } @@ -2723,35 +2662,35 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_redact", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self startActivityIndicator]; - - [self.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{ - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - } failure:^(NSError *error) { - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - NSLog(@"[RoomVC] Redact event (%@) failed", selectedEvent.eventId); - //Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - - }]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + + [self cancelEventSelection]; + + [self startActivityIndicator]; + + [self.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{ + + __strong __typeof(weakSelf)self = weakSelf; + [self stopActivityIndicator]; + + } failure:^(NSError *error) { + + __strong __typeof(weakSelf)self = weakSelf; + [self stopActivityIndicator]; + + NSLog(@"[RoomVC] Redact event (%@) failed", selectedEvent.eventId); + //Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + + }]]; } - + if (BuildSettings.messageDetailsAllowPermalink) { [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_permalink", @"Vector", nil) @@ -2786,12 +2725,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_reaction_history", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - [self cancelEventSelection]; - - // Show reaction history - [self showReactionHistoryForEventId:selectedEvent.eventId animated:YES]; - }]]; + + [self cancelEventSelection]; + + // Show reaction history + [self showReactionHistoryForEventId:selectedEvent.eventId animated:YES]; + }]]; } if (BuildSettings.messageDetailsAllowViewSource) @@ -2811,8 +2750,8 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } }]]; - - + + // Add "View Decrypted Source" for e2ee event we can decrypt if (selectedEvent.isEncrypted && selectedEvent.clearEvent) { @@ -2943,37 +2882,37 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo }]]; } - + if (self.roomDataSource.room.summary.isEncrypted) { [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_view_encryption", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - [self cancelEventSelection]; - - // Display encryption details - [self showEncryptionInformation:selectedEvent]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + [self cancelEventSelection]; + + // Display encryption details + [self showEncryptionInformation:selectedEvent]; + } + + }]]; } } [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - [self hideContextualMenuAnimated:YES]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + [self hideContextualMenuAnimated:YES]; + } + + }]]; // Do not display empty action sheet if (currentAlert.actions.count > 1) @@ -3080,7 +3019,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { NSString *eventId = arguments[1]; MXEvent *event = [self.roomDataSource eventWithEventId:eventId]; - + if (event) { [self reRequestKeysAndShowExplanationAlert:event]; @@ -3157,7 +3096,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo shouldDoAction = NO; break; } - } + } } break; case UITextItemInteractionPresentActions: @@ -3328,19 +3267,19 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { // Search for the sticker picker widget in the user account Widget *widget = [[WidgetManager sharedManager] userWidgets:self.roomDataSource.mxSession ofTypes:@[kWidgetTypeStickerPicker]].firstObject; - + if (widget) { // Display the widget [widget widgetUrl:^(NSString * _Nonnull widgetUrl) { - + StickerPickerViewController *stickerPickerVC = [[StickerPickerViewController alloc] initWithUrl:widgetUrl forWidget:widget]; - + stickerPickerVC.roomDataSource = self.roomDataSource; - + [self.navigationController pushViewController:stickerPickerVC animated:YES]; } failure:^(NSError * _Nonnull error) { - + NSLog(@"[RoomVC] Cannot display widget %@", widget); [[AppDelegate theDelegate] showErrorAsAlert:error]; }]; @@ -3349,73 +3288,61 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { // The Sticker picker widget is not installed yet. Propose the user to install it __weak typeof(self) weakSelf = self; - + [currentAlert dismissViewControllerAnimated:NO completion:nil]; - + NSString *alertMessage = [NSString stringWithFormat:@"%@\n%@", NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert", @"Vector", nil), NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert_add_now", @"Vector", nil) ]; - + currentAlert = [UIAlertController alertControllerWithTitle:nil message:alertMessage preferredStyle:UIAlertControllerStyleAlert]; - + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"no"] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) - { + { if (weakSelf) { typeof(self) self = weakSelf; self->currentAlert = nil; } - + }]]; - + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"yes"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) - { + { if (weakSelf) { typeof(self) self = weakSelf; self->currentAlert = nil; - + // Show the sticker picker settings screen IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] initForMXSession:self.roomDataSource.mxSession inRoom:self.roomDataSource.roomId screen:[IntegrationManagerViewController screenForWidget:kWidgetTypeStickerPicker] widgetId:nil]; - + [self presentViewController:modularVC animated:NO completion:nil]; } }]]; - + [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"]; [self presentViewController:currentAlert animated:YES completion:nil]; } } -#pragma mark - MXKRoomInputToolbarViewDelegate +#pragma mark - VoIP -- (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView isTyping:(BOOL)typing -{ - [super roomInputToolbarView:toolbarView isTyping:typing]; - - // Cancel potential selected event (to leave edition mode) - NSString *selectedEventId = customizedRoomDataSource.selectedEventId; - if (typing && selectedEventId && ![self.roomDataSource canReplyToEventWithId:selectedEventId]) - { - [self cancelEventSelection]; - } -} - -- (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView placeCallWithVideo:(BOOL)video +- (void)placeCallWithVideo:(BOOL)video { __weak __typeof(self) weakSelf = self; - + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; - + // Check app permissions first [MXKTools checkAccessForCall:video manualChangeMessageForAudio:[NSString stringWithFormat:[NSBundle mxk_localizedStringForKey:@"microphone_access_not_granted_for_call"], appDisplayName] @@ -3430,15 +3357,15 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { if (video) { - [self roomInputToolbarView:toolbarView placeCallWithVideo2:video]; + [self placeCallWithVideo2:video]; } else if (self.mainSession.callManager.supportsPSTN) { - [self showVoiceCallActionSheetWith:toolbarView]; + [self showVoiceCallActionSheet]; } else { - [self roomInputToolbarView:toolbarView placeCallWithVideo2:NO]; + [self placeCallWithVideo2:NO]; } } else @@ -3449,149 +3376,145 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo }]; } -- (void)showVoiceCallActionSheetWith:(MXKRoomInputToolbarView *)toolbarView +- (void)showVoiceCallActionSheet { // Ask the user the kind of the call: voice or dialpad? currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - + __weak typeof(self) weakSelf = self; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_place_voice_call", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - [self roomInputToolbarView:toolbarView placeCallWithVideo2:NO]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + + [self placeCallWithVideo2:NO]; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_open_dialpad", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - [self openDialpad]; - } - - }]]; + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + + [self openDialpad]; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] - style:UIAlertActionStyleCancel - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * action) { + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + } + + }]]; - if ([toolbarView isKindOfClass:[RoomInputToolbarView class]]) - { - RoomInputToolbarView *toolbar = (RoomInputToolbarView *)toolbarView; - [currentAlert popoverPresentationController].sourceView = toolbar.voiceCallButton; - [currentAlert popoverPresentationController].sourceRect = toolbar.voiceCallButton.bounds; - } + [currentAlert popoverPresentationController].barButtonItem = self.navigationItem.rightBarButtonItems.firstObject; + [currentAlert popoverPresentationController].permittedArrowDirections = UIPopoverArrowDirectionUp; [self presentViewController:currentAlert animated:YES completion:nil]; } -- (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView placeCallWithVideo2:(BOOL)video +- (void)placeCallWithVideo2:(BOOL)video { - __weak __typeof(self) weakSelf = self; - + __weak __typeof(self) weakSelf = self; + // If there is already a jitsi widget, join it Widget *jitsiWidget = [customizedRoomDataSource jitsiWidget]; if (jitsiWidget) { [[AppDelegate theDelegate] displayJitsiViewControllerWithWidget:jitsiWidget andVideo:video]; } - + // If enabled, create the conf using jitsi widget and open it directly else if (RiotSettings.shared.createConferenceCallsWithJitsi && self.roomDataSource.room.summary.membersCount.joined > 2) { [self startActivityIndicator]; - + [[WidgetManager sharedManager] createJitsiWidgetInRoom:self.roomDataSource.room withVideo:video success:^(Widget *jitsiWidget) { - if (weakSelf) - { - typeof(self) self = weakSelf; - [self stopActivityIndicator]; - - [[AppDelegate theDelegate] displayJitsiViewControllerWithWidget:jitsiWidget andVideo:video]; - } - } + if (weakSelf) + { + typeof(self) self = weakSelf; + [self stopActivityIndicator]; + + [[AppDelegate theDelegate] displayJitsiViewControllerWithWidget:jitsiWidget andVideo:video]; + } + } failure:^(NSError *error) { - if (weakSelf) - { - typeof(self) self = weakSelf; - [self stopActivityIndicator]; - - [self showJitsiErrorAsAlert:error]; - } - }]; + if (weakSelf) + { + typeof(self) self = weakSelf; + [self stopActivityIndicator]; + + [self showJitsiErrorAsAlert:error]; + } + }]; } // Classic conference call is not supported in encrypted rooms else if (self.roomDataSource.room.summary.isEncrypted && self.roomDataSource.room.summary.membersCount.joined > 2) { [currentAlert dismissViewControllerAnimated:NO completion:nil]; - + currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_no_conference_call_in_encrypted_rooms"] message:nil preferredStyle:UIAlertControllerStyleAlert]; - + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; - + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + } + + }]]; + [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCCallAlert"]; [self presentViewController:currentAlert animated:YES completion:nil]; } - + // In case of conference call, check that the user has enough power level else if (self.roomDataSource.room.summary.membersCount.joined > 2 && ![MXCallManager canPlaceConferenceCallInRoom:self.roomDataSource.room roomState:self.roomDataSource.roomState]) { [currentAlert dismissViewControllerAnimated:NO completion:nil]; - + currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_no_power_to_create_conference_call"] message:nil preferredStyle:UIAlertControllerStyleAlert]; - + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - }]]; - + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + } + }]]; + [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCCallAlert"]; [self presentViewController:currentAlert animated:YES completion:nil]; } - + // Classic 1:1 or group call can be done else { @@ -3599,7 +3522,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } } -- (void)roomInputToolbarViewHangupCall:(MXKRoomInputToolbarView *)toolbarView +- (void)hangupCall { MXCall *callInRoom = [self.roomDataSource.mxSession.callManager callInRoom:self.roomDataSource.roomId]; if (callInRoom) @@ -3610,11 +3533,25 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { [[AppDelegate theDelegate].jitsiViewController hangup]; } - + [self refreshActivitiesViewDisplay]; [self refreshRoomInputToolbar]; } +#pragma mark - MXKRoomInputToolbarViewDelegate + +- (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView isTyping:(BOOL)typing +{ + [super roomInputToolbarView:toolbarView isTyping:typing]; + + // Cancel potential selected event (to leave edition mode) + NSString *selectedEventId = customizedRoomDataSource.selectedEventId; + if (typing && selectedEventId && ![self.roomDataSource canReplyToEventWithId:selectedEventId]) + { + [self cancelEventSelection]; + } +} + - (void)roomInputToolbarView:(MXKRoomInputToolbarView*)toolbarView heightDidChanged:(CGFloat)height completion:(void (^)(BOOL finished))completion { if (self.roomInputToolbarContainerHeightConstraint.constant != height) @@ -3637,9 +3574,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (!toolbarView.placeholder) { // Restore the placeholder if any - toolbarView.placeholder = savedInputToolbarPlaceholder.length ? savedInputToolbarPlaceholder : nil; + toolbarView.placeholder = self->savedInputToolbarPlaceholder.length ? self->savedInputToolbarPlaceholder : nil; } - savedInputToolbarPlaceholder = nil; + self->savedInputToolbarPlaceholder = nil; }]; } } @@ -3648,7 +3585,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { MXKDocumentPickerPresenter *documentPickerPresenter = [MXKDocumentPickerPresenter new]; documentPickerPresenter.delegate = self; - + NSArray *allowedUTIs = @[MXKUTI.data]; [documentPickerPresenter presentDocumentPickerWith:allowedUTIs from:self animated:YES completion:nil]; @@ -3686,50 +3623,49 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo #pragma mark - Action +- (IBAction)onVoiceCallPressed:(id)sender +{ + if (self.isCallActive) + { + [self hangupCall]; + } + else + { + [self placeCallWithVideo:NO]; + } +} + +- (IBAction)onVideoCallPressed:(id)sender +{ + [self placeCallWithVideo:YES]; +} + +- (IBAction)onIntegrationsPressed:(id)sender +{ + WidgetPickerViewController *widgetPicker = [[WidgetPickerViewController alloc] initForMXSession:self.roomDataSource.mxSession + inRoom:self.roomDataSource.roomId]; + + [widgetPicker showInViewController:self]; +} + - (IBAction)onButtonPressed:(id)sender { - // Search button - if (sender == self.navigationItem.rightBarButtonItem) - { - [self performSegueWithIdentifier:@"showRoomSearch" sender:self]; - } - // Matrix Apps button - else if (self.navigationItem.rightBarButtonItems.count == 2 && sender == self.navigationItem.rightBarButtonItems[1]) - { - if ([self widgetsCount:NO]) - { - WidgetPickerViewController *widgetPicker = [[WidgetPickerViewController alloc] initForMXSession:self.roomDataSource.mxSession - inRoom:self.roomDataSource.roomId]; - - [widgetPicker showInViewController:self]; - } - else - { - // No widgets -> Directly show the integration manager - IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] initForMXSession:self.roomDataSource.mxSession - inRoom:self.roomDataSource.roomId - screen:kIntegrationManagerMainScreen - widgetId:nil]; - - [self presentViewController:modularVC animated:NO completion:nil]; - } - } - else if (sender == self.jumpToLastUnreadButton) + if (sender == self.jumpToLastUnreadButton) { // Dismiss potential keyboard. [self dismissKeyboard]; - + // Jump to the last unread event by using a temporary room data source initialized with the last unread event id. MXWeakify(self); [RoomDataSource loadRoomDataSourceWithRoomId:self.roomDataSource.roomId initialEventId:self.roomDataSource.room.accountData.readMarkerEventId andMatrixSession:self.mainSession onComplete:^(id roomDataSource) { MXStrongifyAndReturnIfNil(self); - + [roomDataSource finalizeInitialization]; - + // Center the bubbles table content on the bottom of the read marker event in order to display correctly the read marker view. self.centerBubblesTableViewContentOnTheInitialEventBottom = YES; [self displayRoom:roomDataSource]; - + // Give the data source ownership to the room view controller. self.hasRoomDataSourceOwnership = YES; }]; @@ -3925,12 +3861,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo MXWeakify(self); [RoomDataSource loadRoomDataSourceWithRoomId:self.roomDataSource.roomId initialEventId:eventId andMatrixSession:self.mainSession onComplete:^(id roomDataSource) { MXStrongifyAndReturnIfNil(self); - + [roomDataSource finalizeInitialization]; ((RoomDataSource*)roomDataSource).markTimelineInitialEvent = YES; - + [self displayRoom:roomDataSource]; - + self.hasRoomDataSourceOwnership = YES; }]; } @@ -4004,7 +3940,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo MXWeakify(self); [self.roomDataSource.room liveTimeline:^(MXEventTimeline *liveTimeline) { MXStrongifyAndReturnIfNil(self); - + [liveTimeline removeListener:self->typingNotifListener]; self->typingNotifListener = nil; }]; @@ -4022,7 +3958,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo MXWeakify(self); self->typingNotifListener = [self.roomDataSource.room listenToEventsOfTypes:@[kMXEventTypeStringTypingNotification] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { MXStrongifyAndReturnIfNil(self); - + // Handle only live events if (direction == MXTimelineDirectionForwards) { @@ -4034,7 +3970,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { [typingUsers removeObjectAtIndex:index]; } - + // Ignore this notification if both arrays are empty if (self->currentTypingUsers.count || typingUsers.count) { @@ -4043,7 +3979,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } } }]; - + // Retrieve the current typing users list NSMutableArray *typingUsers = [NSMutableArray arrayWithArray:self.roomDataSource.room.typingUsers]; // Remove typing info for the current user @@ -4059,8 +3995,10 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)refreshTypingNotification { - if ([self.activitiesView isKindOfClass:RoomActivitiesView.class]) + if ([self.titleView isKindOfClass:RoomTitleView.class]) { + RoomTitleView *titleView = (RoomTitleView *)self.titleView; + // Prepare here typing notification NSString* text = nil; NSUInteger count = currentTypingUsers.count; @@ -4104,7 +4042,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_many_users_are_typing", @"Vector", nil), names[0], names[1]]; } - [((RoomActivitiesView*) self.activitiesView) displayTypingNotification:text]; + titleView.typingNotificationString = text; } } @@ -4199,7 +4137,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)listenWidgetNotifications { kMXKWidgetManagerDidUpdateWidgetObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kWidgetManagerDidUpdateWidgetNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { - + Widget *widget = notif.object; if (widget.mxSession == self.roomDataSource.mxSession && [widget.roomId isEqualToString:customizedRoomDataSource.roomId]) @@ -4221,10 +4159,10 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo error = [NSError errorWithDomain:error.domain code:error.code userInfo:@{ - NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"room_conference_call_no_power", @"Vector", nil) - }]; + NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"room_conference_call_no_power", @"Vector", nil) + }]; } - + // Alert user [[AppDelegate theDelegate] showErrorAsAlert:error]; } @@ -4238,7 +4176,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { widgetsCount += [[WidgetManager sharedManager] userWidgets:self.roomDataSource.room.mxSession].count; } - + return widgetsCount; } @@ -4249,38 +4187,41 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if ([self.activitiesView isKindOfClass:RoomActivitiesView.class]) { RoomActivitiesView *roomActivitiesView = (RoomActivitiesView*)self.activitiesView; - + // Reset gesture recognizers while (roomActivitiesView.gestureRecognizers.count) { [roomActivitiesView removeGestureRecognizer:roomActivitiesView.gestureRecognizers[0]]; } - + Widget *jitsiWidget = [customizedRoomDataSource jitsiWidget]; - + if ([self.roomDataSource.mxSession.syncError.errcode isEqualToString:kMXErrCodeStringResourceLimitExceeded]) { + self.activitiesViewExpanded = YES; [roomActivitiesView showResourceLimitExceededError:self.roomDataSource.mxSession.syncError.userInfo onAdminContactTapped:^(NSURL *adminContactURL) { [[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) { - if (!success) - { + if (!success) + { NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContactURL); - } + } }]; }]; } else if ([AppDelegate theDelegate].isOffline) { + self.activitiesViewExpanded = YES; [roomActivitiesView displayNetworkErrorNotification:NSLocalizedStringFromTable(@"room_offline_notification", @"Vector", nil)]; } else if (customizedRoomDataSource.roomState.isObsolete) { + self.activitiesViewExpanded = YES; MXWeakify(self); [roomActivitiesView displayRoomReplacementWithRoomLinkTappedHandler:^{ MXStrongifyAndReturnIfNil(self); - + MXEvent *stoneTombEvent = [self->customizedRoomDataSource.roomState stateEventsWithType:kMXEventTypeStringRoomTombStone].lastObject; - + NSString *replacementRoomId = self->customizedRoomDataSource.roomState.tombStoneContent.replacementRoomId; if ([self.roomDataSource.mxSession roomWithRoomId:replacementRoomId]) { @@ -4292,20 +4233,20 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Else auto join it via the server that sent the event NSLog(@"[RoomVC] Auto join an upgraded room: %@ -> %@. Sender: %@", self->customizedRoomDataSource.roomState.roomId, replacementRoomId, stoneTombEvent.sender); - + NSString *viaSenderServer = [MXTools serverNameInMatrixIdentifier:stoneTombEvent.sender]; - + if (viaSenderServer) { [self startActivityIndicator]; [self.roomDataSource.mxSession joinRoom:replacementRoomId viaServers:@[viaSenderServer] success:^(MXRoom *room) { [self stopActivityIndicator]; - + [[AppDelegate theDelegate] showRoom:replacementRoomId andEventId:nil withMatrixSession:self.roomDataSource.mxSession]; - + } failure:^(NSError *error) { [self stopActivityIndicator]; - + NSLog(@"[RoomVC] Failed to join an upgraded room. Error: %@", error); [[AppDelegate theDelegate] showErrorAsAlert:error]; @@ -4327,6 +4268,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } else { + self.activitiesViewExpanded = YES; [roomActivitiesView displayOngoingConferenceCall:^(BOOL video) { NSLog(@"[RoomVC] onOngoingConferenceCallPressed"); @@ -4353,54 +4295,55 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } else { + self.activitiesViewExpanded = YES; [roomActivitiesView displayOngoingConferenceCall:^(BOOL video) { - + NSLog(@"[RoomVC] onOngoingConferenceCallPressed (jitsi)"); - + __weak __typeof(self) weakSelf = self; NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; - + // Check app permissions first [MXKTools checkAccessForCall:video manualChangeMessageForAudio:[NSString stringWithFormat:[NSBundle mxk_localizedStringForKey:@"microphone_access_not_granted_for_call"], appDisplayName] manualChangeMessageForVideo:[NSString stringWithFormat:[NSBundle mxk_localizedStringForKey:@"camera_access_not_granted_for_call"], appDisplayName] showPopUpInViewController:self completionHandler:^(BOOL granted) { - - if (weakSelf) - { - if (granted) - { - // Present the Jitsi view controller - [appDelegate displayJitsiViewControllerWithWidget:jitsiWidget andVideo:video]; - } - else - { - NSLog(@"[RoomVC] onOngoingConferenceCallPressed: Warning: The application does not have the perssion to join the call"); - } - } - }]; - + + if (weakSelf) + { + if (granted) + { + // Present the Jitsi view controller + [appDelegate displayJitsiViewControllerWithWidget:jitsiWidget andVideo:video]; + } + else + { + NSLog(@"[RoomVC] onOngoingConferenceCallPressed: Warning: The application does not have the perssion to join the call"); + } + } + }]; + } onClosePressed:^{ - + [self startActivityIndicator]; - + // Close the widget __weak __typeof(self) weakSelf = self; [[WidgetManager sharedManager] closeWidget:jitsiWidget.widgetId inRoom:self.roomDataSource.room success:^{ - + if (weakSelf) { typeof(self) self = weakSelf; [self stopActivityIndicator]; - + // The banner will automatically leave thanks to kWidgetManagerDidUpdateWidgetNotification } - + } failure:^(NSError *error) { if (weakSelf) { typeof(self) self = weakSelf; - + [self showJitsiErrorAsAlert:error]; [self stopActivityIndicator]; } @@ -4418,13 +4361,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Retrieve the unread messages count NSUInteger unreadCount = self.roomDataSource.room.summary.localUnreadEventCount; - if (unreadCount == 0) - { - // Refresh the typing notification here - // We will keep visible this notification (if any) beside the "scroll to bottom" icon. - [self refreshTypingNotification]; - } - + self.activitiesViewExpanded = YES; [roomActivitiesView displayScrollToBottomIcon:unreadCount onIconTapGesture:^{ [self goBackToLive]; @@ -4433,17 +4370,19 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } else if (serverNotices.usageLimit && serverNotices.usageLimit.isServerNoticeUsageLimit) { - [roomActivitiesView showResourceUsageLimitNotice:serverNotices.usageLimit onAdminContactTapped:^(NSURL *adminContactURL) { + self.activitiesViewExpanded = YES; + [roomActivitiesView showResourceUsageLimitNotice:serverNotices.usageLimit onAdminContactTapped:^(NSURL *adminContactURL) { [[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) { - if (!success) - { + if (!success) + { NSLog(@"[RoomVC] refreshActivitiesViewDisplay: adminContact(%@) cannot be opened", adminContactURL); - } + } }]; }]; } else { + self.activitiesViewExpanded = NO; [self refreshTypingNotification]; } } @@ -4470,22 +4409,22 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { // Switch back to the room live timeline managed by MXKRoomDataSourceManager MXKRoomDataSourceManager *roomDataSourceManager = [MXKRoomDataSourceManager sharedManagerForMatrixSession:self.mainSession]; - + MXWeakify(self); [roomDataSourceManager roomDataSourceForRoom:self.roomDataSource.roomId create:YES onComplete:^(MXKRoomDataSource *roomDataSource) { MXStrongifyAndReturnIfNil(self); - + // Scroll to bottom the bubble history on the display refresh. self->shouldScrollToBottomOnTableRefresh = YES; - + [self displayRoom:roomDataSource]; - + // The room view controller do not have here the data source ownership. self.hasRoomDataSourceOwnership = NO; - + [self refreshActivitiesViewDisplay]; [self refreshJumpToLastUnreadBannerDisplay]; - + if (self.saveProgressTextInput) { // Restore the potential message partially typed before jump to last unread messages. @@ -4500,11 +4439,17 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)refreshMissedDiscussionsCount:(BOOL)force { // Ignore this action when no room is displayed - if (!self.roomDataSource || !missedDiscussionsBarButtonCustomView) + if (!self.roomDataSource || !missedDiscussionsBadgeLabel) { return; } + if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPhone) + { + missedDiscussionsBadgeLabel.text = nil; + return; + } + NSUInteger highlightCount = 0; NSUInteger missedCount = [[AppDelegate theDelegate].masterTabBarController missedDiscussionsCount]; @@ -4538,8 +4483,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo missedDiscussionsCount = missedCount; missedHighlightCount = highlightCount; - NSMutableArray *leftBarButtonItems = [NSMutableArray arrayWithArray: self.navigationItem.leftBarButtonItems]; - if (missedCount) { // Refresh missed discussions count label @@ -4552,65 +4495,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo missedDiscussionsBadgeLabel.text = [NSString stringWithFormat:@"%tu", missedCount]; } - [missedDiscussionsBadgeLabel sizeToFit]; - - // Update the label background view frame - CGRect frame = missedDiscussionsBadgeLabelBgView.frame; - frame.size.width = round(missedDiscussionsBadgeLabel.frame.size.width + 18); - - if ([GBDeviceInfo deviceInfo].osVersion.major < 11) - { - // Consider the main navigation controller if the current view controller is embedded inside a split view controller. - UINavigationController *mainNavigationController = self.navigationController; - if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) - { - mainNavigationController = self.splitViewController.viewControllers.firstObject; - } - UINavigationItem *backItem = mainNavigationController.navigationBar.backItem; - UIBarButtonItem *backButton = backItem.backBarButtonItem; - - if (backButton && !backButton.title.length) - { - // Shift the badge on the left to be close the back icon - frame.origin.x = ([GBDeviceInfo deviceInfo].displayInfo.display > GBDeviceDisplay4Inch ? -35 : -25); - } - else - { - frame.origin.x = 0; - } - } - - // Caution: set label background view frame only in case of changes to prevent from looping on 'viewDidLayoutSubviews'. - if (!CGRectEqualToRect(missedDiscussionsBadgeLabelBgView.frame, frame)) - { - missedDiscussionsBadgeLabelBgView.frame = frame; - } - - // Set the right background color - if (highlightCount) - { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.noticeColor; - } - else - { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.noticeSecondaryColor; - } - - if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) - { - missedDiscussionsButton = [[UIBarButtonItem alloc] initWithCustomView:missedDiscussionsBarButtonCustomView]; - - // Add it in left bar items - [leftBarButtonItems addObject:missedDiscussionsButton]; - } + missedDiscussionsBadgeLabel.textColor = highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.tintColor; } - else if (missedDiscussionsButton) + else { - [leftBarButtonItems removeObject:missedDiscussionsButton]; - missedDiscussionsButton = nil; + missedDiscussionsBadgeLabel.text = nil; } - - self.navigationItem.leftBarButtonItems = leftBarButtonItems; } } @@ -4622,7 +4512,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if ([self.activitiesView isKindOfClass:RoomActivitiesView.class]) { sentStatus = self.roomDataSource.room.sentStatus; - + if (sentStatus != RoomSentStatusOk) { NSString *notification = sentStatus == RoomSentStatusSentFailedDueToUnknownDevices ? @@ -4630,6 +4520,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo NSLocalizedStringFromTable(@"room_unsent_messages_notification", @"Vector", nil); RoomActivitiesView *roomActivitiesView = (RoomActivitiesView*) self.activitiesView; + self.activitiesViewExpanded = YES; [roomActivitiesView displayUnsentMessagesNotification:notification withResendLink:^{ [self resendAllUnsentMessages]; @@ -4651,40 +4542,40 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_resend_unsent_messages", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - [self resendAllUnsentMessages]; - self->currentAlert = nil; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + [self resendAllUnsentMessages]; + self->currentAlert = nil; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_delete_unsent_messages", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - [self cancelAllUnsentMessages]; - self->currentAlert = nil; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + [self cancelAllUnsentMessages]; + self->currentAlert = nil; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + } + + }]]; [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCUnsentMessagesMenuAlert"]; [currentAlert popoverPresentationController].sourceView = roomActivitiesView; @@ -4736,39 +4627,39 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"unknown_devices_verify"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - [self performSegueWithIdentifier:@"showUnknownDevices" sender:self]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + + [self performSegueWithIdentifier:@"showUnknownDevices" sender:self]; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"unknown_devices_send_anyway"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - // Acknowledge the existence of all devices - [self startActivityIndicator]; - [self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{ - - self->unknownDevices = nil; - [self stopActivityIndicator]; - - // And resend pending messages - [self resendAllUnsentMessages]; - }]; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + + // Acknowledge the existence of all devices + [self startActivityIndicator]; + [self.mainSession.crypto setDevicesKnown:self->unknownDevices complete:^{ + + self->unknownDevices = nil; + [self stopActivityIndicator]; + + // And resend pending messages + [self resendAllUnsentMessages]; + }]; + } + + }]]; [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCUnknownDevicesAlert"]; [self presentViewController:currentAlert animated:YES completion:nil]; @@ -4779,7 +4670,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { MXEvent *event = notif.object; NSString *previousId = notif.userInfo[kMXEventIdentifierKey]; - + if ([customizedRoomDataSource.selectedEventId isEqualToString:previousId]) { NSLog(@"[RoomVC] eventDidChangeIdentifier: Update selectedEventId"); @@ -4834,7 +4725,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)cancelAllUnsentMessages { currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_unsent_messages_cancel_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"room_unsent_messages_cancel_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert]; - + MXWeakify(self); [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { MXStrongifyAndReturnIfNil(self); @@ -4856,8 +4747,10 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo index ++; } } + + [self refreshActivitiesViewDisplay]; }]]; - + [self presentViewController:currentAlert animated:YES completion:nil]; } @@ -4973,21 +4866,21 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - - readMarkerTableViewCell.readMarkerViewLeadingConstraint.constant = readMarkerTableViewCell.readMarkerViewTrailingConstraint.constant = readMarkerTableViewCell.bubbleOverlayContainer.frame.size.width / 2; - readMarkerTableViewCell.readMarkerView.alpha = 0; - - // Force to render the view - [readMarkerTableViewCell.bubbleOverlayContainer layoutIfNeeded]; - - } + + readMarkerTableViewCell.readMarkerViewLeadingConstraint.constant = readMarkerTableViewCell.readMarkerViewTrailingConstraint.constant = readMarkerTableViewCell.bubbleOverlayContainer.frame.size.width / 2; + readMarkerTableViewCell.readMarkerView.alpha = 0; + + // Force to render the view + [readMarkerTableViewCell.bubbleOverlayContainer layoutIfNeeded]; + + } completion:^(BOOL finished){ - - readMarkerTableViewCell.readMarkerView.hidden = YES; - readMarkerTableViewCell.readMarkerView.alpha = 1; - - readMarkerTableViewCell = nil; - }]; + + readMarkerTableViewCell.readMarkerView.hidden = YES; + readMarkerTableViewCell.readMarkerView.alpha = 1; + + readMarkerTableViewCell = nil; + }]; }); } @@ -5066,110 +4959,110 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; + + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + } + + }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"invite", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - // Sanity check - if (!weakSelf) - { - return; - } - - typeof(self) self = weakSelf; - self->currentAlert = nil; - - MXSession* session = self.roomDataSource.mxSession; - NSString* roomId = self.roomDataSource.roomId; - MXRoom *room = [session roomWithRoomId:roomId]; - - NSArray *identifiers = contact.matrixIdentifiers; - NSString *participantId; - - if (identifiers.count) - { - participantId = identifiers.firstObject; - - // Invite this user if a room is defined - [room inviteUser:participantId success:^{ - - // Refresh display by removing the contacts picker - [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; - - } failure:^(NSError *error) { - - NSLog(@"[RoomVC] Invite %@ failed", participantId); - // Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - - }]; - } - else - { - if (contact.emailAddresses.count) - { - // This is a local contact, consider the first email by default. - // TODO: Prompt the user to select the right email. - MXKEmail *email = contact.emailAddresses.firstObject; - participantId = email.emailAddress; - } - else - { - // This is the text filled by the user. - participantId = contact.displayName; - } - - // Is it an email or a Matrix user ID? - if ([MXTools isEmailAddress:participantId]) - { - [room inviteUserByEmail:participantId success:^{ - - // Refresh display by removing the contacts picker - [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; - - } failure:^(NSError *error) { - - NSLog(@"[RoomVC] Invite be email %@ failed", participantId); - // Alert user - if ([error.domain isEqualToString:kMXRestClientErrorDomain] - && error.code == MXRestClientErrorMissingIdentityServer) - { - NSString *message = [NSBundle mxk_localizedStringForKey:@"error_invite_3pid_with_no_identity_server"]; - [[AppDelegate theDelegate] showAlertWithTitle:message message:nil]; - } - else - { - [[AppDelegate theDelegate] showErrorAsAlert:error]; - } - }]; - } - else //if ([MXTools isMatrixUserIdentifier:participantId]) - { - [room inviteUser:participantId success:^{ - - // Refresh display by removing the contacts picker - [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; - - } failure:^(NSError *error) { - - NSLog(@"[RoomVC] Invite %@ failed", participantId); - // Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - - }]; - } - } - - }]]; + + // Sanity check + if (!weakSelf) + { + return; + } + + typeof(self) self = weakSelf; + self->currentAlert = nil; + + MXSession* session = self.roomDataSource.mxSession; + NSString* roomId = self.roomDataSource.roomId; + MXRoom *room = [session roomWithRoomId:roomId]; + + NSArray *identifiers = contact.matrixIdentifiers; + NSString *participantId; + + if (identifiers.count) + { + participantId = identifiers.firstObject; + + // Invite this user if a room is defined + [room inviteUser:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite %@ failed", participantId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + else + { + if (contact.emailAddresses.count) + { + // This is a local contact, consider the first email by default. + // TODO: Prompt the user to select the right email. + MXKEmail *email = contact.emailAddresses.firstObject; + participantId = email.emailAddress; + } + else + { + // This is the text filled by the user. + participantId = contact.displayName; + } + + // Is it an email or a Matrix user ID? + if ([MXTools isEmailAddress:participantId]) + { + [room inviteUserByEmail:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite be email %@ failed", participantId); + // Alert user + if ([error.domain isEqualToString:kMXRestClientErrorDomain] + && error.code == MXRestClientErrorMissingIdentityServer) + { + NSString *message = [NSBundle mxk_localizedStringForKey:@"error_invite_3pid_with_no_identity_server"]; + [[AppDelegate theDelegate] showAlertWithTitle:message message:nil]; + } + else + { + [[AppDelegate theDelegate] showErrorAsAlert:error]; + } + }]; + } + else //if ([MXTools isMatrixUserIdentifier:participantId]) + { + [room inviteUser:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite %@ failed", participantId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + } + + }]]; [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCInviteAlert"]; [self presentViewController:currentAlert animated:YES completion:nil]; @@ -5188,22 +5081,22 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self presentReviewUnverifiedSessionsAlert]; return; } - + // Make the re-request [self.mainSession.crypto reRequestRoomKeyForEvent:event]; - + // Observe kMXEventDidDecryptNotification to remove automatically the dialog // if the user has shared the keys from another device mxEventDidDecryptNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXEventDidDecryptNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { MXStrongifyAndReturnIfNil(self); - + MXEvent *decryptedEvent = notif.object; - + if ([decryptedEvent.eventId isEqualToString:event.eventId]) { [[NSNotificationCenter defaultCenter] removeObserver:self->mxEventDidDecryptNotificationObserver]; self->mxEventDidDecryptNotificationObserver = nil; - + if (self->currentAlert == alert) { [self->currentAlert dismissViewControllerAnimated:YES completion:nil]; @@ -5211,51 +5104,51 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } } }]; - + // Show the explanation dialog alert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"rerequest_keys_alert_title", @"Vector", nil) - message:NSLocalizedStringFromTable(@"rerequest_keys_alert_message", @"Vector", nil) - preferredStyle:UIAlertControllerStyleAlert]; + message:NSLocalizedStringFromTable(@"rerequest_keys_alert_message", @"Vector", nil) + preferredStyle:UIAlertControllerStyleAlert]; currentAlert = alert; - - + + [alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) - { - MXStrongifyAndReturnIfNil(self); - - [[NSNotificationCenter defaultCenter] removeObserver:self->mxEventDidDecryptNotificationObserver]; - self->mxEventDidDecryptNotificationObserver = nil; - - self->currentAlert = nil; - }]]; - + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + MXStrongifyAndReturnIfNil(self); + + [[NSNotificationCenter defaultCenter] removeObserver:self->mxEventDidDecryptNotificationObserver]; + self->mxEventDidDecryptNotificationObserver = nil; + + self->currentAlert = nil; + }]]; + [self presentViewController:currentAlert animated:YES completion:nil]; } - (void)presentReviewUnverifiedSessionsAlert { NSLog(@"[MasterTabBarController] presentReviewUnverifiedSessionsAlertWithSession"); - + [currentAlert dismissViewControllerAnimated:NO completion:nil]; - + UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"key_verification_self_verify_unverified_sessions_alert_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"key_verification_self_verify_unverified_sessions_alert_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert]; - + [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"key_verification_self_verify_unverified_sessions_alert_validate_action", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - [self showSettingsSecurityScreen]; - }]]; - + [self showSettingsSecurityScreen]; + }]]; + [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"later", @"Vector", nil) style:UIAlertActionStyleCancel handler:nil]]; - + [self presentViewController:alert animated:YES completion:nil]; - + currentAlert = alert; } @@ -5306,12 +5199,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)listenMXSessionStateChangeNotifications { kMXSessionStateDidChangeObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:self.roomDataSource.mxSession queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { - + if (self.roomDataSource.mxSession.state == MXSessionStateSyncError || self.roomDataSource.mxSession.state == MXSessionStateRunning) { [self refreshActivitiesViewDisplay]; - + // update inputToolbarView [self updateRoomInputToolbarViewClassIfNeeded]; } @@ -5408,10 +5301,10 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo fromSingleTapGesture:usedSingleTapGesture animated:animated completion:^{ - }]; + }]; preventBubblesTableViewScroll = YES; - [self selectEventWithId:selectedEventId]; + [self selectEventWithId:selectedEventId]; } - (void)hideContextualMenuAnimated:(BOOL)animated @@ -5466,7 +5359,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self cancelEventSelection]; [self.roomDataSource resendEventWithEventId:event.eventId success:nil failure:nil]; }; - + return resendMenuItem; } @@ -5494,7 +5387,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self presentViewController:self->currentAlert animated:YES completion:nil]; }]; }; - + return deleteMenuItem; } @@ -5507,7 +5400,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo MXStrongifyAndReturnIfNil(self); [self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil]; [self editEventContentWithId:event.eventId]; - + // And display the keyboard [self.inputToolbarView becomeFirstResponder]; }; @@ -5521,7 +5414,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell *)cell; MXKAttachment *attachment = roomBubbleTableViewCell.bubbleData.attachment; - + MXWeakify(self); BOOL isCopyActionEnabled = !attachment || attachment.type != MXKAttachmentTypeSticker; @@ -5609,7 +5502,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo }]; } }; - + return copyMenuItem; } @@ -5624,7 +5517,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil]; [self selectEventWithId:event.eventId inputToolBarSendMode:RoomInputToolbarViewSendModeReply showTimestamp:NO]; - + // And display the keyboard [self.inputToolbarView becomeFirstResponder]; }; @@ -5642,7 +5535,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self hideContextualMenuAnimated:YES completion:nil]; [self showAdditionalActionsMenuForEvent:event inCell:cell animated:YES]; }; - + return moreMenuItem; } @@ -5702,7 +5595,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (cellRow >= 0) { - NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:cellRow inSection:0]; + NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:cellRow inSection:0]; UITableViewCell *cell = [self.bubblesTableView cellForRowAtIndexPath:cellIndexPath]; sourceView = cell; diff --git a/Riot/Modules/Room/RoomViewController.xib b/Riot/Modules/Room/RoomViewController.xib index 15ac46dc7..1d1205661 100644 --- a/Riot/Modules/Room/RoomViewController.xib +++ b/Riot/Modules/Room/RoomViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -13,6 +13,7 @@ + @@ -36,7 +37,7 @@ - + @@ -51,10 +52,18 @@ + + + + + + + + @@ -153,9 +91,8 @@ - - + @@ -164,19 +101,14 @@ - - - - - + - - - - + + + diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.h b/Riot/Modules/Room/Views/Title/RoomTitleView.h index 882d79fda..a96cb2d26 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.h @@ -35,9 +35,11 @@ @interface RoomTitleView : MXKRoomTitleView @property (weak, nonatomic) IBOutlet UIView *titleMask; -@property (weak, nonatomic) IBOutlet NSLayoutConstraint *displayNameCenterXConstraint; -@property (weak, nonatomic) IBOutlet UIImageView *roomDetailsIconImageView; @property (weak, nonatomic) IBOutlet UIImageView *badgeImageView; +@property (weak, nonatomic) IBOutlet MXKImageView *pictureView; +@property (weak, nonatomic) IBOutlet UILabel *missedDiscussionsBadgeLabel; +@property (weak, nonatomic) IBOutlet UILabel *typingLabel; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *displayNameCenterYConstraint; /** The room preview data may be used when mxRoom instance is not available @@ -49,6 +51,11 @@ */ @property (nonatomic) id tapGestureDelegate; +/** + the typing notification string to be displayed (default nil if notification is hidden). + */ +@property (copy, nonatomic) NSString *typingNotificationString; + /** The method used to handle the gesture recognized by a receiver. */ diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 679fd719f..1680095fd 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -54,8 +54,8 @@ { [super layoutSubviews]; - self.roomDetailsIconImageView.image = self.roomDetailsIconImageView.image; - + self.pictureView.layer.cornerRadius = self.pictureView.bounds.size.width / 2.; + if (self.superview) { // Force the title view layout by adding 2 new constraints on the UINavigationBarContentView instance. @@ -84,7 +84,7 @@ self.backgroundColor = UIColor.clearColor; self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? ThemeService.shared.theme.textPrimaryColor : ThemeService.shared.theme.textSecondaryColor); - self.roomDetailsIconImageView.tintColor = ThemeService.shared.theme.textPrimaryColor; + self.typingLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -133,4 +133,34 @@ } } +- (void)setTypingNotificationString:(NSString *)typingNotificationString +{ + if (typingNotificationString.length > 0) + { + self.typingLabel.text = typingNotificationString; + [self layoutIfNeeded]; + + [UIView animateWithDuration:.3 animations:^{ + self.typingLabel.alpha = 1; + self.displayNameCenterYConstraint.constant = -8; + [self layoutIfNeeded]; + }]; + } + else + { + [UIView animateWithDuration:.3 animations:^{ + self.typingLabel.alpha = 0; + self.displayNameCenterYConstraint.constant = 0; + [self layoutIfNeeded]; + } completion:^(BOOL finished) { + self.typingLabel.text = nil; + }]; + } +} + +- (NSString *)typingNotificationString +{ + return self.typingLabel.text; +} + @end diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.xib b/Riot/Modules/Room/Views/Title/RoomTitleView.xib index 47d170601..0fbeea444 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.xib +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.xib @@ -1,9 +1,9 @@ - + - + @@ -13,69 +13,82 @@ + + + + + + + + + + - + - - + + - + - - - - - - - - - + - - + + - - - - - - + + + + - + + + + - + - + - - + + + - diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index fbf30cb3a..f8ff71ea5 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -23,6 +23,8 @@ #import "DirectoryServerPickerViewController.h" #import "MXSession+Riot.h" #import "RoomFilesViewController.h" +#import "RoomSearchViewController.h" +#import "IntegrationManagerViewController.h" #import "RoomSettingsViewController.h" #import "JitsiWidgetData.h" #import "InviteRecentTableViewCell.h" From 07f1ec19feb1b9d68bff34731d9fe5fff87a2ab0 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 15 Mar 2021 14:36:37 +0100 Subject: [PATCH 004/140] Composer Update - Typing and sending a message - Code tweaks --- Riot/Modules/Room/RoomViewController.m | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 53ad7d9ba..9647d21cd 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -673,7 +673,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo previewHeader.mainHeaderBackgroundHeightConstraint.constant = mainHeaderBackgroundHeight; // Force the layout of previewHeader to update the position of 'bottomBorderView' which - // is used to define the actual of the preview container. + // is used to define the actual height of the preview container. [previewHeader layoutIfNeeded]; } } @@ -1288,10 +1288,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)setShowMissedDiscussionsBadge:(BOOL)showMissedDiscussionsBadge { - BOOL toto = [UIDevice currentDevice].userInterfaceIdiom != - UIUserInterfaceIdiomPhone || !showMissedDiscussionsBadge; - missedDiscussionsBadgeLabel.hidden = [UIDevice currentDevice].userInterfaceIdiom != - UIUserInterfaceIdiomPhone || !showMissedDiscussionsBadge; + missedDiscussionsBadgeLabel.hidden = !showMissedDiscussionsBadge; } #pragma mark - Internals @@ -1633,7 +1630,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo self.roomInfoCoordinatorBridgePresenter = [[RoomInfoCoordinatorBridgePresenter alloc] initWithParameters:parameters]; self.roomInfoCoordinatorBridgePresenter.delegate = self; -// [self.roomInfoCoordinatorBridgePresenter presentFrom:self animated:true]; [self.roomInfoCoordinatorBridgePresenter pushFrom:self.navigationController animated:YES]; } From 400e437d371bb5792283da6903c9ae9b0e6773f3 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 15 Mar 2021 15:12:15 +0100 Subject: [PATCH 005/140] Composer Update - Typing and sending a message - Updated shield icons --- .../encryption_normal.imageset/Contents.json | 12 ++++++------ .../encryption_normal.png | Bin 384 -> 339 bytes .../encryption_normal@2x.png | Bin 627 -> 537 bytes .../encryption_normal@3x.png | Bin 913 -> 760 bytes .../encryption_trusted.imageset/Contents.json | 12 ++++++------ .../encryption_trusted.png | Bin 476 -> 414 bytes .../encryption_trusted@2x.png | Bin 804 -> 724 bytes .../encryption_trusted@3x.png | Bin 1156 -> 973 bytes .../encryption_warning.imageset/Contents.json | 12 ++++++------ .../encryption_warning.png | Bin 423 -> 363 bytes .../encryption_warning@2x.png | Bin 688 -> 601 bytes .../encryption_warning@3x.png | Bin 980 -> 836 bytes 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/Contents.json b/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/Contents.json index 91448ccb6..3b025c1f0 100644 --- a/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/Contents.json @@ -1,23 +1,23 @@ { "images" : [ { - "idiom" : "universal", "filename" : "encryption_normal.png", + "idiom" : "universal", "scale" : "1x" }, { - "idiom" : "universal", "filename" : "encryption_normal@2x.png", + "idiom" : "universal", "scale" : "2x" }, { - "idiom" : "universal", "filename" : "encryption_normal@3x.png", + "idiom" : "universal", "scale" : "3x" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal.png b/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal.png index c628f322ab8e7df9d1f339202ed5a039f60e8fcc..6222e3d16183125ea075150fac17c015ad0f7b0a 100644 GIT binary patch delta 297 zcmV+^0oMM21JeQ_iBL{Q4GJ0x0000DNk~Le0000C0000C2nGNE09JKe=aC^ae*ox7 zL_t(|0lktz3W87&hDQ%z?II{>Z;O`Y$|9(3igtjgb={yF)By^&<|T6VY}q2$3AXp) z1zs~EWuQcxe)t)f`Q|;|n*qorgs7u+^d5cB?NAO1k}%Q1xI^nK2 z8MUJZBV3<%fRJ`7^)Vg}`gE-m+@S^y<{$YAmdf)yS*h0K=ht`0VyP^BE#JpVM;k9f plFSu?Tvw>SU{PGKDf^Hy4)#TendXDDH9-IX002ovPDHLkV1fpOk%<5R diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal@2x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal@2x.png index 07555f27b507248350c4bf6b3a9d187cb4e52caa..e1ff179133623f6f007e0a60d900763a868f7ce1 100644 GIT binary patch delta 497 zcmVmzre*vyZ zL_t(|0qs^jPXa*@o%07EoiTxg#+Y~%7RCsTXp9`CAJi6#tx@QOT8R7uu|qLRi4|u9 zc4{Iu1nl|v1MAFY?^rGedWUwr89 zW4JW327>{7HX2Z=JVWuW#OHSK`+X1&g&-D-^62q+K+?L5~K@m*@)fLyewn(4xVnwm615f7EEo20C91 zs#BeUo?es*!iQ;qHG__$Q^IND7~DeBqQ<3;nk~~nAVWhUal)&lQ_!AN^1_%Fj0@91 z)bBE#;_;#6$b@pGJq6UdHFf1g>SP$+kbzF;3-%A=K+%DC3%O;y9$QfB6MdKCDw|_# z>le^x9h|Ag2R>~8i?pttBdMWa#nyJe`oy^TgjhRN^u zQwO&d-Ag}fnwD?{;KY+MX~2FSNe#nbKT|T9Bsb~0PQl+YuRF^-2h@ZU@iArwxu}c2JnCbHWIJ3w78IKUXlv{I@6#XA0H#Hgjl-X zf@Z?L6BYn)C!Ws~S;X_6ybFkdSW+8mf5BJ45GWoFv3s4Lom2#YYtPS4t(_1t)w{Ry zIbA3#B7@zH0%T@(p=2SVe+pI7!Tw%u>SLU|$7!77Iv^hf-ozO0;`ZkHPwxcA;?8CA zh>YbZtyC~n!2Gj}b~yYkM@O diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal@3x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_normal.imageset/encryption_normal@3x.png index 85e974954d12eefba707fde9226614a6d3feb9d0..ce4f7314a88157712fbba394d5c79bc433a1dcb3 100644 GIT binary patch delta 722 zcmV;@0xkWK2lxdciBL{Q4GJ0x0000DNk~Le0000a0000a2nGNE0O0_bn2{kge*%q3 zL_t(|0qvMEZ__{&$6xpWAxsDD@xTnzp`a60zkw_R21cj^{yGXS&8j>A+|(=c;$P}FtEW;K66j~@qSDIpk~4G_`mR+6U-D4p2q&1G z`ww)_LVj9FvQtH%Ejw_1_I%AmhU-|IufKf*VN1AY&j~XI#MQJ9sP28;d<9`?Wx2ub z>Cmj$XAFpEsbR;p+H-cJi;5mhm^)1zt2Z{j*9~w!ZNllok%^W>fAz*v;5kKehF+79 z8Cn=F%KCf$b>Ib6y3meKmn|)*l;^>(=u7?jWlx0J@`CXt%+#v5wQ+phw_es8*3DaK zsp+@Z2$lO07*qoM6N<$ Ef}o^NKL7v# delta 876 zcmV-y1C#vt1(63KiBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj#Pe*-2- zL_t(|0qvQ;Z__{&$6pX@MOQLqB20iFok`fK!U(AZT}nCuJ0(fGfhxk(z|vMCu+qTX zn3V>Vk+Q@~!q`ap1I+u{=hj@#j`PF0fc%l3Y+tYO_v?G-7M=!EwNI z<`Yd~K!}Fm+v4ae`jEv!^a+c1MF-)US;}N6nY`@R4U^yCfDst#Q5XYaf0FHz^Td5c zABd;iYJI0k$YgHO^77qbW&n(=%0^TM%6urv?cMHg7TvG~Pb%6Em~ql9=V#^_8>o64 z0u3M~4x3F*k1uSXOS2@MzG53%DHObBDr}(a?RPQgLm<9Zdq+CJ!$aT&uwH!Z+wTJX z(P&5#Y6eA@>{}aXlid)AVDYxzAt8J>+ zKhQK$h&MTM!^-kuYojSXU?fs*8_F#^wYM}4kn>X7m=r=h2))6fGJ(<}Mq}Kf7v6By z*W2=hH7TTcFwzcFDxQ&DfY-<#7B60LfkE-NMTWrtl-T)?5RDa zc}ApFSu%1e+NPc^k!^GXj0hhtaqN%sYK)1A3C|y~)ndIUFZeJ30000Oon%B)(Ah!&DW7Ju47o)d0JYkq9|O~X53?QePlZNdV=wz>RQG{N^L8?L+Lbc z^CB}RjzGQg@)qTAC=D==0;PNV+Yt8Kjo7YL1l3XE1xN#>jyy>`jdOZ3NzD+MD4C<8 S>~69E0000D#}xurJ&Ye~zW{Jl-j{r;Zj+yYDxAtXi(LF7Pt=+^sp-ylP^ z&>}khcR$Ax!Ps=cYOlmb4U10k7(SUA$gM>Vv>ah$>eDpF55 zI)0Hrw%!0kJUc8brrOe?jLEkul{6gFXs{_-s12a889CrgJz{fiXilFw*f8o?zf0QoW(GF^S zB4auQ*p-`5f0aF9A(^AM61{M&fTP@(E$w9ezV0~*_DT6@!XDvRfD=-~5V7=liEp*W zVEX2(l`RUNBU}bA(L<$t7-Z+^n#|l(ZI>P{i19U`N4f%jM9)0BOM}{am;DPx2r7ii dQ-MMB3rHo+VFe!P(*OVf2>?k&PDHLkV1nC~zJ&k) diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_trusted.imageset/encryption_trusted@2x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_trusted.imageset/encryption_trusted@2x.png index 02488c979930704f7d79ed2bf9926c351b6b090e..361df06c02c08eae8e223da728cf8d100c795b30 100644 GIT binary patch delta 685 zcmV;e0#f~?2Gj*1iBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_>mzse`!fX zK~#7FrB+L5Q$ZBHDNkELeb0qb!Gs99swq-;A;om5?ZTaqE?l{=8@IZ$-Kfi~bZG;A zSFKQVnMkXk5Pyldu$ZI~m3EQWA|ztrdC%+2IHsAG-+?oe%;%i>+?jbqZQyyH!%Q;M z%#z?elu@q`qF0#<%$jFLO|-ehe~h-$3TdKA&dxHEf(pxSl~!t1T4n-Mhfh%AP?$#d zA8FQm&wRmL4242DWx(RIoZXPE-0cPxer?dw`YJvAS)|SF-_#0`p@WogBEs+(Io6O~ zJ;x@q)_)`A5#B1jV)1pOsE)P9mOlUxNH}4-emqX&JUfX2y~7HYg4v09e=ErTItHju zVANPD6Z$fk9v-1*V;3nke9G9yq8@>@1}lwCy8A6}Y}eBabn(fzPXhO>YXd0`Kpc@2 z1f#+2lM_^oU#3ZpalK56U;C16D-Ia;m1X=E>$mG<|f$ufthEStpPN zE)v@sR2A4bXV0KN;+gOne^tJ;vFaO`plSG;a*4`FVoi4ogdY6(r2b=5uY7(^L5Lkt z8YO)OIV7W8i4o{g0YTf^OObsJr9LhMMhyCnJL;PFpk~0A5~h8>f z_rDjs`0I>!F8|oO`Sqpe{;BJ4b6U*4J8-Ad%xu7;pY7}GqRD7p`)o;fD*P7<%79Em T^Loqx0000z0UuIA}s#9K_bittk$5tJ1;EN*$e&ZVu8U zyR_NtpluvlIuw&Zp@Jr%f)$jWg0*1be4j7hC71h`YfMuLec;Vq?!NDRe&64GAv(^| zbv=%tZc3V_ICk`g${h2D0>epzf6{c`Vyc&a@95>-rboIggR*0&+bX}}X3Cc_jwDBv zqn@bnqry?GU!h2Uh>~X_6dO{-y+w;M3W}msJOS8vLYl_S&taC|-lY7uO{(r{Wu1-z80O(X zZOfSZye^h)R{*T$Pd^rD`oog1y1oFgsqEjHp^a;kwsCbbNBEU50Amx041{Ro`lK)w z-}{I8`~9}fodCo>s|K2Xe?!tdo|QkfEg0|KaEs9^XnF8-uP<{0+VF4#DB@#uc%!IuS?U3&YRTmF;&e@7U5OjJ2s6IKA* zD&PV*Jfu+plg%`F+A=py)U?%H_&HUSC!%GJC=MWrwd{d=0!tJVRd#)m%`ZBYQ`{1m zAut>m>$&ne`4Pr^h9{kD`3lD!2G9-!U;;_;5VzjIF8LyQ+q{aIk6h%m>3arUn8k^J7fMLn^a(Tmzw^Ravx vW$Cblle7FIVpUl#;qJ%;f=JSdj;sCwPKd4rD_Fx!00000NkvXXu0mjfA9!#b diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_trusted.imageset/encryption_trusted@3x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_trusted.imageset/encryption_trusted@3x.png index 9154725c9392d4f51d3798edd699e14903b6f34a..7abd021d44f8d89d579b9d5c0828d00b38be52c5 100644 GIT binary patch delta 936 zcmV;Z16TZn3C#x~iBL{Q4GJ0x0000DNk~Le0000a0000a2nGNE0O0_bn2{kge*3(;v&5F}cKAtbpEgVX5QTQJ@ZET!{NR+^WMF`cka3Oo_mRk zR5qIpu=TRdvKNrEYzZ0~4v`;HPB6P?=Mrx|4rv7tnG*H({J%L8DQJC#1gN0Ec*KrDUx zNE^vGZKmRsKK?^)RO3HQ-3&EQ+iK-Kc&g77XoDNxWB?VyO9iWH8Lo}`8Sqk7oes!v z^wP}NEzdzzq03?T*w>fu=>9)N|Cvq%2yx_8Wd#DrT>CAGUw@zkwiEfOOacsIBq##c z>F6wrhcFLmVP+1tIFOGVf4%Fuhg6s*G2c9kzf*vm%2N-?Fgxs($;g_kIy?iCVPcsy z4eo@trHh8@J9IFBUHZO9#mbR~u&$vYf7MHflfAC{y64=E zC?jb-6jLvnE30)6q9Los5X5d^nkx&^khBp{E^`a!(*hloQBVU0LF^`1LhNa@Z3Gmy z1A-* zM@3jZMnA8*9^Qx3#vZ#G-vk=|cPlL?dKFU~Fi0000< KMNUMnLSTY8)vtH} delta 1121 zcmV-n1fKiN2ZRYBiBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj#Pe*_sx zL_t(|0qt4OPZL2Dekdm50U9*{6A6VxA$n*p1~rj_B;pCsgGUfeIHGdkrhtC{0q^|k z(ZmGw#DP#QCdLrxL4#hp6%QrBP)q<1ChPmAyG_~7>~6O$#iU>IGP~1h`+f7{y_q*e zWt0{bR3zxS?&G4LEy=c8QBk4Me@O?E_Op$$t?1c6-7~bIlLRKzZjg@Y?y=4`$rhwi zz#t6*yLK!iJ27DnK!aKQCV7CXHK3>FGkU9+QuEp;YnS}{hoXB43U5VeG4V~j1HQ_$ z)Kk|?-E}RZw1LJJVO!)ivq1R>Fi3-N$S9Sh-!s|ytqmr>ohEGuA*Qy4e?k`<$Y14C zHN)bMut5j}CCQBdW0B2Ls>hY2!#}u}w>N3^SDf-e=t2YaT@E^l0U%_+Dnuq=jEhlg zy>^hK@Xsg{*77E;0>t$2$aG(7R*8AR0wyynD(!wS`a2=!@;nodA0(;RK*zv_zb;Xr zx=sihYHH0Clcma50LZ`of4)kk06GumJ9Cy^T@5MQoudC7WdWr|Nd*L|YiX@*kk;-D zIt4f-N+tm0mv8k8Zxg7gqv=2oc|l18z&(OIJdBAw7ZF^BN;+or*9WqC8U!smNI-U6`GbORar_+c_H@_=UnAhgppLOb_IY$GLrf6ry)@8(G!@GRiv zl~8&Sf}l!->@$-*%6#EjfYocrh!&eXAQPaO5B_uN{W-jbW+4Hx6W8vgp9?`A@gf6R zUzE8~&3tG(-#{vu3vl^%-;urhP}5EJ^L`PWC{OZ$r4u)-pUXx7jgsbUo5!R6? z6#0g#8WE{Y@L?ume{GW`z&Ns{mG=BYFI1fBliP(Y&mkRDdy5FySg^g1zJfs|cK(@t*X!$C(Kpi5n5w^buT10VC10 zV!q>Od0fX!i3e*`^g3SWzkl zB>N>yoesP2xDfzHyw2t~>xRE9(VN&ODkLQ2HMS0?w7lb1!f>k{lo8-2u6H?Z;BtXv zv!{^@@`4|^gpqQ@bn=^Zi-}D!8u7zD@&atd-`#j5B6kKfa!DS@>4wIbPRN_4{VFnc z@J`6y;xroQ_32=@EW*Rvj8Ts8d`D)) z35l`jhnq{q%=%VR(-1 zOD}UKjcHk0Fo|AWaz_Rs3gR)ZS4u?%lX|S%U-m)GH*-44Fs9X*MaZsESMcdlw2N*4 nBfU-I?zo}cgDd(H(y_`aVbn#48n5pu&mBp}G4lU)%_*tZ<)DcR z8e5m*7I7-1!reJyz6_F7DCB{~e+)46rY0Snm`tve14ekhDDKH$O{vI7VJe_52-Q@` zD82R#$Y%c*TwoM`y?n`ZfuZx)(S#5#1ub+taq#W{r*ph+nJi#Yt`ps1ib3D~c1Ct3 z>>B&VL!QHkmm(6Oc~r@4aj_P< zK~#7F%~LH;13?gdSIHr2Km!s|Ndm4OgQ>w3gFyfW6iKf^kW>&7f(L`)M-&tdpeP`@ zljIOIVHZ2h>~>j7KhkSWU-Ir_=gsWwzFlAdh$t^a7POOgnRWV7pJY*ImYH+^^?^&` zSDCpEt&6yO1RD21^TnzPOTfx9f3V67!y6vCVBQ8nkhlU7iz~Rg2Hp}tf7`?bo=|BZ z{qR#37J-eD6s>ZBDEAv^zFN9u!4@}l9Ch~WbZz7?CMKsq3$rubQQ40)?H;$Q(nBc%`Q~@zr>6t6bqBTQ%jH{r|kQs zvCS<<>}ovtnI*;=@xO0}a;WG%B|14LS}R!|)rgcLbKr)7oOxz!3Ozl$yHG?{aMI>T biCORiGZCXIzK8&^00000NkvXXu0mjfoZ6pi diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_warning.imageset/encryption_warning@2x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_warning.imageset/encryption_warning@2x.png index 15bd69270b338ecdee0bdd7bc1ae973c4cd1e16f..d99aa7fa100f8fa3abfdef726c5b88b9a2176661 100644 GIT binary patch delta 562 zcmV-20?qxf1=$24iBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_>mzre*x}E zL_t(|0i{+UP{S}3{pF^p!LUhsljFFCfIEGKS|rPYqtd6-D`SH@?P@ulN4YIJkOg$mXQr)SMZ#^!CxUntH^6) z-%CedwAn#gNm_;^TE=1xSr!cOf7U_1a}r7`080gcycO4bK|UZ`hG95?0gBsL90bjV zLx7J@fX63*J8U-`K_asAXtW5hTI7bNDc9D}#Lh%ViX*(dLUA`;R7UR`;NIaRkjeHI zHx-zP8gw{S#FOCnmoNi5FlRY6pl(3%Jv-*qFv%#lWTQ7jGsQ5f&wv)xe+OlmBJ|e4 z7uHAu^$-z$Mw}YZGwAiSv&c6XuxE59j^prTdi+BTrs=PN%bxj#$(?iA$SzGpsL_=T z9A0Tn4nZA{tG(UydK!H=fY-nP52XP!p$3)BbO8#{=|y^dsp!8ssObg<0yXxmZ17Vu z3G%@f2lb(Yj-%#e{Qi^)a`VWG;!*aV||*a6-?8R+tE#i#WT`^FWkBNc60|% z7k82Cet5qQ~usp-bW6Ah%9*vKmTK(nFC=;l^rN@rAb6OOG%X!ailyXHxQ*vq$FKBOht!G0Ug3L zNQeSlKn227AZRQh=m3}46u5zQnSXarcem%evn+!^@-L0=wKwza<7UUeLzYr1N5fsp z1}%wQsz7IA3%3FzPM_MK3r8HU1&$7n#g42U zn|sfPfp)9j2fA-7e7{KGU zjXUXa;hO+_2%MMZ(%UEae1vYrpuUC%(XF}%=#lyWeSmuh(9*xmV7*r0vxO9Zn*L=j z&(hKg&}d46xiXnBOH9e(7*=j3tbiNQr~p(pkSeC$pTE(u3Sa%Ra`?780({ugw0@fH zh3IQYPeDDr6UG4KA?N3Zf4(4b+FIbV`B`J}8X(#(=zY$q?KL z*(+M%OLB1fpfB<1_P#AZh_t4iCqbOngLA(!3X7w{cg@h(B=}#nQQMM?vSryeSdww2 zbJe>G(=Rey0M0pw-SoUF_SsHv=Kvv)k{tf%3sy%2Nh&_LMgRK+U;Pys%_Q}_V*m?5 zClg?C+PE+fTh(ZzXs_AZNeNy;uOtw|Vylsoe0o-?|3#%v&cbE+HrwL1#LC(J5pl(P jdEAvkAha>`^-y&KCp1Jv;FKP!00000NkvXXu0mjfAIL7F diff --git a/Riot/Assets/Images.xcassets/Encryption/encryption_warning.imageset/encryption_warning@3x.png b/Riot/Assets/Images.xcassets/Encryption/encryption_warning.imageset/encryption_warning@3x.png index 2629a149aede296257c10ae790be93ec0d9bff85..33b1b439721b6b9f01ba5f68a0e5729ef2a54dd3 100644 GIT binary patch delta 798 zcmV+(1L6GC2gC*;iBL{Q4GJ0x0000DNk~Le0000a0000a2nGNE0O0_bn2{kge*)P_ zL_t(|0o|BCOcX&B#@`t#_lj#gOD~ohON>?=(Mk(!Y;5j~!NO>O##Ts7Y)r&LOF0@6 zwGev!2d=d25EEAqAV}?KGF7$0QkWm zyL;w#^-DyzM~QCT6oA=s+1@kQavW&Q2m^=}_V(5vVg4bNl5>%vt~1xQ_#+7NIs)MGLOEq$>ENz=9`4E?`(mH7DroiUv`pb@eaX4F%j zoCiEsmcFLXyi)^u^iWK1sLC_y^;@!$eaNbgsykJ(l|9gbuj<`hvXwnhbj*}pG!3!` z@_loCKn)>e5wCRZW*Br1e?6p)A$uVEbqHa??81P?H)@DLJ7KMkEkePME4=dLIh7Vx zc%}X0N;G6@=VsUzWD0v8{Q>#XpRs8Ia#iCiR9M)2eeMu_`XK6sfwX7*&IUrqc3iBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj#Pe*1ZlAeg8`)1eCs?Z8q7l7S7W$v=R?zyd>( z1qrcGB$$HgP9Q)6fy&sJjiy7pl=XOD?()O-`C>abj*vg;$9z=tuWU88OOyl@X%ILv z()_+B&5Sl%9rvUN2($)-^kv)HzI&Ag^@1SrxVd`%twNq_i4^qxuY+XK=jBZwQxwFSjhB&LPDP3=HgfgJ?b{1>L?iEXLyzW&t4o;uS^03P1SH znmpfr7ydpNJXkh6xQ_;>e<%*jo+rAuE+5__06&ib@d#MFsA*fEI1rD32_hAcG*SUc zBNdP|QUOWhzZ78i&+tu?H1JhAfG4Oi3($Sj1cC0;J8BH!9K>(#zjXr8Nh+P=i{~#; zXdvjp=kq~FMsGMrFccObKQsdz%vkO&o_GKu8%JdjQRp@xLPDS(e-D&h}y+#MKfW>SG>$Jek zy{t8#ZMeJ4H_1X6H=m|Q*hOk7&dNXd|`=tt^{COgAj=tQsUlT z*QuB;39=Kf((vAZe+R%lOo*}%c*)yjaGf54=0^vu5<97m~h@9=cu5rhw#uP!$@L@I~IV*l$G2G0IL0(xpwg z+Yex|t@`RI~uW S_0IqR002ov22Mn-LSTZ`P^fkQ From edce991e141811685072cd1b86d591d653e321e5 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 15 Mar 2021 15:57:36 +0100 Subject: [PATCH 006/140] Composer Update - Typing and sending a message - Updated typing animation after UI review --- Riot/Modules/Room/Views/Title/RoomTitleView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 1680095fd..b9ae630f6 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -140,7 +140,7 @@ self.typingLabel.text = typingNotificationString; [self layoutIfNeeded]; - [UIView animateWithDuration:.3 animations:^{ + [UIView animateWithDuration:.1 animations:^{ self.typingLabel.alpha = 1; self.displayNameCenterYConstraint.constant = -8; [self layoutIfNeeded]; @@ -148,7 +148,7 @@ } else { - [UIView animateWithDuration:.3 animations:^{ + [UIView animateWithDuration:.1 animations:^{ self.typingLabel.alpha = 0; self.displayNameCenterYConstraint.constant = 0; [self layoutIfNeeded]; From 9544d156d8f53e1e03e3e20e03a0eae594ad2b0d Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 18 Mar 2021 07:06:59 +0100 Subject: [PATCH 007/140] Composer Update - Typing and sending a message - Updated input bar paddings according to design review --- .../Views/InputToolbar/RoomInputToolbarView.m | 6 +- .../InputToolbar/RoomInputToolbarView.xib | 67 +++++++++---------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 3afe8c8fb..140e841e9 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -86,6 +86,8 @@ growingTextView.textColor = ThemeService.shared.theme.textPrimaryColor; growingTextView.tintColor = ThemeService.shared.theme.tintColor; + growingTextView.internalTextView.showsVerticalScrollIndicator = NO; + growingTextView.internalTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; if (growingTextView.isFirstResponder) { @@ -187,7 +189,7 @@ { [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.rightInputToolbarButton.alpha = 1; - self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 4; + self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 12; [self layoutIfNeeded]; } completion:^(BOOL finished) { }]; @@ -196,7 +198,7 @@ { [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.rightInputToolbarButton.alpha = 0; - self.messageComposerContainerTrailingConstraint.constant = 8; + self.messageComposerContainerTrailingConstraint.constant = 12; [self layoutIfNeeded]; } completion:^(BOOL finished) { }]; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib index d0b4ac337..fab7ebe7d 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib @@ -10,20 +10,31 @@ - + - + + - + - + - + @@ -31,50 +42,35 @@ - - - + + + - + - - - - - - - - - - - + + + + + + + + + + @@ -98,7 +94,6 @@ - From 86a9abc5ca96fe0dc39988f8049feaa86d5e0c56 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Sat, 20 Mar 2021 21:31:17 +0100 Subject: [PATCH 008/140] Composer update - UI enhancements - Composer height =58px - Frame = 42px - Replace current scroll to bottom implementation with a scroll to Bottom FAB on both themes - The text inside the composer frame should be centered - The padding between the "reveal plus" button, composer frame and Left + Right sides should be at equal distance on default mode - Verify that the "Send a message..." String matches with the colour indicated on Figma. - The padding between each component (buttons and composer frame) should be at equal distance on default mode. E.g : It should be at 12px for each gap. - The input text jumps down when users start typing. It should be centered at all times. - Remove the Scroll bar in the text frame. - DARK THEME --- .../scrolldown.imageset/Contents.json | 3 - .../scrolldown.imageset/scrolldown.png | Bin 733 -> 588 bytes .../scrolldown.imageset/scrolldown@2x.png | Bin 1306 -> 1071 bytes .../scrolldown.imageset/scrolldown@3x.png | Bin 1723 -> 1615 bytes .../scrolldown_dark.imageset/Contents.json | 23 +++++++ .../scrolldown_dark.png | Bin 0 -> 776 bytes .../scrolldown_dark@2x.png | Bin 0 -> 1442 bytes .../scrolldown_dark@3x.png | Bin 0 -> 2031 bytes .../Contents.json | 3 + .../upload_icon_dark.imageset/Contents.json | 23 +++++++ .../upload_icon_dark.png | Bin 0 -> 823 bytes .../upload_icon_dark@2x.png | Bin 0 -> 1563 bytes .../upload_icon_dark@3x.png | Bin 0 -> 2232 bytes Riot/Generated/Images.swift | 2 + Riot/Managers/Theme/Theme.swift | 1 + Riot/Managers/Theme/Themes/DarkTheme.swift | 2 + Riot/Managers/Theme/Themes/DefaultTheme.swift | 4 +- Riot/Modules/BadgeLabel/BadgeLabel.swift | 2 +- Riot/Modules/Room/RoomViewController.h | 6 ++ Riot/Modules/Room/RoomViewController.m | 63 +++++++++++++----- Riot/Modules/Room/RoomViewController.xib | 25 +++++++ .../Views/Activities/RoomActivitiesView.h | 10 --- .../Views/Activities/RoomActivitiesView.m | 56 ---------------- .../Views/InputToolbar/RoomInputToolbarView.m | 33 +++++---- .../InputToolbar/RoomInputToolbarView.xib | 26 ++++---- 25 files changed, 167 insertions(+), 115 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/scrolldown_dark.png create mode 100644 Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/scrolldown_dark@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/scrolldown_dark@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@3x.png diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/Contents.json index 8d7bcd9ce..4e597c1e4 100644 --- a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/Contents.json @@ -19,8 +19,5 @@ "info" : { "author" : "xcode", "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" } } diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown.png index ac61fd1ead4bb29ef04f8ddba1bbc52f2720aaaa..4e639fb9b10123c918815eedb85e2b73a9c708b2 100644 GIT binary patch delta 548 zcmV+<0^9xF1xKx9hLFt$RWwAf;$9O* z*gfxOLicKF9&sM08tk`woHQvG+^;0&xseG$9F9iD{bOaoNlOFalAtU!-3;s_eD?T9 zbH?68`0zWB;0&Y@4c64o2G$WBYiwZNuh!GcD-Ms(a9?}&s|vH-!9n%}f49{KNMNu5 z-LF>5?BMPF1Lv35f0|(NqrwGDs^4mVLIRx)_%0Ny%Zo@Qm#y+36JGJ9g*j|(CLuvQ z21!!Mm4POD#do$hWShkV?9V}JxnvVesa&;8Ftdr7p~YF7=K-Go4V9-#x^4LwGtm&L$24Id&2nONxQ*fG7-46lDAX_=VcoBN m4U&kTm!VGK$P8wJW030erP zg7O|$w^FIJWo#-@z;rtOXS3Nfe|=Dt0Jl|DwU*1}ZM9mpV}nPd5rLPoz%3u}h`v{) zQt4J2JRA;96ism$nSfu2C@`Qc6oxpgT7Wmg57bvs^An&{9k&059|R-r_xlE%q9s00 z4z3G~{5k-`do^sA4xB-gwX#~RPS`({N<9d9P0{ZZ-ad1u8e8U994N)Df0E5+Z4ple z4A6C27mRIVh$9ID{LT2FVr^@2N4uxoD5wH@CXOrm)enNdizAEio@-nb$CpO%hhp)b z%B$jwMDR?eAx|5LHd408B-oZ{XqC(5Qy9K_=RLz=J(J0NL)jJ4ny4_=lW3@o$72QX z%Pnw18wiEgd_LEhokSU9f40IA%cLr2i^bv}k^==nK7i+Pxd4jt1cBjBA{aS1jJgWL z7Xm%kFVeeVv<*l@*Yzpt?lbfkF`%xmaM@Iz6u7w&5<c(|Wz; z899~gSR{xu6&K3Uf@QHDBmx*kGm%J`LQ>2oQRHJJgRbZM$={2de`_!pm@ssxB=05F zajvnp=l=bhWDmz=3tnf40}AK8g+#v|e)cA0vH`zNJWtKuqOI4^tze2%g0F1IgvlL1 zI_r6Odc%tP3&SMPK=r5RxjWl?K*sAE?i6m-_u54o^5vySIui#NFQP2?Ak=Ly^tJ(< d>;n3F0%Ol6*^gPm4I%&l002ovPDHLkV1h!(IEDZK diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@2x.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@2x.png index 490d720c2c941ea2b300257991b774ce85000abc..aabb2b1213f7c4fc8e41418c31392fe28bff4372 100644 GIT binary patch delta 1035 zcmV+m1oZow3aO5)!Ix)SX0KDAVPfTqm-FT|0^I_17bv*s&tV@9}%DeZLGSMhH=%jY(0X zn5W?HC1>l#rsz4_V~P%kVHh^De+G#*DH;@(m>!E_o6m_fLl;=0*r4bNbyyTDLb@s) zXc9gO|JPRHiJ%Ku6MBV@Vo|I>H=KEjmPikl(B%e^{9O-%uW21B5whH+oeii!$VX9D z*p8~pi1H&kA-|N|MYiCVsKu}!&4m5H$!6BXGqrJ?;ERyY_pGypNf5HOf6ohnPX{AF ze1$egkd2l+z>Ta$zlK#%9neC4#51hLw?6nU0Ybi7R**kTzoOtN0*>|h?pKgcxF}Sq zDD(ygMjfz*{EBC|D0o~jbU+R(z92j3vM7q}f@A>a0Q(<29zd8h9HA^Y1Z zC=Mk@^RNi4pm;3vN52RZf6V>^Y$^s-!>Ro(6q70!ff|a7c?mHl;LFi>d}#0EYUv7| zFF!)LJcqd0-D~69kDs`+a05>sFCivsu{q$+`Cq(#`ySoy8BVNIyxM-#-;V=6@8^TB z{qub~IPCAoM1>PDj~F3bOf44lxrcHvMc>bT; z3pWuHC4LGB#K`Vmi!6HRImQ?LV)fZrbwZH%anBP*>b0cAGrLNQe}J1HCnPAI>2Lx%(1c$S+-MfhbP{O}Py3z_Bh?vaxX6Y^MxBt5 zcZ8+Sg60VEBhf^@7}or5f;vQ2p}3i>8P?)EnBbcL$0m6y3iXMW-UzwuCF^Wr z8t4Q~kzJZ$`l3#j=D9;z8$>-O+lO9rq+VfX*7Xju!%h_OV?$2Z6zQh{mCzroi=r-> zaV3ElO<5v6VYEaNOX!4L#Au1+(0A7_NCLZ|A@nbtW*Ek# zZQERius&LS9JZCQjmy>j{rz`rf3j|GZ%gy@^H-vQlqiHE`}_Md5Mg4~l;*H-o^KF; z0P$r}gc8ApLV=dtl;%YSLGfF&v$K{oNmGJbAhZUEKF95`K0Q5sATfz07_K|o*Vnfz zEfQLXy_=hxtvIf3NJLIfPBOi{y+wICv1A2pI6OW+UY3Z2wlD({tV;J?f0OniJ2Nx0 z5%%Cvf?csWe4Lc_qzD&(9md5U70mk;?vwLBKidrkG(5r<9uwVAa8ks2xT2>Tby^w* zEx7T1Qp6IpbqsAjG;8Vkd+S2!J<7jso2i1wFD&^8vwkyO^_=H~Xoimq21y1u?nL3CQwkvHIamZ*bi(Xpta>xn%*J>{UC_1}yr zf|F$oxA0_%0@#ybp;|(U#_@q-VTffcDyttBwK~sX{AgYje-T1-1-Pu;BC)*C&b$yO z5$_hfFGV4I=1~kjoCah@9 zV(n^eHMJ$wgxM-n6w}DPHH&qEB5F(H-n!x2socsW$kMvS%3tfQ*R;id1gy-4g^M!L zf8DV(x{RDmf67f-#bVh*7q#Ze(Ca@6(QFkF`wSn4MKPYGA@Ts?htZ3AE1GaG?uQ3$ zsCRHapI<{^TzlzMBed=ctozl!qizC#9e-S*ZAm7)Z+Gg6C4m_axB~-NQIbayQF%RR zXP{tqMsPnbs2+stgl$Ee-!wX=VNQ#p8C8=Y8g2X$e`f08qe(oT!0j}&t9vs*ouQ4d zluRzIrcfwk@o33J{hmgg0L6F{_N9=>4d*O9&Y9r6MtMS*=tCQ}5RG@Dd@uGZ0C-Ms zqT{eEt+zH^*kT7M&MN>-HI@_EaFsv0^(o!L9ii^qEwK|8DqrK_)F4ykdF5Y9sA-`d zs$bM%PG5Nu;yFpijPV=QIWLOLBOvXld`nH68!~O=&L1&xuTQWx%UX26t9VyfO2~PY iu>KQ+i@dH^@%{ijx4xwwX#*7i0000x{;?A_k}nw_1wdmriLe%a3M_sx56 zXKrS;1xpb^wB^IHGEdr~dThrmf6j?AUp?MZ&j)0!R_g>7(t;%@!Plj|FRg=6Y@H00 zU6*z!9pYo&Am8j$Zc>tFXimxps9m11# zq%HCk*obaPAtQE;aYTe`L`Y1$xc7B0zOK=Iv6m3O>R}$ov*AZv=b|7QYA{Ld`PC zi~tdif9!!NLuOH)>VP>MV$cnxpp|Ju7Fj9i8?g9QpxU`J?FUjLfK!iFXyEQ}(g)KV zFa)=LUHH-gOOrmBn1WR6_rU1FOB*km7y;b+Yk>;#QnGI_76IJ)e`|vZayR+rSOjqE zua&V{@K^+haCVpnrY@)!bmDI$Q&1O7-8?o#F-k$I*EigbfFio)V1j1#Y zM!D(V#;-U2#Q*mnf8h03U%|VpZ=wn4IIi_?$m6(=7oU3;AAhulr_MeJgDe|&!12i` zu6*~?==IIvZTvp?3tw)0ZuI2;IQknu?Ef-)ednLM`0w7SJdV#`kY%a?9t?8ubARkT zI{7PmKL!zDf~5En)EMskdlv@rj5{C=Q%*<|KZ4ScK>`One*=S@fBszRXLUOvOZcaR(5(o#2Z2 z1UbNpouqU*f59d3B`4N6fT-#O$HXV>asW}*2@Z-+_~d|Fu#CJ;I6giNUOOs2agX`| zw6=8<7LwIZprM2JR^OU9z!zb$_{45Y&D!08rCjU(7L3`K!E*75ZAwA8*R(bPjU8QB zTSZYE5T6)0^Oa+wb1X&M7mOl6U5*}tshflN-VwkJ9 z(vw>D(mu?yY2Uo=j;;eA8TT2OIx|lF;x?GFT+X`5L*~>(6+YZID9-M*)Dyv57uSOi zom&^HKSbl#R?VWb6dz&U&!tta2#DbA>vK`hfA;l+`or8mNN1yn_(b9L0jjX@mC-oc zd5Uh5LMbSY?Nb^JQ|kUPL}>>QyuWn7Mwyl$QON;>D$I0i6A$x6aAjCD=O?M`0D^C2 zSRO5l^wfc@U_N@xbdD=J#IFUa3&QQ2IHy6k=iBL{Q4GJ0x0000DNk~Le00015000152nGNE063^Y0+As!e+E!V zL_t(|0qvbxcG^f3hOcGp*QR$s_Xa{g8#}@)aIYYCHehE3ZF&R2y@8MwI9UOBI({@+ zf!!+zdB&Lhzf$6eK|(^MQeo;lM`&Qw&(*C#w{C5TW!&E0)?Z#;>RVe|bWWK<9$z!Mx!qlu_YyQb93WEn70tfr>L`H=A?(u z{D$?H{r&x(lt?K;Q(UZ$u)NbOY%CC*R!`wSmm#__p}XB~b$5676qomzDRJXaqMr|k z!>eYq`6LD?TxgpFj-dm=TSW_An9yq=@GNZzeo>U*g$R9jcSnKG*F@k6f1yi3jpegw zMyt@U;@Zy6&L?d8vflJy-6uM&+Y?RDiYt}MgRH;E#D~E=piX}#n#gU@^u_p5|6o(w zkFtz5T*(K?NiLz4tGL8wU0yNt-Ota@%{;DTWuYlDTtyd!M@=?>ykf89qakvAlSC#w zSDrKbVq^s}TXaO^wW_*le}o-b&8(ePnJikli^~lbnN;CME~!P9H>I}dP4mgi$m+9G zTeK5-8fw8B7pu2vUY|;66aXKc$P1~fHpEhv3e6Uuyxzu$4$jiFAQOGG^2-k!UihV9 zfWDExlKgd|MYDs*iJXe6>P(9zR_N>N>tnI3g9s&k3zqXcm(ggHf4l!dGk%f_S?D?} zt;&5sBcUBVfP0VZ^G;P58G=O$u8kfPTZM6)XKxg(C>alIHiz*Csp;gaW zwCa(26w81$FTDD2xsJsy7FzY3MQ?9!pNk_83$1!eXj-%9dGExL3%K3W*%srJ(6DA- z96Fe@>M5ZuE5X+qe_C~PeJ`Oa zDl)#4V{(j!R;YAvlO}ji%)%bSu12v_iHy~;nCA;0e*&RZ9yrt0JY8a2D>CctVUE3M zkfZj5O)1DNw#AlA7ulO^hZ`#Xt}ErRQfh`}lqoWS@is$?o*ICIANF0!yW^r&Yzstw zgvft}``*lx7g8R98@a!~&pn2wY>^4PLo2#JCA1p1S7vWs6)n|H9YKmOlk z`R`Jh2KqtTvtyebzkoHj(bQggA2L-)7%q!*F?bhdT~PfQsc!bB5?b9o{=3Au2cM)afKy-c~J@Zh`=GGP43HthD_{aNc2!# z#ut8l)sy?i5zeTrGL`v~pCF$!g~ey~vA)J`ZzHFxPC`wctQ|3Uu)TMvQ=62*gf(O&#f4-upwMTtdE zqBK(N$sc>M$2O-XG|oKVOq!6aNi&JrZ9iCM*?l|Tx9`o)ehiWC~DIJ#Z-gPX<`A7m6Wr&b7_Ca zxNbMh8y}GRIsi?>e*yEGO3Zf4NJjzYt%X!YKJ{QY@b!pHcgltcUYK7fCWlOJ;E9?l z&Mzz`gE!hT5W<@W@lPh20_rta%OR3CMQkd0q_HNNC8#gB(8&$FZ7vI&f$h})f(XH- zm@uWV84%*n3`7jvQug!40@r>^stt%9WnK#tqAF_{*d6fJUdsqUcnWq2C`3x|0+{R- zxcY4c?%lZ!pFe%<6$%^c>u~Gl4fybWsb?%IN(v9OAL~z~qcFK7aLg8HkeoJoRSrwLJ`C@iFmNv=21C14&cRCmI5R=Y0ua|7f@38vls;@q5DpZ^dIG%l~CfFb5HX z*t8l?U_V3BG7k}h*fE>Y3dm*CJ`vo7h+w!Hwye1k?bmXK2Oq+RU#W9Jn*h5OluU;# z!kW_79-(b3Hl;wRvmuG#xn(xk8|=Nt#K2@?l&$kH7N(iQ*zj&WqEmAUY+41P^KNOn zWlegHMo01kH>W|=+jI7hY~k2OO?GV0k=t`XZqJ2td;S+N;YJqWUmz6#0000wc57eP75TR-+5GxRl>O@2$b|VoIS3)=&!~)6bFKF@$XeAbiO_B}y z=pwa))RH=i5wHMJ#Z@UQK88ibF7b*~n7N00#*XVr$MKAPXKc?ri_F9sP5i!d?zvxQ z7SB?Gk!uy)h_ZZ--3O*;?LeP0J=g*&Y#YLI98t@%mh9+*XUN0rh@Az;wJ&2FG%X#y1b^z@@q{G`__Gs!144qFFy$KO^n=#$ zAlPmHB(b{YngLuu7D5IS>?$2=O@Og?AY?EGY4cd``~QRxBBIq{&LhSsgq5n6hzNnB zGAn`#9{l_h6u-F#FP=LGGqcysqbk16Z^7eV9>J@xU4*IhG^l_fH?=E?fTN=$xV`=r z93CFPAHV+wUw-j993C8i3h2JyfA_6~R|5#McensOK|b_VIyUnEW}$c(l6?U}pG_r)>7+3fHV|(?NHD8S>og1)5|Nu! zfeFE{W2<~w<5s;l*2sw=LS*Tta+m;)R*y_<7zkM5voVBA>Xva9s-#YvjE zK9!TV=DObw@1+JZf~rluj0ly&o9?L|vj|Z@meO(s4gXGGzdYRvGhs%I w(Rwk~B`2@XBZ|L}X=RB1TgpsM>fj;&18sA4+)_Zj^8f$<07*qoM6N<$f-I(#cK`qY literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/scrolldown_dark@3x.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown_dark.imageset/scrolldown_dark@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..14ae3aa1b10c73fb47cde7d1a40d0e5380bed409 GIT binary patch literal 2031 zcmVv6NPz($GlIHb|(gkSdTWmHY)w{(=?>35iS7 z3u#kO(zF$jMsgxJm5)Y3aN=V*P;O07q$VQS9p+ts;MiGv?cE*kI`g~4UOS2XJTvdR zJ3I3ZLqfSSozHe>Hv5=FAEdMx6*Ih(c*TTr_IU5O}tpEl0Ew~c#F=2U84;@i6l%C+SCHHm--y_ah{b@(>Ab}=&L!3A zkD~)%921TZ<8dVG$PM`X_WWtr#pM)*o1nzf8zM7+lI-Kcy{JyOKSW2vED;iffd+5ieW zrseyw`Ysu>3Rkt6zpT&xA^0fj4EBYqQDMa>%0um?=e&Z#?A{0a=s6Cf$qHDCu0 zF+|OZ8nWoGH)K&a1aZDO1|xnLvTDfUQoT3$_5c%lqQhk}H*)Oo!gjCu_5dY*pd?~w zO!2PZ_OESskXk=X=!p``Z@h?af6%o4s9|6i>3XXAc#Q$3^~Z)cEvNb*uRUN|e_Ryj zL~UV<0oQNM(<}xHhPbe3s!rvBEe1#_&%h8XG$ph0dHFh^c-8v{46&mI>Uv58b^rGO zu`vLH7Ali**#H3^>gKW`I5Zu<^wzU0y6@s9X-+%iR-+r@*^|duT`}_-d z<<&!I2lP4S=f3hj$KKvv92*)&_wL=$1uetPcQ{#m^eKJzG1qh`v0TLM>4T)#8_+#z3D%8%le1 zO%U;d=oZmsf}i*$bTxtk(&Ea2C!mqN`+9v}i`#@o;`i*?gQuQ;2D(t0cR!b47Bn(= zK0ul zBv^bR8+wgc7~(b|;o^I=)c_(c6Vf0)(RKrfs7*+V_yng)Q%C?&nUE&&6)SWanwU~v zVNFPx_=LJ4!;;YhO0;T13dN@jF`IkE?Gi>%6KL>^NTc|KE9F1pty8BDGKPal7|*F; zY7+QwpTV)!)m8lR^H1L6nJ;em{+* zU0nQbK+NLo873>FQ%O22e6i%5BOH!``m&cZ~s*jMXWr$psO!UF#=&7Y3MI z5GggWzl86!6qm`fFhqi1>nD5-C{}n%)fiC{ksK5CHhri&G0Szts7c77u%!@n^J!fJ zMuu~?8n+mQp(VU6Pa16U&~R!Zbss5Vt__-mGz+rdOrW`;yIe7*e%LSs#a=6D){sC3 zc-IDw$eDZ)2ycIxpqu3<^5xbP(>n4ed$8j3A4Rn=qeq>#7r|}E$kq? zGeRM9&Bpv~{!VzzR)(z;$s#=(vUto9{X5}`nZ6_K4-?hawviVKD&~cb+jE9O4vmW? zc01cjC?tVzj&a61qZB5?jGGaoso2oDk`Cw%Hr<%=+x;R6wA3m~n-LUl=)QQX=k`th zFMXuI2%DzmtT~y9sCLY5gjNGecxCb>C_fxW0-!0GG%GO9P*dlBw+}B_i;V%QTdjL) zJc&*-!gaQGpU;sDN@hT^0TreWfXRrfIWn6;E;wL|>kgl3r|6X=#(-*Q!yBrr>6O)# z(qfG7S06S@CDy3QS9PH&N}OKZ3#o<(n6$kL0F2qR6qHsYCPnaS{sTg-j_j+-ut@*_ N002ovPDHLkV1i&)zX<>U literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json index 30afe661d..390e9a858 100644 --- a/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/Room/Input/input_text_background.imageset/Contents.json @@ -19,5 +19,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" } } diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/Contents.json new file mode 100644 index 000000000..c5bb14104 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "upload_icon_dark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "upload_icon_dark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "upload_icon_dark@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..cb0316cf93ded219526f03359826fe276832b665 GIT binary patch literal 823 zcmV-71IYY|P)OxYD(<3{Q#&-+eAw>(T2uEgDy?5TNftotUD7m?lE09lqxB;O@!hL zS8B@#kgW+MO-vW`5<%`6XP_Xj%6-5sztu1txc}Tab6yArS&nUcTnwg3!zpCoMFbac z7^!@TkS7i~2ABn;G*KZH@cXky{vY)kM%EKIIAhnv54>Oi0>}_i`0m2orXKsQf>yQ? zUPWU|!f+g{fS4_7+N*BDjuf;Ui;XzZ5k$ZM^bk%wtYRT_&+pHJUO~}#e7satUNC@3 z=m+9$5gjac@-OTp=1)-xSw13@qFCbxc}%v5k#Oz-bUv5QgrfvieZ~ec{~kW+)zdiQmbz}m}BK&DZXs8PU zX6>kwiFXsb-@lH51r(75DpKS%7bn@Dcw+#Wl4PD_M@S4t)AQ2`F0jeFzdVa^YW~3Pme7Fos7EOB{0eU z{;y%ZwitPv{8TSNP4ejBgUZEt`s`&ItbmwjoWlVO3Y_N{GN#LiY(dmWA`WR87#J|k zhEAUP3~v<1w33ORq_;@+tHjOnl-DU05%qNTR6 zx{=(pvwUqrIP>lKEAw($4~&dx362TbK-SiELAMs>(j0ggY(_q_v72p59V#z`go%A& zKpd6I9igVJR-0)2i)a*!HZ_X0C~sEdc3X0lVc^8@a8QJT9Q299iAbB6j)H2URIc9X zhfm4>Eb!C!JBg8W9mgEbg@U~p$DpP?k(cMcW}p)(tlBOa>riAC&_v+v*}$q5>Gb8& z@0n_IAnI{h0ym8GWI4kL(oEq$NQG1&;4?JR`wNe~9XAj~MjHSC002ovPDHLkV1iT& BY@GlA literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@2x.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b58c78907c54b319abb9faa07e09c97e08f77655 GIT binary patch literal 1563 zcmV+$2ITpPP)*EW6Nn4aTvaqiP;-vC6|&G#C|ITdSakk=s?0WI% z6o^Tc-NyFHZbe;;>l{wyO)CyV)Ty%Dmwc_oPAMwTb`jV>sk~ZL3E(GR(fDd9P-Jd? zu-+?VJ3)b=$*G%`T?b2nP_{L8ty2Z0$@5mORv-}9J1yZ_`6yT8jzs>;IRbIkQsN9l ziy{z1`Bs!8&_+fZcFTHFsg!o}`^Bg3-2UkhAA=jHtd?&@IRd$9J&~*599~?Q@0p$c z?(o-_!$-g+@~voBpoyu4VK-yX-FUpqJid4DZ})01WknsLbIAO5S0EB%2s{jkBn;8OarSSxKX$R1U07`1{d2kN=R3C#fz8-1 zP&%D_Z_s=dKlXUI(c&7!I5LV4`H9_>3Jr3{P?rB|6RN`vou!^J?M|leUMYp zfAZ-U`?{Oe3f^gJy9G59yaid+LAVSamhe7pRR_sc@UTPz#Z`|Q9NmcB$Y`h~1Zl$c zU|6r9j&YINTw7JqsHz>H%?|G!61+WDwLIeBkpqu7@Yn5@E7C3S$bsiS_^Tn%np}^9 zM-D1`J+>gj&2~)6W81w#!B>pzzFSFqZuS_{y_j8r3^#Kzn?0=-o96LR7Z$s_ASSYB z&vJITy17|=T{YT%Q@y1BRlDRl)e*3}@l`HLknm{MCiAxJH`gf@=@5QbX1;t%kb!|0 z9)O!D>&bR6CTBIz!CDfOJ;%^&AP?g01ZR_ib_ZJ#_d%f5KwKHMnBOQ6h^!7s z)b)?8Ubk$RjgFj-5m3vx8ec14v(16v!JCLU&i zq?9z4ADFY*vnTz=t1qsiEb;?=Y}v?zF2t7O$WX6IWNLm;Xl>^kE^s6Kr{d|kV(Gm2k5vI@ zx6MqZksd6tBBgx4R6w?(synNk-BOf#s{x8h;{S0?w!dACI84nCH({4U(RQ{DA8xY3 z%ZEx`s^HgvO-!m@k^~rbT_}z<1lN*uFmfjNe9a9&TOY8*u}RNlhFuVfxGJ_&7!${y zVaDTCJmTQsE`Hki6jS~5AJ(KVYNs$Jjz8qhSkI-?Cu|VQ5QHs-Z*)2-N;ZxQl+WbU zLO*HPOC-A0HTUv1WZr3O^_V~~s$N`H$NwP8#DOgl`&YEDIxR{zj{wE#R6G%pHl_do N002ovPDHLkV1j1R+rj_< literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@3x.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon_dark.imageset/upload_icon_dark@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b04f2a977beb382725f9ac0cf90d50f1b799e9a1 GIT binary patch literal 2232 zcmV;p2uJscP)uK~#7F?VU?( zTSXK=?;R&i{YhX!L5b)`0s@F-x|Bzdr+-qMb07 zln}9PM7TwLxIPF07FdvST;S|PvcG>4G(rnuI!LNUQQlKKA36yd5UMa16~lN^ASC@r zb)JGaDGT%yU^W$I)P*AKvs0(KWj-<}0UiYdkrKwk5*Mg2j;Jn-?=w}@Qo;}yh%lp4 zU%en^B+*cE$Ac*d0N;fj9Y5U{DTo8=4|PK;qpopS5U&mFyl(=0#5Z9aRdI|BB483$ z5hQ77_s*>c!6$qX#znRrR8-ZR$&E z*Y^8|z(YJ0HZ*p2Pyh^qrG%=8Q(hJ%o(OYBDkAZH>eIDEx$ZSmjg;hY_MjJIluZj; zDB0gvk<|;9s;Edy=P3Jpv(lOpW@Xif7t$IQW@R--v(g$8W@R-;GtvY!02dfmR^#xw zi&1nxG(g?LxOBJGVDktewmIjr-uKmW@W_cXNqe8=9egf%prOw9xPynA)Fsc#@|dQd_JN@A9=k@{WG=Z!w(MMIyE&F<)6E{x~@F8_r-JTZn*IZ7|0A| z?_D~gzbwK`j;^uepRO;;Vy363*Btx!=q50fN)_WWVFiHAU?_j2)7LM3?b4--#-_$f z72_gdBWmQ>-gjw)su&ZZb6fdKi-eJyqXCOn5Xmj&KbM4Yv7y_;bQY&7>?==;C1LZk zXzaDC)hSPlC1Exl>PvZAbcAup*>tEcfJz+7ExU41W6Cm1bgc*Vm zqFeA6u$Y2MiBj5>Xb5V$B_R;VHrkj1k%}-tE6fmxS6v-BarT?A+S#}VW8~wHHvMJD ztnm8v8!`h=K6O5{9udTh2($O_@Vjr{Zi+01+YJuC`_AnU7W||Ogv7bueo1hX3>XG~ zW^SW{kO)m!G#W2}q2zKiZ4eTn3EQx707Epjxd2X!VJMliBihTU@?VBA*?WSkdPK_(ddt0F@laY9h2hm zhwr%@=DnE3J&!$dPudyjAOfQ{JzI@9dz?XOXo{>b&5;X^9AQGzw_wp4lz1(|GB|4^ zOmlLWy(WyGR4?X8i+-@1;%Wk==@mqq7IlTUbS!>f5;h}q<6zMefmq6ZC1Ex#>IpkZ z_HQi>&@Y;CwrNp6%F`jUNSKor?Wl)7AWkmbj(CwUPK%Pj)BUc3`|Ct|drIc>#tI9w4b3wuL>E)BFOjEQgb+rqnb-JpW$=N=epK$uAW}WQZ8jvqmQUmxO>Oe zgKiFWC5%&Jdq>Bhtr~qmol`YPvDfY4uAdKc?#%#Q{V%Z8gGjAZ6)rm(>fnj(4~(m^ ztQ1&0fzRcx?f2JJAJqK>CYPP+O?DKdNrZrtwMzJk?}G-IrtBfx%h)(-=;_>aA$kZJ zpsB6x6Bv8nE{<6rEGtLR7xwhu9o*LTMXa>?XjT@}lrY9hbB7nQn5LI~;Cr+g$~|uj zk?L@P;e{-w=?E+5*x1=YvRmJmL+S({ZloHlhNr@qkrQ7fRRXa4XCh2PLB6$XN!L^J zzt#snJN13{Tt1&#wOd=Mu|Xbgs%Hel^{)mW86G>cf0gaBPHNPBI7_jV7uTyw_$rJ! zcKmdo6yiY3N1KW&p3ibKMbgxtfq-xd65hzW)vj&oTBWA-hcgr%@++zq|G5C+Ynz;# z8#KA+u?$l8R$r)c{a_HHiUcaGh~eTKQQX<&M^RCWP=pmJiYrLDS@UZg@kC>gsjnKL z3M+?qxaC~}HQKm`7QRd%(swg5HXf#^BH9Qm!cjLrJG(g~d0I*;M>}EV92xzgGe(&{ z6zxhJ^?EGOk;AF(>cTSkyO4!%GZ;_nCaD~)g;nD7&%f-=<6Muk$&Z8{6wuAPTkwVn zh>%!z+i+FLj5=nT*M^jmvTDeCk{3mj|KUV3xz(ukBL4?9ByDP2`{ecj0000 + + @@ -130,6 +132,19 @@ + + @@ -158,12 +173,16 @@ + + + + @@ -184,8 +203,14 @@ + + + + + + diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h index 54eb3feb7..b66c61a5f 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h @@ -73,16 +73,6 @@ */ - (void)displayOngoingConferenceCall:(void (^)(BOOL video))ongoingConferenceCallPressed onClosePressed:(void (^)(void))ongoingConferenceCallClosePressed; -/** - Display a "scroll to bottom" icon. - Replace the current notification if any. - - @param newMessagesCount the count of the unread messages. - @param onIconTapGesture block called when user taps on notification icon. - */ -- (void)displayScrollToBottomIcon:(NSUInteger)newMessagesCount onIconTapGesture:(void (^)(void))onIconTapGesture; - - /** Notify that the a room is obsolete and a replacement room is available. diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 46bce5f6f..1f65678ad 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -268,62 +268,6 @@ [self checkHeight:YES]; } -- (void)displayScrollToBottomIcon:(NSUInteger)newMessagesCount onIconTapGesture:(void (^)(void))onIconTapGesture -{ - if (newMessagesCount) - { - [self reset]; - - self.iconImageView.image = [UIImage imageNamed:@"scrolldown"]; - self.iconImageView.tintColor = ThemeService.shared.theme.noticeColor; - - NSString *notification; - if (newMessagesCount > 1) - { - notification = NSLocalizedStringFromTable(@"room_new_messages_notification", @"Vector", nil); - } - else - { - notification = NSLocalizedStringFromTable(@"room_new_message_notification", @"Vector", nil); - } - self.messageLabel.text = [NSString stringWithFormat:notification, newMessagesCount]; - self.messageLabel.textColor = ThemeService.shared.theme.warningColor; - self.messageLabel.hidden = NO; - } - else - { - self.unsentMessagesContentView.hidden = YES; - - // We keep the current message if any - [self resetIcon]; - - self.messageLabel.text = nil; - self.iconImageView.image = [UIImage imageNamed:@"scrolldown"]; - self.iconImageView.tintColor = ThemeService.shared.theme.textPrimaryColor; - } - self.iconImageView.hidden = NO; - - // Make VoiceOver consider it as a button - self.iconImageView.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessiblity_scroll_to_bottom", @"Vector", nil); - self.iconImageView.isAccessibilityElement = YES; - self.iconImageView.accessibilityTraits = UIAccessibilityTraitButton; - - if (onIconTapGesture) - { - objc_setAssociatedObject(self.iconImageView, "onIconTapGesture", [onIconTapGesture copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); - - // Listen to icon tap - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onIconTap:)]; - [tapGesture setNumberOfTouchesRequired:1]; - [tapGesture setNumberOfTapsRequired:1]; - [tapGesture setDelegate:self]; - [self.iconImageView addGestureRecognizer:tapGesture]; - self.iconImageView.userInteractionEnabled = YES; - } - - [self checkHeight:YES]; -} - - (void)displayRoomReplacementWithRoomLinkTappedHandler:(void (^)(void))onRoomReplacementLinkTapped { [self reset]; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 140e841e9..00cbb0d78 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -85,7 +85,7 @@ growingTextView.font = [UIFont systemFontOfSize:15]; growingTextView.textColor = ThemeService.shared.theme.textPrimaryColor; growingTextView.tintColor = ThemeService.shared.theme.tintColor; - + growingTextView.placeholderColor = ThemeService.shared.theme.textTertiaryColor; growingTextView.internalTextView.showsVerticalScrollIndicator = NO; growingTextView.internalTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; @@ -100,6 +100,19 @@ UIImage *image = [UIImage imageNamed:@"input_text_background"]; image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(9, 15, 10, 16)]; self.inputTextBackgroundView.image = image; + self.inputTextBackgroundView.tintColor = ThemeService.shared.theme.roomInputTextBorder; + + if ([ThemeService.shared.themeId isEqualToString:@"light"]) + { + [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon"] forState:UIControlStateNormal]; + } + else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"]) + { + [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal]; + } + else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) { + [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal]; + } } #pragma mark - @@ -187,21 +200,15 @@ if (self.rightInputToolbarButton.isEnabled && !self.rightInputToolbarButton.alpha) { - [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{ - self.rightInputToolbarButton.alpha = 1; - self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 12; - [self layoutIfNeeded]; - } completion:^(BOOL finished) { - }]; + self.rightInputToolbarButton.alpha = 1; + self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 12; + [self layoutIfNeeded]; } else if (!self.rightInputToolbarButton.isEnabled && self.rightInputToolbarButton.alpha) { - [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{ - self.rightInputToolbarButton.alpha = 0; - self.messageComposerContainerTrailingConstraint.constant = 12; - [self layoutIfNeeded]; - } completion:^(BOOL finished) { - }]; + self.rightInputToolbarButton.alpha = 0; + self.messageComposerContainerTrailingConstraint.constant = 12; + [self layoutIfNeeded]; } } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib index fab7ebe7d..c8ac8203d 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib @@ -14,13 +14,13 @@ - + - + - + - + @@ -52,7 +52,7 @@ - + - - + - - - + + + + From 4834042b8e176c5491bf2d207f4d3638c6470ba7 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 22 Mar 2021 19:55:41 +0100 Subject: [PATCH 009/140] Explore typing notifications inspired by web - First iteration --- Riot/Modules/DotsView/DotsView.swift | 152 ++++++++++++++++++ .../Modules/Room/DataSources/RoomDataSource.h | 5 + .../Modules/Room/DataSources/RoomDataSource.m | 41 ++++- Riot/Modules/Room/RoomViewController.m | 63 +++----- Riot/Modules/Room/RoomViewController.xib | 4 +- .../BubbleCells/RoomTypingBubbleCell.swift | 105 ++++++++++++ .../BubbleCells/RoomTypingBubbleCell.xib | 54 +++++++ 7 files changed, 375 insertions(+), 49 deletions(-) create mode 100644 Riot/Modules/DotsView/DotsView.swift create mode 100644 Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift create mode 100644 Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.xib diff --git a/Riot/Modules/DotsView/DotsView.swift b/Riot/Modules/DotsView/DotsView.swift new file mode 100644 index 000000000..ca69fb6de --- /dev/null +++ b/Riot/Modules/DotsView/DotsView.swift @@ -0,0 +1,152 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 UIKit + +@IBDesignable +@objcMembers +class DotsView: UIView { + // MARK: - Public properties + + @IBInspectable var highlightedDotColor: UIColor = .darkGray { + didSet { + } + } + + @IBInspectable var dotColor: UIColor = .lightGray { + didSet { + } + } + + @IBInspectable var dotMaxWidth: CGFloat = 10 { + didSet { + self.sizeToFit() + } + } + + @IBInspectable var dotMinWidth: CGFloat = 8 { + didSet { + self.sizeToFit() + } + } + + @IBInspectable var numberOfDots: UInt = 3 { + didSet { + createDotViews() + } + } + + @IBInspectable var interSpaceMargin: CGFloat = 7 { + didSet { + self.sizeToFit() + } + } + + // MARK: - Private members + + private var dotLayers: Array = Array() + private var highlightedDotIndex: UInt = 0 { + didSet { + updateDotViews() + } + } + private let updateInterval: TimeInterval = 0.4 + private var lastUpdateDate: Date = Date() + private var animating: Bool = false { + didSet { + let displayLink = CADisplayLink(target: self, selector: #selector(fireTimer)) + displayLink.add(to: .current, forMode: .default) + } + } + + // MARK: - Lifecycle + + required init?(coder: NSCoder) { + super.init(coder: coder) + createDotViews() + } + + override init(frame: CGRect) { + super.init(frame: frame) + createDotViews() + } + + override func layoutSubviews() { + super.layoutSubviews() + + updateDotViews() + } + + override var intrinsicContentSize: CGSize { + return CGSize(width: dotMaxWidth + (CGFloat(numberOfDots) - 1) * (dotMinWidth + interSpaceMargin), height: dotMaxWidth) + } + + override func didMoveToSuperview() { + animating = superview != nil + } + + // MARK: - Interface Builder + + override func prepareForInterfaceBuilder() { + super.prepareForInterfaceBuilder() + createDotViews() + } + + // MARK: - Private methods + + private func createDotViews() { + while dotLayers.count > numberOfDots { + dotLayers.popLast()?.removeFromSuperlayer() + } + + while dotLayers.count < numberOfDots { + let dotLayer = CALayer() + dotLayer.masksToBounds = true + layer.addSublayer(dotLayer) + dotLayers.append(dotLayer) + } + + if highlightedDotIndex >= dotLayers.count { + highlightedDotIndex = 0 + updateDotViews() + } + } + + private func updateDotViews() { + CATransaction.begin() + CATransaction.setAnimationDuration(1) + var x: CGFloat = 0 + for (index, dotLayer) in dotLayers.enumerated() { + if index == highlightedDotIndex { + dotLayer.frame = CGRect(x: x, y: (bounds.height - dotMaxWidth) / 2, width: dotMaxWidth, height: dotMaxWidth) + dotLayer.backgroundColor = dotColor.cgColor + } else { + dotLayer.frame = CGRect(x: x, y: (bounds.height - dotMinWidth) / 2, width: dotMinWidth, height: dotMinWidth) + dotLayer.backgroundColor = index == ((highlightedDotIndex + 1) % numberOfDots) ? highlightedDotColor.cgColor : dotColor.cgColor + } + dotLayer.cornerRadius = dotLayer.bounds.height / 2 + x = dotLayer.frame.maxX + interSpaceMargin + } + lastUpdateDate = Date() + CATransaction.commit() + } + + func fireTimer() { + if Date().timeIntervalSince(lastUpdateDate) >= updateInterval { + self.highlightedDotIndex = (self.highlightedDotIndex + 1) % self.numberOfDots + } + } +} diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.h b/Riot/Modules/Room/DataSources/RoomDataSource.h index f28f91fac..ced9e687a 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.h +++ b/Riot/Modules/Room/DataSources/RoomDataSource.h @@ -48,6 +48,11 @@ */ @property(nonatomic, readonly) RoomEncryptionTrustLevel encryptionTrustLevel; +/** + List of members who are typing in the room. + */ +@property(nonatomic, nullable) NSArray *currentTypingUsers; + /** Check if there is an active jitsi widget in the room and return it. diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 8975281c8..880f6dc65 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -53,6 +53,8 @@ @property (nonatomic) BOOL showRoomCreationCell; +@property (nonatomic) NSInteger typingCellIndex; + @end @implementation RoomDataSource @@ -185,6 +187,16 @@ [self setNeedsUpdateAdditionalContentHeightForCellData:cellData]; } +- (CGFloat)cellHeightAtIndex:(NSInteger)index withMaximumWidth:(CGFloat)maxWidth +{ + if (index == self.typingCellIndex) + { + return 24; + } + + return [super cellHeightAtIndex:index withMaximumWidth:maxWidth]; +} + - (void)setNeedsUpdateAdditionalContentHeightForCellData:(id)cellData { RoomBubbleCellData *roomBubbleCellData; @@ -261,16 +273,37 @@ [self updateStatusInfo]; } - // we may have changed the number of bubbles in this block, consider that change - return bubbles.count; + if (self.currentTypingUsers.count == 0) + { + // we may have changed the number of bubbles in this block, consider that change + return bubbles.count; + } + + self.typingCellIndex = bubbles.count; + return bubbles.count + 1; } - // leave it as is, if coming as 0 from super - return count; + if (self.currentTypingUsers.count == 0) + { + self.typingCellIndex = -1; + + // leave it as is, if coming as 0 from super + return count; + } + + self.typingCellIndex = count; + return count + 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.row == self.typingCellIndex) + { + RoomTypingBubbleCell *cell = [tableView dequeueReusableCellWithIdentifier:RoomTypingBubbleCell.cellIdentifier forIndexPath:indexPath]; + [cell updateTypingUsers:_currentTypingUsers mediaManager:self.mxSession.mediaManager]; + return cell; + } + // Do cell data customization that needs to be done before [MXKRoomBubbleTableViewCell render] RoomBubbleCellData *roomBubbleCellData = [self cellDataAtIndex:indexPath.row]; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 963fc991f..442a6fd79 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -370,6 +370,8 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self.bubblesTableView registerClass:RoomCreationIntroCell.class forCellReuseIdentifier:RoomCreationIntroCell.defaultReuseIdentifier]; + [self.bubblesTableView registerNib:[UINib nibWithNibName:@"RoomTypingBubbleCell" bundle:nil] forCellReuseIdentifier:RoomTypingBubbleCell.cellIdentifier]; + [self vc_removeBackTitle]; // Replace the default input toolbar view. @@ -4025,54 +4027,29 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)refreshTypingNotification { - if ([self.titleView isKindOfClass:RoomTitleView.class]) + RoomDataSource *roomDataSource = (RoomDataSource *) self.roomDataSource; + BOOL needsUpdate = currentTypingUsers.count != roomDataSource.currentTypingUsers.count; + + NSMutableArray *typingUsers = [NSMutableArray new]; + for (NSUInteger i = 0 ; i < currentTypingUsers.count ; i++) { + NSString *userId = currentTypingUsers[i]; + MXRoomMember* member = [self.roomDataSource.roomState.members memberWithUserId:userId]; + [typingUsers addObject:member]; + needsUpdate = needsUpdate || member.userId != ((MXRoomMember *) roomDataSource.currentTypingUsers[i]).userId; + } + + if (needsUpdate) { - RoomTitleView *titleView = (RoomTitleView *)self.titleView; - - // Prepare here typing notification - NSString* text = nil; - NSUInteger count = currentTypingUsers.count; - - // get the room member names - NSMutableArray *names = [[NSMutableArray alloc] init]; - - // keeps the only the first two users - for(int i = 0; i < MIN(count, 2); i++) + roomDataSource.currentTypingUsers = typingUsers; + [self.bubblesTableView reloadData]; + if (self.isScrollToBottomHidden) { - NSString* name = currentTypingUsers[i]; - - MXRoomMember* member = [self.roomDataSource.roomState.members memberWithUserId:name]; - - if (member && member.displayname.length) + NSInteger count = [self.roomDataSource tableView:self.bubblesTableView numberOfRowsInSection:0]; + if (count) { - name = member.displayname; - } - - // sanity check - if (name) - { - [names addObject:name]; + [self scrollBubblesTableViewToBottomAnimated:YES]; } } - - if (0 == names.count) - { - // something to do ? - } - else if (1 == names.count) - { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_one_user_is_typing", @"Vector", nil), names[0]]; - } - else if (2 == names.count) - { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_two_users_are_typing", @"Vector", nil), names[0], names[1]]; - } - else - { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_many_users_are_typing", @"Vector", nil), names[0], names[1]]; - } - - titleView.typingNotificationString = text; } } diff --git a/Riot/Modules/Room/RoomViewController.xib b/Riot/Modules/Room/RoomViewController.xib index a43b40a18..afcb068b5 100644 --- a/Riot/Modules/Room/RoomViewController.xib +++ b/Riot/Modules/Room/RoomViewController.xib @@ -140,7 +140,7 @@ diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 184dd2187..80c070485 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -135,6 +135,27 @@ _sendMode = sendMode; [self updatePlaceholder]; + [self updateToolbarButtonLabel]; +} + +- (void)updateToolbarButtonLabel +{ + UIImage *buttonImage; + + switch (_sendMode) + { + case RoomInputToolbarViewSendModeReply: + buttonImage = [UIImage imageNamed:@"send_icon"]; + break; + case RoomInputToolbarViewSendModeEdit: + buttonImage = [UIImage imageNamed:@"save_icon"]; + break; + default: + buttonImage = [UIImage imageNamed:@"send_icon"]; + break; + } + + [self.rightInputToolbarButton setImage:buttonImage forState:UIControlStateNormal]; } - (void)updatePlaceholder From 6849fa808363730821f741997b75e5b466b27bc3 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 24 Mar 2021 09:14:31 +0100 Subject: [PATCH 012/140] Room directory: Fix crash #4137 This is a quick fix. We should remove all forced unwrapping --- CHANGES.rst | 1 + .../ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 3a59ebcf1..09e73d4d3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Changes to be released in next version 🐛 Bugfix * RoomVC: Fix timeline blink on sending. * RoomVC: Fix not visible last bubble issue. + * Room directory: Fix crash (#4137). ⚠️ API Changes * diff --git a/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift b/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift index 577ea6a02..2df14e8e2 100644 --- a/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift +++ b/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift @@ -97,7 +97,7 @@ extension DirectoryRoomTableViewCell: Themable { numberOfUsersLabel.textColor = theme.textSecondaryColor topicLabel.textColor = theme.textSecondaryColor - if viewModel.isJoined { + if let viewModel = viewModel, viewModel.isJoined { joinButton.backgroundColor = theme.backgroundColor joinButton.tintColor = theme.textSecondaryColor joinButton.layer.borderWidth = 1.0 From 1a3753bc719cb93736b96901a9cc38f35295bae1 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 24 Mar 2021 09:15:02 +0100 Subject: [PATCH 013/140] cocoapods++ in Gemfile --- Gemfile | 2 +- Gemfile.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 1f57bb8b0..3ba15fb52 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" gem "xcode-install" gem "fastlane" -gem "cocoapods", '~>1.10.0' +gem "cocoapods", '~>1.10.1' plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index fcfae5852..31e7491fe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,7 +2,7 @@ GEM remote: https://rubygems.org/ specs: CFPropertyList (3.0.2) - activesupport (5.2.4.4) + activesupport (5.2.4.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -31,10 +31,10 @@ GEM aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.0.3) - cocoapods (1.10.0) + cocoapods (1.10.1) addressable (~> 2.6) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.10.0) + cocoapods-core (= 1.10.1) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 1.4.0, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -49,7 +49,7 @@ GEM nap (~> 1.0) ruby-macho (~> 1.4) xcodeproj (>= 1.19.0, < 2.0) - cocoapods-core (1.10.0) + cocoapods-core (1.10.1) activesupport (> 5.0, < 6) addressable (~> 2.6) algoliasearch (~> 1.0) @@ -72,7 +72,7 @@ GEM colored2 (3.1.2) commander-fastlane (4.4.6) highline (~> 1.7.2) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) declarative (0.0.20) declarative-option (0.1.0) digest-crc (0.6.1) @@ -170,7 +170,7 @@ GEM http-cookie (1.0.3) domain_name (~> 0.5) httpclient (2.8.3) - i18n (1.8.5) + i18n (1.8.9) concurrent-ruby (~> 1.0) jmespath (1.4.0) json (2.3.1) @@ -178,7 +178,7 @@ GEM memoist (0.16.2) mini_magick (4.11.0) mini_mime (1.0.2) - minitest (5.14.2) + minitest (5.14.4) molinillo (0.6.6) multi_json (1.15.0) multipart-post (2.0.0) @@ -219,7 +219,7 @@ GEM tty-cursor (~> 0.7) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.8) + tzinfo (1.2.9) thread_safe (~> 0.1) uber (0.1.0) unf (0.1.4) @@ -245,11 +245,11 @@ PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.10.0) + cocoapods (~> 1.10.1) fastlane fastlane-plugin-versioning fastlane-plugin-xcodegen xcode-install BUNDLED WITH - 2.1.4 + 2.2.14 From 05e036a64759317599be9c4b4234bddfbfd07967 Mon Sep 17 00:00:00 2001 From: Element Translate Bot Date: Wed, 24 Mar 2021 14:45:18 +0100 Subject: [PATCH 014/140] Translations update from Weblate (#4141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translated using Weblate (Hungarian) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ * Translated using Weblate (Ukrainian) Currently translated at 20.4% (243 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Swedish) Currently translated at 96.6% (1146 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sv/ * Translated using Weblate (Estonian) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ * Added translation using Weblate (Arabic) * Translated using Weblate (Dutch) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ * Translated using Weblate (German) Currently translated at 99.4% (1179 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (German) Currently translated at 99.4% (1179 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (French) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ * Translated using Weblate (Japanese) Currently translated at 44.0% (523 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ * Translated using Weblate (Italian) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ * Translated using Weblate (Ukrainian) Currently translated at 20.9% (249 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ * Translated using Weblate (Swedish) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sv/ * Translated using Weblate (Arabic) Currently translated at 8.6% (102 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ar/ * Translated using Weblate (German) Currently translated at 99.5% (1181 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ * Translated using Weblate (Norwegian Bokmål) Currently translated at 59.9% (711 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nb_NO/ Co-authored-by: Szimszon Co-authored-by: Ihor Hordiichuk Co-authored-by: LinAGKar Co-authored-by: Priit Jõerüüt Co-authored-by: zer0-x <1rn0kmrwo@relay.firefox.com> Co-authored-by: jelv Co-authored-by: Sven Grewe Co-authored-by: inthepan Co-authored-by: Thibault Martin Co-authored-by: Kaede Co-authored-by: random Co-authored-by: semisenex Co-authored-by: Marcelo Filho Co-authored-by: Thor Arne Johansen Co-authored-by: Weblate --- Riot/Assets/ar.lproj/Vector.strings | 120 +++++ Riot/Assets/de.lproj/Vector.strings | 394 ++++++++++------- Riot/Assets/et.lproj/Vector.strings | 58 ++- Riot/Assets/fr.lproj/Vector.strings | 573 ++++++++++++++++-------- Riot/Assets/hu.lproj/Vector.strings | 56 ++- Riot/Assets/it.lproj/Vector.strings | 58 ++- Riot/Assets/ja.lproj/Vector.strings | 8 + Riot/Assets/nb-NO.lproj/Vector.strings | 54 ++- Riot/Assets/nl.lproj/Vector.strings | 588 ++++++++++++++++++++++++- Riot/Assets/pt_BR.lproj/Vector.strings | 62 ++- Riot/Assets/sv.lproj/Vector.strings | 62 ++- Riot/Assets/uk.lproj/Vector.strings | 14 +- 12 files changed, 1658 insertions(+), 389 deletions(-) create mode 100644 Riot/Assets/ar.lproj/Vector.strings diff --git a/Riot/Assets/ar.lproj/Vector.strings b/Riot/Assets/ar.lproj/Vector.strings new file mode 100644 index 000000000..bdf811f06 --- /dev/null +++ b/Riot/Assets/ar.lproj/Vector.strings @@ -0,0 +1,120 @@ + + +"room_recents_create_empty_room" = "إنشاءُ غُرفَة"; +"room_recents_start_chat_with" = "بَدءُ مُحادَثَة"; +"room_recents_no_conversation" = "لَا غُرَف"; +"room_recents_conversations_section" = "الغُرَف"; +"room_recents_people_section" = "الأشخَاص"; +"room_recents_favourites_section" = "المُفَضَّلَة"; +"room_creation_privacy" = "الخُصُوصِيَّة"; +"room_creation_appearance_name" = "الاِسم"; +"room_creation_appearance" = "المَظهَر"; +"room_creation_account" = "الحِساب"; + +// Chat creation +"room_creation_title" = "مُحادَثَة جَدِيدَة"; +"auth_softlogout_clear_data_sign_out" = "تَسجِيلُ الخُرُوج"; +"auth_softlogout_sign_in" = "تَسجيلُ الدُّخُول"; +"auth_reset_password_error_is_required" = "لَم يَتِمّ ضَبط خادِم هُويَّة: أضِف وَاحِدًا لإعادَة تَعيِين كَلِمَة المُرُور الخَاصَّة بِكَ."; +"auth_reset_password_next_step_button" = "لَقَد تَحَقَّقتُ مِن عُنوانِ بَريدي الإلِكتُرونيّ"; +"auth_reset_password_email_validation_message" = "لَقَد تَمَّ إرسَال بَريد الإلِكتُرونيّ إلى %@. بِمُجَرَّدِ اِتِّبَاع الرَّابِط الَّذِي يَحوِيه، اُنقُر أدنَاه."; +"auth_reset_password_missing_password" = "يَجِبُ إدخَال كَلِمَة مُرُور جَدِيدَة."; +"auth_reset_password_missing_email" = "يَجِبُ إدخَال عُنوان البَريد إلِكتُرونيّ المُرتَبِط بِحِسَابك."; +"auth_reset_password_message" = "لِإعادَةِ تَعيِينِ كَلِمَةِ المُرُور الخاصَّةِ بِك، أدخِل عُنوان البَريد إلِكتُرونيّ المُرتَبِط بِحِسَابك:"; +"auth_recaptcha_message" = "يُرِيدُ هَذَا الخادِم الرَّئيس التَّأكُّد مِن أنَّكَ لَستَ رُوبُوتًا"; +"auth_msisdn_validation_error" = "يَتَعَذَّرُ التَّحَقُّق مِن رَقمِ الهَاتِف."; +"auth_msisdn_validation_message" = "لَقَد أرسَلنا رِسَالَة SMS تَحوِي رَمزًا لِلتَفعِيل. يُرجَى إدخَال هَذَا الرَّمز أَدناه."; +"auth_msisdn_validation_title" = "قَيد التَّحَقُّق"; +"auth_email_validation_message" = "يُرجَى التَّحَقُّق مِن البَريد الإلِكتُرونيّ الخاصّ بِك لِمُوَاصَلَة التَّسجِيل"; +"auth_use_server_options" = "اِستِخدامُ إعدادَاتٍ مُخَصَّصَةٍ لِلخَادِم (مُتَقَدِّم)"; +"auth_email_not_found" = "فَشَلَ إرسَالُ البَريد الإلِكتُرونيّ: لَم يَتِمّ العُثُور عَلَى عُنوان البَريد الإلِكتُرونيّ هَذَا"; +"auth_forgot_password_error_no_configured_identity_server" = "لَم يَتِمّ ضَبط خادِم هُويَّة: أضِف وَاحِدًا لإعادَة تَعيِين كَلِمَة المُرُور الخَاصَّة بِكَ."; +"auth_forgot_password" = "هَل نَسِيتَ كَلِمَة المُرُور؟"; +"auth_username_in_use" = "اِسم مُستَخدِم مُستَخدَم"; +"auth_password_dont_match" = "كَلِمَةُ المُرُورِ لَا تَتَطَابَق"; +"auth_untrusted_id_server" = "خادِمُ الهُويَّة غَيرُ مَوثُوقٍ بِه"; +"auth_phone_is_required" = "لَم يَتِمّ ضَبط خادِم هُويَّة لِذَلِك لا يُمكِنُكَ إضافَة رَقم هَاتِف لإعادَة تَعيِين كَلِمَة المُرُور الخَاصَّة بِكَ فِي المُستَقبَل."; +"auth_email_is_required" = "لَم يَتِمّ ضَبط خادِم هُويَّة لِذَلِك لا يُمكِنُكَ إضافَة عُنوان بَريد إلِكتُرونيّ لإعادَة تَعيِين كَلِمَة المُرُور الخَاصَّة بِكَ فِي المُستَقبَل."; +"auth_phone_in_use" = "رَقم الهَاتِف هَذَا مُستَخدَمٌ بِالفِعل"; +"auth_email_in_use" = "هَذَا البَريد الإلِكتُرونيّ مُستَخدَم بِالفِعل"; +"auth_missing_email_or_phone" = "عُنوان البَريد إلِكتُرونيّ مَفقُود أو رَقم الهَاتِف"; +"auth_missing_phone" = "رَقم الهَاتِف مَفقُود"; +"auth_add_email_message_2" = "عَيِّن بَريدً إلِكتُرونيًّ لِاِستِردَادِ الحِساب، وَلاحِقًا لِتَكُونَ قابِلاً لِلاِكتِشاف اِختِيَاريًّا مِن قِبَلِ الأشخاصِ الَّذينَ يَعرِفُونَك."; +"auth_missing_password" = "نِسيانُ كَلِمَةِ المُرُور"; +"auth_invalid_phone" = "هَذَا لا يَبدُو كَرَقم هَاتِف صَالِح"; +"auth_invalid_email" = "هَذَا لا يَبدُو كَعُنوان بَريد إلِكتُرونيّ صَالِح"; +"auth_invalid_password" = "كَلِمَةُ المُرُورِ قَصِيرَةٌ جِدَا (الحَدُّ الأدنَى 6)"; +"auth_invalid_user_name" = "يُمكِنُ أن تَحتَوِي أسماءُ المُستَخدِمين فَقَط عَلَى أحرُف، أرقَام، نِقَاط، شَرَطَات وَشَرَطَات سُفلِيَّة"; +"auth_invalid_login_param" = "اِسمُ مُستَخدِم وَ/أو كَلِمَةُ مُرُور غَيرُ صَحِيحَة"; +"auth_identity_server_placeholder" = "عُنوان URL (مِثل. https://vector.im)"; +"auth_home_server_placeholder" = "عُنوان URL (مِثل. https://matrix.org)"; +"auth_repeat_new_password_placeholder" = "أكِّد كَلِمَةَ مُرُورِكَ الجَديدَة"; +"auth_repeat_password_placeholder" = "إعادَةُ كَلِمَةِ المُرُور"; +"auth_phone_placeholder" = "رَقم هَاتِف"; +"auth_optional_phone_placeholder" = "رَقم هَاتِف (اِختياري)"; +"auth_email_placeholder" = "عُنوان بَريد إلِكتُرونيّ"; +"auth_optional_email_placeholder" = "عُنوان بَريد إلِكتُرونيّ (اِختياري)"; +"auth_user_name_placeholder" = "اِسم مُستَخدِم"; +"auth_user_id_placeholder" = "بَريد إلِكتُرونيّ أو اِسم مُستَخدِم"; +"auth_new_password_placeholder" = "كَلِمَةُ مُرُورٍ جَديدَة"; +"auth_password_placeholder" = "كَلِمَةُ المُرُور"; +"auth_return_to_login" = "العَودَة إلى شاشَة تَسجيل الدُّخُول"; +"auth_send_reset_email" = "إرسَال بَريد إعادة ضَبط"; +"auth_login_single_sign_on" = "تَسجيلُ الدُّخُول"; +"auth_skip" = "تَخَطِّي"; +"auth_submit" = "التَّسلِيم"; +"auth_register" = "التَّسجيل"; + +// Authentication +"auth_login" = "تَسجيلُ الدُّخُول"; + +// Call Bar +"callbar_only_single_active" = "مُكالَمَة نَشِطَة (%@)"; +"less" = "أقَلّ"; +"more" = "المَزيد"; +"switch" = "تَبدِيل"; +"joined" = "مُنضَمّ"; +"skip" = "تَخَطِّي"; +"close" = "إغلاق"; +"sending" = "يَجري الإرسَال"; +"send_to" = "إرسَال إلى %@"; +"collapse" = "تضييق"; +"rename" = "إعادَة التَّسميَة"; +"later" = "لاَحِقًا"; +"active_call_details" = "مُكالَمَة نَشِطَة (%@)"; +"active_call" = "مُكالَمَة نَشِطَة"; +"video" = "مَقطَع مَرئي"; +"voice" = "صَوت"; +"camera" = "الكاميرا"; +"preview" = "مُعايَنَة"; +"accept" = "قُبُول"; +"decline" = "الرَّفض"; +"join" = "الاِنضِمام"; +"save" = "حِفظ"; +"cancel" = "إلغَاء"; +"off" = "إطفَاء"; +"on" = "تَشغيل"; +"retry" = "إعادَةُ المُحاوَلة"; +"invite" = "اُدعُ"; +"remove" = "إزالَة"; +"leave" = "المُغادَرَة"; +"start" = "البَدء"; +"create" = "إنشاء"; +"continue" = "الاِستِمرار"; +"back" = "الرُّجُوع"; +"next" = "التَّالي"; + +// Actions +"view" = "الاِطِّلاع"; +"warning" = "تَحذير"; +"title_groups" = "المُجتَمَعَات"; +"title_rooms" = "الغُرَف"; +"title_people" = "الأشخَاص"; +"title_favourites" = "المُفَضَّلَة"; + +// Titles +"title_home" = "الرَّئيسَة"; +"store_promotional_text" = "تَطبِيقُ المُحادَثَةِ وَالتَّعاوُن المُحَافِظ لِلخُصُوصِيَّةِ عَلَى شَبَكَةٍ مَفتُوحَة. لاَمَركَزِيٌّ لِوَضعِكَ فِي التَّحَكُّم. لَا تَنقِيبٌ عَنِ البَيَانَات، لَا أبوابَ خَلفِيَّةٍ وَلَا وُصُولٌ لِأيِّ طَرَفٍ ثَالِث."; +"store_full_description" = "Element هُوَ نَوعٌ جَديدٌ مِن تَطبيقاتِ المُراسَلَة وَالتَّعَاوُن الَّذي:\n\n1. يَمنَحُكَ التَّحَكُّم فِي لِلحِفاظِ عَلَى خُصُوصِيَّتِك\n2. يُتيحُ لَكَ التَّواصُلُ مَعَ أيّ شَخص عَلَى شَبَكَةِ Matrix ، وَحَتَّى خارِجَهَا مِن خِلال التَّكامُل مَعَ التَّطبيقات مِثل Slack\n3. يَحميكَ مِنَ الإعلانات، التَّنقيبُ عَنِ البَيانات، الأبوابُ الخَلفِيَّة وَعَمَلِيَّاتُ الحَدائِقِ المُسَوَّرَة\n4. يُؤمِنُكَ مِن خِلاِل تَعمِيَةِ النِّهايَة-إلى-النِّهايَة، مَعَ التَّوقيعِ المُتَبادَلِ لِلتَحَقُّقِ مِنَ الآخَرَين\n\nيَختَلِفُ Element تَمامًا عَن تَطبيقاتِ المُراسَلَةِ وَالتَّعاوُن الأُخرَى لأنَّهُ لا مَركَزي وَمَفتُوح المَصدَر.\n\nيُتيحُ لَكَ Element إمكانيةُ الاِستِضافَة الذّاتيَّة -أو اِختيارُ مُضيف- بِحَيث تَتَمَتَّع بِالخُصُوصِيَّة وَالمُلكيَّة وَالتَّحَكُّم فِي بَيانَاتك وَمُحَادَثاتك. يُتيحُ لَكَ الوُصُول إلى شَبَكَة مَفتُوحَة؛ لِذَلِكَ لا يَقتَصِرُ الأمر عَلَى التَّحدُث إلى مُستَخدِمي Element الآخَرين فَقَط. كَما اَنهُ آمِنٌ لِلغايَة.\n\nإنَّ Element قادِرٌ عَلَى إتاحَةِ كُلِ ذَلِك لِأنَهُ يَعمَلُ عَلَى Matrix -مِعيار التَّواصُل المَفتُوح اللَّامَركَزي.\n\nإنَّ Element يَمنَحُكَ زِمَامَ التَّحَكُم مِن خِلال السَّماح لَك بِاختيار مَن يَستَضيفُ المُحادَثاتِ الخَاصَّةِ بِك. مِن تَطبيقِ Element يُمكِنُكَ اِختيار الاِستِضافَة بِطُرُقٍ مُختَلِفَة:\n\n1. الحُصُول عَلَى حِساب مَجانيّ عَلَى الخادِم العَامّ matrix.org\n2. اِستِضافَة حِسابك بِنَفسِك عَن طَريق تَشغيل خادِم عَلَى أجهِزَتِكَ الخَاصَّة\n3. التَّسجيل لِلحُصُولِ عَلَى حِساب عَلَى خادِم مُخصص بمُجرد الاِشتِراك فِي مِنَصَّة اِستِضافَة Element Matrix Services\n\nلِمَاذَا تَختارُ Element؟\n\nتَملَّك بَياناتَك: أنتَ مَن تُقرر أين تَحتَفِظ ببياناتك ورسائلك. أنت تمتلكها وتتحكم فيها، وليس بعض الشركات الكُبرى الإحتكارية التي تُنقِّب عن بياناتك أو تُتيح الوصول إلى أطراف ثالثة.\n\n\nتَراسُل وَتَعَاوُن مَفتُوح يُمكِنُكَ مُحادَثَة أي شَخص آخَر عَلَى شَبَكَة Matrix، سَواءً كانُوا يَستَخدِمُونَ Element أو تَطبيقُ Matrix آخَر، وَحَتّى إذا كانُوا يَستَخدِمُونَ نِظامَ مُراسلةٍ مُختَلِف مِثل Slack أو IRC أو XMPP.\n\nالأمان-الخارِق: تَعميَة حَقيقيَة مِنَ النِّهايَة إلى النِّهايَة (فَقَط أطراف المُحادَثَة مَن يُمكِنَهُم فَكّ تَعميَة الرَّسائِل)، وَالتَّوقِيع المُتَبادَل لِلتحقق من أجهزة المُشاركين في المُحادثة.\n\nالتواصل الكامل: المُراسلة، المُكالمات الصوتية والمرئية، مُشاركة الملفات، مُشاركة الشاشة، مجموعة كاملة وكبيرة من عمليات التكامُل، الروبوتات والأدوات. بناء الغُرف، المُجتمعات، ابق على اتصال وأنجز المهام.\n\nأين ما كُنت: ابق على اتصال أينما كنت مع سجل الرسائل المتزامن بالكامل عبر جميع أجهزتك وفي الويب على https://app.element.io."; +// String for App Store +"store_short_description" = "مُحادَثَةٌ/VoIP آمنةٌ لَا مَركَزِيَّة"; diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index a4f929dcd..a2fe5d961 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -8,7 +8,7 @@ "view" = "Ansehen"; "invite" = "Einladen"; // Room Details -"room_details_title" = "Raum Details"; +"room_details_title" = "Raumdetails"; "title_favourites" = "Favoriten"; "title_people" = "Personen"; "title_rooms" = "Räume"; @@ -151,8 +151,8 @@ "room_new_message_notification" = "%d neue Nachricht"; "room_new_messages_notification" = "%d neue Nachrichten"; "room_one_user_is_typing" = "%@ tippt…"; -"room_two_users_are_typing" = "%@ & %@ tippen…"; -"room_many_users_are_typing" = "%@, %@ & andere tippen…"; +"room_two_users_are_typing" = "%@ und %@ tippen…"; +"room_many_users_are_typing" = "%@, %@ und andere tippen…"; "room_message_placeholder" = "Nachricht senden (unverschlüsselt)…"; "encrypted_room_message_placeholder" = "Verschlüsselte Nachricht…"; "room_message_short_placeholder" = "Sende eine Nachricht…"; @@ -168,7 +168,7 @@ "room_event_action_more" = "Mehr"; "room_event_action_share" = "Teilen"; "room_event_action_permalink" = "Permalink"; -"room_event_action_view_source" = "Zeige Quellcode"; +"room_event_action_view_source" = "Zeige Quelltext"; "room_event_action_report" = "Inhalt melden"; "room_event_action_report_prompt_reason" = "Grund fürs Melden dieses Inhalts"; "room_event_action_report_prompt_ignore_user" = "Möchtest du alle Nachrichten dieses Nutzers verbergen?"; @@ -181,7 +181,7 @@ // Unknown devices "unknown_devices_alert_title" = "Raum enthält unbekannte Sitzungen"; "unknown_devices_send_anyway" = "Trotzdem senden"; -"unknown_devices_call_anyway" = "Trotzdem Anrufen"; +"unknown_devices_call_anyway" = "Trotzdem anrufen"; "unknown_devices_answer_anyway" = "Trotzdem beantworten"; "unknown_devices_verify" = "Verifiziere…"; "unknown_devices_title" = "Unbekannte Sitzungen"; @@ -209,7 +209,7 @@ "settings_ignored_users" = "IGNORIERTE NUTZER"; "settings_contacts" = "LOKALE KONTAKTE"; "settings_advanced" = "ERWEITERT"; -"settings_other" = "ANDERES"; +"settings_other" = "WEITERES"; "settings_devices" = "SITZUNGEN"; "settings_cryptography" = "VERSCHLÜSSELUNG"; "settings_sign_out" = "Abmelden"; @@ -224,17 +224,17 @@ "settings_email_address_placeholder" = "Gib deine E-Mail-Adresse ein"; "settings_add_email_address" = "E-Mail-Adresse hinzufügen"; "settings_remove_phone_prompt_msg" = "Bist du sicher, dass du die Telefon-Nummer %@ entfernen möchtest?"; -"settings_night_mode" = "Nacht Modus"; +"settings_night_mode" = "Nachtmodus"; "settings_enable_push_notif" = "Benachrichtungen auf diesem Gerät"; "settings_unignore_user" = "Alle Nachrichten von %@ anzeigen?"; -"settings_contacts_phonebook_country" = "Telefonbuch-Land"; +"settings_contacts_phonebook_country" = "Land des Telefonbuches"; "settings_labs_e2e_encryption" = "Ende-zu-Ende-Verschlüsselung"; "settings_version" = "Version %@"; "settings_olm_version" = "Olm-Version %@"; -"settings_copyright" = "Kopierrecht"; +"settings_copyright" = "Urheberrecht"; "settings_term_conditions" = "Geschäftsbedingungen"; "settings_privacy_policy" = "Datenschutzerklärung"; -"settings_send_crash_report" = "Sende anonyme Absturz- & Nutzungsdaten"; +"settings_send_crash_report" = "Sende anonyme Absturz- und Nutzungsdaten"; "settings_change_password" = "Passwort ändern"; "settings_old_password" = "altes Passwort"; "settings_new_password" = "neues Passwort"; @@ -244,21 +244,21 @@ "settings_crypto_device_key" = "\nSitzungs-Schlüssel:\n"; "settings_crypto_export" = "Schlüssel exportieren"; "room_details_settings" = "Einstellungen"; -"room_details_photo" = "Raum-Bild"; -"room_details_room_name" = "Raum-Name"; +"room_details_photo" = "Raumbild"; +"room_details_room_name" = "Raumname"; "room_details_topic" = "Thema"; "room_details_favourite_tag" = "Favorit"; "room_details_low_priority_tag" = "Niedrige Priorität"; "room_details_access_section" = "Wer kann auf diesen Raum zugreifen?"; "room_details_access_section_invited_only" = "Nur Personen, die eingeladen wurden"; -"room_details_access_section_anyone_apart_from_guest" = "Jeder, der den Raum-Link kennt - außer Gäste"; -"room_details_access_section_anyone" = "Jeder, der den Raum-Link kennt - auch Gäste"; +"room_details_access_section_anyone_apart_from_guest" = "Jeder, der den Raumlink kennt - außer Gäste"; +"room_details_access_section_anyone" = "Jeder, der den Raumlink kennt - auch Gäste"; "room_details_history_section" = "Wer kann die Historie lesen?"; "room_details_history_section_anyone" = "Jeder"; "room_details_history_section_members_only" = "Nur Mitglieder (seit diese Option ausgewählt ist)"; "room_details_history_section_members_only_since_invited" = "Nur Mitglieder (ab ihrer Einladung)"; "room_details_history_section_members_only_since_joined" = "Nur Mitglieder (Ab ihrem Beitritt)"; -"room_details_history_section_prompt_title" = "Datenschutz-Warnung"; +"room_details_history_section_prompt_title" = "Datenschutzwarnung"; "room_details_addresses_section" = "Adressen"; "room_details_no_local_addresses" = "Dieser Raum hat keine lokalen Adressen"; "room_details_new_address" = "Füge neue Adresse hinzu"; @@ -277,13 +277,13 @@ "auth_add_phone_message" = "Füge eine Telefonnummer hinzu, damit dich andere Benutzer finden können."; "auth_add_email_phone_message" = "Füge eine E-Mail-Adresse und/oder Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen."; "auth_add_email_and_phone_message" = "Füge eine E-Mail-Adresse und eine Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen."; -"auth_use_server_options" = "Individuelle Server Optionen"; +"auth_use_server_options" = "Individuelle Server-Optionen"; "auth_email_validation_message" = "Prüfe dein E-Mail-Konto um mit der Registrierung fortzufahren"; -"auth_recaptcha_message" = "Dieser Homeserver will sicherstellen dass du kein Robot bist"; +"auth_recaptcha_message" = "Dieser Heimserver will sicherstellen dass du kein Roboter bist"; "auth_reset_password_message" = "E-Mail-Adresse angeben, um das Passwort zurückzusetzen:"; "auth_reset_password_missing_email" = "Die E-Mail-Adresse die mit dem Konto verbunden ist muss eingegeben werden."; "auth_reset_password_error_unauthorized" = "Konnte E-Mail-Adresse nicht verifizieren. Klicke den Link in der Registrierungs-E-Mail"; -"auth_reset_password_error_not_found" = "Diese E-Mail-Adresse ist nicht mit einer Matrix-ID auf diesem Homeserver verknüpft."; +"auth_reset_password_error_not_found" = "Diese E-Mail-Adresse ist nicht mit einer Matrix-ID auf diesem Heimserver verknüpft."; "auth_reset_password_success_message" = "Dein Passwort wurde zurückgesetzt.\n\nDu wurdest aus allen Sitzungen abgemeldet, diese bekommen jetzt keine Push-Benachrichtigungen mehr. Um diese wieder einzuschalten, melde dich auf den Geräten erneut an."; "auth_add_email_and_phone_warning" = "Registrierung mit E-Mail und Telefonnummer zugleich ist noch nicht unterstützt. Nur die Telefonnummer wird berücksichtigt. Du kannst deine E-Mail-Adresse in deinem Profil ergänzen."; "room_creation_make_public_prompt_msg" = "Sicher, dass du diesen Raum öffentlich machen willst? Jeder kann deine Nachrichten lesen und dem Raum beitreten."; @@ -298,18 +298,18 @@ "room_participants_invite_malformed_id" = "Ungültige ID. Sollte eine E-Mail-Adresse oder Matrix-ID wie \"@thomas:matrix.org' sein"; "room_participants_idle" = "Untätig"; "room_participants_ago" = "her"; -"room_participants_action_section_admin_tools" = "Admin Werkzeuge"; +"room_participants_action_section_admin_tools" = "Admin-Werkzeuge"; "room_participants_action_unban" = "Entsperren"; "room_participants_action_set_default_power_level" = "Zurück auf normale Berechtigung"; "room_participants_action_start_voice_call" = "Starte Sprach-Anruf"; "room_ongoing_conference_call" = "Laufender Konferenz-Anruf. Trete bei als %@ oder %@."; "room_event_action_redact" = "Entfernen"; -"room_warning_about_encryption" = "Ende-zu-Ende Verschlüsselung ist in Beta und ist evtl. nicht zuverlässig.\n\nMan sollte noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte werden Nachrichten von vor dem Beitritt des Raumes nicht entschlüsseln können.\n\nVerschlüsselte Nachrichten sind nicht lesbar auf Clients, die Verschlüsselung noch nicht implementiert haben."; -"unknown_devices_alert" = "Dieser Raum enthält unbekannte Sitzungen, die nicht verifiziert wurden.\nDas bedeutet, es gibt keine Garantie, dass sie dem/r angegebenen Benutzer!n gehören.\nWir empfehlen eine Überprüfung für jedes Gerät, bevor du weitermachst. Du kannst die Nachricht auch ohne Verifizierung erneut senden."; +"room_warning_about_encryption" = "Ende-zu-Ende Verschlüsselung ist in Beta und ist evtl. nicht zuverlässig.\n\nMan sollte noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte werden Nachrichten von vor dem Beitritt des Raumes nicht entschlüsseln können.\n\nVerschlüsselte Nachrichten sind nicht lesbar auf Clients, die die Verschlüsselung noch nicht implementiert haben."; +"unknown_devices_alert" = "Dieser Raum enthält unbekannte Sitzungen, die nicht verifiziert wurden.\nDas bedeutet, es gibt keine Garantie, dass sie den angegebenen Benutzern gehört.\nWir empfehlen eine Überprüfung für jedes Gerät, bevor du weitermachst. Du kannst die Nachricht auch ohne Verifizierung erneut senden."; "room_preview_unlinked_email_warning" = "Diese Einladung wurde an %@ gesendet, welche diesem Konto nicht zugeordnet ist. Möglicherweise möchtest du dich mit einem anderen Konto anmelden oder diese E-Mail zu deinem Konto hinzufügen."; "room_preview_try_join_an_unknown_room" = "Du versuchst auf %@ zuzugreifen. Möchtest du dem Raum beitreten um teilzunehmen?"; "settings_config_identity_server" = "Identitätsserver ist %@"; -"settings_labs" = "Labor"; +"settings_labs" = "LABORE"; "settings_sign_out_e2e_warn" = "Du wirst die Ende-zu-Ende Schlüssel verlieren. Du kannst dann auf diesem Gerät in verschlüsselten Räumen keine alten Nachrichten mehr lesen."; "settings_phone_number" = "Telefon"; "settings_add_phone_number" = "Telefonnummer hinzufügen"; @@ -318,7 +318,7 @@ "settings_pin_rooms_with_missed_notif" = "Pinnen von Räumen mit verpassten Benachrichtigungen"; "settings_pin_rooms_with_unread" = "Pinnen von Räumen mit ungelesenen Nachrichten"; "settings_on_denied_notification" = "Benachrichtigungen verboten für %@, bitte in den Geräte-Einstellungen erlauben"; -"settings_contacts_discover_matrix_users" = "Entdecke andere Benutzer!nnen mittels E-Mail-Adressen oder Telefonnummern"; +"settings_contacts_discover_matrix_users" = "Entdecke andere Benutzer mittels E-Mail-Adressen oder Telefonnummern"; "settings_labs_e2e_encryption_prompt_message" = "Zum Fertigstellen der Verschlüsselung bitte neu anmelden."; "settings_third_party_notices" = "Anmerkungen von Dritten"; "settings_clear_cache" = "Cache löschen"; @@ -326,31 +326,31 @@ "settings_crypto_device_id" = "\nSitzungs-ID: "; "settings_crypto_blacklist_unverified_devices" = "Verschlüssele nur zu verifizierten Sitzungen"; "room_details_people" = "Mitglieder"; -"room_details_files" = "Uploads"; +"room_details_files" = "Hochgeladenes"; "room_details_mute_notifs" = "Benachrichtigungen stummschalten"; "room_details_access_section_no_address_warning" = "Um einen Raum zu betreten, muss er eine Adresse haben"; "room_details_access_section_directory_toggle" = "Zeige alle Räume in diesem Verzeichnis"; "room_details_history_section_prompt_msg" = "Änderungen an der Leseberechtigung des Verlaufs wird nur auf zukünftige Nachrichten dieses Raums angewandt. Die Sichtbarkeit des existierenden Verlaufs wird nicht verändert."; -"room_details_addresses_invalid_address_prompt_title" = "Ungültiges Alias-Format"; +"room_details_addresses_invalid_address_prompt_title" = "Ungültiges Aliasformat"; "room_details_addresses_invalid_address_prompt_msg" = "%@ ist kein gültiges Format für einen Alias"; -"room_details_addresses_disable_main_address_prompt_title" = "Hauptadresse Warnung"; +"room_details_addresses_disable_main_address_prompt_title" = "Hauptadressenwarnung"; "room_details_addresses_disable_main_address_prompt_msg" = "Du hast keine Hauptadresse angegeben. Die Hauptadresse für diesem Raum wird zufällig gewählt"; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Nur zu verifizierten Sitzungen verschlüsseln"; "room_details_advanced_e2e_encryption_prompt_message" = "Ende-zu-Ende Verschlüsselung ist experimentell und möglicherweise nicht zuverlässig.\n\nDu solltest noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte können keine Nachrichten von vor dem Beitritt des Raumes entschlüsseln.\n\nWenn die Verschlüsselung aktiviert wurde, kann sie derzeit nicht wieder abgeschaltet werden.\n\nVerschlüsselte Nachrichten werden nicht auf Geräten angezeigt, die keine Verschüsselung unterstützen."; -"room_details_fail_to_update_avatar" = "Aktualisierung des Raum-Bildes fehlgeschlagen"; +"room_details_fail_to_update_avatar" = "Aktualisierung des Raumbildes fehlgeschlagen"; "room_details_fail_to_update_room_name" = "Aktualisierung des Raumnamens fehlgeschlagen"; "room_details_fail_to_update_topic" = "Aktualisieren des Themas fehlgeschlagen"; "room_details_fail_to_update_room_guest_access" = "Aktualisierung des Gäste-Zugangs fehlgeschlagen"; -"room_details_fail_to_update_room_join_rule" = "Aktualisierung des Beitrittsregel fehlgeschlagen"; +"room_details_fail_to_update_room_join_rule" = "Aktualisierung der Beitrittsregel fehlgeschlagen"; "room_details_fail_to_update_room_directory_visibility" = "Aktualisierung der Raumlisten-Sichtbarkeit fehlgeschlagen"; "room_details_fail_to_update_history_visibility" = "Aktualisierung der Verlaufs-Sichtbarkeit fehlgeschlagen"; "room_details_fail_to_add_room_aliases" = "Hinzufügen der neuen Raum-Adresse fehlgeschlagen"; "room_details_fail_to_remove_room_aliases" = "Entfernen der Raum-Adresse fehlgeschlagen"; -"room_details_fail_to_update_room_canonical_alias" = "Aktualisierung der Haupt-Adresse fehlgeschlagen"; +"room_details_fail_to_update_room_canonical_alias" = "Aktualisierung der Hauptadresse fehlgeschlagen"; "room_details_fail_to_enable_encryption" = "Aktivieren der Verschlüsselung für diesen Raum fehlgeschlagen"; "room_details_save_changes_prompt" = "Möchtest du die Änderungen speichern?"; -"room_details_set_main_address" = "Als Haupt-Adresse setzen"; -"room_details_unset_main_address" = "Als Haupt-Adresse entfernen"; +"room_details_set_main_address" = "Als Hauptadresse setzen"; +"room_details_unset_main_address" = "Als Hauptadresse entfernen"; "room_details_copy_room_id" = "Kopiere Raum-ID"; "room_details_copy_room_address" = "Kopiere Raum-Adresse"; "room_details_copy_room_url" = "Kopiere Raum-URL"; @@ -365,7 +365,7 @@ "directory_server_picker_title" = "Wähle ein Verzeichnis"; "directory_server_all_rooms" = "Alle Räume auf %@ Server"; "directory_server_all_native_rooms" = "Alle nativen Matrix-Räume"; -"directory_server_type_homeserver" = "Gib einen Homeserver ein, um davon öffentliche Räume zu listen"; +"directory_server_type_homeserver" = "Gib einen Heimserver ein, um davon öffentliche Räume zu listen"; "directory_server_placeholder" = "matrix.org"; // Others "or" = "oder"; @@ -374,18 +374,18 @@ "yesterday" = "Gestern"; "network_offline_prompt" = "Keine Verbindung zum Internet."; "public_room_section_title" = "Öffentliche Räume (at %@):"; -"bug_report_prompt" = "Die Applikation ist letztes Mal abgestürzt. Möchtest du einen Crash Report senden?"; -"rage_shake_prompt" = "Du scheinst das Gerät frustriert zu schütteln. Möchtest du einen Bug Report senden?"; +"bug_report_prompt" = "Die Applikation ist letztes Mal abgestürzt. Möchtest du einen Absturzbericht senden?"; +"rage_shake_prompt" = "Du scheinst das Gerät frustriert zu schütteln. Möchtest du einen Fehlerbericht senden?"; "camera_access_not_granted" = "%@ hat keine Berechtigung die Kamera zu nutzen, bitte berechtigen"; "large_badge_value_k_format" = "%.1fK"; // Call -"call_incoming_voice_prompt" = "Eingehender Sprach-Anruf von %@"; -"call_incoming_video_prompt" = "Eingehender Video-Anruf von %@"; +"call_incoming_voice_prompt" = "Eingehender Sprachanruf von %@"; +"call_incoming_video_prompt" = "Eingehender Videoanruf von %@"; // No VoIP support "no_voip_title" = "Eingehener Anruf"; "no_voip" = "%@ ruft dich an, aber %@ unterstützt derzeit keine Anrufe.\nDu kannst diese Benachrichtung ignorieren und den Anruf von einem anderen Gerät annehmen oder ihn abweisen."; // Crash report -"google_analytics_use_prompt" = "Möchtest du helfen %@ zu verbessern, indem du anonyme Crash Reports und Daten über die Verwendung sendest?"; +"google_analytics_use_prompt" = "Möchtest du helfen %@ zu verbessern, indem du anonyme Absturzberichte und Daten über die Verwendung sendest?"; // Crypto "e2e_enabling_on_app_update" = "Element unterstützt nun Ende-zu-Ende Verschlüsselung. Um sie zu aktivieren musst du dich erneut anmelden.\n\nDu kannst sie nun aktivieren oder später in den Einstellungen."; "e2e_need_log_in_again" = "Du musst dich erneut anmelden um Ende-zu-Ende Schlüssel für diese Sitzung zu erstellen und zum Server zu senden.\nDies ist nur einmal notwendig."; @@ -394,11 +394,11 @@ "bug_report_description" = "Beschreibe den Fehler. Was hast du gemacht? Was hast du erwartet? Was ist tatsächlich passiert?"; "bug_crash_report_title" = "Absturzmeldung"; "bug_crash_report_description" = "Bitte beschreibe was du vor dem Absturz gemacht hast:"; -"bug_report_logs_description" = "Um Probleme analysieren zu können werden Log-Daten dieses Clients mit dem Bug Report gesendet. Wenn du nur den Text oben senden willst, bitte abwählen:"; -"bug_report_send_logs" = "Sende Log-Daten"; +"bug_report_logs_description" = "Um Probleme analysieren zu können werden Protokolldateien dieses Clients mit dem Fehlerbericht gesendet. Wenn du nur den Text oben senden willst, bitte abwählen:"; +"bug_report_send_logs" = "Sende Protokolldateien"; "bug_report_send_screenshot" = "Sende Bildschirmfoto"; -"bug_report_progress_zipping" = "Sammele Log-Daten"; -"bug_report_progress_uploading" = "Report hochladen"; +"bug_report_progress_zipping" = "Sammele Protokolle"; +"bug_report_progress_uploading" = "Bericht hochladen"; "bug_report_send" = "Gesendet"; "collapse" = "zusammenklappen"; "auth_email_in_use" = "Diese E-Mail-Adresse wird bereits verwendet"; @@ -431,15 +431,15 @@ "sending" = "Senden"; "room_event_failed_to_send" = "Senden fehlgeschlagen"; "room_details_direct_chat" = "Direkter Chat"; -"room_details_fail_to_update_room_direct" = "Setzen der Direkt-Kennzeichnung in diesem Raum fehlgeschlagen"; +"room_details_fail_to_update_room_direct" = "Setzen der Direktkennzeichnung in diesem Raum fehlgeschlagen"; "event_formatter_widget_added" = "Widget %@ wurde von %@ hinzugefügt"; "event_formatter_widget_removed" = "Widget %@ wurde von %@ entfernt"; "event_formatter_jitsi_widget_added" = "VoIP-Konferenz von %@ hinzugefügt"; "event_formatter_jitsi_widget_removed" = "VoIP-Konferenz von %@ entfernt"; "call_incoming_voice" = "Eingehender Anruf…"; -"call_incoming_video" = "Eingehender Video-Anruf…"; +"call_incoming_video" = "Eingehender Videoanruf…"; // Widget Integration Manager -"widget_integration_need_to_be_able_to_invite" = "Du musst Benutzer!nnen einladen können um das zu tun."; +"widget_integration_need_to_be_able_to_invite" = "Du musst Benutzer einladen können um das zu tun."; "widget_integration_unable_to_create" = "Erstellen des Widgets nicht möglich."; "widget_integration_failed_to_send_request" = "Senden der Anfrage fehlgeschlagen."; "widget_integration_room_not_recognised" = "Dieser Raum wurde nicht erkannt."; @@ -450,8 +450,8 @@ "widget_integration_missing_user_id" = "user_id fehlt in der Anfrage."; "widget_integration_room_not_visible" = "Raum %@ ist nicht sichtbar."; // Share extension -"share_extension_auth_prompt" = "Melde dich in der Haupt-App an um Inhalte zu teilen"; -"share_extension_failed_to_encrypt" = "Senden fehlgeschlagen. Prüfe in der Hauptapp die Verschlüsselungseinstellungen für diesen Raum"; +"share_extension_auth_prompt" = "Melde dich in der Hauptanwendung an um Inhalte zu teilen"; +"share_extension_failed_to_encrypt" = "Senden fehlgeschlagen. Prüfe in der Hauptanwendung die Verschlüsselungseinstellungen für diesen Raum"; "settings_ui_theme_picker_message" = "\"Auto\" nutzt die \"Farben invertieren\"-Einstellung deines Geräts"; "search_in_progress" = "Suche…"; "room_event_action_cancel_send" = "Senden abbrechen"; @@ -460,10 +460,10 @@ "settings_enable_callkit" = "Eingebettetes Anrufen"; "settings_callkit_info" = "Empfange eingehende Anrufe auf deinem Sperrbildschirm und sehe deine Element-Anrufe in der Anruf-Historie deines Systems. Wenn iCloud aktiviert ist, wird diese Anruf-Historie mit Apple geteilt."; "settings_enable_rageshake" = "Schüttle stark um einen Fehler zu melden"; -"do_not_ask_again" = "Nicht erneut fragen"; +"do_not_ask_again" = "Nicht erneut nachfragen"; "settings_ui_theme_black" = "Schwarz"; // Room key request dialog -"e2e_room_key_request_title" = "Verschlüsselungs-Schlüssel-Anfrage"; +"e2e_room_key_request_title" = "Verschlüsselungs-Schlüsselanfrage"; "e2e_room_key_request_message" = "Deine nicht-verifizierte Sitzung '%@' fragt Verschlüsselungs-Schlüssel an."; "e2e_room_key_request_start_verification" = "Starte Verifikation…"; "e2e_room_key_request_share_without_verifying" = "Teile ohne zu verifizieren"; @@ -473,7 +473,7 @@ "group_invite_section" = "EINLADUNGEN"; "group_section" = "COMMUNITIES"; "settings_flair" = "Zeige Abzeichen, wo es erlaubt ist"; -"room_details_flair_section" = "Zeige Flair für Communities"; +"room_details_flair_section" = "Zeige Abzeichen für Communities"; "room_details_new_flair_placeholder" = "Füge neue Community-ID hinzu (z.B. +foo%@)"; "room_details_flair_invalid_id_prompt_title" = "Ungültiges Format"; "room_details_flair_invalid_id_prompt_msg" = "%@ ist kein valider Bezeichner für eine Community"; @@ -505,35 +505,35 @@ // Group rooms "group_rooms_filter_rooms" = "Filtere Community-Räume"; "e2e_room_key_request_message_new_device" = "Du hast die neue Sitzung '%@' hinzugefügt, welche Verschlüsselungs-Schlüssel anfordert."; -"room_do_not_have_permission_to_post" = "Du hast keine Berechtigung in diesem Raum zu posten"; -"room_event_action_kick_prompt_reason" = "Grund für den Rauswurf des/r Benutzer!n"; -"room_event_action_ban_prompt_reason" = "Grund für die Verbannung des/r Benutzer!n"; +"room_do_not_have_permission_to_post" = "Du hast keine Berechtigung Nachrichten in diesem Raum zu senden"; +"room_event_action_kick_prompt_reason" = "Grund für den Rauswurf des Benutzers"; +"room_event_action_ban_prompt_reason" = "Grund für die Verbannung des Benutzers"; "room_action_send_photo_or_video" = "Foto oder Video senden"; -"room_action_send_sticker" = "Sticker senden"; -"settings_deactivate_account" = "DEAKTIVIERE ACCOUNT"; -"settings_deactivate_my_account" = "Deaktivere meinen Account"; -"widget_sticker_picker_no_stickerpacks_alert" = "Du hast aktuell keine Sticker-Packete aktiviert."; +"room_action_send_sticker" = "Aufkleber senden"; +"settings_deactivate_account" = "DEAKTIVIERTES KONTO"; +"settings_deactivate_my_account" = "Deaktivere meinen Konto"; +"widget_sticker_picker_no_stickerpacks_alert" = "Du hast aktuell keine Aufkleberpakete aktiviert."; "widget_sticker_picker_no_stickerpacks_alert_add_now" = "Welche hinzufügen?"; // GDPR "gdpr_consent_not_given_alert_message" = "Um den %@ -Heimserver weiter zu verwenden, musst du die Geschäftsbedingungen sichten und ihnen zustimmen."; "gdpr_consent_not_given_alert_review_now_action" = "Jetzt sichten"; -"deactivate_account_title" = "Deaktiviere Account"; -"deactivate_account_informations_part1" = "Dies wird deinen Account permanent unbenutzbar machen. Du wirst dich nicht erneut anmelden können und keiner wird dieselbe Nutzer-ID erneut registrieren. Alle Räume, in denen dein Account ist, werden verlassen werden und deine Account-Daten werden vom Identitätsserver gelöscht werden. "; +"deactivate_account_title" = "Deaktiviere Konto"; +"deactivate_account_informations_part1" = "Dies wird deinen Konto permanent unbenutzbar machen. Du wirst dich nicht erneut anmelden können und keiner wird in der Lage sein, dieselbe Nutzer-ID erneut zu registrieren. Alle Räume, in denen dein Konto ist, werden verlassen und deine Kontodaten werden vom Identitätsserver gelöscht. "; "deactivate_account_informations_part2_emphasize" = "Diese Aktion ist irreversibel."; -"deactivate_account_informations_part3" = "\n\nDeinen Account deaktivieren "; +"deactivate_account_informations_part3" = "\n\nDeinen Konto deaktivieren "; "deactivate_account_informations_part4_emphasize" = "wird standardmäßig nicht dafür sorgen, dass wir alle Nachrichten löschen, die du gesendet hast. "; -"deactivate_account_informations_part5" = "Wenn du möchtest, dass wir deine Nachrichten löschen, wähle das Auswahlfeld unten aus.\n\nDie Sichtbarkeit der Nachrichten in Matrix ist wie bei E-Mails: Wenn wir deine Nachrichten löschen, werden sie nicht mehr mit neuen oder nicht registrierten Benutzer!nnen geteilt. Bereits registrierte Nutzer!nnen behalten den Zugriff auf ihre Kopie deiner Nachrichten."; -"deactivate_account_forget_messages_information_part1" = "Bitte vergesst alle Nachrichten, die ich gesendet habe, wenn mein Account deaktiviert wird ("; +"deactivate_account_informations_part5" = "Wenn du möchtest, dass wir deine Nachrichten löschen, wähle das Auswahlfeld unten aus.\n\nDie Sichtbarkeit der Nachrichten in Matrix ist wie bei E-Mails: Wenn wir deine Nachrichten löschen, werden sie nicht mehr mit neuen oder nicht registrierten Benutzer geteilt. Bereits registrierte Nutzer behalten den Zugriff auf ihre Kopie deiner Nachrichten."; +"deactivate_account_forget_messages_information_part1" = "Bitte alle Nachrichten vergessen, die ich gesendet habe, wenn mein Konto deaktiviert wird ("; "deactivate_account_forget_messages_information_part2_emphasize" = "Warnung"; "deactivate_account_forget_messages_information_part3" = ": Dies wird dafür sorgen, dass zukünftige Nutzer eine unvollständige Konversation sehen)"; -"deactivate_account_validate_action" = "Account deaktiveren"; -"deactivate_account_password_alert_title" = "Account deaktivieren"; -"deactivate_account_password_alert_message" = "Zum Fortfahren, Password eingeben"; -"event_formatter_rerequest_keys_part1_link" = "Verschlüsselungsschlüssel erneut"; +"deactivate_account_validate_action" = "Konto deaktiveren"; +"deactivate_account_password_alert_title" = "Konto deaktivieren"; +"deactivate_account_password_alert_message" = "Zum Fortfahren, Passwort eingeben"; +"event_formatter_rerequest_keys_part1_link" = "Verschlüsselungsschlüssel neu anfordern"; "event_formatter_rerequest_keys_part2" = " von deinen anderen Sitzungen anfragen."; // Re-request confirmation dialog "rerequest_keys_alert_title" = "Anfrage gesendet"; -"rerequest_keys_alert_message" = "Bitte öffne Element auf einem anderen Gerät, das die Nachricht entschlüsseln kann, damit es die Schlüssel an diese Sitzung senden kann."; +"rerequest_keys_alert_message" = "Bitte Element auf einem anderen Gerät öffenen, das die Nachricht entschlüsseln kann, damit es die Schlüssel an diese Sitzung senden kann."; "room_message_reply_to_placeholder" = "Antwort senden (unverschlüsselt)…"; "encrypted_room_message_reply_to_placeholder" = "Sende eine verschlüsselte Antwort…"; "room_message_reply_to_short_placeholder" = "Sende eine Antwort…"; @@ -543,23 +543,23 @@ "room_predecessor_link" = "Tippe hier um ältere Nachrichten zu sehen."; "settings_labs_room_members_lazy_loading" = "Raummitglieder später laden"; "settings_labs_room_members_lazy_loading_error_message" = "Dein Heimserver unterstützt das verzögerte Laden von Raummitgliedern noch nicht. Versuche es später erneut."; -"room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quellcode"; +"room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quelltext"; "room_recents_server_notice_section" = "SYSTEMBENACHRICHTIGUNGEN"; "room_resource_limit_exceeded_message_contact_1" = " Bitte "; "room_resource_limit_exceeded_message_contact_2_link" = "kontaktiere deinen Dienst-Administrator"; -"room_resource_limit_exceeded_message_contact_3" = " um diesen Service weiter zu nutzen."; +"room_resource_limit_exceeded_message_contact_3" = " um diesen Dienst weiter zu nutzen."; "homeserver_connection_lost" = "Konnte keine Verbindung zum Heimserver herstellen."; -"room_resource_usage_limit_reached_message_1_default" = "Dieser Heimserver hat einen seiner Ressourcen-Limits überschritten, sodass "; -"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Dieser Heimserver hat sein Limit an monatlich aktiven Benutzer!nnen überschritten, sodass "; -"room_resource_usage_limit_reached_message_2" = "einige Benutzer!nnen werden nicht in der Lage sein, sich einzuloggen."; -"room_resource_usage_limit_reached_message_contact_3" = " um dieses Limit erhöhen zu lassen."; +"room_resource_usage_limit_reached_message_1_default" = "Dieser Heimserver hat einer seiner Ressourcengrenzen überschritten, sodass "; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Dieser Heimserver hat seine Begrenzung an monatlich aktiven Benutzer überschritten, sodass "; +"room_resource_usage_limit_reached_message_2" = "einige Benutzer nicht in der Lage sein werden, sich anzumelden."; +"room_resource_usage_limit_reached_message_contact_3" = " um diese Obergrenze erhöhen zu lassen."; "auth_accept_policies" = "Bitte Regeln dieses Heimservers ansehen und akzeptieren:"; -"settings_key_backup" = "SCHLÜSSEL SICHERHEITSKOPIE"; +"settings_key_backup" = "SCHLÜSSEL-SICHERHEITSKOPIE"; "settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich du und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen."; "settings_key_backup_info_checking" = "Überprüfe…"; "settings_key_backup_info_none" = "Deine Schlüssel werden nicht von dieser Sitzung gesichert."; "settings_key_backup_info_signout_warning" = "Verbinde diese Sitzung mit der Schlüsselsicherung, bevor du dich abmeldest, um den Verlust von Schlüsseln zu vermeiden, die sich möglicherweise nur auf diesem Gerät befinden."; -"settings_key_backup_info_version" = "Schlüssel Sicherheitskopie Version: %@"; +"settings_key_backup_info_version" = "Version der Schlüsselsicherung: %@"; "settings_key_backup_info_algorithm" = "Algorithmus"; "settings_key_backup_info_valid" = "Diese Sitzung sichert deine Schlüssel."; "settings_key_backup_info_not_valid" = "Diese Sitzung sichert nicht dein Schlüssel, es ist jedoch eine Sicherungskopie vorhanden, von der du deine Schlüssel wiederherstellen und die du später hinzufügen kannst."; @@ -578,17 +578,17 @@ "settings_key_backup_delete_confirmation_prompt_title" = "Sicherheitskopie löschen"; "settings_key_backup_delete_confirmation_prompt_msg" = "Bist du Sicher? Damit gehen alle verschlüsselten Mitteilungen verloren wenn deine Schlüssel nicht anderweitig richtig gespeichert wurden."; "room_does_not_exist" = "%@ existiert nicht"; -"key_backup_setup_title" = "Schlüssel Sicherheitskopie"; +"key_backup_setup_title" = "Sicherheitskopie des Schlüssels"; "key_backup_setup_skip_alert_title" = "Bist du sicher?"; "key_backup_setup_skip_alert_message" = "Du könntest deine verschlüsselten Mitteilungen verlieren wenn du dich abmeldest oder dein Gerät verlierst."; "key_backup_setup_skip_alert_skip_action" = "Überspringen"; "key_backup_setup_intro_title" = "Verliere niemals verschlüsselte Nachrichten"; -"key_backup_setup_intro_info" = "Nachrichten in verschlüsselten Räumen werden durch Ende-zu-Ende-Verschlüsselung gesichert. Nur Du und der / die Empfänger haben die Schlüssel zum Lesen dieser Nachrichten.\n\nSichere deine Schlüssel sicher, um sie nicht zu verlieren."; +"key_backup_setup_intro_info" = "Nachrichten in verschlüsselten Räumen werden durch Ende-zu-Ende-Verschlüsselung gesichert. Nur Du und der/die Empfänger haben die Schlüssel zum Lesen dieser Nachrichten.\n\nSichere deine Schlüssel auf einer sicheren Art, um sie nicht zu verlieren."; "key_backup_setup_intro_setup_action_without_existing_backup" = "Beginne Schlüsselsicherung zu nutzen"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Benutze Schlüsselsicherung"; -"key_backup_setup_passphrase_title" = "Sichere dein Backup mit einer Passphrase"; +"key_backup_setup_passphrase_title" = "Sichere deine Datensicherung mit einer Passphrase"; "key_backup_setup_passphrase_info" = "Wir speichern eine verschlüsselte Kopie deiner Schlüssel auf unserem Server. Schütze deine Sicherung mit einer Passphrase, um sie sicher zu halten.\n\nFür maximale Sicherheit sollte sich dies von deinem Kontopasswort unterscheiden."; -"key_backup_setup_passphrase_passphrase_title" = "Enter"; +"key_backup_setup_passphrase_passphrase_title" = "Eingeben"; "key_backup_setup_passphrase_passphrase_placeholder" = "Passphrase eingeben"; "key_backup_setup_passphrase_passphrase_valid" = "Gut!"; "key_backup_setup_passphrase_passphrase_invalid" = "Versuche ein Wort hinzuzufügen"; @@ -597,11 +597,11 @@ "key_backup_setup_passphrase_confirm_passphrase_valid" = "Gut!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrasen müssen übereinstimmen"; "key_backup_setup_passphrase_set_passphrase_action" = "Setze Passphrase"; -"key_backup_setup_passphrase_setup_recovery_key_info" = "Oder sichere deine Sicherung mit einem Wiederherstellungsschlüssel, und sichere sie an einem sicheren Ort."; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Oder sichere deine Sicherung mit einem Wiederherstellungsschlüssel, und speichere sie an einem sicheren Ort ab."; "key_backup_setup_passphrase_setup_recovery_key_action" = "(Erweitert) Mit Wiederherstellungsschlüssel einrichten"; "key_backup_setup_success_title" = "Erfolgreich!"; // Success from passphrase -"key_backup_setup_success_from_passphrase_info" = "Deine Schlüssel werden gesichert.\n\nDein Wiederherstellungsschlüssel ist ein Sicherheitsnetzwerk - Du kannst damit den Zugriff auf deine verschlüsselten Nachrichten wiederherstellen, wenn du deine Passphrase vergisst.\n\nBewahre den Wiederherstellungsschlüssel an einem sehr sicheren Ort auf, beispielsweise einem Kennwortmanager (oder einem Tresor)."; +"key_backup_setup_success_from_passphrase_info" = "Deine Schlüssel werden gesichert.\n\nDein Wiederherstellungsschlüssel ist ein Sicherheitsnetzwerk - Du kannst damit den Zugriff auf deine verschlüsselten Nachrichten wiederherstellen, wenn du deine Passphrase vergisst.\n\nBewahre den Wiederherstellungsschlüssel an einem sehr sicheren Ort auf, beispielsweise in einer Passwortverwaltung (oder einem Tresor)."; "key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Wiederherstellungsschlüssel speichern"; "key_backup_setup_success_from_passphrase_done_action" = "Erledigt"; // Success from recovery key @@ -609,20 +609,20 @@ "key_backup_setup_success_from_recovery_key_recovery_key_title" = "Wiederherstellungsschlüssel"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "Mache eine Kopie"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "Ich fertigte eine Kopie an"; -"key_backup_recover_title" = "Sichere Nachrichten"; +"key_backup_recover_title" = "Nachrichten sichern"; "key_backup_recover_invalid_passphrase_title" = "Falsche Wiederherstellungspassphrase"; "key_backup_recover_invalid_passphrase" = "Sicherung konnte nicht mit dieser Passphrase entschlüsselt werden: Bitte stelle sicher, dass du die richtige Wiederherstellungspassphrase eingegeben hast."; "key_backup_recover_invalid_recovery_key_title" = "Wiederherstellungsschlüssel passt nicht"; "key_backup_recover_invalid_recovery_key" = "Sicherung konnte mit diesem Schlüssel nicht entschlüsselt werden: Bitte stelle sicher, dass du den richtigen Wiederherstellungsschlüssel eingegeben hast."; "key_backup_recover_from_passphrase_info" = "Nutze deine Wiederherstellungspassphrase um deinen sicheren Chatverlauf zu entschlüsseln"; -"key_backup_recover_from_passphrase_passphrase_title" = "Gebe"; +"key_backup_recover_from_passphrase_passphrase_title" = "Eingeben"; "key_backup_recover_from_passphrase_passphrase_placeholder" = "Passphrase eingeben"; "key_backup_recover_from_passphrase_recover_action" = "Historie entschlüsseln"; -"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Kenne deine Wiederherstellungskennphrase nicht? Du kannst "; -"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "nutze deinen Wiederherstellungsschlüssel"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Kennst deinen Wiederherstellungskennphrase nicht? Du kannst "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "deinen Wiederherstellungsschlüssel nutzen"; "key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; "key_backup_recover_from_recovery_key_info" = "Nutze deinen Wiederherstellungsschlüssel um deinen sicheren Chatverlauf zu entschlüsseln"; -"key_backup_recover_from_recovery_key_recovery_key_title" = "Gebe"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Eingeben"; "key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Gebe Wiederherstellungsschlüssel ein"; "key_backup_recover_from_recovery_key_recover_action" = "Historie entschlüsseln"; "key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Hast du deinen Wiederherstellungsschlüssel verloren? Du kannst in den Einstellungen einen neuen einrichten."; @@ -650,10 +650,10 @@ "e2e_key_backup_wrong_version_button_settings" = "Einstellungen"; "e2e_key_backup_wrong_version_button_wasme" = "Das war ich"; "key_backup_setup_intro_manual_export_info" = "(Erweitert)"; -"key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel Export"; +"key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel-Export"; // String for App Store "store_short_description" = "Sicherer, dezentralisierter Chat/VoIP"; -"store_full_description" = "Element ist die neue Art von Messenger- und Kooperations-App, die:\n\n1. dir die Kontrolle gibt deine Privatsphäre zu schützen,\n2. dir die Kommunikation mit anderen Personen im Matrix-Netzwerk und darüber hinaus Integration in Apps wie Slack ermöglicht,\n3. dich vor Werbung, Datenerfassung, Hintertüren und ummauerten Gärten schützt,\n4. dich durch End-to-End-Verschlüsselung absichert und mit Cross-Signing andere zu überprüfen.\n\nElement unterscheidet sich grundlegend von anderen Messaging- und Kooperations-Diensten, da es dezentralisiert und open-source ist.\n\nMit Element kannst du dich selbst hosten oder einen Host auswählen, sodass du Datenschutz, Eigentum und Kontrolle über deine Daten und Konversationen hast. Du erhältst Zugriff auf ein offenes Netzwerk und bist nicht auf Element-Nutzer beschränkt. Und es ist sehr sicher.\n\nElement ist in der Lage, all dies zu tun, da es mit Matrix arbeitet - dem Standard für offene, dezentrale Kommunikation.\n\nMit Element hast du die Kontrolle, indem du auswählen kannst, wer deine Konversationen hostet. In der Element-App kannst du verschiedene Hosts auswählen:\n\n1. Hole dir ein kostenloses Konto auf dem öffentlichen Server von matrix.org\n2. Hoste dein Konto selbst, indem du einen Server auf deiner eigenen Hardware ausführst\n3. Melde dich für ein Konto auf einem benutzerdefinierten Server an, indem du einfach die Hosting-Plattform von Element Matrix Services abonnierst\n\nWarum Element?\n\nBESITZE DEINE DATEN: Du entscheidest, wo deine Daten und Nachrichten aufbewahrt werden sollen. Du besitzt und kontrollierst sie, nicht irgendeine MEGACORP, die deine Daten verwertet oder Dritten Zugriff gewährt.\n\nOPEN MESSAGING UND ZUSAMMENARBEIT: Du kannst mit allen anderen Mitgliedern des Matrix-Netzwerks chatten, unabhängig davon, ob sie Element oder eine andere Matrix-App verwenden, sogar selbst wenn sie ein anderes Messaging-System wie Slack, IRC oder XMPP verwenden.\n\nSUPERSICHER: Echte End-to-End-Verschlüsselung (nur diejenigen in der Konversation können Nachrichten entschlüsseln) und Cross-Signing, um die Geräte der Konversationsteilnehmer zu überprüfen.\n\nVOLLSTÄNDIGE KOMMUNIKATION: Messaging, Sprach- und Videoanrufe, Dateifreigabe, Bildschirmfreigabe und eine ganze Reihe von Integrationen, Bots und Widgets. Baue Räume, Gemeinschaften, bleib in Kontakt und erledige Dinge.\n\nÜBERALL, WO Du BIST: Bleibe mit dem vollständig synchronisierten Nachrichtenverlauf auf all deinen Geräten und im Internet (unter https://element.io/app) unabhängig voneinander in Kontakt."; +"store_full_description" = "Element ist die neue Art von Messenger- und Kooperations-App, die:\n\n1. dir die Kontrolle gibt deine Privatsphäre zu schützen,\n2. dir die Kommunikation mit anderen Personen im Matrix-Netzwerk und darüber hinaus Integration in Apps wie Slack ermöglicht,\n3. dich vor Werbung, Datenerfassung, Hintertüren und geschlossene Plattformen schützt,\n4. dich durch End-to-End-Verschlüsselung absichert und mit Quersignaturen andere überprüft.\n\nElement unterscheidet sich grundlegend von anderen Messaging- und Kooperations-Diensten, da es dezentralisiert und open-source ist.\n\nMit Element kannst du dich selbst hosten oder einen Host auswählen, sodass du Datenschutz, Eigentum und Kontrolle über deine Daten und Konversationen hast. Du erhältst Zugriff auf ein offenes Netzwerk und bist nicht auf Element-Nutzer beschränkt. Und es ist sehr sicher.\n\nElement ist in der Lage, all dies zu tun, da es mit Matrix arbeitet - dem Standard für offene, dezentrale Kommunikation.\n\nMit Element hast du die Kontrolle, indem du auswählen kannst, wer deine Konversationen hostet. In der Element-App kannst du verschiedene Hosts auswählen:\n\n1. Hole dir ein kostenloses Konto auf dem öffentlichen Server von matrix.org\n2. Hoste dein Konto selbst, indem du einen Server auf deiner eigenen Hardware ausführst\n3. Melde dich für ein Konto auf einem benutzerdefinierten Server an, indem du einfach die Hosting-Plattform von Element Matrix Services abonnierst\n\nWarum Element?\n\nBESITZE DEINE DATEN: Du entscheidest, wo deine Daten und Nachrichten aufbewahrt werden sollen. Du besitzt und kontrollierst sie, nicht irgendein MEGAKONZERN, die deine Daten verwertet oder Dritten Zugriff gewährt.\n\nOPEN MESSAGING UND ZUSAMMENARBEIT: Du kannst mit allen anderen Mitgliedern des Matrix-Netzwerks chatten, unabhängig davon, ob sie Element oder eine andere Matrix-App verwenden, sogar selbst wenn sie ein anderes Messaging-System wie Slack, IRC oder XMPP verwenden.\n\nSUPERSICHER: Echte End-to-End-Verschlüsselung (nur diejenigen in der Konversation können Nachrichten entschlüsseln) und Quersignierung, um die Geräte der Konversationsteilnehmer zu überprüfen.\n\nVOLLSTÄNDIGE KOMMUNIKATION: Messaging, Sprach- und Videoanrufe, Dateifreigabe, Bildschirmfreigabe und eine ganze Reihe von Integrationen, Bots und Widgets. Baue Räume, Gemeinschaften, bleib in Kontakt und erledige Dinge.\n\nÜBERALL, WO DU BIST: Bleibe mit dem vollständig synchronisierten Nachrichtenverlauf auf all deinen Geräten und im Internet (unter https://element.io/app) unabhängig voneinander in Kontakt."; "auth_login_single_sign_on" = "Anmelden"; "auth_autodiscover_invalid_response" = "Ungültige Antwort beim Entdecken des Heimservers"; "room_message_unable_open_link_error_message" = "Konnte Link nicht öffnen."; @@ -735,16 +735,16 @@ "device_verification_emoji_headphones" = "Kopfhörer"; "close" = "Schließen"; "auth_softlogout_signed_out" = "Du bist abgemeldet"; -"auth_softlogout_sign_in" = "Einloggen"; -"auth_softlogout_reason" = "Deine Heimserver-Administration (%1$@) hat dich von deinem Konto %2$@ (%3$@) abgemeldet."; -"auth_softlogout_recover_encryption_keys" = "Melden dich an, um ausschließlich auf diesem Gerät gespeicherte Verschlüsselungsschlüssel wiederherzustellen. Du benötigst sie, um deine verschlüsselten Nachrichten auf jedem Gerät zu lesen."; +"auth_softlogout_sign_in" = "Anmelden"; +"auth_softlogout_reason" = "Deine Heimserver-Administrator (%1$@) hat dich von deinem Konto %2$@ (%3$@) abgemeldet."; +"auth_softlogout_recover_encryption_keys" = "Melde dich an, um ausschließlich auf diesem Gerät gespeicherte Verschlüsselungsschlüssel wiederherzustellen. Du benötigst sie, um deine verschlüsselten Nachrichten auf jedem Gerät zu lesen."; "auth_softlogout_clear_data" = "Persönliche Daten löschen"; "auth_softlogout_clear_data_message_1" = "Warnung: Deine persönlichen Daten (einschließlich Verschlüsselungsschlüssel) sind noch auf diesem Gerät gespeichert."; "auth_softlogout_clear_data_message_2" = "Deaktiviere es, wenn du dieses Gerät nicht mehr verwendest oder du dich mit einem anderen Konto anmelden möchtst."; "auth_softlogout_clear_data_button" = "Lösche alle Daten"; "auth_softlogout_clear_data_sign_out_title" = "Bist du sicher?"; "auth_softlogout_clear_data_sign_out_msg" = "Möchtest du wirklich alle derzeit auf diesem Gerät gespeicherten Daten löschen? Melde dich erneut an, um auf deine Kontodaten und Nachrichten zuzugreifen."; -"auth_softlogout_clear_data_sign_out" = "Ausloggen"; +"auth_softlogout_clear_data_sign_out" = "Abmelden"; "room_event_action_reaction_show_all" = "Zeige alles"; "room_event_action_reaction_show_less" = "Zeige weniger"; "room_event_action_reaction_history" = "Reaktionsverlauf"; @@ -754,11 +754,11 @@ "widget_no_integrations_server_configured" = "Kein Integrationsserver konfiguriert"; "widget_integrations_server_failed_to_connect" = "Verbindung zum Integrationsserver fehlgeschlagen"; "device_verification_security_advice" = "Für maximale Sicherheit empfehlen wir, dies persönlich zu tun oder ein anderes vertrauenswürdiges Kommunikationsmittel zu verwenden"; -"device_verification_incoming_description_1" = "Überprüfe diese Sitzung, um sie als vertrauenswürdig zu markieren. Sitzungen von Partner!nnen zu vertrauen gibt dir zusätzliche Sicherheit bei der Verwendung von Ende-zu-Ende verschlüsselten Nachrichten."; +"device_verification_incoming_description_1" = "Überprüfe diese Sitzung, um sie als vertrauenswürdig zu markieren. Sitzungen von Partnern zu vertrauen gibt dir zusätzliche Sicherheit bei der Verwendung von Ende-zu-Ende verschlüsselten Nachrichten."; "device_verification_incoming_description_2" = "Wenn du diese Sitzung verifizierst, wird es sie vertrauenswürdig und für dein Gegenüber als vertrauenswürdig gekennzeichnet."; // MARK: Start "device_verification_start_title" = "Verifizieren durch Vergleichen eines kurzen Textes"; -"device_verification_start_wait_partner" = "Warten auf Annahme durch Partner!n…"; +"device_verification_start_wait_partner" = "Warten auf Annahme durch Partner…"; "device_verification_start_use_legacy" = "Passiert nichts? Noch nicht alle Clients unterstützen die interaktive Verifizierung. Verwende die alte Verifizierungsmethode."; "device_verification_start_use_legacy_action" = "Verwende alte Verifizierungsmethode"; // MARK: Verify @@ -777,19 +777,19 @@ "device_verification_emoji_hourglass" = "Sanduhr"; "device_verification_emoji_clock" = "Uhr"; "device_verification_emoji_pencil" = "Bleistift"; -"device_verification_emoji_lock" = "sperren"; +"device_verification_emoji_lock" = "Schloss"; "device_verification_emoji_folder" = "Ordner"; -"device_verification_emoji_pin" = "Stift"; +"device_verification_emoji_pin" = "Stecknadel"; // MARK: File upload "file_upload_error_title" = "Datei hochladen"; "file_upload_error_unsupported_file_type_message" = "Dateityp wird nicht unterstützt."; // MARK: Emoji picker "emoji_picker_title" = "Reaktionen"; -"emoji_picker_people_category" = "Smileys & Menschen"; -"emoji_picker_nature_category" = "Tiere & Natur"; +"emoji_picker_people_category" = "Smileys und Menschen"; +"emoji_picker_nature_category" = "Tiere und Natur"; "emoji_picker_foods_category" = "Essen und Trinken"; "emoji_picker_activity_category" = "Aktivitäten"; -"emoji_picker_places_category" = "Reisen & Orte"; +"emoji_picker_places_category" = "Reisen und Orte"; "emoji_picker_objects_category" = "Objekte"; "emoji_picker_symbols_category" = "Symbole"; "emoji_picker_flags_category" = "Flaggen"; @@ -811,13 +811,13 @@ "service_terms_modal_message" = "Um fortzufahren, musst du die Nutzungsbedingungen akzeptieren (%@)."; "service_terms_modal_accept_button" = "Akzeptieren"; "service_terms_modal_description_for_identity_server" = "Für andere auffindbar sein"; -"service_terms_modal_description_for_integration_manager" = "Verwende Bots, Bridges, Widgets und Sticker-Pakete"; +"service_terms_modal_description_for_integration_manager" = "Bots, Brücken, Widgets und Aufkleberpakete verwenden"; "auth_email_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine E-Mail-Adresse hinzufügen kannst, um dein Kennwort in Zukunft zurückzusetzen."; "auth_phone_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine Telefonnummer hinzufügen kannst, um dein Kennwort in Zukunft zurückzusetzen."; "auth_reset_password_error_is_required" = "Es ist kein Identitätsserver konfiguriert: Füge einen in die Serveroptionen ein, um dein Kennwort zurückzusetzen."; // Errors "error_user_already_logged_in" = "Du versuchst anscheinend, eine Verbindung zu einem anderen Heimserver herzustellen. Möchtest du dich abmelden?"; -"contacts_address_book_no_identity_server" = "Kein Integrationsserver konfiguriert"; +"contacts_address_book_no_identity_server" = "Kein Identitätsserver konfiguriert"; "room_participants_remove_third_party_invite_prompt_msg" = "Möchtest du diese Einladung wirklich widerrufen?"; "room_accessiblity_scroll_to_bottom" = "Zum Seitenende springen"; "room_accessibility_search" = "Suchen"; @@ -830,20 +830,20 @@ "media_type_accessibility_video" = "Video"; "media_type_accessibility_location" = "Standort"; "media_type_accessibility_file" = "Datei"; -"media_type_accessibility_sticker" = "Sticker"; -"settings_identity_server_settings" = "IDENTITÄT SERVER"; +"media_type_accessibility_sticker" = "Aufkleber"; +"settings_identity_server_settings" = "IDENTITÄTSERVER"; "settings_three_pids_management_information_part1" = "Verwalte hier, mit welchen E-Mail-Adressen oder Telefonnummern du dich anmeldest, oder dein Konto wiederherstellen kannst. Kontrolliere, wer dich finden kann "; "settings_three_pids_management_information_part3" = "."; "settings_calls_stun_server_fallback_button" = "Ausweich-Anruf-Assistenz-Server zulassen"; "settings_devices_description" = "Der öffentliche Name der Sitzung ist für Personen sichtbar, mit denen du kommunizierst"; "settings_discovery_no_identity_server" = "Du verwendest derzeit keinen Identitätsserver. Füge einen hinzu, um für vorhandene, dir bekannte Kontakte sichtbar zu sein."; "settings_discovery_terms_not_signed" = "Stimme den Nutzungsbedingungen des Identitätsservers (%@) zu, um zu erlauben per E-Mail oder Telefonnummer gefunden zu werden."; -"settings_discovery_three_pids_management_information_part1" = "Verwalte, welche E-Mail-Adressen oder Telefonnummern andere Benutzer!nnen verwenden können, um dich zu entdecken und dich in Räume einzuladen. Füge in dieser Liste E-Mail-Adressen oder Telefonnummern hinzu oder entferne sie "; +"settings_discovery_three_pids_management_information_part1" = "Verwalte, welche E-Mail-Adressen oder Telefonnummern andere Benutzer verwenden können, um dich zu entdecken und dich in Räume einzuladen. Füge in dieser Liste E-Mail-Adressen oder Telefonnummern hinzu oder entferne sie "; "settings_discovery_three_pids_management_information_part2" = "Nutzereinstellungen"; "settings_discovery_three_pids_management_information_part3" = "."; "settings_discovery_error_message" = "Es ist ein Fehler aufgetreten. Bitte erneut versuchen."; "settings_discovery_three_pid_details_title_email" = "E-Mail verwalten"; -"settings_discovery_three_pid_details_information_email" = "Verwalte die Einstellungen für diese E-Mail-Adresse, die andere Benutzer!nnen verwenden können, um dich zu entdecken und dich in Räume einzuladen. Hinzufügen oder Entfernen von E-Mail-Adressen in Konten."; +"settings_discovery_three_pid_details_information_email" = "Verwalte die Einstellungen für diese E-Mail-Adresse, die andere Benutzer verwenden können, um dich zu entdecken und dich in Räume einzuladen. Hinzufügen oder Entfernen von E-Mail-Adressen in Konten."; "settings_discovery_three_pid_details_title_phone_number" = "Telefonnummer verwalten"; "settings_discovery_three_pid_details_share_action" = "Teilen"; "settings_discovery_three_pid_details_revoke_action" = "Widerrufen"; @@ -874,12 +874,12 @@ "auth_add_phone_message_2" = "Richte eine Telefonnummer ein. Später kannst du einrichten, dass Personen dich über diese finden."; "auth_add_email_phone_message_2" = "Lege eine E-Mail-Adresse für die Kontowiederherstellung fest. Später kann optional eine E-Mail-Adresse oder eine Telefonnummer dazu verwendet werden, um von anderen Personen gefunden zu werden."; "settings_calls_stun_server_fallback_description" = "Ausweich-Anruf-Assistenz-Server %@ zulassen, wenn dein Heimserver keinen anbietet (deine IP-Adresse wird während eines Anrufs weitergegeben)."; -"settings_discovery_three_pid_details_information_phone_number" = "Verwalte die Einstellungen für diese Telefonnummer, die andere Benutzer!nnen verwenden können, um dich zu entdecken und dich in Räume einzuladen. Hinzufügen oder Entfernen von Telefonnummern in Konten."; +"settings_discovery_three_pid_details_information_phone_number" = "Verwalte die Einstellungen für diese Telefonnummer, die andere Benutzer verwenden können, um dich zu entdecken und dich in Räume einzuladen. Hinzufügen oder Entfernen von Telefonnummern in Konten."; "settings_identity_server_description" = "Mithilfe des oben festgelegten Identitätsservers kannst du vorhandene Kontakte finden und dich für diese sichtbar machen."; "settings_identity_server_no_is_description" = "Du nutzt momentan keinen Identitätsserver. Um von bestehenden Kontakten gefunden zu werden und diese zu finden, füge oben einen hinzu."; "identity_server_settings_description" = "Du nutzt aktuell %@ um vorhandene Kontakte zu finden und um von dir bekannten Kontakten gefunden zu werden."; "identity_server_settings_no_is_description" = "Du nutzt momentan keinen Identitätsserver. Um von bestehenden Kontakten gefunden zu werden und diese zu finden, füge oben einen hinzu."; -"identity_server_settings_alert_no_terms" = "Der Identitätsserver den du ausgewählt hast, hat keine Nutzungsbedingungen. Fahre nur fort, wenn du dem/r Besitzer!n des Dienstes vertraust."; +"identity_server_settings_alert_no_terms" = "Der Identitätsserver den du ausgewählt hast, hat keine Nutzungsbedingungen. Fahre nur fort, wenn du dem Besitzer des Dienstes vertraust."; "identity_server_settings_alert_change" = "Verbindung zum Identitätsserver %1$@ trennen und stattdessen zu %2$@ verbinden?"; "identity_server_settings_alert_disconnect" = "Verbindung zum Identitätsserver %@ trennen?"; "identity_server_settings_alert_error_terms_not_accepted" = "Du musst die Nutzungsbedingungen von %@ akzeptieren, um ihn als Identitätsserver festzulegen."; @@ -888,12 +888,12 @@ "call_no_stun_server_error_message_2" = "Alternativ kannst du versuchen, den öffentlichen Server unter %@ zu verwenden. Dieser wird nicht so zuverlässig sein, und deine IP-Adresse wird mit ihm geteilt. Du kannst dies auch in den Einstellungen konfigurieren"; "service_terms_modal_message_identity_server" = "Akzeptiere die Bedingungen des Identitätsservers (%@), um Kontakte zu finden."; "identity_server_settings_alert_disconnect_still_sharing_3pid" = "Du teilst noch deine persönlichen Daten mit dem Identitätsserver %@.\n\nWir empfehlen dir deine E-Mail-Adresse und Telefonnummer zu entfernen, bevor du die Verbindung zum Identitätsserver trennst."; -"settings_add_3pid_password_title_email" = "E-Mail Adresse hinzufügen"; +"settings_add_3pid_password_title_email" = "E-Mail-Adresse hinzufügen"; "settings_add_3pid_password_title_msidsn" = "Telefonnummer hinzufügen"; "settings_add_3pid_password_message" = "Um fortzufahren, bitte Passwort eingeben"; -"settings_add_3pid_invalid_password_message" = "Ungültiges Passwort"; -"identity_server_settings_disconnect_info" = "Eine Trennung von deinem Identitätsserver würde bedeuten, dass du weder von anderen Nutzer!nnen gefunden werden, noch diese dich per E-Mail oder Telefonnummer einladen können."; -"error_not_supported_on_mobile" = "Dies ist in %@ mobile nicht möglich."; +"settings_add_3pid_invalid_password_message" = "Ungültige Anmeldedaten"; +"identity_server_settings_disconnect_info" = "Eine Trennung von deinem Identitätsserver würde bedeuten, dass du weder von anderen Nutzer gefunden werden, noch diese dich per E-Mail oder Telefonnummer einladen können."; +"error_not_supported_on_mobile" = "Dies ist in der Mobilvariante von %@ nicht möglich."; "settings_integrations" = "INTEGRATIONEN"; "settings_integrations_allow_button" = "Integrationen verwalten"; "widget_menu_refresh" = "Aktualisierung"; @@ -912,18 +912,18 @@ "room_participants_security_loading" = "Lade…"; "room_participants_security_information_room_not_encrypted" = "Nachrichten in diesem Raum sind nicht Ende-zu-Ende verschlüsselt."; "settings_security" = "SICHERHEIT"; -"settings_integrations_allow_description" = "Benutze einen Integrations-Manager (%@), um Bots, Bridges, Widgets und Sticker-Packs zu verwalten.\n\nIntegrations-Manager erhalten Konfigurations-Daten und können Widgets verändern, Raum-Einladungen versenden sowie Berechtigungen in deinem Namen einstellen."; +"settings_integrations_allow_description" = "Benutze einen Integrationsverwalter (%@), um Bots, Bridges, Widgets und Aufkleberpakete zu verwalten.\n\nIntegrationsverwalter erhalten Konfigurationsdaten und können Widgets verändern, Raum-Einladungen versenden sowie Berechtigungen in deinem Namen einstellen."; "settings_labs_enable_cross_signing" = "Aktiviere Cross-Signing, um deinen Gesprächspartner anstatt dessen Gerät zu verifizieren (in Entwicklung)"; // Security settings "security_settings_title" = "Sicherheit"; "security_settings_crypto_sessions" = "MEINE SITZUNGEN"; "security_settings_crypto_sessions_loading" = "Lade Sitzungen…"; -"room_participants_security_information_room_encrypted" = "Nachrichten in diesem Raum sind Ende-zu-Ende verschlüsselt.\n\nDeine Nachrichten sind mit digitalen Schlüsseln gesichert, nur du und der/die Empfänger!n haben die einzigen Schlüssel, um jene zu entsperren."; +"room_participants_security_information_room_encrypted" = "Nachrichten in diesem Raum sind Ende-zu-Ende verschlüsselt.\n\nDeine Nachrichten sind mit digitalen Schlüsseln gesichert, nur du und der Empfänger haben die einzigen Schlüssel, um jene zu entsperren."; "security_settings_crypto_sessions_description" = "Vertraue Sitzungen, um Zugriff auf Ende-zu-Ende verschlüsselte Nachrichten zu gewähren. Wenn du eine Sitzung nicht kennst, ändere dein Anmeldepasswort und setze dein Nachrichtenpasswort für die Nachrichtensicherung zurück."; "security_settings_backup" = "NACHRICHTENSICHERUNG"; "security_settings_advanced" = "ERWEITERT"; "security_settings_blacklist_unverified_devices" = "Sende niemals Nachrichten an nicht-vertrauenswürdige Sitzungen"; -"security_settings_blacklist_unverified_devices_description" = "Verifiziere alle Sitzungen eines/einer Benutzer!n, um sie als vertrauenswürdig zu markieren, und sende ihr/ihm Nachrichten."; +"security_settings_blacklist_unverified_devices_description" = "Verifiziere alle Sitzungen eines Benutzer, um sie als vertrauenswürdig zu markieren, und sende ihm Nachrichten."; "security_settings_export_keys_manually" = "Schlüssel manuell exportieren"; // Manage session "manage_session_title" = "Sitzung verwalten"; @@ -942,8 +942,8 @@ "room_widget_permission_avatar_url_permission" = "Deine Avatar-URL"; "room_widget_permission_user_id_permission" = "Deine Benutzer-ID"; "room_widget_permission_theme_permission" = "Dein Thema"; -"room_widget_permission_widget_id_permission" = "Widget ID"; -"room_widget_permission_room_id_permission" = "Raum ID"; +"room_widget_permission_widget_id_permission" = "Widget-ID"; +"room_widget_permission_room_id_permission" = "Raum-ID"; // Service terms - Variant for identity server when displayed out of a context "service_terms_modal_title_identity_server" = "Kontakte entdecken"; "service_terms_modal_policy_checkbox_accessibility_hint" = "Prüfen um zu akzeptieren %@"; @@ -960,7 +960,7 @@ "key_verification_tile_request_status_cancelled_by_me" = "Du hast abgebrochen"; "key_verification_tile_request_status_cancelled" = "%@ abgebrochen"; "key_verification_tile_request_status_accepted" = "Du hast akzeptiert"; -"key_verification_tile_request_incoming_approval_accept" = "Akzeptieren"; +"key_verification_tile_request_incoming_approval_accept" = "Annehmen"; "key_verification_tile_request_incoming_approval_decline" = "Ablehnen"; "key_verification_tile_conclusion_done_title" = "Verifiziert"; "key_verification_tile_conclusion_warning_title" = "Nicht vertrauenswürdige Anmeldung"; @@ -984,12 +984,12 @@ "user_verification_session_details_information_trusted_other_user_part2" = " verifiziert:"; "user_verification_session_details_information_untrusted_current_user" = "Verifiziere diese Sitzung, um sie als vertrauenswürdig zu markieren, und gewähren ihr Zugriff auf verschlüsselte Nachrichten:"; "user_verification_session_details_information_untrusted_other_user" = " hat sich in einer neuen Sitzung angemeldet:"; -"user_verification_session_details_additional_information_untrusted_other_user" = "Bis diese/r Benutzer!n dieser Sitzung vertraut, werden an und von ihr/ihm gesendete Nachrichten mit Warnungen gekennzeichnet. Alternativ kannst du dies manuell überprüfen."; +"user_verification_session_details_additional_information_untrusted_other_user" = "Bis dieser Benutzer diese Sitzung vertraut, werden an und von ihm gesendete Nachrichten mit Warnungen gekennzeichnet. Alternativ kannst du dies manuell überprüfen."; "user_verification_session_details_additional_information_untrusted_current_user" = "Wenn du dich nicht zu dieser Sitzung angemeldet hast, ist dein Konto möglicherweise gefährdet."; "user_verification_session_details_verify_action_current_user" = "Interaktiv überprüfen"; "user_verification_session_details_verify_action_other_user" = "Manuell Verifizieren"; "room_participants_action_security_status_loading" = "Lade…"; -"security_settings_crosssigning" = "CROSS-SIGNING"; +"security_settings_crosssigning" = "QUERSIGNIERUNG"; "security_settings_cryptography" = "VERSCHLÜSSELUNG"; "device_verification_self_verify_alert_title" = "Neue Anmeldung. Warst du das?"; "device_verification_self_verify_alert_message" = "Bestätige neue Anmeldung zu deinem Konto: %@"; @@ -1003,7 +1003,7 @@ "skip" = "Überspringen"; // MARK: Clients "client_desktop_name" = "Element Desktop"; -"security_settings_crosssigning_info_not_bootstrapped" = "Cross-signing ist bisher nicht konfiguriert."; +"security_settings_crosssigning_info_not_bootstrapped" = "Quersignierung ist bisher nicht konfiguriert."; "client_web_name" = "Element Web"; "client_ios_name" = "Element iOS"; "client_android_name" = "Element Android"; @@ -1011,27 +1011,27 @@ "room_member_power_level_moderator_in" = "Moderator in %@"; "room_member_power_level_custom_in" = "Benutzerdefiniert (%@) in %@"; "room_member_power_level_short_admin" = "Admin"; -"room_member_power_level_short_moderator" = "Mod"; +"room_member_power_level_short_moderator" = "Moderator"; "room_member_power_level_short_custom" = "Benutzerdefiniert"; -"security_settings_secure_backup" = "SICHERES BACKUP"; +"security_settings_secure_backup" = "SICHERE SICHERHEITSKOPIE"; "security_settings_secure_backup_synchronise" = "Synchronisiere"; "security_settings_secure_backup_delete" = "Lösche"; -"security_settings_crosssigning_info_ok" = "Cross-signing ist angeschaltet."; -"security_settings_crosssigning_reset" = "Cross-signing zurücksetzen"; -"security_settings_coming_soon" = "Entschuldigung, diese Funktion ist noch nicht für Element iOS verfügbar. Bitte nutze einen anderen Matrix Client, um es einzurichten. Element iOS wird es benutzen."; +"security_settings_crosssigning_info_ok" = "Quersignierung ist angeschaltet."; +"security_settings_crosssigning_reset" = "Quersignierung zurücksetzen"; +"security_settings_coming_soon" = "Entschuldigung, diese Funktion ist noch nicht für Element iOS verfügbar. Bitte nutze einen anderen Matrix-Client, um es einzurichten. Element iOS wird es benutzen."; "security_settings_user_password_description" = "Bestätige deine Identität durch Eingabe des Kontopassworts"; // AuthenticatedSessionViewControllerFactory -"authenticated_session_flow_not_supported" = "Diese App unterstützt nicht diese Authentifizierungsmethode für deinen Home-Server."; -"secure_key_backup_setup_intro_title" = "Sicheres Backup"; +"authenticated_session_flow_not_supported" = "Diese App unterstützt nicht diese Authentifizierungsmethode für deinen Heimserver."; +"secure_key_backup_setup_intro_title" = "Sichere Datensicherung"; "store_promotional_text" = "Privatsphäre-wahrende Kollaborations-App in einem offenen Netzwerk. Dezentral, um dir die Kontrolle zu geben. Keine Datenerfassung, keine Hintertüren und kein Zugriff durch Dritte."; "room_participants_action_security_status_complete_security" = "Vollständige Sicherheit"; "external_link_confirmation_title" = "Überprüfe diesen Link genau"; "external_link_confirmation_message" = "Der Link %@ braucht zu lange auf der anderen Seite: %@\n\nSicher, dass du fortfahren möchtest?"; -"security_settings_crypto_sessions_description_2" = "Wenn du dich nicht eingeloggt hast, ändere dein Passwort und setze das Sichere Backup zurück."; +"security_settings_crypto_sessions_description_2" = "Wenn du dich nicht angemeldet hast, ändere dein Passwort und setze die Sichere Sicherheitskopie zurück."; "security_settings_secure_backup_description" = "Sichere deine verschlüsselten Nachrichten und Daten, indem du die Schlüssel auf deinem Server sicherst."; -"security_settings_crosssigning_info_exists" = "Dein Konto hat eine Cross-Signing Identität, aber dieser Sitzung wird noch nicht vertraut. Vervollständige die Sicherheit auf diese Sitzung."; -"security_settings_crosssigning_info_trusted" = "Cross-Signing ist aktiviert. Du kannst anderen Nutzern und deinen anderen Sitzungen basierend auf Cross-Signing vertrauen, aber du kannst in dieser Sitzung kein Cross-Signing durchführen, da sie keine privaten Cross-Signing-Schlüssel enthält. Vervollständige die Sicherheit dieser Sitzung."; -"security_settings_crosssigning_bootstrap" = "Cross-Signing einrichten"; +"security_settings_crosssigning_info_exists" = "Dein Konto hat eine Quersignatur-Identität, aber dieser Sitzung wird noch nicht vertraut. Vervollständige die Sicherheit auf diese Sitzung."; +"security_settings_crosssigning_info_trusted" = "Quersignierung ist aktiviert. Du kannst anderen Nutzern und deinen anderen Sitzungen basierend auf der Quersignatur vertrauen, aber du kannst in dieser Sitzung keine Quersignierung durchführen, da sie keine privaten Quersignatur-Schlüssel enthält. Vervollständige die Sicherheit dieser Sitzung."; +"security_settings_crosssigning_bootstrap" = "Quersignierung einrichten"; "security_settings_complete_security_alert_title" = "Vollständige Sicherheit"; "security_settings_complete_security_alert_message" = "Du solltest zuerst die Sicherheit deiner aktuellen Sitzung vervollständigen."; // Events formatter with you @@ -1039,21 +1039,21 @@ "event_formatter_widget_removed_by_you" = "Du hast das Widget entfernt: %@"; "event_formatter_jitsi_widget_added_by_you" = "Du hast eine VoIP-Konferenz hinzugefügt"; "event_formatter_jitsi_widget_removed_by_you" = "Du hast eine VoIP-Konferenz entfernt"; -"secure_key_backup_setup_intro_info" = "Absicherung um den Zugriffsverlust auf verschlüsselte Nachrichten & Daten zu verhindern, indem die Schlüssel für die Entschlüsselung auf dem Server gesichert werden."; +"secure_key_backup_setup_intro_info" = "Absicherung um den Zugriffsverlust auf verschlüsselte Nachrichten und Daten zu verhindern, indem die Schlüssel für die Entschlüsselung auf dem Server gesichert werden."; "secure_key_backup_setup_intro_use_security_key_title" = "Benutze einen Sicherheitsschlüssel"; -"secure_key_backup_setup_intro_use_security_key_info" = "Generiere einen Sicherheitsschlüssel, welcher z.B. in einem Passwortmanager oder in einem Tresor sicher aufbewahrt werden sollte."; +"secure_key_backup_setup_intro_use_security_key_info" = "Generiere einen Sicherheitsschlüssel, welcher z.B. in einer Passwortverwaltung oder in einem Tresor sicher aufbewahrt werden sollte."; "secure_key_backup_setup_intro_use_security_passphrase_title" = "Benutze Sicherheitsphrase"; -"secure_key_backup_setup_intro_use_security_passphrase_info" = "Gib eine geheime Phrase ein, die nur du kennst, um einen Schlüssel als Backup zu generieren."; -"secure_key_backup_setup_existing_backup_error_title" = "Ein Backup für Nachrichten existiert bereits"; -"secure_key_backup_setup_existing_backup_error_info" = "Entsperre es, um es im sicheren Backup wiederzuverwenden, oder lösche es, um eine neue Nachrichtensicherung zu erstellen."; +"secure_key_backup_setup_intro_use_security_passphrase_info" = "Gib eine geheime Phrase ein, die nur du kennst, um einen Schlüssel für die Sicherung zu generieren."; +"secure_key_backup_setup_existing_backup_error_title" = "Eine Sicherheitskopie für Nachrichten existiert bereits"; +"secure_key_backup_setup_existing_backup_error_info" = "Entsperre es, um es in der sicheren Datensicherung wiederzuverwenden, oder lösche es, um eine neue Nachrichtensicherung zu erstellen."; "secure_key_backup_setup_existing_backup_error_unlock_it" = "Entschlüsseln"; "secure_key_backup_setup_cancel_alert_title" = "Sicher?"; -"secure_key_backup_setup_cancel_alert_message" = "Wenn du jetzt abbrichst und den Zugriff zu deinen Sitzungen verlierst, kannst du verschlüsselte Nachrichten & Daten verlieren.\n\nDu kannst auch ein Backup einrichten & deine Schlüssel in den Einstellungen verwalten."; -"secure_backup_setup_banner_title" = "Sicheres Backup"; -"secure_backup_setup_banner_subtitle" = "Absicherung gegen den Zugriffsverlust auf verschlüsselte Nachrichten & Daten"; +"secure_key_backup_setup_cancel_alert_message" = "Wenn du jetzt abbrichst und den Zugriff zu deinen Sitzungen verlierst, kannst du verschlüsselte Nachrichten & Daten verlieren.\n\nDu kannst auch eine Sicherung einrichten und deine Schlüssel in den Einstellungen verwalten."; +"secure_backup_setup_banner_title" = "Sichere Datensicherung"; +"secure_backup_setup_banner_subtitle" = "Absicherung gegen den Zugriffsverlust auf verschlüsselte Nachrichten und Daten"; // Recover from private key -"key_backup_recover_from_private_key_info" = "Backup wird wiederhergestellt…"; -"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Richte sicheres Backup ein"; +"key_backup_recover_from_private_key_info" = "Sicherung wird wiederhergestellt…"; +"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Richte sichere Datensicherung ein"; // MARK: - Device Verification "key_verification_other_session_title" = "Sitzung verifizieren"; "key_verification_new_session_title" = "Neue Sitzung verifizieren"; @@ -1063,10 +1063,10 @@ "key_verification_self_verify_current_session_alert_title" = "Verifiziere diese Sitzung"; "key_verification_self_verify_current_session_alert_message" = "Andere Benutzer vertrauen ihr vielleicht nicht."; "key_verification_self_verify_unverified_sessions_alert_title" = "Überprüfe, wo du angemeldet bist"; -"key_verification_self_verify_unverified_sessions_alert_message" = "Verifiziere alle deine Sitzungen, um sicher zu stellen, dass dein Konto & deine Nachrichten sicher sind."; +"key_verification_self_verify_unverified_sessions_alert_message" = "Verifiziere alle deine Sitzungen, um sicher zu stellen, dass dein Konto und deine Nachrichten sicher sind."; "key_verification_self_verify_unverified_sessions_alert_validate_action" = "Überprüfung"; "device_verification_self_verify_wait_new_sign_in_title" = "Diese Anmeldung verifizieren"; -"device_verification_self_verify_wait_additional_information" = "Dies funktioniert mit Element oder einem anderen Matrix Client, der Cross-Signing unterstützt."; +"device_verification_self_verify_wait_additional_information" = "Dies funktioniert mit Element oder einem anderen Matrix-Client, der Quersignierung unterstützt."; "device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Wiederherstellungsschlüssel verwenden"; "device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Nutze eine Wiederherstellungsmethode"; "device_verification_self_verify_wait_recover_secrets_additional_information" = "Falls du keinen Zugang zu einer existierenden Sitzung hast"; @@ -1076,18 +1076,18 @@ "key_verification_verify_sas_validate_action" = "Sie passen"; "key_verification_verify_sas_additional_information" = "Für ultimative Sicherheit verwende ein anderes vertrauenswürdiges Kommunikationsmittel oder mache es persönlich."; "key_verification_manually_verify_device_title" = "Verifiziere manuell mit einem Text"; -"key_verification_manually_verify_device_instruction" = "Vergleiche die folgenden Zeichen mit den Einstellungen in der Sitzung des/der anderen Nutzer!n und bestätige:"; +"key_verification_manually_verify_device_instruction" = "Vergleiche die folgenden Zeichen mit den Einstellungen in der Sitzung des anderen Nutzers und bestätige:"; "key_verification_manually_verify_device_name_title" = "Name der Sitzung"; "key_verification_manually_verify_device_id_title" = "Sitzungs-ID"; "key_verification_manually_verify_device_key_title" = "Sitzungsschlüssel"; "key_verification_manually_verify_device_additional_information" = "Falls sie nicht übereinstimmen, wurde die Kommunikation vielleicht kompromittiert."; "key_verification_verified_new_session_title" = "Neue Sitzung verifiziert!"; -"key_verification_verified_other_session_information" = "Du kannst nun sichere Nachrichten in deiner anderen Sitzung lesen. Andere Benutzer/innen wissen, dass sie ihr vertrauen können."; -"key_verification_verified_new_session_information" = "Du kannst nun sichere Nachrichten auf deinem anderen Gerät lesen. Andere Benutzer/innen wissen, dass sie ihr vertrauen können."; -"key_verification_verified_this_session_information" = "Du kannst nun sichere Nachrichten auf diesem Gerät lesen. Andere Benutzer/innen wissen, dass sie vertrauenswürdig ist."; +"key_verification_verified_other_session_information" = "Du kannst nun sichere Nachrichten in deiner anderen Sitzung lesen. Andere Benutzer wissen, dass sie ihr vertrauen können."; +"key_verification_verified_new_session_information" = "Du kannst nun sichere Nachrichten auf deinem neuen Gerät lesen. Andere Benutzer wissen, dass sie es vertrauen können."; +"key_verification_verified_this_session_information" = "Du kannst nun sichere Nachrichten auf diesem Gerät lesen. Andere Benutzer wissen, dass sie es vertrauen können."; "key_verification_verified_user_information" = "Nachrichten mit diesem Gegenüber sind Ende-zu-Ende verschlüsselt und können nicht von Dritten gelesen werden."; "key_verification_bootstrap_not_setup_title" = "Fehler"; -"key_verification_bootstrap_not_setup_message" = "Du musst erst Cross-Signing einrichten."; +"key_verification_bootstrap_not_setup_message" = "Du musst erst die Quersignatur einrichten."; "key_verification_verify_qr_code_title" = "Verifizierung durch Scannen eines QR-Codes"; "key_verification_verify_qr_code_information" = "Scanne den Code für eine gegenseitige Überprüfung."; "key_verification_verify_qr_code_information_other_device" = "Scanne den Code unten zur Überprüfung:"; @@ -1106,18 +1106,18 @@ "key_verification_scan_confirmation_scanned_user_information" = "Zeigt %@ dasselbe Schild an?"; "key_verification_scan_confirmation_scanned_device_information" = "Zeigt das andere Gerät das gleiche Schild an?"; "user_verification_session_details_verify_action_current_user_manually" = "Überprüfe manuell mit einem Text"; -"secrets_recovery_with_passphrase_title" = "Wiederherstellungs-Passphrase"; -"secrets_recovery_with_passphrase_information_default" = "Gib deine Wiederherstellungs-Passphrase ein, um auf deine verschlüsselten Nachrichten und deine Cross-Signing-Identität zuzugreifen. Mit der Cross-Signing-Identität kannst du andere Sitzungen verifizieren."; +"secrets_recovery_with_passphrase_title" = "Wiederherstellungspassphrase"; +"secrets_recovery_with_passphrase_information_default" = "Gib deine Wiederherstellungspassphrase ein, um auf deine verschlüsselten Nachrichten und deine Quersignatur-Identität zuzugreifen. Mit der Quersignatur-Identität kannst du andere Sitzungen verifizieren."; "secrets_recovery_with_passphrase_information_verify_device" = "Nutze deinen Wiederherstellungsphrase um dieses Gerät zu verifizieren."; "secrets_recovery_with_passphrase_passphrase_placeholder" = "Gib die Wiederherstellungspassphrase ein"; "secrets_recovery_with_passphrase_recover_action" = "Nutze Passphrase"; "secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Wenn du deine Wiederherstellungspassphrase nicht weißt, kannst du "; -"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "nutze deinen Wiederherstellungsschlüssel"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "deinen Wiederherstellungsschlüssel nutzen"; "secrets_recovery_with_passphrase_lost_passphrase_action_part3" = "."; "secrets_recovery_with_passphrase_invalid_passphrase_title" = "Auf sicheren Speicher kann nicht zugegriffen werden"; "secrets_recovery_with_passphrase_invalid_passphrase_message" = "Bitte stell sicher, dass du die korrekte Wiederherstellungspassphrase eingegeben hast."; "secrets_recovery_with_key_title" = "Wiederherstellungsschlüssel"; -"secrets_recovery_with_key_information_default" = "Gib deinen Wiederherstellungs-Schlüssel ein, um auf deine verschlüsselten Nachrichten und deine Cross-Signing-Identität zuzugreifen. Mit der Cross-Signing-Identität kannst du andere Sitzungen verifizieren."; +"secrets_recovery_with_key_information_default" = "Gib deinen Wiederherstellungsschlüssel ein, um auf deine verschlüsselten Nachrichten und deine Quersignatur-Identität zuzugreifen. Mit der Quersignatur-Identität kannst du andere Sitzungen verifizieren."; "secrets_recovery_with_key_information_verify_device" = "Nutze deinen Wiederherstellungsschlüssel um dieses Gerät zu verifizieren."; "secrets_recovery_with_key_recovery_key_placeholder" = "Wiederherstellungsschlüssel eingeben"; "secrets_recovery_with_key_recover_action" = "Schlüssel benutzen"; @@ -1130,26 +1130,26 @@ "secrets_setup_recovery_key_done_action" = "Erledigt"; "secrets_setup_recovery_key_storage_alert_title" = "Bewahre ihn sicher auf"; "key_verification_verify_qr_code_scan_other_code_success_message" = "Der QR-Code wurde erfolgreich validiert."; -"security_settings_secure_backup_setup" = "Konfiguration"; +"security_settings_secure_backup_setup" = "Einrichten"; "security_settings_crosssigning_complete_security" = "Vollständige Sicherheit"; "secure_key_backup_setup_existing_backup_error_delete_it" = "Lösche es"; "device_verification_self_verify_alert_validate_action" = "Überprüfen"; "key_verification_self_verify_current_session_alert_validate_action" = "Überprüfen"; "key_verification_manually_verify_device_validate_action" = "Überprüfen"; -"secrets_recovery_with_passphrase_passphrase_title" = "Enter"; -"secrets_recovery_with_key_recovery_key_title" = "Enter"; -"secrets_setup_recovery_key_storage_alert_message" = "✓ Drucken ihn aus und bewahre ihn an einem sicheren Ort auf\n✓ Speicher ihn auf einem USB-Stick oder einem Backup-Laufwerk\n✓ Kopiere ihn in deinen persönlichen Cloud-Speicher"; +"secrets_recovery_with_passphrase_passphrase_title" = "Eingeben"; +"secrets_recovery_with_key_recovery_key_title" = "Eingeben"; +"secrets_setup_recovery_key_storage_alert_message" = "✓ Drucke ihn aus und bewahre ihn an einem sicheren Ort auf\n✓ Speichere ihn auf einem USB-Stick oder einem Sicherungslaufwerk\n✓ Kopiere ihn zu deinem persönlichen Speicher im Netz"; "secrets_setup_recovery_passphrase_title" = "Setze Sicherheitsphrase"; "secrets_setup_recovery_passphrase_information" = "Gib eine Sicherheitsphrase ein, welche nur du kennst und deine Daten auf dem Server geheim halten soll."; -"secrets_setup_recovery_passphrase_additional_information" = "Benutze dein Accountpasswort nicht mehrfach."; +"secrets_setup_recovery_passphrase_additional_information" = "Benutze dein Kontopasswort nicht mehrfach."; "secrets_setup_recovery_passphrase_validate_action" = "Fertig"; "secrets_setup_recovery_passphrase_confirm_information" = "Gib deine Sicherheitsphrase zur Bestätigung erneut ein."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Bestätigen"; "secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Passphrase bestätigen"; "cross_signing_setup_banner_title" = "Verschlüsselung einrichten"; -"cross_signing_setup_banner_subtitle" = "Verifiziere deine anderen Geräte einfacher"; +"cross_signing_setup_banner_subtitle" = "Verifiziere deine weiteren Geräte bequemer"; "major_update_title" = "Riot ist jetzt Element"; -"major_update_information" = "Wir sind begeistert unsere Namensänderung mitteilen zu können! Deine App ist auf dem neusten Stand und du bist mit deinem Account angemeldet."; +"major_update_information" = "Wir sind begeistert unsere Namensänderung mitteilen zu können! Deine App ist auf dem neusten Stand und du bist mit deinem Konto angemeldet."; "major_update_learn_more_action" = "Mehr erfahren"; "major_update_done_action" = "Verstanden"; "pin_protection_choose_pin" = "Erstelle eine PIN für mehr Sicherheit"; @@ -1163,7 +1163,7 @@ "pin_protection_mismatch_error_title" = "Die PINs stimmen nicht überein"; "pin_protection_mismatch_error_message" = "Bitte versuche es erneut"; "pin_protection_mismatch_too_many_times_error_message" = "Wenn du dich nicht an deine PIN erinnern kannst, drücke \"PIN vergessen\"."; -"pin_protection_settings_section_header_x" = "PIN & %@"; +"pin_protection_settings_section_header_x" = "PIN und %@"; "pin_protection_settings_section_footer" = "Um deine PIN zurückzusetzen, musst du dich erneut anmelden und eine neue erstellen."; "pin_protection_settings_enabled_forced" = "PIN aktiviert"; "pin_protection_settings_enable_pin" = "PIN aktivieren"; @@ -1194,16 +1194,16 @@ "create_room_title" = "Neuer Raum"; "create_room_section_header_name" = "Raumname"; "create_room_placeholder_name" = "Name"; -"create_room_section_header_topic" = "Raum-Thema (optional)"; +"create_room_section_header_topic" = "Raumthema (optional)"; "create_room_placeholder_topic" = "Thema"; -"create_room_section_header_encryption" = "Raum-Verschlüsselung"; +"create_room_section_header_encryption" = "Raumverschlüsselung"; "create_room_enable_encryption" = "Verschlüsselung aktivieren"; "create_room_section_footer_encryption" = "Verschlüsselung kann im Nachhinein nicht deaktiviert werden."; -"create_room_section_header_type" = "Raum-Typ"; +"create_room_section_header_type" = "Raumtyp"; "create_room_type_private" = "Privater Raum"; "create_room_type_public" = "Öffentlicher Raum"; "create_room_section_footer_type" = "Personen können einen privaten Raum nur mit Einladung betreten."; -"create_room_show_in_directory" = "Zeige den Raum im Raum-Verzeichnis"; +"create_room_show_in_directory" = "Zeige den Raum im Raumverzeichnis"; "create_room_section_header_address" = "Raum-Adresse"; "create_room_placeholder_address" = "#testraum:matrix.org"; "room_info_list_room_encrypted" = "Nachrichten in diesem Raum sind Ende-zu-Ende verschlüsselt"; @@ -1214,19 +1214,19 @@ "room_participants_filter_room_members_for_dm" = "Mitglieder filtern"; "room_participants_security_information_room_not_encrypted_for_dm" = "Die Nachrichten hier sind nicht Ende-zu-Ende verschlüsselt."; "room_participants_leave_prompt_msg_for_dm" = "Bist du sicher, dass du die Konversation verlassen möchtest?"; -"room_participants_security_information_room_encrypted_for_dm" = "Nachrichten hier sind Ende-zu-Ende verschlüsselt.\n\nDeine Nachrichten sind mit digitalen Schlüsseln gesichert, nur du und der/die Empfänger!n haben die einzigen Schlüssel, um jene zu entsperren."; +"room_participants_security_information_room_encrypted_for_dm" = "Nachrichten hier sind Ende-zu-Ende verschlüsselt.\n\nDeine Nachrichten sind mit digitalen Schlüsseln gesichert, nur du und der Empfänger haben die einzigen Schlüssel, um jene zu entsperren."; "room_details_title_for_dm" = "Details"; "room_details_photo_for_dm" = "Bild"; "room_details_room_name_for_dm" = "Name"; "room_details_access_section_for_dm" = "Wer hat Zugriff hierauf?"; "room_details_access_section_anyone_apart_from_guest_for_dm" = "Alle, die den Link kennen (ausgenommen Gäste)"; "room_details_access_section_anyone_for_dm" = "Alle, die den Link kennen (auch Gäste)"; -"room_details_access_section_directory_toggle_for_dm" = "Im Raum-Verzeichnis auflisten"; +"room_details_access_section_directory_toggle_for_dm" = "Im Raumverzeichnis auflisten"; "room_details_no_local_addresses_for_dm" = "Keine lokalen Adressen vorhanden"; "room_details_advanced_room_id_for_dm" = "ID:"; "room_details_advanced_e2e_encryption_enabled_for_dm" = "Verschlüsselung ist hier aktiviert"; "room_details_advanced_e2e_encryption_disabled_for_dm" = "Verschlüsselung ist hier nicht aktiviert."; -"pin_protection_kick_user_alert_message" = "Zu viele Fehler. Du wurdest ausgeloggt"; +"pin_protection_kick_user_alert_message" = "Zu viele Fehler. Du wurdest abgemeldet"; // MARK: - Secrets reset @@ -1237,16 +1237,16 @@ "secrets_recovery_reset_action_part_1" = "Wiederherstellungsoptionen vergessen oder verloren? "; "less" = "Weniger"; -"secrets_reset_authentication_message" = "Gib dein Konto-Passwort ein, um zu bestätigen"; +"secrets_reset_authentication_message" = "Gib dein Kontopasswort ein, um zu bestätigen"; "secrets_reset_reset_action" = "Zurücksetzen"; -"secrets_reset_warning_message" = "Du wirst ohne Nachrichtenverlauf, Nachrichten, vertraute Geräte oder vertraute Benutzer neu-starten."; +"secrets_reset_warning_message" = "Du wirst ohne Nachrichtenverlauf, Nachrichten, vertraute Geräte oder vertraute Benutzer neustarten."; "secrets_reset_warning_title" = "Falls du alles zurücksetzt"; "secrets_reset_information" = "Tu dies nur, wenn du kein anderes Gerät hast, mit dem du dieses Gerät überprüfen kannst."; // MARK: - Home "home_empty_view_title" = "Willkommen bei %@,\n%@"; -"secrets_setup_recovery_passphrase_summary_information" = "Erinnere dich an deine Sicherheitsphrase. Sie kann zum entschlüsseln der Nachrichten & Daten verwendet werden."; +"secrets_setup_recovery_passphrase_summary_information" = "Erinnere dich an deine Sicherheitsphrase. Sie kann zum entschlüsseln der Nachrichten und Daten verwendet werden."; "secrets_setup_recovery_passphrase_summary_title" = "Sichere deine Sicherheitsphrase"; "rooms_empty_view_title" = "Räume"; "people_empty_view_information" = "Sicher kommunizieren mit allen. Drücke + um Leute hinzuzufügen."; @@ -1269,9 +1269,61 @@ "social_login_button_title_sign_up" = "Registrieren mit %@"; "social_login_button_title_sign_in" = "Anmelden mit %@"; "social_login_button_title_continue" = "Weiter mit %@"; -"social_login_list_title_sign_up" = "Oder Registrieren mit"; -"social_login_list_title_sign_in" = "Oder Anmelden mit"; +"social_login_list_title_sign_up" = "Oder"; +"social_login_list_title_sign_in" = "Oder"; // Social login "social_login_list_title_continue" = "Weiter mit"; +"room_intro_cell_information_multiple_dm_sentence2" = "Nur ihr seid in diesem Gespräch, außer ihr lädt jemand anderen ein."; +"room_intro_cell_information_dm_sentence2" = "Nur zwei von euch sind in diesem Gespräch. Keine anderer kann beitreten."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Dies ist der Beginn deiner Direktnachricht mit "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " damit Leute wissen worum es in diesem geht."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Thema hinzufügen"; +"room_intro_cell_information_room_with_topic_sentence2" = "Thema: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Dies ist der Beginn von "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Leute hinzufügen"; +"room_avatar_view_accessibility_hint" = "Raumavatar ändern"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "Avatar"; +"call_transfer_error_message" = "Rufumleitung fehlgeschlagen"; +"call_transfer_error_title" = "Fehler"; +"call_transfer_contacts_all" = "Alle"; +"call_transfer_contacts_recent" = "Neulich"; +"call_transfer_dialpad" = "Wähltastatur"; +"call_transfer_users" = "Nutzer"; + +// MARK: - Call Transfer +"call_transfer_title" = "Umleiten"; + +// MARK: - Dial Pad +"dialpad_title" = "Wähltastatur"; +"call_actions_unhold" = "Fortsetzen"; +"event_formatter_call_back" = "Zurückrufen"; +"event_formatter_call_you_declined" = "Du lehntest diesen Anruf ab"; +"event_formatter_call_you_currently_in" = "Du bist aktuell in diesem Anruf"; +"event_formatter_call_has_ended" = "Dieser Anruf ist beendet"; +"event_formatter_call_video" = "Videoanruf"; +"event_formatter_call_voice" = "Sprachanruf"; +"settings_show_NSFW_public_rooms" = "Öffentliche Räume mit anstößigen Inhalte anzeigen"; +"room_open_dialpad" = "Wähltastatur"; +"room_place_voice_call" = "Sprachanruf"; +"room_unsent_messages_cancel_message" = "Bist du dir sicher alle nicht gesendete Nachrichten in diesem Raum zu löschen?"; +"room_unsent_messages_cancel_title" = "Lösche nicht gesendete Nachrichten"; +"callbar_return" = "Zurück"; +"callbar_only_multiple_paused" = "%@ pausierte Anrufe"; +"callbar_only_single_paused" = "Pausierter Anruf"; +"callbar_active_and_multiple_paused" = "1 aktiver Anruf (%@) · %@ pausierte Anrufe"; +"callbar_active_and_single_paused" = "1 aktiver Anruf (%1$s) · 1 pausierter Anruf"; + +// Call Bar +"callbar_only_single_active" = "Laufender Anruf (%@)"; +"room_event_action_delete_confirmation_message" = "Möchtest Du die nicht gesendete Nachricht wirklich löschen?"; +"room_event_action_delete_confirmation_title" = "Nicht gesendete Nachricht löschen"; diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index 522656a5a..f150ffbcf 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -536,7 +536,7 @@ "settings_add_3pid_password_title_email" = "Lisa e-posti aadress"; "settings_add_3pid_password_title_msidsn" = "Lisa telefoninumber"; "settings_add_3pid_password_message" = "Jätkamiseks palun sisesta oma salasõna"; -"settings_add_3pid_invalid_password_message" = "Vigane kasutajanimi"; +"settings_add_3pid_invalid_password_message" = "Vigane kasutajanimi või salasõna"; "settings_crypto_device_name" = "Sessiooni nimi: "; "settings_crypto_device_id" = "\nSessiooni tunnus: "; "settings_crypto_device_key" = "\nSessiooni võti:\n"; @@ -1229,9 +1229,61 @@ "social_login_button_title_sign_up" = "Loo konto kasutades %@ teenust"; "social_login_button_title_sign_in" = "Logi sisse kasutades %@ teenust"; "social_login_button_title_continue" = "Jätka kasutades %@ teenust"; -"social_login_list_title_sign_up" = "Või registreeru kasutajaks kasutades"; -"social_login_list_title_sign_in" = "Või logi sisse kasutades"; +"social_login_list_title_sign_up" = "Või"; +"social_login_list_title_sign_in" = "Või"; // Social login "social_login_list_title_continue" = "Jätka kasutades"; +"settings_show_NSFW_public_rooms" = "Näita avalikke jututubasid, kus on ebasobilikku sisu"; +"room_intro_cell_information_room_sentence1_part3" = "jututuba. "; +"room_intro_cell_information_room_sentence1_part1" = "Siit maalt algab "; +"room_intro_cell_information_multiple_dm_sentence2" = "Seni kuni keegi teist kolmandaid osapooli liituma ei kutsu, olete siin vestluses vaid teie omavahel."; +"room_intro_cell_information_dm_sentence2" = "Vestlete vaid teie omavahel ning keegi teine ei saa liituda."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "See on otsesõnumite algus selle kasutajaga "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " selleks et kõik teaks, millega siin jututoas tegeletakse."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Lisa jututoa teema"; +"room_intro_cell_information_room_with_topic_sentence2" = "Teema: %@"; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Lisa inimesi"; +"room_avatar_view_accessibility_hint" = "Muuda jututoa tunnuspilti ehk avatari"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "tunnuspilt"; +"call_transfer_error_message" = "Kõne suunamine ei õnnestunud"; +"call_transfer_error_title" = "Viga"; +"call_transfer_contacts_all" = "Kõik"; +"call_transfer_contacts_recent" = "Hiljutised"; +"call_transfer_dialpad" = "Numbriklahvistik"; +"call_transfer_users" = "Kasutajad"; + +// MARK: - Call Transfer +"call_transfer_title" = "Suuna kõne edasi"; + +// MARK: - Dial Pad +"dialpad_title" = "Numbriklahvistik"; +"call_actions_unhold" = "Jätka"; +"event_formatter_call_back" = "Helista tagasi"; +"event_formatter_call_you_declined" = "Sina keeldusid sellest kõnest"; +"event_formatter_call_you_currently_in" = "Sul on parasjagu see kõne pooleli"; +"event_formatter_call_has_ended" = "See kõne on lõppenud"; +"event_formatter_call_video" = "Videokõne"; +"event_formatter_call_voice" = "Häälkõne"; +"room_open_dialpad" = "Numbriklahvistik"; +"room_place_voice_call" = "Häälkõne"; +"room_event_action_delete_confirmation_message" = "Kas sa kindlasti soovid selle saatmata sõnumi kustutada?"; +"room_event_action_delete_confirmation_title" = "Kustuta saatmata sõnum"; +"room_unsent_messages_cancel_message" = "Kas sa kindlasti soovid sellest jututoast kustutada kõik saatmata sõnumid?"; +"room_unsent_messages_cancel_title" = "Kustuta saatmata sõnumid"; +"callbar_return" = "Pöördu tagasi"; +"callbar_only_multiple_paused" = "%@ ootel kõnet"; +"callbar_only_single_paused" = "Pooleli kõne"; +"callbar_active_and_multiple_paused" = "Käsil on üks kõne (%@) · %@ kõnet on ootel"; +"callbar_active_and_single_paused" = "Käsil on üks kõne (%@) · üks kõne on ootel"; + +// Call Bar +"callbar_only_single_active" = "Kõne on käsil (%@)"; diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index c53844af1..150fe8623 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -6,7 +6,7 @@ "title_groups" = "Communautés"; "warning" = "Attention"; // Actions -"view" = "Voir"; +"view" = "Afficher"; "next" = "Suivant"; "back" = "Retour"; "continue" = "Continuer"; @@ -25,7 +25,7 @@ "accept" = "Accepter"; "preview" = "Aperçu"; "camera" = "Appareil photo"; -"voice" = "Voix"; +"voice" = "Audio"; "video" = "Vidéo"; "active_call" = "Appel en cours"; "active_call_details" = "Appel en cours (%@)"; @@ -33,25 +33,25 @@ "rename" = "Renommer"; // Authentication "auth_login" = "Se connecter"; -"auth_register" = "S'inscrire"; +"auth_register" = "S’inscrire"; "auth_submit" = "Valider"; "auth_skip" = "Ignorer"; "auth_send_reset_email" = "Envoyer un e-mail de réinitialisation"; -"auth_return_to_login" = "Retour à l'écran de connexion"; -"auth_user_id_placeholder" = "E-mail ou nom d'utilisateur"; +"auth_return_to_login" = "Retour à l’écran de connexion"; +"auth_user_id_placeholder" = "E-mail ou nom d’utilisateur"; "auth_password_placeholder" = "Mot de passe"; "auth_new_password_placeholder" = "Nouveau mot de passe"; -"auth_user_name_placeholder" = "Nom d'utilisateur"; +"auth_user_name_placeholder" = "Nom d’utilisateur"; "auth_optional_email_placeholder" = "Adresse e-mail (facultatif)"; "auth_email_placeholder" = "Adresse e-mail"; "auth_optional_phone_placeholder" = "Numéro de téléphone (facultatif)"; "auth_phone_placeholder" = "Numéro de téléphone"; "auth_repeat_password_placeholder" = "Répéter le mot de passe"; "auth_repeat_new_password_placeholder" = "Confirmer le nouveau mot de passe"; -"auth_invalid_login_param" = "Nom d'utilisateur et/ou mot de passe incorrect"; -"auth_invalid_user_name" = "Les noms d'utilisateur ne peuvent contenir que des lettres, des chiffres, des points, des traits d'union ou des tirets bas"; +"auth_invalid_login_param" = "Nom d’utilisateur et/ou mot de passe incorrect"; +"auth_invalid_user_name" = "Les noms d’utilisateur ne peuvent contenir que des lettres, des chiffres, des points, des traits d’union ou des tirets bas"; "auth_invalid_password" = "Mot de passe trop court (min 6)"; -"auth_invalid_email" = "L'adresse e-mail ne semble pas valide"; +"auth_invalid_email" = "L’adresse e-mail ne semble pas valide"; "auth_invalid_phone" = "Le numéro de téléphone ne semble pas valide"; "auth_missing_password" = "Mot de passe manquant"; "auth_add_email_message" = "Ajouter une adresse e-mail au compte pour que les utilisateurs puissent vous retrouver et pour réinitialiser votre mot de passe."; @@ -62,23 +62,23 @@ "auth_missing_phone" = "Numéro de téléphone manquant"; "auth_missing_email_or_phone" = "Adresse e-mail ou numéro de téléphone manquant"; "auth_password_dont_match" = "Les mots de passe ne correspondent pas"; -"auth_username_in_use" = "L'identifiant est déjà utilisé"; -"auth_forgot_password" = "Mot de passe oublié ?"; +"auth_username_in_use" = "L’identifiant est déjà utilisé"; +"auth_forgot_password" = "Mot de passe oublié ?"; "auth_use_server_options" = "Utiliser un serveur personnalisé (avancé)"; -"auth_email_validation_message" = "Merci de vérifier vos e-mails pour continuer l'inscription"; +"auth_email_validation_message" = "Merci de vérifier vos e-mails pour continuer l’inscription"; "auth_msisdn_validation_title" = "Vérification en attente"; -"auth_msisdn_validation_message" = "Nous vous avons envoyé un SMS avec un code d'activation. Merci de le recopier ci-dessous."; +"auth_msisdn_validation_message" = "Nous vous avons envoyé un SMS avec un code d’activation. Merci de le recopier ci-dessous."; "auth_msisdn_validation_error" = "Impossible de vérifier votre numéro de téléphone."; "auth_recaptcha_message" = "Ce serveur d’accueil voudrait s’assurer que vous n’êtes pas un robot"; -"auth_reset_password_message" = "Pour réinitialiser votre mot de passe, saisissez l'adresse e-mail liée à votre compte :"; -"auth_reset_password_missing_email" = "Vous devez saisir l'adresse e-mail liée à votre compte."; +"auth_reset_password_message" = "Pour réinitialiser votre mot de passe, saisissez l’adresse e-mail liée à votre compte :"; +"auth_reset_password_missing_email" = "Vous devez saisir l’adresse e-mail liée à votre compte."; "auth_reset_password_missing_password" = "Vous devez spécifier un nouveau mot de passe."; -"auth_reset_password_email_validation_message" = "Un e-mail a été envoyé à %@. Cliquez d'abord sur le lien dans l'e-mail, puis ci-dessous."; -"auth_reset_password_next_step_button" = "J'ai vérifié mon adresse e-mail"; -"auth_reset_password_error_unauthorized" = "Impossible de vérifier l'adresse e-mail : assurez-vous de cliquer sur le lien dans l'e-mail"; +"auth_reset_password_email_validation_message" = "Un e-mail a été envoyé à %@. Cliquez d’abord sur le lien dans l’e-mail, puis ci-dessous."; +"auth_reset_password_next_step_button" = "J’ai vérifié mon adresse e-mail"; +"auth_reset_password_error_unauthorized" = "Impossible de vérifier l’adresse e-mail : assurez-vous de cliquer sur le lien dans l’e-mail"; "auth_reset_password_error_not_found" = "Votre adresse e-mail ne semble pas associée à un identifiant Matrix sur ce serveur d’accueil."; "auth_reset_password_success_message" = "Votre mot de passe a été réinitialisé.\n\nVous avez été déconnecté de toutes vos sessions et ne recevrez plus de notifications. Pour réactiver les notifications, reconnectez-vous sur chaque appareil."; -"auth_add_email_and_phone_warning" = "L'inscription avec un e-mail et un numéro de téléphone à la fois n'est pas supporté tant que l'API n'existe pas. Seul votre numéro de téléphone sera pris en compte. Vous pourrez ajouter l'adresse e-mail dans vos options de profil."; +"auth_add_email_and_phone_warning" = "L’inscription avec un e-mail et un numéro de téléphone à la fois n’est pas prise en charge tant que l’API n'existe pas. Seul votre numéro de téléphone sera pris en compte. Vous pourrez ajouter l’adresse e-mail dans vos options de profil."; // Chat creation "room_creation_title" = "Nouvelle discussion"; "room_creation_account" = "Compte"; @@ -89,8 +89,8 @@ "room_creation_private_room" = "Cette discussion est privée"; "room_creation_public_room" = "Cette discussion est publique"; "room_creation_make_public" = "Rendre publique"; -"room_creation_make_public_prompt_title" = "Voulez-vous rendre cette discussion publique ?"; -"room_creation_make_public_prompt_msg" = "Voulez-vous vraiment rendre cette discussion publique ? Tout le monde pourra lire vos messages et rejoindre la discussion."; +"room_creation_make_public_prompt_title" = "Voulez-vous rendre cette discussion publique ?"; +"room_creation_make_public_prompt_msg" = "Voulez-vous vraiment rendre cette discussion publique ? Tout le monde pourra lire vos messages et rejoindre le salon."; "room_creation_keep_private" = "Garder privée"; "room_creation_make_private" = "Rendre privée"; "room_creation_wait_for_creation" = "Un salon est déjà en cours de création. Veuillez patienter."; @@ -140,7 +140,7 @@ "contacts_address_book_matrix_users_toggle" = "Utilisateurs Matrix uniquement"; "contacts_address_book_no_contact" = "Aucun contact local"; "contacts_address_book_permission_required" = "Permissions requises pour accéder aux contacts locaux"; -"contacts_address_book_permission_denied" = "Vous n'avez pas autorisé Element à accéder à vos contacts locaux"; +"contacts_address_book_permission_denied" = "Vous n’avez pas autorisé Element à accéder à vos contacts locaux"; "contacts_user_directory_section" = "RÉPERTOIRE UTILISATEURS"; "contacts_user_directory_offline_section" = "RÉPERTOIRE UTILISATEURS (hors-ligne)"; // Chat participants @@ -149,25 +149,25 @@ "room_participants_one_participant" = "1 membre"; "room_participants_multi_participants" = "%d membres"; "room_participants_leave_prompt_title" = "Quitter le salon"; -"room_participants_leave_prompt_msg" = "Voulez-vous vraiment quitter le salon ?"; +"room_participants_leave_prompt_msg" = "Voulez-vous vraiment quitter le salon ?"; "room_participants_remove_prompt_title" = "Confirmation"; -"room_participants_remove_prompt_msg" = "Voulez-vous vraiment exclure %@ de ce salon ?"; +"room_participants_remove_prompt_msg" = "Voulez-vous vraiment exclure %@ de ce salon ?"; "room_participants_invite_prompt_title" = "Confirmation"; -"room_participants_invite_prompt_msg" = "Voulez-vous vraiment inviter %@ dans ce salon ?"; +"room_participants_invite_prompt_msg" = "Voulez-vous vraiment inviter %@ dans ce salon ?"; "room_participants_filter_room_members" = "Filtrer les membres du salon"; "room_participants_invite_another_user" = "Rechercher/inviter par identifiant, nom ou e-mail"; -"room_participants_invite_malformed_id_title" = "Erreur lors de l'invitation"; +"room_participants_invite_malformed_id_title" = "Erreur lors de l’invitation"; "room_participants_remove_third_party_invite_msg" = "Supprimer une invitation de tiers n'est pas prise en charge tant que l'API n'existe pas"; -"room_participants_invite_malformed_id" = "Identifiant au mauvais format. Une adresse e-mail ou un identifiant Matrix au format \"@utilisateur:domaine\" est attendu"; +"room_participants_invite_malformed_id" = "Identifiant au mauvais format. Une adresse e-mail ou un identifiant Matrix au format « @utilisateur:domaine » est attendu"; "room_participants_invited_section" = "INVITÉS"; "room_participants_online" = "En ligne"; "room_participants_offline" = "Hors ligne"; "room_participants_unknown" = "Inconnu"; "room_participants_idle" = "Inactif"; "room_participants_now" = "maintenant"; -"room_participants_ago" = "d'inactivité"; -"room_participants_action_section_admin_tools" = "Outils d'administration"; -"room_participants_action_section_direct_chats" = "Discussions directes"; +"room_participants_ago" = "d’inactivité"; +"room_participants_action_section_admin_tools" = "Outils d’administration"; +"room_participants_action_section_direct_chats" = "Conversations privées"; "room_participants_action_section_devices" = "Sessions"; "room_participants_action_section_other" = "Options"; "room_participants_action_invite" = "Inviter"; @@ -181,7 +181,7 @@ "room_participants_action_set_moderator" = "Nommer modérateur"; "room_participants_action_set_admin" = "Nommer administrateur"; "room_participants_action_start_new_chat" = "Commencer une nouvelle discussion"; -"room_participants_action_start_voice_call" = "Commencer un appel vocal"; +"room_participants_action_start_voice_call" = "Commencer un appel audio"; "room_participants_action_start_video_call" = "Commencer un appel vidéo"; "room_participants_action_mention" = "Mentionner"; // Chat @@ -190,7 +190,7 @@ "room_new_messages_notification" = "%d nouveaux messages"; "room_one_user_is_typing" = "%@ écrit…"; "room_two_users_are_typing" = "%@ et %@ écrivent…"; -"room_many_users_are_typing" = "%@, %@ et d'autres écrivent…"; +"room_many_users_are_typing" = "%@, %@ et d’autres écrivent…"; "room_message_placeholder" = "Envoyer un message (non chiffré)…"; "encrypted_room_message_placeholder" = "Envoyer un message chiffré…"; "room_message_short_placeholder" = "Envoyer un message…"; @@ -211,14 +211,14 @@ "room_event_action_view_source" = "Voir la source"; "room_event_action_report" = "Signaler le contenu"; "room_event_action_report_prompt_reason" = "Raison pour le signalement du contenu"; -"room_event_action_report_prompt_ignore_user" = "Voulez-vous masquer tous les messages de cet utilisateur ?"; +"room_event_action_report_prompt_ignore_user" = "Voulez-vous masquer tous les messages de cet utilisateur ?"; "room_event_action_save" = "Enregistrer"; "room_event_action_resend" = "Renvoyer"; "room_event_action_delete" = "Supprimer"; -"room_event_action_cancel_send" = "Annuler l'envoi"; +"room_event_action_cancel_send" = "Annuler l’envoi"; "room_event_action_cancel_download" = "Annuler le téléchargement"; "room_event_action_view_encryption" = "Informations sur le chiffrement"; -"room_warning_about_encryption" = "Le chiffrement de bout en bout est en version bêta et peut ne pas être fiable.\n\nIl ne doit pas être considéré comme fiable pour sécuriser des données.\n\nLes appareils ne pourront pas encore déchiffrer l'historique de messages d'avant leur arrivée sur le salon.\n\nLes messages chiffrés ne seront pas visibles sur les clients qui n'ont pas encore implémenté le chiffrement."; +"room_warning_about_encryption" = "Le chiffrement de bout en bout est en version bêta et peut ne pas être fiable.\n\nIl ne doit pas être considéré comme fiable pour sécuriser des données.\n\nLes appareils ne pourront pas encore déchiffrer l’historique de messages d’avant leur arrivée sur le salon.\n\nLes messages chiffrés ne seront pas visibles sur les clients qui n’ont pas encore implémenté le chiffrement."; // Unknown devices "unknown_devices_alert_title" = "Le salon contient des sessions inconnues"; "unknown_devices_alert" = "Ce salon contient des sessions inconnues qui n’ont pas été vérifiées.\nCela signifie qu’il n’y a aucune garantie que les sessions appartiennent aux utilisateurs qu’elles prétendent.\nNous vous recommandons d’effectuer le processus de vérification pour chaque session avant de continuer, mais vous pouvez renvoyer le message sans vérifier si vous préférez."; @@ -235,10 +235,10 @@ "room_title_members" = "%@ membres"; "room_title_one_member" = "1 membre"; // Room Preview -"room_preview_invitation_format" = "Vous avez été invité(e) à rejoindre ce salon par %@"; +"room_preview_invitation_format" = "Vous avez été invité à rejoindre ce salon par %@"; "room_preview_subtitle" = "Ceci est un aperçu du salon. Les interactions avec le salon sont désactivées."; -"room_preview_unlinked_email_warning" = "Cette invitation a été envoyée à %@, qui n'est pas associé à ce compte. Vous pouvez vous identifier avec un compte différent ou ajouter cette adresse e-mail à votre compte."; -"room_preview_try_join_an_unknown_room" = "Vous essayez d'accéder à %@. Voulez-vous rejoindre la discussion afin d'y participer ?"; +"room_preview_unlinked_email_warning" = "Cette invitation a été envoyée à %@, qui n’est pas associé à ce compte. Vous pouvez vous identifier avec un compte différent ou ajouter cette adresse e-mail à votre compte."; +"room_preview_try_join_an_unknown_room" = "Vous essayez d'accéder à %@. Voulez-vous rejoindre la discussion afin d’y participer ?"; "room_preview_try_join_an_unknown_room_default" = "un salon"; // Settings "settings_title" = "Paramètres"; @@ -247,7 +247,7 @@ "settings_mark_all_as_read" = "Marquer tous les messages comme lus"; "settings_report_bug" = "Signaler une erreur"; "settings_config_home_server" = "Le serveur d’accueil est %@"; -"settings_config_identity_server" = "Le serveur d'identité est %@"; +"settings_config_identity_server" = "Le serveur d’identité est %@"; "settings_config_user_id" = "Identifié en tant que %@"; "settings_user_settings" = "PRÉFÉRENCES UTILISATEUR"; "settings_notifications_settings" = "PRÉFÉRENCES DE NOTIFICATIONS"; @@ -255,19 +255,19 @@ "settings_contacts" = "CONTACTS LOCAUX"; "settings_advanced" = "AVANCÉ"; "settings_other" = "AUTRES"; -"settings_labs" = "LABORATOIRE"; +"settings_labs" = "EXPÉRIMENTAL"; "settings_devices" = "SESSIONS"; "settings_cryptography" = "CHIFFREMENT"; "settings_sign_out" = "Se déconnecter"; -"settings_sign_out_confirmation" = "Êtes-vous sûr(e) ?"; +"settings_sign_out_confirmation" = "Êtes-vous sûr ?"; "settings_sign_out_e2e_warn" = "Vous perdrez vos clés de chiffrement de bout en bout. Cela signifie que vous ne pourrez plus lire les anciens messages des salons chiffrés depuis cet appareil."; "settings_profile_picture" = "Image de profil"; -"settings_display_name" = "Nom d'affichage"; +"settings_display_name" = "Nom d’affichage"; "settings_first_name" = "Prénom"; "settings_surname" = "Nom"; "settings_remove_prompt_title" = "Confirmation"; -"settings_remove_email_prompt_msg" = "Voulez-vous vraiment supprimer l'adresse e-mail %@ ?"; -"settings_remove_phone_prompt_msg" = "Voulez-vous vraiment supprimer le numéro de téléphone %@ ?"; +"settings_remove_email_prompt_msg" = "Voulez-vous vraiment supprimer l’adresse e-mail %@ ?"; +"settings_remove_phone_prompt_msg" = "Voulez-vous vraiment supprimer le numéro de téléphone %@ ?"; "settings_email_address" = "E-mail"; "settings_email_address_placeholder" = "Saisir votre adresse e-mail"; "settings_add_email_address" = "Ajouter une adresse e-mail"; @@ -280,19 +280,19 @@ "settings_pin_rooms_with_missed_notif" = "Épingler les salons avec des notifications non lues"; "settings_pin_rooms_with_unread" = "Épingler les salons avec des messages non lus"; "settings_on_denied_notification" = "Les notifications sont refusées pour %@, merci de les autoriser dans les paramètres de votre appareil"; -"settings_unignore_user" = "Afficher tous les messages de %@ ?"; +"settings_unignore_user" = "Afficher tous les messages de %@ ?"; "settings_contacts_discover_matrix_users" = "Utiliser un e-mail ou un numéro de téléphone pour retrouver des utilisateurs"; "settings_contacts_phonebook_country" = "Pays pour le répertoire téléphonique"; "settings_labs_e2e_encryption" = "Chiffrement de bout en bout"; "settings_labs_e2e_encryption_prompt_message" = "Pour terminer la configuration du chiffrement, vous devez vous reconnecter."; "settings_version" = "Version %@"; "settings_olm_version" = "Version de olm %@"; -"settings_copyright" = "Droits d'auteur"; +"settings_copyright" = "Droits d’auteur"; "settings_term_conditions" = "Termes et conditions"; "settings_privacy_policy" = "Politique de confidentialité"; "settings_third_party_notices" = "Licences tierces"; -"settings_send_crash_report" = "Envoyer des rapports d'erreur anonymes et des statistiques d'utilisation"; -"settings_enable_rageshake" = "Secouer l'appareil pour signaler un bug"; +"settings_send_crash_report" = "Envoyer des rapports d’anomalies anonymes et des statistiques d’utilisation"; +"settings_enable_rageshake" = "Secouer l’appareil pour signaler un bug"; "settings_clear_cache" = "Vider le cache"; "settings_change_password" = "Changer de mot de passe"; "settings_old_password" = "ancien mot de passe"; @@ -317,52 +317,52 @@ "room_details_low_priority_tag" = "Priorité basse"; "room_details_mute_notifs" = "Désactiver les notifications"; "room_details_direct_chat" = "Discussion directe"; -"room_details_access_section" = "Qui peut accéder à ce salon ?"; +"room_details_access_section" = "Qui peut accéder à ce salon ?"; "room_details_access_section_invited_only" = "Seules les personnes qui ont été invitées"; "room_details_access_section_anyone_apart_from_guest" = "Tous ceux qui connaissent le lien du salon, à part les visiteurs"; -"room_details_access_section_anyone" = "Tous ceux qui connaissent le lien du salon, y compris les visiteurs"; +"room_details_access_section_anyone" = "Toute personne ayant le lien du salon, y compris les visiteurs"; "room_details_access_section_no_address_warning" = "Pour récupérer le lien vers un salon, celui-ci doit avoir une adresse"; -"room_details_access_section_directory_toggle" = "Lister ce salon dans le répertoire des salons"; -"room_details_history_section" = "Qui peut lire l'historique ?"; -"room_details_history_section_anyone" = "N'importe qui"; -"room_details_history_section_members_only" = "Uniquement les membres (à partir de l'activation de cette option)"; +"room_details_access_section_directory_toggle" = "Publier ce salon dans le répertoire des salons"; +"room_details_history_section" = "Qui peut lire l’historique ?"; +"room_details_history_section_anyone" = "N’importe qui"; +"room_details_history_section_members_only" = "Uniquement les membres (à partir de l’activation de cette option)"; "room_details_history_section_members_only_since_invited" = "Uniquement les membres (depuis leur invitation)"; -"room_details_history_section_members_only_since_joined" = "Uniquement les membres (depuis qu'ils sont arrivés)"; +"room_details_history_section_members_only_since_joined" = "Uniquement les membres (depuis leur arrivée)"; "room_details_history_section_prompt_title" = "Alerte de confidentialité"; -"room_details_history_section_prompt_msg" = "Les changements d'accès à l'historique ne s'appliqueront qu'aux futurs messages du salon. La visibilité de l'historique existant demeurera inchangée."; +"room_details_history_section_prompt_msg" = "Les changements d’accès à l’historique ne s’appliqueront qu’aux futurs messages du salon. La visibilité de l’historique existant demeurera inchangée."; "room_details_addresses_section" = "Adresses"; -"room_details_no_local_addresses" = "Ce salon n'a pas d'adresse locale"; +"room_details_no_local_addresses" = "Ce salon n’a pas d’adresse locale"; "room_details_new_address" = "Ajouter une adresse"; "room_details_new_address_placeholder" = "Ajouter une adresse (par ex. #foo%@)"; -"room_details_addresses_invalid_address_prompt_title" = "Format d'alias non valide"; -"room_details_addresses_invalid_address_prompt_msg" = "%@ n'est pas un format valide pour un alias"; -"room_details_addresses_disable_main_address_prompt_title" = "Alerte sur l'adresse principale"; -"room_details_addresses_disable_main_address_prompt_msg" = "Vous n'aurez aucune adresse principale spécifiée. L'adresse principale par défaut de ce salon sera choisie aléatoirement"; +"room_details_addresses_invalid_address_prompt_title" = "Format d’alias non valide"; +"room_details_addresses_invalid_address_prompt_msg" = "%@ n’est pas un format valide pour un alias"; +"room_details_addresses_disable_main_address_prompt_title" = "Alerte sur l’adresse principale"; +"room_details_addresses_disable_main_address_prompt_msg" = "Vous n’aurez aucune adresse principale explicitement définie. L’adresse principale par défaut de ce salon sera choisie aléatoirement"; "room_details_banned_users_section" = "Utilisateurs bannis"; "room_details_advanced_section" = "Avancé"; -"room_details_advanced_room_id" = "Identifiant du salon :"; -"room_details_advanced_enable_e2e_encryption" = "Activer le chiffrement (attention : ne peut pas être désactivé !)"; +"room_details_advanced_room_id" = "Identifiant du salon :"; +"room_details_advanced_enable_e2e_encryption" = "Activer le chiffrement (attention : ne peut pas être désactivé !)"; "room_details_advanced_e2e_encryption_enabled" = "Le chiffrement est activé sur ce salon"; "room_details_advanced_e2e_encryption_disabled" = "Le chiffrement est désactivé sur ce salon."; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Chiffrer uniquement vers les sessions vérifiées"; "room_details_advanced_e2e_encryption_prompt_message" = "Le chiffrement de bout en bout est en version bêta et peut ne pas être fiable.\n\nIl ne doit pas être considéré comme fiable pour sécuriser des données.\n\nLes appareils ne pourront pas encore déchiffrer l'historique de messages d'avant leur arrivée sur le salon.\n\nUne fois le chiffrement activé pour un salon, il ne peut plus être désactivé (pour l'instant).\n\nLes messages chiffrés ne seront pas visibles sur les clients qui n'ont pas encore implémenté le chiffrement."; -"room_details_fail_to_update_avatar" = "Échec de mise à jour de l'image du salon"; +"room_details_fail_to_update_avatar" = "Échec de mise à jour de l’image du salon"; "room_details_fail_to_update_room_name" = "Échec de mise à jour du nom du salon"; "room_details_fail_to_update_topic" = "Échec de mise à jour du sujet"; -"room_details_fail_to_update_room_guest_access" = "Échec de mise à jour de l'accès au salon pour les visiteurs"; +"room_details_fail_to_update_room_guest_access" = "Échec de mise à jour de l’accès au salon pour les visiteurs"; "room_details_fail_to_update_room_join_rule" = "Échec de mise à jour des règles pour rejoindre le salon"; "room_details_fail_to_update_room_directory_visibility" = "Échec de mise à jour de la visibilité du salon dans le répertoire"; -"room_details_fail_to_update_history_visibility" = "Échec de mise à jour de la visibilité de l'historique"; -"room_details_fail_to_add_room_aliases" = "Échec de l'ajout des nouvelles adresses du salon"; +"room_details_fail_to_update_history_visibility" = "Échec de mise à jour de la visibilité de l’historique"; +"room_details_fail_to_add_room_aliases" = "Échec de l’ajout des nouvelles adresses du salon"; "room_details_fail_to_remove_room_aliases" = "Échec de la suppression des adresses du salon"; -"room_details_fail_to_update_room_canonical_alias" = "Échec de la mise à jour de l'adresse principale"; -"room_details_fail_to_update_room_direct" = "Échec de mise à jour de l'étiquette de discussion directe"; -"room_details_fail_to_enable_encryption" = "Échec de l'activation du chiffrement de ce salon"; +"room_details_fail_to_update_room_canonical_alias" = "Échec de la mise à jour de l’adresse principale"; +"room_details_fail_to_update_room_direct" = "Échec de mise à jour de l’étiquette de conversation privée"; +"room_details_fail_to_enable_encryption" = "Échec de l’activation du chiffrement de ce salon"; "room_details_save_changes_prompt" = "Voulez-vous enregistrer les modifications ?"; "room_details_set_main_address" = "Définir comme adresse principale"; "room_details_unset_main_address" = "Désactiver comme adresse principale"; -"room_details_copy_room_id" = "Copier l'identifiant du salon"; -"room_details_copy_room_address" = "Copier l'adresse du salon"; +"room_details_copy_room_id" = "Copier l’identifiant du salon"; +"room_details_copy_room_address" = "Copier l’adresse du salon"; "room_details_copy_room_url" = "Copier le lien du salon"; // Group Details "group_details_title" = "Détails de la communauté"; @@ -385,14 +385,14 @@ "group_participants_invite_prompt_msg" = "Voulez-vous vraiment inviter %@ dans ce groupe ?"; "group_participants_filter_members" = "Filtrer les membres de la communauté"; "group_participants_invite_another_user" = "Rechercher/inviter par identifiant ou nom"; -"group_participants_invite_malformed_id_title" = "Erreur lors de l'invitation"; -"group_participants_invite_malformed_id" = "Identifiant au mauvais format. Un identifiant Matrix au format \"@utilisateur:domaine\" est attendu"; +"group_participants_invite_malformed_id_title" = "Erreur lors de l’invitation"; +"group_participants_invite_malformed_id" = "Identifiant au mauvais format. Un identifiant Matrix au format « @utilisateur:domaine » est attendu"; "group_participants_invited_section" = "INVITÉS"; // Group rooms "group_rooms_filter_rooms" = "Filtrer les salons de la communauté"; // Read Receipts "read_receipts_list" = "Liste des accusés de lecture"; -"receipt_status_read" = "Lu : "; +"receipt_status_read" = "Lu : "; // Media picker "media_picker_library" = "Médiathèque"; "media_picker_select" = "Sélectionner"; @@ -401,54 +401,54 @@ "directory_server_picker_title" = "Sélectionner un répertoire"; "directory_server_all_rooms" = "Tous les salons sur le serveur %@"; "directory_server_all_native_rooms" = "Tous les salons Matrix natifs"; -"directory_server_type_homeserver" = "Saisir un serveur d'accueil pour lister ses salons publics"; +"directory_server_type_homeserver" = "Saisir un serveur d’accueil pour lister ses salons publics"; "directory_server_placeholder" = "matrix.org"; // Others "or" = "ou"; "you" = "Vous"; -"today" = "Aujourd'hui"; +"today" = "Aujourd’hui"; "yesterday" = "Hier"; "network_offline_prompt" = "La connexion Internet semble être hors-ligne."; -"public_room_section_title" = "Salons publics (sur %@) :"; -"bug_report_prompt" = "L'application s'est terminée brusquement la dernière fois. Voulez-vous envoyer un rapport d'erreur ?"; -"rage_shake_prompt" = "Vous semblez secouer le téléphone avec frustration. Souhaitez-vous soumettre un rapport d'erreur ?"; +"public_room_section_title" = "Salons publics (sur %@) :"; +"bug_report_prompt" = "L’application s’est arrêtée brusquement la dernière fois. Voulez-vous envoyer un rapport d’anomalie ?"; +"rage_shake_prompt" = "Vous semblez secouer le téléphone avec frustration. Souhaitez-vous soumettre un rapport d’anomalie ?"; "do_not_ask_again" = "Ne plus demander"; -"camera_access_not_granted" = "%@ n'a pas la permission pour utiliser l'appareil photo, veuillez modifier les options de vie privée"; +"camera_access_not_granted" = "%@ n’a pas la permission pour utiliser l’appareil photo, veuillez modifier les options de confidentialité"; "large_badge_value_k_format" = "%.1fK"; // Call -"call_incoming_voice_prompt" = "Appel vocal entrant de %@"; +"call_incoming_voice_prompt" = "Appel audio entrant de %@"; "call_incoming_video_prompt" = "Appel vidéo entrant de %@"; // No VoIP support "no_voip_title" = "Appel entrant"; -"no_voip" = "%@ vous appelle mais %@ ne supporte pas encore les appels.\nVous pouvez ignorer cette notification et répondre à l'appel depuis un autre appareil, ou bien le rejeter."; +"no_voip" = "%@ vous appelle mais %@ ne prend pas encore en charge les appels.\nVous pouvez ignorer cette notification et répondre à l’appel depuis un autre appareil, ou bien le rejeter."; // Crash report -"google_analytics_use_prompt" = "Souhaitez-vous aider à améliorer %@ en envoyant automatiquement des rapports d'erreur et des statistiques d'utilisation ?"; +"google_analytics_use_prompt" = "Souhaitez-vous aider à améliorer %@ en envoyant automatiquement des rapports d’anomalie et des statistiques d’utilisation ?"; // Crypto -"e2e_enabling_on_app_update" = "Element prend désormais en charge le chiffrement de bout en bout, mais vous devez vous reconnecter pour l'activer.\n\nVous pouvez le faire maintenant ou plus tard à partir des paramètres de l'application."; +"e2e_enabling_on_app_update" = "Element prend désormais en charge le chiffrement de bout en bout, mais vous devez vous reconnecter pour l’activer.\n\nVous pouvez le faire maintenant ou plus tard à partir des paramètres de l’application."; "e2e_need_log_in_again" = "Vous devez vous reconnecter pour générer les clés de chiffrement de bout en bout pour cette session et envoyer la clé publique vers votre serveur d’accueil.\nCeci ne se produira qu’une fois. Veuillez nous excuser pour ce désagrément."; // Bug report -"bug_report_title" = "Rapport d'erreur"; -"bug_report_description" = "Veuillez décrire l'erreur. Qu'avez-vous fait ? Quel était le comportement attendu ? Que s'est-il réellement passé ?"; -"bug_crash_report_title" = "Rapport d'erreur"; -"bug_crash_report_description" = "Merci de décrire ce que vous faisiez avant l'arrêt de l'application :"; -"bug_report_logs_description" = "Afin de diagnostiquer les problèmes, les journaux de ce client seront envoyés avec le rapport d'erreur. Si vous préférez envoyer uniquement le texte ci-dessus, veuillez décocher la case :"; +"bug_report_title" = "Rapport d’anomalie"; +"bug_report_description" = "Veuillez décrire l’anomalie. Qu’avez-vous fait ? Quel était le comportement attendu ? Que s’est-il réellement passé ?"; +"bug_crash_report_title" = "Rapport d’arrêt brutal"; +"bug_crash_report_description" = "Merci de décrire ce que vous faisiez avant l’arrêt de l’application :"; +"bug_report_logs_description" = "Afin de diagnostiquer les problèmes, les journaux de ce client seront envoyés avec le rapport d’anomalie. Si vous préférez envoyer uniquement le texte ci-dessus, veuillez décocher la case :"; "bug_report_send_logs" = "Envoyer les journaux"; -"bug_report_send_screenshot" = "Envoyer une capture d'écran"; +"bug_report_send_screenshot" = "Envoyer une capture d’écran"; "bug_report_progress_zipping" = "Collecte des journaux"; "bug_report_progress_uploading" = "Envoi du rapport"; "bug_report_send" = "Envoyer"; "auth_email_in_use" = "Cette adresse e-mail est déjà utilisée"; "auth_phone_in_use" = "Ce numéro de téléphone est déjà utilisé"; -"auth_email_not_found" = "Échec de l'envoi de l'e-mail : Cette adresse e-mail n'a pas pu être trouvée"; +"auth_email_not_found" = "Échec de l’envoi de l’e-mail : cette adresse e-mail n’a pas pu être trouvée"; "settings_ui_language" = "Langue"; "settings_ui_theme" = "Thème"; "settings_ui_theme_auto" = "Auto"; "settings_ui_theme_light" = "Clair"; "settings_ui_theme_dark" = "Sombre"; -"settings_ui_theme_picker_title" = "Selectionnez un thème"; -"settings_ui_theme_picker_message" = "\"Auto\" utilise le paramètre \"Inverser les couleurs\" de votre appareil"; +"settings_ui_theme_picker_title" = "Sélectionnez un thème"; +"settings_ui_theme_picker_message" = "« Auto » utilise le paramètre « Inverser les couleurs » de votre appareil"; "collapse" = "réduire"; -"auth_untrusted_id_server" = "Le serveur d'identité n'est pas fiable"; +"auth_untrusted_id_server" = "Le serveur d'identité n’est pas fiable"; "settings_user_interface" = "INTERFACE UTILISATEUR"; // Events formatter "event_formatter_member_updates" = "%tu modifications dans les membres"; @@ -467,17 +467,17 @@ "sending" = "Envoi"; "call_incoming_voice" = "Appel entrant…"; "call_incoming_video" = "Appel vidéo entrant…"; -"widget_integration_must_be_in_room" = "Vous n'êtes pas dans ce salon."; +"widget_integration_must_be_in_room" = "Vous n’êtes pas dans ce salon."; "widget_integration_no_permission_in_room" = "Vous n’avez pas la permission de faire cela dans ce salon."; -"widget_integration_room_not_visible" = "Le salon %@ n'est pas visible."; +"widget_integration_room_not_visible" = "Le salon %@ n’est pas visible."; "auth_share_extension_prompt" = "Se connecter dans l'application principale pour partager du contenu"; -"room_event_failed_to_send" = "Échec de l'envoi"; -"event_formatter_jitsi_widget_added" = "Téléconférence en Voix sur IP ajoutée par %@"; -"event_formatter_jitsi_widget_removed" = "Téléconférence en Voix sur IP supprimée par %@"; +"room_event_failed_to_send" = "Échec de l’envoi"; +"event_formatter_jitsi_widget_added" = "Téléconférence en VoIP ajoutée par %@"; +"event_formatter_jitsi_widget_removed" = "Téléconférence en VoIP supprimée par %@"; // Widget Integration Manager "widget_integration_need_to_be_able_to_invite" = "Vous devez être capable d’inviter des utilisateurs pour faire ça."; "widget_integration_unable_to_create" = "Impossible de créer le widget."; -"widget_integration_failed_to_send_request" = "Échec de l'envoi de la requête."; +"widget_integration_failed_to_send_request" = "Échec de l’envoi de la requête."; "widget_integration_room_not_recognised" = "Ce salon n'est pas reconnu."; "widget_integration_positive_power_level" = "Le rang doit être un entier positif."; "widget_integration_missing_room_id" = "Absence du room_id dans la requête."; @@ -485,12 +485,12 @@ "settings_calls_settings" = "APPELS"; "settings_show_decrypted_content" = "Afficher les messages chiffrés en clair"; "settings_enable_callkit" = "Appels intégrés"; -"settings_callkit_info" = "Recevez les appels entrants sur votre écran de verrouillage. Voir vos appels Element dans l'historique des appels du système. Si iCloud est activé, cet historique d'appels sera partagé avec Apple."; -"event_formatter_widget_added" = "Widget %@ ajoutée par %@"; -"event_formatter_widget_removed" = "Widget %@ supprimée par %@"; +"settings_callkit_info" = "Recevez les appels entrants sur votre écran de verrouillage. Retrouvez vos appels Element dans l’historique des appels du système. Si iCloud est activé, cet historique d’appels sera partagé avec Apple."; +"event_formatter_widget_added" = "Widget %@ ajouté par %@"; +"event_formatter_widget_removed" = "Widget %@ supprimé par %@"; // Share extension -"share_extension_auth_prompt" = "Connectez-vous dans l'application pour partager du contenu"; -"share_extension_failed_to_encrypt" = "Échec d'envoi. Vérifiez les paramètres de chiffrement de ce salon dans l'application"; +"share_extension_auth_prompt" = "Connectez-vous dans l’application pour partager du contenu"; +"share_extension_failed_to_encrypt" = "Échec de l’envoi. Vérifiez les paramètres de chiffrement de ce salon dans l’application"; "settings_ui_theme_black" = "Noir"; // Room key request dialog "e2e_room_key_request_title" = "Demande de clés de chiffrement"; @@ -503,27 +503,27 @@ "room_details_flair_section" = "Afficher le badge pour des communautés"; "room_details_new_flair_placeholder" = "Ajouter un nouvel identifiant de communauté (par ex. +foo%@)"; "room_details_flair_invalid_id_prompt_title" = "Format invalide"; -"room_details_flair_invalid_id_prompt_msg" = "%@ n'est pas un identifiant valide pour une communauté"; +"room_details_flair_invalid_id_prompt_msg" = "%@ n’est pas un identifiant valide pour une communauté"; "room_details_fail_to_update_room_communities" = "Échec de la mise à jour des communautés liées"; "room_do_not_have_permission_to_post" = "Vous n’avez pas la permission d’envoyer des messages dans ce salon"; -"room_event_action_kick_prompt_reason" = "Motif de l'expulsion de l'utilisateur"; -"room_event_action_ban_prompt_reason" = "Raison du bannissement de l'utilisateur"; +"room_event_action_kick_prompt_reason" = "Motif de l’expulsion de l’utilisateur"; +"room_event_action_ban_prompt_reason" = "Raison du bannissement de l’utilisateur"; // GDPR "gdpr_consent_not_given_alert_message" = "Pour continuer à utiliser le serveur d'accueil %@, vous devez lire et accepter les conditions générales."; "gdpr_consent_not_given_alert_review_now_action" = "Voir maintenant"; "room_action_send_photo_or_video" = "Envoyer une photo ou une vidéo"; -"room_action_send_sticker" = "Envoyer un sticker"; +"room_action_send_sticker" = "Envoyer un autocollant"; "settings_deactivate_account" = "DÉSACTIVER LE COMPTE"; "settings_deactivate_my_account" = "Désactiver mon compte"; -"widget_sticker_picker_no_stickerpacks_alert" = "Vous n'avez aucun pack de stickers activé."; +"widget_sticker_picker_no_stickerpacks_alert" = "Vous n’avez aucun jeu d’autocollants activé."; "widget_sticker_picker_no_stickerpacks_alert_add_now" = "En ajouter maintenant ?"; "deactivate_account_title" = "Désactiver le compte"; -"deactivate_account_informations_part1" = "Votre compte sera inutilisable de façon permanente. Vous ne pourrez plus vous connecter et personne ne pourra se réenregistrer avec le même identifiant d'utilisateur. Votre compte quittera tous les salons auxquels il participe, et tous les détails du compte seront supprimés du serveur d'identité. "; +"deactivate_account_informations_part1" = "Votre compte sera inutilisable de façon permanente. Vous ne pourrez plus vous connecter et personne ne pourra se réenregistrer avec le même identifiant d’utilisateur. Votre compte quittera tous les salons auxquels il participe, et toutes les informations du compte seront supprimés du serveur d’identité. "; "deactivate_account_informations_part2_emphasize" = "Cette action est irréversible."; "deactivate_account_informations_part3" = "\n\nLa désactivation de votre compte "; "deactivate_account_informations_part4_emphasize" = "ne nous fait pas oublier les messages que vous avez envoyés par défaut. "; "deactivate_account_informations_part5" = "Si vous souhaitez que nous oubliions vos messages, cochez la case ci-dessous\n\nLa visibilité des messages dans Matrix est similaire à celle des e-mails. Notre oubli des messages signifie que les messages que vous avez envoyés ne seront pas partagés avec les nouveaux utilisateurs ou les utilisateurs non enregistrés, mais les utilisateurs qui ont déjà accès à ces messages auront toujours accès à leur copie."; -"deactivate_account_forget_messages_information_part1" = "Veuillez oublier tous les messages que j'ai envoyé quand mon compte sera désactivé ("; +"deactivate_account_forget_messages_information_part1" = "Veuillez oublier tous les messages que j’ai envoyés quand mon compte sera désactivé ("; "deactivate_account_forget_messages_information_part2_emphasize" = "Avertissement"; "deactivate_account_forget_messages_information_part3" = ": les futurs utilisateurs auront alors une vue incomplète des conversations)"; "deactivate_account_validate_action" = "Désactiver le compte"; @@ -537,28 +537,28 @@ "room_message_reply_to_placeholder" = "Envoyer une réponse (non chiffrée)…"; "encrypted_room_message_reply_to_placeholder" = "Envoyer une réponse chiffrée…"; "room_message_reply_to_short_placeholder" = "Envoyer une réponse…"; -"room_replacement_information" = "Ce salon a été remplacé et n'est plus actif."; +"room_replacement_information" = "Ce salon a été remplacé et n’est plus actif."; "room_replacement_link" = "La conversation continue ici."; -"room_predecessor_information" = "Ce salon est la suite d'une autre conversation."; -"room_predecessor_link" = "Appuyer ici pour voir les vieux messages."; +"room_predecessor_information" = "Ce salon est la suite d’une autre conversation."; +"room_predecessor_link" = "Appuyer ici pour voir les anciens messages."; "settings_labs_room_members_lazy_loading" = "Chargement différé des participants des salons"; "settings_labs_room_members_lazy_loading_error_message" = "Votre serveur d'accueil ne prend pas en charge le chargement différé des participants des salons. Réessayez plus tard."; "room_event_action_view_decrypted_source" = "Voir la source déchiffrée"; "room_recents_server_notice_section" = "ALERTES SYSTÈME"; "room_resource_limit_exceeded_message_contact_1" = " Veuillez "; -"room_resource_limit_exceeded_message_contact_2_link" = "contacter l'administrateur de votre service"; -"room_resource_limit_exceeded_message_contact_3" = " pour continuer à l'utiliser."; -"homeserver_connection_lost" = "Connexion impossible au serveur d'accueil."; -"room_resource_usage_limit_reached_message_1_default" = "Ce serveur d'accueil a dépassé une de ses limites de ressources donc "; -"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Ce serveur d'accueil a atteint sa limite mensuelle d'utilisateurs actifs donc "; +"room_resource_limit_exceeded_message_contact_2_link" = "contacter l’administrateur de votre service"; +"room_resource_limit_exceeded_message_contact_3" = " pour continuer à l’utiliser."; +"homeserver_connection_lost" = "Connexion impossible au serveur d’accueil."; +"room_resource_usage_limit_reached_message_1_default" = "Ce serveur d’accueil a dépassé une de ses limites de ressources donc "; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Ce serveur d’accueil a atteint sa limite mensuelle d’utilisateurs actifs donc "; "room_resource_usage_limit_reached_message_2" = "quelques utilisateurs ne pourront pas se connecter."; "room_resource_usage_limit_reached_message_contact_3" = " pour augmenter cette limite."; -"auth_accept_policies" = "Veuillez lire et accepter les politiques de ce serveur d'accueil :"; +"auth_accept_policies" = "Veuillez lire et accepter les politiques de ce serveur d’accueil :"; "settings_key_backup" = "SAUVEGARDE DE CLÉS"; "settings_key_backup_info_checking" = "Vérification…"; "settings_key_backup_info_none" = "Vos clés ne sont pas sauvegardées depuis cette session."; -"settings_key_backup_info_version" = "Version de sauvegarde de clé : %@"; -"settings_key_backup_info_algorithm" = "Algorithme : %@"; +"settings_key_backup_info_version" = "Version de sauvegarde de clé : %@"; +"settings_key_backup_info_algorithm" = "Algorithme : %@"; "settings_key_backup_info_valid" = "Cette session sauvegarde vos clés."; "settings_key_backup_info_not_valid" = "Cette session ne sauvegarde pas vos clés, mais vous avez une sauvegarde existante que vous pouvez restaurer et joindre."; "settings_key_backup_info_progress" = "Sauvegarde de %@ clés…"; @@ -576,26 +576,26 @@ "settings_key_backup_button_delete" = "Supprimer la sauvegarde"; "settings_key_backup_button_verify" = "Vérifier"; "settings_key_backup_delete_confirmation_prompt_title" = "Supprimer la sauvegarde"; -"settings_key_backup_delete_confirmation_prompt_msg" = "En êtes-vous sûr(e) ? Vous perdrez vos messages chiffrés si vos clés ne sont pas sauvegardées correctement."; -"room_does_not_exist" = "%@ n'existe pas"; +"settings_key_backup_delete_confirmation_prompt_msg" = "En êtes-vous sûr ? Vous perdrez vos messages chiffrés si vos clés ne sont pas sauvegardées correctement."; +"room_does_not_exist" = "%@ n’existe pas"; "key_backup_setup_title" = "Sauvegarde de clés"; "key_backup_setup_skip_action" = "Passer"; -"key_backup_setup_skip_alert_title" = "En êtes-vous certain(e) ?"; +"key_backup_setup_skip_alert_title" = "En êtes-vous sûr ?"; "key_backup_setup_skip_alert_message" = "Vous pourriez perdre vos messages sécurisés si vous vous déconnectez ou si vous perdez votre appareil."; "key_backup_setup_skip_alert_skip_action" = "Passer"; "key_backup_setup_intro_title" = "Ne perdez jamais vos messages chiffrés"; "key_backup_setup_intro_info" = "Les messages des salons chiffrés sont sécurisés avec un chiffrement de bout en bout. Seuls vous et le(s) destinataire(s) avez les clés pour lire ces messages.\n\nSauvegardez vos clés de façon sécurisée pour éviter de les perdre."; "key_backup_setup_intro_setup_action" = "Configurer"; -"key_backup_setup_passphrase_info" = "Nous conserverons une copie chiffrée de vos clés sur notre serveur. Protégez votre sauvegarde avec une phrase de passe pour qu'elle soit sécurisée.\n\nPour une sécurité maximale, elle devrait être différente du mot de passe de votre compte."; +"key_backup_setup_passphrase_info" = "Nous conserverons une copie chiffrée de vos clés sur notre serveur. Protégez votre sauvegarde avec une phrase secrète pour qu’elle soit en sécurité.\n\nPour une sécurité maximale, elle devrait être différente du mot de passe de votre compte."; "key_backup_setup_passphrase_passphrase_title" = "Saisir"; -"key_backup_setup_passphrase_passphrase_placeholder" = "Saisir la phrase de passe"; -"key_backup_setup_passphrase_passphrase_valid" = "Super !"; -"key_backup_setup_passphrase_passphrase_invalid" = "Essayez d'ajouter un mot"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Saisir la phrase secrète"; +"key_backup_setup_passphrase_passphrase_valid" = "Super !"; +"key_backup_setup_passphrase_passphrase_invalid" = "Essayez d’ajouter un mot"; "key_backup_setup_passphrase_confirm_passphrase_title" = "Confirmer"; -"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirmer la phrase de passe"; -"key_backup_setup_passphrase_confirm_passphrase_valid" = "Super !"; -"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Les phrases de passe ne correspondent pas"; -"key_backup_setup_passphrase_set_passphrase_action" = "Définir la phrase de passe"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirmer la phrase secrète"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Super !"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Les phrases secrètes ne correspondent pas"; +"key_backup_setup_passphrase_set_passphrase_action" = "Définir la phrase secrète"; "key_backup_setup_recovery_key_info" = "Faites une copie de cette clé de récupération et conservez-la en lieu sûr.\n\nPar mesure de précaution, vous pouvez l'utiliser pour restaurer votre historique de messages chiffrés si vous oubliez votre phrase de passe de récupération."; "key_backup_setup_recovery_key_recovery_key_title" = "Clé de récupération"; "key_backup_setup_recovery_key_make_copy_action" = "En faire une copie"; @@ -603,20 +603,20 @@ "key_backup_recover_title" = "Messages sécurisés"; "key_backup_recover_empty_backup_title" = "Sauvegarde vide"; "key_backup_recover_empty_backup_message" = "Il n'y a aucune clé à restaurer"; -"key_backup_recover_from_passphrase_info" = "Utilisez votre phrase de passe de récupération pour déverrouiller votre historique de messages sécurisés"; +"key_backup_recover_from_passphrase_info" = "Utilisez votre phrase secrète de récupération pour déverrouiller votre historique de messages sécurisés"; "key_backup_recover_from_passphrase_passphrase_title" = "Saisir"; -"key_backup_recover_from_passphrase_passphrase_placeholder" = "Saisir la phrase de passe"; -"key_backup_recover_from_passphrase_recover_action" = "Déverrouiller l'historique"; -"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Vous ne connaissez pas votre phrase de passe de récupération ? Vous pouvez "; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Saisir la phrase secrète"; +"key_backup_recover_from_passphrase_recover_action" = "Déverrouiller l’historique"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Vous ne connaissez pas votre phrase secrète de récupération ? Vous pouvez "; "key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "utiliser votre clé de récupération"; "key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; -"key_backup_recover_from_recovery_key_info" = "Utiliser votre clé de récupération pour déverrouiller l'historique de vos messages sécurisés"; +"key_backup_recover_from_recovery_key_info" = "Utiliser votre clé de récupération pour déverrouiller l’historique de vos messages sécurisés"; "key_backup_recover_from_recovery_key_recovery_key_title" = "Saisir"; "key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Saisir la clé de récupération"; -"key_backup_recover_from_recovery_key_recover_action" = "Déverrouiller l'historique"; -"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Vous avez perdu votre clé de récupération ? Vous pouvez en configurer une autre dans les réglages."; -"key_backup_recover_success_info" = "Sauvegarde restaurée !"; -"key_backup_recover_done_action" = "Effectué"; +"key_backup_recover_from_recovery_key_recover_action" = "Déverrouiller l’historique"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Vous avez perdu votre clé de récupération ? Vous pouvez en configurer une autre dans les réglages."; +"key_backup_recover_success_info" = "Sauvegarde restaurée !"; +"key_backup_recover_done_action" = "Terminé"; "key_backup_setup_banner_title_part1" = "Configurer la récupération de messages sécurisée"; "key_backup_setup_banner_title_part2" = " pour ne jamais perdre vos messages chiffrés"; "key_backup_recover_banner_title_part1" = "Lancer la récupération de messages sécurisée"; @@ -626,54 +626,54 @@ "settings_key_backup_button_use" = "Utiliser la sauvegarde de clés"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Commencer à utiliser la sauvegarde de clés"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Utiliser la sauvegarde de clés"; -"key_backup_setup_passphrase_title" = "Protégez votre sauvegarde avec une phrase de passe"; +"key_backup_setup_passphrase_title" = "Protégez votre sauvegarde avec une phrase secrète"; "key_backup_setup_passphrase_setup_recovery_key_info" = "Sinon, protégez votre sauvegarde avec une clé de récupération, en la conservant dans un endroit sûr."; "key_backup_setup_passphrase_setup_recovery_key_action" = "(Avancé) Configurer avec la clé de récupération"; "key_backup_setup_success_title" = "Terminé !"; // Success from passphrase -"key_backup_setup_success_from_passphrase_info" = "Vos clés sont en cours de sauvegarde.\n\nVotre clé de récupération est une mesure de précaution. Vous pouvez l'utiliser pour restaurer l'accès à vos messages chiffrés si vous oubliez votre phrase de passe.\n\nConservez votre clé de récupération dans un lieu très sûr, comme un gestionnaire de mots de passe (ou un coffre-fort)."; +"key_backup_setup_success_from_passphrase_info" = "Vos clés sont en cours de sauvegarde.\n\nVotre clé de récupération est une mesure de précaution. Vous pouvez l’utiliser pour restaurer l'accès à vos messages chiffrés si vous oubliez votre phrase de passe.\n\nConservez votre clé de récupération dans un lieu très sûr, comme un gestionnaire de mots de passe (ou un coffre-fort)."; "key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Sauvegarder la clé de récupération"; "key_backup_setup_success_from_passphrase_done_action" = "Terminé"; // Success from recovery key "key_backup_setup_success_from_recovery_key_info" = "Vos clés sont en cours de sauvegarde.\n\nFaites une copie de cette clé de récupération et conservez-la en lieu sûr."; "key_backup_setup_success_from_recovery_key_recovery_key_title" = "Clé de récupération"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "En faire une copie"; -"key_backup_setup_success_from_recovery_key_made_copy_action" = "J'ai fait une copie"; -"key_backup_recover_invalid_passphrase_title" = "Phrase de passe de récupération incorrecte"; -"key_backup_recover_invalid_passphrase" = "La sauvegarde n'a pas pu être déchiffrée avec cette phrase de passe : vérifiez que vous avez saisi la bonne phrase de passe de récupération."; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "J’en ai fait une copie"; +"key_backup_recover_invalid_passphrase_title" = "Phrase secrète de récupération incorrecte"; +"key_backup_recover_invalid_passphrase" = "La sauvegarde n’a pas pu être déchiffrée avec cette phrase secrète : vérifiez que vous avez saisi la bonne phrase secrète de récupération."; "key_backup_recover_invalid_recovery_key_title" = "La clé de récupération ne correspond pas"; -"key_backup_recover_invalid_recovery_key" = "La sauvegarde n'a pas pu être déchiffrée avec cette clé : vérifiez que vous avez saisi la bonne clé de récupération."; +"key_backup_recover_invalid_recovery_key" = "La sauvegarde n’a pas pu être déchiffrée avec cette clé : vérifiez que vous avez saisi la bonne clé de récupération."; "key_backup_setup_banner_title" = "Ne perdez jamais vos messages chiffrés"; "key_backup_setup_banner_subtitle" = "Commencez à utiliser la sauvegarde de clés"; "key_backup_recover_banner_title" = "Ne perdez jamais vos messages chiffrés"; "key_backup_recover_banner_subtitle" = "Utilisez la sauvegarde de clés"; "sign_out_existing_key_backup_alert_title" = "Voulez-vous vraiment vous déconnecter ?"; "sign_out_existing_key_backup_alert_sign_out_action" = "Se déconnecter"; -"sign_out_non_existing_key_backup_alert_title" = "Vous n'aurez plus accès à vos messages chiffrés si vous vous déconnectez maintenant"; +"sign_out_non_existing_key_backup_alert_title" = "Vous n’aurez plus accès à vos messages chiffrés si vous vous déconnectez maintenant"; "sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Commencer à utiliser la sauvegarde de clés"; "sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Je ne veux pas de mes messages chiffrés"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Vous perdrez vos messages chiffrés"; -"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Vous n'aurez plus accès à vos messages chiffrés sauf si vous sauvegardez vos clés avant de vous déconnecter."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Vous n’aurez plus accès à vos messages chiffrés sauf si vous sauvegardez vos clés avant de vous déconnecter."; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Se déconnecter"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Sauvegarde"; -"sign_out_key_backup_in_progress_alert_title" = "Sauvegarde de clés en cours. Si vous vous déconnectez maintenant vous n'aurez plus accès à vos messages chiffrés."; +"sign_out_key_backup_in_progress_alert_title" = "Sauvegarde de clés en cours. Si vous vous déconnectez maintenant vous n’aurez plus accès à vos messages chiffrés."; "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Je ne veux plus de mes messages chiffrés"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Je vais patienter"; // Key backup wrong version "e2e_key_backup_wrong_version_title" = "Nouvelle sauvegarde de clés"; -"e2e_key_backup_wrong_version" = "Une nouvelle sauvegarde de clés de messages sécurisés a été détectée.\n\nSi cela ne vient pas de vous, définissez une nouvelle phrase de passe dans les paramètres."; +"e2e_key_backup_wrong_version" = "Une nouvelle sauvegarde de clés de messages sécurisés a été détectée.\n\nSi cela ne vient pas de vous, définissez une nouvelle phrase secrète dans les paramètres."; "e2e_key_backup_wrong_version_button_settings" = "Paramètres"; "e2e_key_backup_wrong_version_button_wasme" = "Ça vient de moi"; "key_backup_setup_intro_manual_export_info" = "(Avancé)"; "key_backup_setup_intro_manual_export_action" = "Exporter les clés manuellement"; // String for App Store "store_short_description" = "Discussions et appels sécurisés et décentralisés"; -"store_full_description" = "Element est un nouveau type d'application de chat et de collaboration qui permet de :\n\n1. Vous place en control afin de vous permettre de préserver votre vie privée \n2. Vous permet de communiquer avec n'importe qui du réseau Matrix, et même plus en intégrants des implications tel que Slack \n3. Vous protège des pubs, du datamining , des porte dérobées et des walled gardens\n4. Vous sécurise à travers une inscription de bout en bout, avec des co-enregistrement pour vérifier les autres\n\nElement est totalement differents des autres applications de chat et de collaboration puisqu'il est décentralisé et open source.\n\nElement vous place en control en vous laissant choisir qui sont les hôtes de vos conversations. Depuis l'application Element, vous pouvez être un hôte de différentes façons: \n\n1. Obtenez un compte gratuitement sur les serveurs publics de matrix.org\n2. Host votre compte à l'aide de votre propre serveur et matérielle\n3. Inscrivez vous pour un compte sur un serveur customisé simplement en vous abonnant a la plateforme hôte de Services Matrix Element\n\nPourquoi choisir Element ?\n\n• COMMUNICATION COMPLÈTE : Construisez des salons autours de vos équipes, de vos amis, de votre communauté comme vous le souhaitez ! Discutez, partagez des fichiers, ajoutez des widgets et passez des appels audio et vidéo gratuitement.\n\n• INTÉGRATIONS PUISSANTES : Utilisez Element avec les outils que vous connaissez déjà. Avec Element vous pouvez même discuter avec les utilisateurs et les groupes qui utilisent d'autres applications de discussion.\n\n• PRIVÉ ET SÉCURISÉ : Gardez vos conversations secrètes. Un chiffrement de bout en bout de pointe vous garanti que vos communications privées restent privées.\n\n• OUVERT, PAS FERMÉ : Open source, et construit autour de Matrix. Restez en possession de vos données en hébergeant votre propre serveur, ou choisissez celui auquel vous faites confiance.\n\n• PARTOUT OÙ VOUS ÊTES : Restez en contact où que vous soyez avec la synchronisation complète de l'historique de vos messages entre vos différents appareils et en ligne sur https://app.element.io."; -"auth_login_single_sign_on" = "Se connecter avec l'authentification unique"; +"store_full_description" = "Element est un nouveau type d’application de messagerie et de collaboration qui :\n\n1. Vous permet de préserver votre vie privée \n2. Vous permet de communiquer avec n’importe qui sur le réseau Matrix, et même plus en intégrant des applications telles que Slack \n3. Vous protège des pubs, du de l’extraction de vos données, des porte dérobées et des silos\n4. Vous protège avec le chiffrement de bout en bout et la signature croisée pour vérifier l’identité des autres\n\nElement est totalement différent des autres applications de messagerie et de collaboration puisqu’il est décentralisé et open source.\n\nElement vous permet de vous auto-héberger, ou de choisir un serveur, pour vous permettre de garder la main sur votre confidentialité, vos données et vous conversations. Il vous permet d’accéder à un réseau ouvert, de sorte à ce que vous ne soyez pas limité aux discussions avec les autres utilisateurs d’Element exclusivement. Il est très sécurisé.\n\nElement s’appuie sur Matrix - la norme pour les communications ouvertes et décentralisées.\n\nElement vous permet de choisir qui héberge vos conversations. Depuis l’application Element, vous pouvez choisir votre fournisseur de plusieurs manières :\n\n1. Inscrivez vous gratuitement sur les serveurs publics de matrix.org\n2. Hébergez votre compte sur votre propre serveur\n3. Obtenez un serveur personnalisé en vous abonnant a la plateforme d’hébergement Element Matrix Services\n\nPourquoi choisir Element ?\n\nVOS DONNÉES VOUS APPARTIENNENT : vous décidez où stocker vos données et messages. Ils vous appartiennent et vous les maîtrisez. Aucune multinationale ne viendra extraire vos données pour les envoyer au plus offrant.\n\nMESSAGERIE ET COLLABORATION OUVERTES : vous pouvez discuter avec tout le réseau Matrix, qu’ils utilisent Element ou une autre application Matrix, même s’ils utilisent une autre plateforme de messagerie telle que Slack, IRC ou XMPP.\n\nULTRA SÉCURISÉ : chiffrement de bout en bout (seuls les membres d’une conversation peuvent déchiffrer les messages), et signature croisée pour vérifier les appareils de vos interlocuteurs.\n\nTOUTES VOS COMMUNICATIONS : messagerie, appels audio et vidéo, partage de fichier, partage d’écran et un grand nombre d’intégrations, robots et widgets. Participez à des salons, des communautés, restez en contact et faites avancer vos projets.\n\nPARTOUT AVEC VOUS : votre historique reste synchronisé entre tous vos appareils et sur le web sur https://element.io/app."; +"auth_login_single_sign_on" = "Se connecter avec l’authentification unique"; "room_message_unable_open_link_error_message" = "Impossible d’ouvrir le lien."; "auth_autodiscover_invalid_response" = "Réponse de découverte du serveur d’accueil non valide"; "room_event_action_reply" = "Répondre"; -"room_event_action_edit" = "Éditer"; +"room_event_action_edit" = "Modifier"; "room_event_action_reaction_agree" = "D’accord %@"; "room_event_action_reaction_disagree" = "Pas d’accord %@"; "room_event_action_reaction_like" = "J’aime %@"; @@ -691,7 +691,7 @@ "device_verification_error_cannot_load_device" = "Impossible de charger les informations de la session."; // Mark: Incoming "device_verification_incoming_title" = "Demande de vérification entrante"; -"device_verification_incoming_description_1" = "Vérifiez cette session pour qu’elle soit marquée comme fiable. Faire confiance aux sessions de vos partenaires vous permet d’être sereins quand vous utilisez des messages chiffrés de bout en bout."; +"device_verification_incoming_description_1" = "Vérifiez cette session pour qu’elle soit marquée comme fiable. Faire confiance aux sessions de vos partenaires vous permet d’être tranquilles quand vous utilisez des messages chiffrés de bout en bout."; "device_verification_incoming_description_2" = "En vérifiant cette session, elle sera marquée comme fiable, et votre session sera aussi marquée comme fiable pour votre partenaire."; // MARK: Start "device_verification_start_title" = "Vérifier en comparant une chaîne de caractères courte"; @@ -773,7 +773,7 @@ "device_verification_emoji_headphones" = "Écouteurs"; "device_verification_emoji_folder" = "Dossier"; "device_verification_emoji_pin" = "Épingle"; -"event_formatter_message_edited_mention" = "(édité)"; +"event_formatter_message_edited_mention" = "(modifié)"; // Widget "widget_no_integrations_server_configured" = "Aucun serveur d’intégrations n’est configuré"; "widget_integrations_server_failed_to_connect" = "Échec de connexion au serveur d’intégrations"; @@ -781,25 +781,25 @@ "room_event_action_reaction_show_all" = "Tout afficher"; "room_event_action_reaction_show_less" = "Réduire"; "close" = "Fermer"; -"room_message_edits_history_title" = "Éditions de message"; +"room_message_edits_history_title" = "Modifications du message"; "room_action_send_file" = "Envoyer un fichier"; // MARK: File upload "file_upload_error_title" = "Envoi de fichier"; "file_upload_error_unsupported_file_type_message" = "Type de fichier non pris en charge."; -"auth_softlogout_signed_out" = "Vous êtes déconnecté(e)"; +"auth_softlogout_signed_out" = "Vous êtes déconnecté"; "auth_softlogout_sign_in" = "Se connecter"; "auth_softlogout_reason" = "L’administrateur de votre serveur d’accueil (%1$@) vous a déconnecté de votre compte %2$@ (%3$@)."; "auth_softlogout_recover_encryption_keys" = "Connectez-vous pour récupérer les clés de chiffrement stockées uniquement sur cet appareil. Vous en avez besoin pour lire tous les messages sécurisés sur n’importe quel appareil."; "auth_softlogout_clear_data" = "Effacer les données personnelles"; -"auth_softlogout_clear_data_message_1" = "Attention : Vos données personnelles (y compris vos clés de chiffrement) sont toujours stockées sur cet appareil."; +"auth_softlogout_clear_data_message_1" = "Attention : vos données personnelles (y compris vos clés de chiffrement) sont toujours stockées sur cet appareil."; "auth_softlogout_clear_data_message_2" = "Effacez-les si vous n’utilisez plus cet appareil ou si vous voulez vous connecter avec un autre compte."; "auth_softlogout_clear_data_button" = "Effacer toutes les données"; -"auth_softlogout_clear_data_sign_out_title" = "En êtes-vous sûr(e) ?"; +"auth_softlogout_clear_data_sign_out_title" = "En êtes-vous sûr ?"; "auth_softlogout_clear_data_sign_out_msg" = "Voulez vous vraiment supprimer toutes les données stockées actuellement sur cet appareil ? Reconnectez-vous pour accéder aux données et messages de votre compte."; "auth_softlogout_clear_data_sign_out" = "Se déconnecter"; // MARK: Emoji picker "emoji_picker_title" = "Réactions"; -"emoji_picker_people_category" = "Émoticônes et personnes"; +"emoji_picker_people_category" = "Émojis et personnes"; "emoji_picker_nature_category" = "Animaux et nature"; "emoji_picker_foods_category" = "Nourriture et boisson"; "emoji_picker_activity_category" = "Activités"; @@ -817,8 +817,8 @@ "image_picker_action_camera" = "Prendre une photo"; "image_picker_action_library" = "Choisir dans la médiathèque"; "camera_unavailable" = "L’appareil photo n’est pas disponible sur votre appareil"; -"photo_library_access_not_granted" = "%@ n’a pas la permission pour accéder à la médiathèque, veuillez modifier les options de vie privée"; -"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser votre mot de passe."; +"photo_library_access_not_granted" = "%@ n’a pas la permission pour accéder à la médiathèque, veuillez modifier les options de confidentialité"; +"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser votre mot de passe."; "room_creation_error_invite_user_by_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de participant avec un e-mail."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas commencer de discussion avec un contact en utilisant un e-mail."; // Service terms @@ -826,8 +826,8 @@ "service_terms_modal_message" = "Pour continuer vous devez accepter les conditions de ce service (%@)."; "service_terms_modal_accept_button" = "Accepter"; "service_terms_modal_description_for_identity_server" = "Se rendre découvrable pour les autres"; -"service_terms_modal_description_for_integration_manager" = "Utiliser des robots, des passerelles, des widgets et des packs de stickers"; -"room_participants_remove_third_party_invite_prompt_msg" = "Voulez-vous vraiment retirer cette invitation ?"; +"service_terms_modal_description_for_integration_manager" = "Utiliser des robots, des passerelles, des widgets et des jeux d’autocollants"; +"room_participants_remove_third_party_invite_prompt_msg" = "Voulez-vous vraiment retirer cette invitation ?"; // Errors "error_user_already_logged_in" = "On dirait que vous essayez de vous connecter à un autre serveur d’accueil. Voulez-vous vous déconnecter ?"; "room_accessiblity_scroll_to_bottom" = "Défiler vers le bas"; @@ -841,14 +841,14 @@ "media_type_accessibility_video" = "Vidéo"; "media_type_accessibility_location" = "Emplacement"; "media_type_accessibility_file" = "Fichier"; -"media_type_accessibility_sticker" = "Sticker"; +"media_type_accessibility_sticker" = "Autocollant"; // Widget Picker "widget_picker_title" = "Intégrations"; "auth_add_email_message_2" = "Définissez une adresse e-mail pour la récupération de compte, et pour être éventuellement découvrable par les personnes qui vous connaissent."; "auth_add_phone_message_2" = "Définissez un numéro de téléphone pour être éventuellement découvrable par les personnes qui vous connaissent."; "auth_add_email_phone_message_2" = "Définissez une adresse e-mail pour la récupération de compte. Vous pouvez ensuite utiliser votre e-mail ou votre numéro de téléphone pour être découvrable par les personnes qui vous connaissent."; -"auth_email_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter d’adresse e-mail pour pouvoir réinitialiser votre mot de passe dans le futur."; -"auth_phone_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de numéro de téléphone pour pouvoir réinitialiser votre mot de passe dans le futur."; +"auth_email_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter d’adresse e-mail pour pouvoir réinitialiser votre mot de passe ultérieurement."; +"auth_phone_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de numéro de téléphone pour pouvoir réinitialiser votre mot de passe ultérieurement."; "auth_reset_password_error_is_required" = "Aucun serveur d’identité n’est configuré : ajoutez-en un dans les options du serveur pour réinitialiser votre mot de passe."; "contacts_address_book_no_identity_server" = "Aucun serveur d’identité n’est configuré"; "settings_discovery_settings" = "DÉCOUVERTE"; @@ -911,7 +911,7 @@ "settings_add_3pid_password_title_email" = "Ajouter une adresse e-mail"; "settings_add_3pid_password_title_msidsn" = "Ajouter un numéro de téléphone"; "settings_add_3pid_password_message" = "Pour continuer, saisissez votre mot de passe"; -"settings_add_3pid_invalid_password_message" = "Mot de passe non valide"; +"settings_add_3pid_invalid_password_message" = "Informations d’authentification invalides"; "error_not_supported_on_mobile" = "Vous ne pouvez pas faire cela depuis %@ mobile."; "widget_menu_refresh" = "Actualiser"; "widget_menu_open_outside" = "Ouvrir dans le navigateur"; @@ -919,7 +919,7 @@ "widget_menu_remove" = "Supprimer pour tout le monde"; "settings_integrations" = "INTÉGRATIONS"; "settings_integrations_allow_button" = "Gérer les intégrations"; -"settings_integrations_allow_description" = "Utilisez un gestionnaire d’intégrations (%@) pour gérer les bots, les passerelles, les widgets et les packs de stickers.\n\nLes gestionnaires d’intégration reçoivent des données de configuration et peuvent modifier les widgets, envoyer des invitations de salon et définir des rangs à votre place."; +"settings_integrations_allow_description" = "Utilisez un gestionnaire d’intégrations (%@) pour gérer les robots, les passerelles, les widgets et les jeux d’autocollants.\n\nLes gestionnaires d’intégration reçoivent des données de configuration et peuvent modifier les widgets, envoyer des invitations de salon et définir des rangs à votre place."; "widget_integration_manager_disabled" = "Vous devez activer le gestionnaire d’intégrations dans les paramètres"; "widget_room_permission_title" = "Charger le widget"; "widget_room_permission_creator_info_title" = "Ce widget a été ajouté par :"; @@ -929,7 +929,7 @@ "room_widget_permission_creator_info_title" = "Ce widget a été ajouté par :"; "room_widget_permission_webview_information_title" = "Son utilisation peut entraîner l’utilisation de cookies et le partage de données avec %@ :\n"; "room_widget_permission_information_title" = "Son utilisation peut entraîner le partage de données avec %@ :\n"; -"room_widget_permission_display_name_permission" = "Votre nom affiché"; +"room_widget_permission_display_name_permission" = "Votre nom d’affichage"; "room_widget_permission_avatar_url_permission" = "L’URL de votre avatar"; "room_widget_permission_user_id_permission" = "Votre identifiant d’utilisateur"; "room_widget_permission_theme_permission" = "Votre thème"; @@ -985,10 +985,10 @@ "key_verification_verified_user_description_1" = "Vous avez vérifié cet utilisateur."; "key_verification_verified_user_description_2" = "Les messages avec cet utilisateur dans ce salon sont chiffrés de bout en bout et ne peuvent être lus par des tiers."; "user_verification_start_verify_action" = "Commencer la vérification"; -"user_verification_start_information_part1" = "Pour une meilleur sécurité, vérifiez "; +"user_verification_start_information_part1" = "Pour plus de sécurité, vérifiez "; "user_verification_start_information_part2" = " en comparant un code à usage unique sur vos deux appareils."; "user_verification_start_waiting_partner" = "Nous attendons %@…"; -"user_verification_start_additional_information" = "Pour une meilleure sécurité, faites cela en personne ou utilisez un autre moyen de communication."; +"user_verification_start_additional_information" = "Pour plus de sécurité, faites cela en personne ou utilisez un autre moyen de communication."; "user_verification_sessions_list_user_trust_level_trusted_title" = "Fiable"; "user_verification_sessions_list_user_trust_level_warning_title" = "Attention"; "user_verification_sessions_list_user_trust_level_unknown_title" = "Inconnu"; @@ -1027,7 +1027,7 @@ "device_verification_self_verify_start_information" = "Utilisez cette session pour vérifier la nouvelle, ce qui lui permettra d’accéder aux messages chiffrés."; "device_verification_self_verify_start_waiting" = "En attente…"; "skip" = "Passer"; -"device_verification_self_verify_wait_title" = "Compléter la sécurité"; +"device_verification_self_verify_wait_title" = "Améliorer la sécurité"; "device_verification_self_verify_wait_information" = "Vérifiez cette session depuis une de vos autres sessions, ce qui lui permettra d’avoir accès aux messages chiffrés.\n\nUtilisez la dernière version de Element sur vos autres appareils :"; "device_verification_self_verify_wait_waiting" = "En attente…"; "room_member_power_level_admin_in" = "Administrateur dans %@"; @@ -1046,16 +1046,16 @@ "key_verification_scan_confirmation_scanned_title" = "On y est presque !"; "key_verification_scan_confirmation_scanned_user_information" = "Est-ce que %@ affiche le même bouclier ?"; "key_verification_scan_confirmation_scanned_device_information" = "Est-ce que l’autre appareil affiche le même bouclier ?"; -"room_participants_action_security_status_complete_security" = "Compléter la sécurité"; +"room_participants_action_security_status_complete_security" = "Améliorer la sécurité"; "security_settings_crosssigning_info_not_bootstrapped" = "La signature croisée n’est pas encore configurée."; -"security_settings_crosssigning_info_exists" = "Votre compte a une identité de signature croisée, mais cette session ne lui fait pas encore confiance. Complétez la sécurité de cette session."; -"security_settings_crosssigning_info_trusted" = "La signature croisée est activée. Vous pouvez faire confiance à d’autres utilisateurs et à vos autres sessions selon la signature croisée mais vous ne pouvez pas effectuer des signatures croisées depuis cette session car elle n’a pas de clés privées de signature croisée. Complétez la sécurité de cette session."; +"security_settings_crosssigning_info_exists" = "Votre compte a une identité de signature croisée, mais cette session ne lui fait pas encore confiance. Améliorez la sécurité de cette session."; +"security_settings_crosssigning_info_trusted" = "La signature croisée est activée. Vous pouvez faire confiance à d’autres utilisateurs et à vos autres sessions selon la signature croisée mais vous ne pouvez pas effectuer des signatures croisées depuis cette session car elle n’a pas de clés privées de signature croisée. Améliorez la sécurité de cette session."; "security_settings_crosssigning_info_ok" = "La signature croisée est activée."; "security_settings_crosssigning_bootstrap" = "Configurer la signature croisée"; "security_settings_crosssigning_reset" = "Réinitialiser la signature croisée"; "security_settings_crosssigning_complete_security" = "Compléter la sécurité"; -"security_settings_complete_security_alert_title" = "Compléter la sécurité"; -"security_settings_complete_security_alert_message" = "Vous devriez d’abord compléter la sécurité de votre session actuelle."; +"security_settings_complete_security_alert_title" = "Améliorer la sécurité"; +"security_settings_complete_security_alert_message" = "Vous devriez d’abord améliorer la sécurité de votre session actuelle."; "security_settings_coming_soon" = "Désolé, cette action n’est pas encore disponible dans Element iOS. Utilisez un autre client Matrix pour le configurer. Element iOS l’utilisera."; // MARK: Clients "client_desktop_name" = "Element pour ordinateur"; @@ -1063,7 +1063,7 @@ "client_ios_name" = "Element iOS"; "client_android_name" = "Element Android"; "device_verification_self_verify_wait_new_sign_in_title" = "Vérifier cette connexion"; -"device_verification_self_verify_wait_additional_information" = "ou un autre client Matrix qui prend en charge la signature croisée"; +"device_verification_self_verify_wait_additional_information" = "ou un autre client Matrix qui prend en charge la signature croisée."; // MARK: - Device Verification "key_verification_other_session_title" = "Vérifier la session"; "key_verification_new_session_title" = "Vérifiez votre nouvelle session"; @@ -1079,7 +1079,7 @@ "key_verification_verified_other_session_information" = "Vous pouvez à présent lire les messages sécurisés sur votre autre session, et les autres utilisateurs sauront qu’ils peuvent lui faire confiance."; "key_verification_verified_new_session_information" = "Vous pouvez à présent lire les messages sécurisés sur votre nouvel appareil et les autres utilisateurs sauront qu’ils peuvent lui faire confiance."; "key_verification_verified_this_session_information" = "Vous pouvez à présent lire les messages sécurisés sur cet appareil et les autres utilisateurs sauront qu’ils peuvent lui faire confiance."; -"key_verification_verified_user_information" = "Les messages avec cet utilisateurs sont chiffrés de bout en bout et ne peuvent être lus par des tiers."; +"key_verification_verified_user_information" = "Les messages avec cet utilisateur sont chiffrés de bout en bout et ne peuvent être lus par des tiers."; "key_verification_verify_qr_code_emoji_information" = "Vérifier en comparant des émojis uniques."; "key_verification_verify_qr_code_start_emoji_action" = "Vérifier par émojis"; "device_verification_self_verify_alert_validate_action" = "Vérifier"; @@ -1125,8 +1125,8 @@ "secure_key_backup_setup_intro_use_security_key_title" = "Utiliser une clé de sécurité"; "secure_key_backup_setup_intro_use_security_key_info" = "Générer une clé de sécurité à stocker dans un endroit sûr comme un gestionnaire de mots de passe ou un coffre."; "secure_key_backup_setup_intro_use_security_passphrase_title" = "Utiliser une phrase secrète de sécurité"; -"secure_key_backup_setup_intro_use_security_passphrase_info" = "Saisissez une phrase secrète que vous êtes seul·e à connaître et générez une clé pour la sauvegarde."; -"secure_key_backup_setup_cancel_alert_title" = "En êtes-vous sûr·e ?"; +"secure_key_backup_setup_intro_use_security_passphrase_info" = "Saisissez une phrase secrète que vous êtes seul à connaître et générez une clé pour la sauvegarde."; +"secure_key_backup_setup_cancel_alert_title" = "En êtes-vous sûr ?"; "secure_key_backup_setup_cancel_alert_message" = "Si vous annulez maintenant, vous pourriez perdre les messages et données chiffrés si vous perdez l’accès à vos connexions.\n\nVous pouvez également configurer la sauvegarde sécurisée et gérer vos clés dans les paramètres."; "secrets_setup_recovery_key_title" = "Enregistrer votre clé de sécurité"; "secrets_setup_recovery_key_information" = "Stockez votre clé de récupération dans un endroit sûr. Elle peut être utilisée pour déverrouiller vos messages et données chiffrés."; @@ -1136,7 +1136,7 @@ "secrets_setup_recovery_key_storage_alert_title" = "Conservez-la en lieu sûr"; "secrets_setup_recovery_key_storage_alert_message" = "✓ Imprimez-la et stockez-la dans un endroit sûr\n✓ Sauvegardez-la sur une clé USB ou un disque de sauvegarde\n✓ Copiez-la sur votre stockage personnel dans le cloud"; "secrets_setup_recovery_passphrase_title" = "Définir une phrase de sécurité"; -"secrets_setup_recovery_passphrase_information" = "Saisissez une phrase de sécurité que vous seul·e connaissez, utilisée pour sécuriser les secrets sur votre serveur."; +"secrets_setup_recovery_passphrase_information" = "Saisissez une phrase de sécurité que vous seul connaissez, utilisée pour sécuriser les secrets sur votre serveur."; "secrets_setup_recovery_passphrase_additional_information" = "N’utilisez pas le mot de passe de votre compte."; "secrets_setup_recovery_passphrase_validate_action" = "Terminé"; "secrets_setup_recovery_passphrase_confirm_information" = "Saisissez à nouveau votre phrase de sécurité pour la confirmer."; @@ -1165,3 +1165,202 @@ "event_formatter_widget_removed_by_you" = "Vous avez supprimé le widget : %@"; "event_formatter_jitsi_widget_added_by_you" = "Vous avez ajouté une conférence en VoIP"; "event_formatter_jitsi_widget_removed_by_you" = "Vous avez supprimé une conférence en VoIP"; +"favourites_empty_view_information" = "Vous pouvez marquer comme favoris de plusieurs manières. La plus rapide est simplement d’appuyer et maintenir. Appuyez sur l’étoile et ils apparaîtront automatiquement."; +"room_event_action_delete_confirmation_message" = "Êtes-vous sûr de vouloir supprimer ce message non envoyé ?"; +"room_unsent_messages_cancel_message" = "Êtes-vous sûr de vouloir supprimer tous les messages non envoyés dans ce salon ?"; +"room_participants_leave_prompt_msg_for_dm" = "Êtes-vous sûr de vouloir partir ?"; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "Bon retour parmi nous."; +"room_intro_cell_information_multiple_dm_sentence2" = "Vous n’êtes que tous les deux dans cette conversation, à moins que l’un de vous invite quelqu’un à vous rejoindre."; +"room_intro_cell_information_dm_sentence2" = "Vous êtes les deux seuls membres de cette conversation, personne d’autre ne peut vous rejoindre."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Ceci est le début de votre conversation privée avec "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " pour permettre aux gens de connaître le sujet de ce salon."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Ajouter un sujet"; +"room_intro_cell_information_room_with_topic_sentence2" = "Sujet : %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Ceci est le début de "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Ajouter des personnes"; +"room_avatar_view_accessibility_hint" = "Changer l’avatar du salon"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "avatar"; +"invite_friends_share_text" = "Hé, venez me parler sur %@ : %@"; + +// MARK: - Invite friends + +"invite_friends_action" = "Inviter des amis dans %@"; + +// MARK: - Favourites + +"favourites_empty_view_title" = "Salons et personnes favoris"; +"home_empty_view_information" = "L’application tout-en-un de messagerie pour les équipes, amis et organisations. Appuyez sur le bouton « + » ci-dessous pour ajouter des personnes et des salons."; + +// MARK: - Home + +"home_empty_view_title" = "Bienvenue dans %@,\n%@"; +"call_transfer_error_message" = "Échec du transfert de l’appel"; +"call_transfer_error_title" = "Erreur"; +"call_transfer_contacts_all" = "Tous"; +"call_transfer_contacts_recent" = "Récent"; +"call_transfer_dialpad" = "Pavé de numérotation"; +"call_transfer_users" = "Utilisateurs"; + +// MARK: - Call Transfer +"call_transfer_title" = "Transférer"; + +// MARK: - Dial Pad +"dialpad_title" = "Pavé de numérotation"; +"room_info_list_section_other" = "Autres"; +"room_info_list_several_members" = "%@ membres"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 membre"; +"create_room_placeholder_address" = "#salondetest:matrix.org"; +"create_room_section_header_address" = "Adresse du salon"; +"create_room_show_in_directory" = "Publier le salon dans le répertoire"; +"create_room_section_footer_type" = "Les personnes ne rejoignent un salon privé que sur invitation."; +"create_room_type_public" = "Salon public"; +"create_room_type_private" = "Salon privé"; +"create_room_section_header_type" = "Type de salon"; +"create_room_section_footer_encryption" = "Le chiffrement ne peut pas être désactivé ensuite."; +"create_room_enable_encryption" = "Activer le chiffrement"; +"create_room_section_header_encryption" = "Chiffrement du salon"; +"create_room_placeholder_topic" = "Sujet"; +"create_room_section_header_topic" = "Sujet du salon (facultatif)"; +"create_room_placeholder_name" = "Nom"; +"create_room_section_header_name" = "Nom du salon"; + +// MARK: - Create Room + +"create_room_title" = "Nouveau salon"; +"searchable_directory_search_placeholder" = "Nom ou identifiant"; +"searchable_directory_x_network" = "Réseau %@"; + +// MARK: - Searchable Directory View Controller + +"searchable_directory_create_new_room" = "Créer un nouveau salon"; +"biometrics_cant_unlocked_alert_message_retry" = "Réessayez"; +"biometrics_cant_unlocked_alert_message_login" = "Ré-authentifiez vous"; +"biometrics_cant_unlocked_alert_message_x" = "Pour déverrouiller, utilisez %@ ou ré-authentifiez vous et réactivez %@"; +"biometrics_cant_unlocked_alert_title" = "Impossible de déverrouiller l’application"; +"biometrics_usage_reason" = "Authentifiez vous pour accéder à votre application"; +"biometrics_desetup_disable_button_title_x" = "Désactiver %@"; +"biometrics_desetup_title_x" = "Désactiver %@"; +"biometrics_setup_subtitle" = "Ne perdez pas de temps"; +"biometrics_setup_enable_button_title_x" = "Activer %@"; +"biometrics_setup_title_x" = "Activer %@"; +"biometrics_settings_enable_x" = "Activer %@"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - Biometrics Protection + +"biometrics_mode_touch_id" = "Touch ID"; +"pin_protection_kick_user_alert_message" = "Trop de tentatives, vous avez été déconnecté"; +"pin_protection_explanatory" = "Mettre en place un code PIN vous permet de protéger vos données telles que vos messages et contacts de sorte à ce que vous soyez le seul à pouvoir y accéder en saisissant votre code PIN au démarrage de l’application."; +"pin_protection_not_allowed_pin" = "Pour des raisons de sécurité, ce code PIN n’est pas disponible. Essayez un autre code PIN"; +"pin_protection_settings_change_pin" = "Changer le code PIN"; +"pin_protection_settings_enable_pin" = "Activer le code PIN"; +"pin_protection_settings_enabled_forced" = "Code PIN activé"; +"pin_protection_settings_section_footer" = "Pour réinitialiser votre code PIN, vous devez vous ré-authentifier et en créer un nouveau."; +"pin_protection_settings_section_header_x" = "PIN & %@"; +"pin_protection_mismatch_too_many_times_error_message" = "Si vous avez oublié votre code PIN, appuyez sur le bouton « PIN oublié »."; +"pin_protection_mismatch_error_message" = "Essayez à nouveau"; +"pin_protection_mismatch_error_title" = "Les codes PIN ne correspondent pas"; +"pin_protection_reset_alert_action_reset" = "Réinitialiser"; +"pin_protection_reset_alert_message" = "Pour réinitialiser votre code PIN, vous devez vous ré-authentifier et en créer un nouveau"; +"pin_protection_reset_alert_title" = "Réinitialiser le code PIN"; +"pin_protection_forgot_pin" = "Code PIN oublié"; +"pin_protection_enter_pin" = "Saisissez votre code PIN"; +"pin_protection_confirm_pin_to_change" = "Confirmez votre code PIN pour le changer"; +"pin_protection_confirm_pin_to_disable" = "Confirmez votre code PIN pour le désactiver"; +"pin_protection_confirm_pin" = "Confirmez votre code PIN"; +"pin_protection_choose_pin" = "Créer un code PIN pour améliorer la sécurité"; +"pin_protection_choose_pin_welcome_after_register" = "Bienvenue."; +"major_update_done_action" = "Compris"; +"major_update_learn_more_action" = "En savoir plus"; +"major_update_information" = "Nous sommes ravis d’annoncer que nous avons changé de nom ! Votre application est à jour, et vous êtes connecté sur votre compte."; + +// MARK: - Major update + +"major_update_title" = "Riot est désormais Element"; +"secrets_reset_authentication_message" = "Saisir votre mot de passe de compte pour confirmer"; +"secrets_reset_reset_action" = "Réinitialiser"; +"secrets_reset_warning_message" = "Vous allez reprendre sans historique, sans message, appareil ou utilisateur de confiance."; +"secrets_reset_warning_title" = "Si vous réinitialisez tout"; +"secrets_reset_information" = "Ne faites ceci que si vous n’avez aucun appareil qui peut vérifier celui-ci."; + +// MARK: - Secrets reset + +"secrets_reset_title" = "Tout réinitialiser"; +"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Contrôle des autres fonctionnalités de vérification…"; +"event_formatter_call_you_currently_in" = "Vous êtes actuellement dans cet appel"; +"rooms_empty_view_information" = "Les salons sont utiles pour toute conversation de groupe, privée ou publique. Appuyez sur « + » pour trouver des salons existants, ou en créer de nouveaux."; +"rooms_empty_view_title" = "Salons"; +"people_empty_view_information" = "Communiquez de manière sécurisée avec n’importe qui. Appuyez sur « + » pour commencer à ajouter des personnes."; +"social_login_button_title_sign_up" = "S’inscrire avec %@"; +"social_login_button_title_sign_in" = "Se connecter avec %@"; +"secrets_setup_recovery_passphrase_summary_information" = "Mémorisez votre phrase de sécurité. Elle peut être utilisée pour déverrouiller vos messages et données chiffrés."; +"secrets_setup_recovery_passphrase_summary_title" = "Enregistrer votre phrase de sécurité"; +"secrets_recovery_reset_action_part_2" = "Tout réinitialiser"; + +// MARK: - Secrets recovery + +"secrets_recovery_reset_action_part_1" = "À cours d’options de récupération ? "; +"bug_report_background_mode" = "Poursuivre en arrière-plan"; +"call_actions_unhold" = "Reprendre"; +"event_formatter_call_back" = "Rappeler"; +"event_formatter_call_you_declined" = "Vous avez refusé cet appel"; +"event_formatter_call_has_ended" = "L’appel est terminé"; +"event_formatter_call_video" = "Appel vidéo"; +"event_formatter_call_voice" = "Appel audio"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "Le chiffrement n’est pas activé ici."; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "Le chiffrement est activé ici"; +"room_details_advanced_room_id_for_dm" = "Identifiant :"; +"room_details_no_local_addresses_for_dm" = "Ce salon n’a pas d’adresse locale"; +"room_details_access_section_directory_toggle_for_dm" = "Publier le salon dans le répertoire"; +"room_details_access_section_anyone_for_dm" = "Toute personne ayant le lien, y compris les invités"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "Toute personne ayant le lien, à l’exception des invités"; +"room_details_access_section_for_dm" = "Qui peut accéder à ceci ?"; +"room_details_room_name_for_dm" = "Nom"; +"room_details_photo_for_dm" = "Photo"; +"room_details_title_for_dm" = "Détails"; +"settings_show_NSFW_public_rooms" = "Afficher les salons publics au contenu choquant"; +"external_link_confirmation_message" = "Le lien %@ vous emmène vers un autre site : %@\n\nÊtes vous sûr de vouloir poursuivre ?"; +"external_link_confirmation_title" = "Inspectez ce lien"; +"room_open_dialpad" = "Pavé de numérotation"; +"room_place_voice_call" = "Appel audio"; +"room_event_action_delete_confirmation_title" = "Supprimer les messages non envoyés"; +"room_unsent_messages_cancel_title" = "Supprimer les messages non envoyés"; +"room_participants_security_information_room_encrypted_for_dm" = "Ces messages sont chiffrés de bout en bout.\n\nVos messages sont chiffrés, et seuls vous et le destinataire disposez des clés uniques pour les déchiffrer."; +"room_participants_security_information_room_not_encrypted_for_dm" = "Ces messages ne sont pas chiffrés de bout en bout."; +"room_participants_filter_room_members_for_dm" = "Filtrer les membres"; +"room_participants_leave_prompt_title_for_dm" = "Partir"; +"people_empty_view_title" = "Personnes"; +"social_login_button_title_continue" = "Poursuivre avec %@"; +"social_login_list_title_sign_up" = "Ou"; +"social_login_list_title_sign_in" = "Ou"; + +// Social login + +"social_login_list_title_continue" = "Poursuivre avec"; +"callbar_return" = "Retour"; +"callbar_only_multiple_paused" = "%@ appels en attente"; +"callbar_only_single_paused" = "Appel en attente"; +"callbar_active_and_multiple_paused" = "1 appel en cours (%@) · %@ appels en attente"; +"callbar_active_and_single_paused" = "1 appel en cours (%@) · 1 appel en attente"; + +// Call Bar +"callbar_only_single_active" = "Appel en cours (%@)"; +"less" = "Moins"; +"more" = "Plus"; +"switch" = "Basculer"; +"joined" = "Arrivé"; +"store_promotional_text" = "Application de messagerie et collaboration respectueuse de la vie privée, sur un réseau ouvert. Décentralisée pour vous donner le contrôle. Pas d’extraction de vos données, pas de porte dérobée, pas d’accès réservé à des tiers."; diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index cb403d9af..a44ee794f 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -1292,9 +1292,61 @@ "social_login_button_title_sign_up" = "Fiókkészítés ezzel: %@"; "social_login_button_title_sign_in" = "Bejelentkezés ezzel: %@"; "social_login_button_title_continue" = "Folytatás ezzel: %@"; -"social_login_list_title_sign_up" = "Vagy fiókkészítés ezzel:"; -"social_login_list_title_sign_in" = "Vagy bejelentkezés ezzel:"; +"social_login_list_title_sign_up" = "Vagy"; +"social_login_list_title_sign_in" = "Vagy"; // Social login "social_login_list_title_continue" = "Folytatás ezzel:"; +"settings_show_NSFW_public_rooms" = "Nyilvános kifogásolható tartalmakat tartalmazó szobák megjelenítése"; +"room_intro_cell_information_multiple_dm_sentence2" = "Csak önök vannak ebben a beszélgetésben, hacsak nem hívnak meg mást."; +"room_intro_cell_information_dm_sentence2" = "Csak ketten vannak ebben a beszélgetésben, senki más nem tud csatlakozni hozzá."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Ez a közvetlen beszélgetés kezdete vele: "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " hogy a többiek tudják, miről van szó ebben a szobában."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Téma megadása"; +"room_intro_cell_information_room_with_topic_sentence2" = "Téma: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Ez a kezdete ennek: "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Felhasználók meghívása"; +"room_avatar_view_accessibility_hint" = "Szoba profilkép megváltoztatása"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "profilkép"; +"call_transfer_error_message" = "Hívás átadás nem sikerült"; +"call_transfer_error_title" = "Hiba"; +"call_transfer_contacts_all" = "Mind"; +"call_transfer_contacts_recent" = "Legutóbbi"; +"call_transfer_dialpad" = "Tárcsázó számlap"; +"call_transfer_users" = "Felhasználók"; + +// MARK: - Call Transfer +"call_transfer_title" = "Átadás"; + +// MARK: - Dial Pad +"dialpad_title" = "Tárcsázó számlap"; +"call_actions_unhold" = "Folytatás"; +"event_formatter_call_back" = "Visszahívás"; +"event_formatter_call_you_declined" = "Elutasította ezt a hívást"; +"event_formatter_call_you_currently_in" = "Jelenleg ebben a hívásban van"; +"event_formatter_call_has_ended" = "Hívás befejeződött"; +"event_formatter_call_video" = "Videóhívás"; +"event_formatter_call_voice" = "Hang hívás"; +"room_open_dialpad" = "Tárcsázó számlap"; +"room_place_voice_call" = "Hang hívás"; +"room_event_action_delete_confirmation_message" = "Biztosan el szeretné távolítani ezt az elküldetlen üzenetet?"; +"room_event_action_delete_confirmation_title" = "Elküldetlen üzenet törlése"; +"room_unsent_messages_cancel_message" = "Biztos, hogy törli az összes el nem küldött üzenetet a szobában?"; +"room_unsent_messages_cancel_title" = "El nem küldött üzenetek törlése"; +"callbar_return" = "Visszatérés"; +"callbar_only_multiple_paused" = "%@ hívás tartásban"; +"callbar_only_single_paused" = "Hívás tartásban"; +"callbar_active_and_multiple_paused" = "1 aktív hívás (%@) · %@ hívás tartásban"; +"callbar_active_and_single_paused" = "1 aktív hívás (%@) · 1 hívás tartásban"; + +// Call Bar +"callbar_only_single_active" = "Aktív hívás (%@)"; diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index aa6b12724..9b71e4f72 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -886,7 +886,7 @@ "settings_add_3pid_password_title_email" = "Aggiungi indirizzo email"; "settings_add_3pid_password_title_msidsn" = "Aggiungi numero di telefono"; "settings_add_3pid_password_message" = "Per continuare, inserisci la tua password"; -"settings_add_3pid_invalid_password_message" = "Password non valida"; +"settings_add_3pid_invalid_password_message" = "Credenziali non valide"; "error_not_supported_on_mobile" = "Non puoi farlo da %@ mobile."; "widget_menu_refresh" = "Ricarica"; "widget_menu_open_outside" = "Apri nel browser"; @@ -1263,9 +1263,61 @@ "social_login_button_title_sign_up" = "Registrati con %@"; "social_login_button_title_sign_in" = "Accedi con %@"; "social_login_button_title_continue" = "Continua con %@"; -"social_login_list_title_sign_up" = "O registrati con"; -"social_login_list_title_sign_in" = "O accedi con"; +"social_login_list_title_sign_up" = "O"; +"social_login_list_title_sign_in" = "O"; // Social login "social_login_list_title_continue" = "Continua con"; +"room_intro_cell_information_multiple_dm_sentence2" = "Ci sei solo tu in questa conversazione, a meno che uno di voi non inviti qualcuno."; +"room_intro_cell_information_dm_sentence2" = "Solo voi due siete in questa conversazione, nessun altro può unirsi."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Questo è l'inizio dei tuoi messaggi diretti con "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " per far sapere alle persone di cosa parla questa stanza."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Aggiungi un argomento"; +"room_intro_cell_information_room_with_topic_sentence2" = "Argomento: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Questo è l'inizio di "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Aggiungi persone"; +"room_avatar_view_accessibility_hint" = "Cambia avatar stanza"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "avatar"; +"call_transfer_error_message" = "Trasferimento chiamata fallito"; +"call_transfer_error_title" = "Errore"; +"call_transfer_contacts_all" = "Tutti"; +"call_transfer_contacts_recent" = "Recenti"; +"call_transfer_dialpad" = "Tastierino numerico"; +"call_transfer_users" = "Utenti"; + +// MARK: - Call Transfer +"call_transfer_title" = "Trasferisci"; + +// MARK: - Dial Pad +"dialpad_title" = "Tastierino numerico"; +"call_actions_unhold" = "Riprendi"; +"event_formatter_call_back" = "Richiama"; +"event_formatter_call_you_declined" = "Hai rifiutato questa chiamata"; +"event_formatter_call_you_currently_in" = "Sei attualmente in questa chiamata"; +"event_formatter_call_has_ended" = "Questa chiamata è terminata"; +"event_formatter_call_video" = "Videochiamata"; +"event_formatter_call_voice" = "Telefonata"; +"settings_show_NSFW_public_rooms" = "Mostra stanze pubbliche per adulti"; +"room_open_dialpad" = "Tastierino numerico"; +"room_place_voice_call" = "Telefonata"; +"room_event_action_delete_confirmation_message" = "Vuoi veramente eliminare questo messaggio non inviato?"; +"room_event_action_delete_confirmation_title" = "Elimina messaggio non inviato"; +"room_unsent_messages_cancel_title" = "Elimina messaggi non inviati"; +"room_unsent_messages_cancel_message" = "Vuoi veramente eliminare tutti i messaggi non inviati in questa stanza?"; +"callbar_return" = "Torna"; +"callbar_only_multiple_paused" = "%@ chiamate in pausa"; +"callbar_only_single_paused" = "Chiamata in pausa"; +"callbar_active_and_multiple_paused" = "1 chiamata attiva (%@) · %@ chiamate in pausa"; +"callbar_active_and_single_paused" = "1 chiamata attiva (%@) · 1 chiamata in pausa"; + +// Call Bar +"callbar_only_single_active" = "Chiamata attiva (%@)"; diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 7c9dd284b..68462127c 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -593,3 +593,11 @@ "create_room_title" = "新しい部屋"; "create_room_enable_encryption" = "暗号化を有効にする"; "room_details_room_name_for_dm" = "名前"; +"room_participants_security_information_room_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されます。\n\nメッセージは安全に保護されており、あなたと宛先のみがメッセージの閲覧に必要な鍵を所持します。"; +"room_participants_security_information_room_not_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されません。"; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "参加者を追加"; +"room_participants_security_information_room_encrypted" = "この部屋で送受信されるメッセージはエンドツーエンド暗号化されます。\n\nメッセージは安全に保護されており、この部屋の参加者のみがメッセージの閲覧に必要な鍵を所持します。"; +"room_participants_security_information_room_not_encrypted" = "この部屋で送受信されるメッセージはエンドツーエンド暗号化されません。"; diff --git a/Riot/Assets/nb-NO.lproj/Vector.strings b/Riot/Assets/nb-NO.lproj/Vector.strings index be44defbb..eb35c73c6 100644 --- a/Riot/Assets/nb-NO.lproj/Vector.strings +++ b/Riot/Assets/nb-NO.lproj/Vector.strings @@ -206,7 +206,7 @@ "identity_server_settings_alert_change_title" = "Bytt ut identitetstjener"; "identity_server_settings_alert_disconnect_button" = "Koble fra"; "room_details_people" = "Medlemmer"; -"room_details_files" = "Filer"; +"room_details_files" = "Filopplastinger"; "room_details_settings" = "Instillinger"; "room_details_room_name" = "Rommets navn"; "room_details_topic" = "Emne"; @@ -308,7 +308,7 @@ "sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Logg av"; // MARK: - Device Verification "device_verification_title" = "Verifiser økten"; -"device_verification_self_verify_alert_title" = "Ny innlogging"; +"device_verification_self_verify_alert_title" = "Ny innlogging. Var dette deg?"; "device_verification_self_verify_alert_cancel_action" = "Det var ikke meg"; "device_verification_self_verify_start_verify_action" = "Begynn verifisering"; "device_verification_self_verify_start_waiting" = "Venter …"; @@ -400,7 +400,7 @@ "user_verification_session_details_verify_action_current_user" = "Bekreft"; // String for App Store "store_short_description" = "Sikker desentralisert chat/IP-telefoni"; -"store_full_description" = "Kommuniser. På din måte.\n\nEn chatte-app som er fleksibel og fullstendig under din kontroll. Riot lar deg kommunisere slik du vil. Laget for [matrix] - standarden for åpen, desentralisert kommunikasjon.\n\nSkaff deg en gratis matrix.org-konto og din egen server på https://modular.im, eller bruk en annen Matrix-server.\n\nHvorfor velge Riot.im?\n\nKOMPLETT KOMMUNIKASJON: Bygg et eget rom til laget ditt, vennene dine, samfunnet ditt - akkurat på den måten du ønsker! Chat, del filer, legg til widgeter og foreta tale- og videosamtaler - alt sammen helt gratis.\n\nKRAFTIGE INTEGRASJONER: Bruk Riot.im med verktøyene du kjenner og elsker. Med Riot.im kan du til og med chatte med brukere og grupper på andre chatte-apper.\n\nPRIVAT OG SIKKER: Hold samtalene hemmelige. Topp moderne ende-til-ende-kryptering sikrer at privat kommunikasjon forblir privat.\n\nÅPEN, IKKE LUKKET: Åpen kildekode, og bygd på Matrix. Ei dine egne data ved å være vert for din egen server, eller velg en server du stoler på.\n\nUansett hvor du er: Hold kontakten hvor enn du er med synkronisert meldingshistorikk på alle enhetene dine, samt på nettet på https://riot.im."; +"store_full_description" = "Element er en ny type melding og samhandlings app som:\n\n1. Setter deg i førersetet for å kontrollere personlig informasjon\n2. Lar deg kommunisere med alle brukere i Matrix-nettverket, i tillegg til brukere i tilknyttede nettverk slik som Slack\n3. Beskytter deg fra annonser, datainnhenting, bakdører og lukkede nettverk. \n4. Beskytter deg gjennom at kommunikasjonen er ende-til-ende-kryptert, og at motparten er verifisert. \n\nElement er veldig annerledes enn andre melding og samhandlingsapper ved at det er en desentralisert løsning og laget som åpen kildekode.\n\nElement lar deg sette opp en egen tjener eller velge en offentlig tjener - slik at du kan beskytte tilgang og eierskap til dine data og samtaler. Det gir deg tilgang tiI et åpent nettverk slik at du ikke er begrenset til å kommunisere kun med Element brukere. Og det er veldig sikkert.\n\nElement gjør dette mulig ved at det opererer i Matrix - standarden for åpen og desentralisert kommunikasjon. \n\nElement setter deg selv i førersetet ved å la deg bestemme hvor dine samtaler skal befinne seg. Fra Element appen kan du velge forskjellige opsjoner/verter:\n\n1. Få en gratis konto på den offentlige matrix.org tjeneren. \n2. Sett opp en egen tjener for din konto på egne maskiner\n3. Registrer deg og opprett en egen tjener og konto på Element Matrix Services platformen.\n\nHvorfor velge Element?\n\nEI DINE EGNE DATA: Du bestemmer hvor dine data og meldinger oppbevares. Du eier og kontrollerer det, ikke et stort MEGACORP som samler dine data og tilbyr de til tredjeparter.\n\nÅPEN KOMMUNIKASJON OG SAMHANDLING: Du kan melde med hvem som helst i Matrix nettverket; uavhengig om de bruker Element eller en annen Matrix app, og uavhengig av om de bruker andre meldingssystemer slik som Slack, IRC eller XMPP.\n\nSUPER-SIKKER: Sann ende-til-ende-kryptering (kun de i som deltar i samtalen kan dekryptere meldinger), and kryss-signering for å sikre at alle enheter i samtalen er verifisert. \n\nKOMPLETT KOMMUNIKASJONSLØSNING: Meldinger, tale og videosamtaler, fildeling, skjermdeling og en hele rekke integrasjoner, bots og widgets. Bygg rom og samfunn, hold kontakt, og få ting gjort.\n\nOVERALT DU ER: Hold deg oppdatert uansett hvor du er, og med en fullt synkronisert meldingshistorikk, på tvers av alle enhetene dine og på web, hos https://element.io/app."; "title_favourites" = "Favoritter"; "on" = "På"; "skip" = "Hopp over"; @@ -411,7 +411,7 @@ "client_web_name" = "Riot Web"; "client_ios_name" = "Element iOS"; "client_android_name" = "Element Android"; -"auth_login_single_sign_on" = "Logg inn med én innlogging"; +"auth_login_single_sign_on" = "Logg inn"; "auth_invalid_login_param" = "Feil brukernavn og/eller passord"; "auth_invalid_user_name" = "Brukernavn kan bare inneholde bokstaver, tall, punktum, bindestrek og understrek"; "auth_invalid_password" = "Passordet er for kort (minimum 6 tegn)"; @@ -648,8 +648,8 @@ "room_conference_call_no_power" = "Du trenger tillatelse for å administrere konferansesamtaler i dette rommet"; "room_ongoing_conference_call_with_close" = "Pågående konferansesamtale. Bli med som %@ eller %@. %@ det."; "room_ongoing_conference_call" = "Pågående konferansesamtale. Bli med som %@ eller %@."; -"room_unsent_messages_unknown_devices_notification" = "Meldingen ble ikke sendt på grunn av ukjente økter. %@ eller %@ nå?"; -"room_unsent_messages_notification" = "Meldinger ikke sendt. %@ eller %@ nå?"; +"room_unsent_messages_unknown_devices_notification" = "Meldingen ble ikke sendt på grunn av ukjente økter."; +"room_unsent_messages_notification" = "Meldinger ikke sendt."; "room_offline_notification" = "Tilkoblingen til serveren har gått tapt."; "encrypted_room_message_reply_to_placeholder" = "Send et kryptert svar…"; "encrypted_room_message_placeholder" = "Send en kryptert melding…"; @@ -726,7 +726,7 @@ "auth_autodiscover_invalid_response" = "Ugyldig svar på hjemmeserver"; "auth_accept_policies" = "Vennligst gjennomgå og godta retningslinjene til denne hjemmeserveren:"; "auth_add_email_and_phone_warning" = "Registrering med e-post og telefonnummer på en gang støttes ikke ennå før api eksisterer. Bare telefonnummeret blir tatt i betraktning. Du kan legge til e-postmeldingen din i profilen din i innstillingene."; -"auth_reset_password_success_message" = "Passordet ditt har blitt tilbakestilt.\n\nDu er logget ut av alle økter og vil ikke lenger motta push-varsler. For å aktivere varsler på nytt, logg på på nytt på hver enhet."; +"auth_reset_password_success_message" = "Passordet ditt har blitt tilbakestilt.\n\nDu er logget ut av alle økter og vil ikke lenger motta push-varsler. For å aktivere varsler på nytt, logg inn på nytt på hver enhet."; "auth_reset_password_error_is_required" = "Ingen identitetsserver er konfigurert: legg til en i serveralternativene for å tilbakestille passordet ditt."; "auth_reset_password_error_not_found" = "E-postadressen din ser ikke ut til å være tilknyttet en Matrix-ID på denne hjemmeserveren."; "auth_reset_password_error_unauthorized" = "Kunne ikke bekrefte e-postadressen: sørg for at du har klikket på lenken i e-posten"; @@ -745,3 +745,43 @@ "auth_email_is_required" = "Ingen identitetsserver er konfigurert, så du kan ikke legge til en e-postadresse for å tilbakestille passordet ditt i fremtiden."; "active_call_details" = "Aktiv samtale (%@)"; "active_call" = "Aktiv samtale"; + +// MARK: - Invite friends + +"invite_friends_action" = "Inviter venner til %@"; +"home_empty_view_information" = "Alt-i-ett sikker chat-app for team, venner og organisasjoner. Tapp på + knappen under for å legge til personer og rom."; + +// MARK: - Home + +"home_empty_view_title" = "Velkommen til %@,\n%@"; +"room_member_power_level_admin_in" = "Admin i %@"; +"room_participants_action_section_direct_chats" = "Direktesamtaler"; +"contacts_user_directory_offline_section" = "Brukerliste (frakoblet)"; +"contacts_user_directory_section" = "Brukerliste"; +"directory_searching_title" = "Søker i katalog…"; +"directory_search_results_more_than" = ">%tu resultater funnet for %@"; +"directory_search_results_title" = "Utforsk listeresultater"; +"directory_cell_description" = "%tu rom"; + +// Directory +"directory_cell_title" = "Utforsk liste"; + +// Room recents +"room_recents_directory_section" = "Romliste"; +"social_login_button_title_sign_up" = "Registrer deg med %@"; +"social_login_button_title_sign_in" = "Logg inn med %@"; +"social_login_button_title_continue" = "Fortsett med %@"; +"social_login_list_title_sign_up" = "Eller"; +"social_login_list_title_sign_in" = "Eller"; + +// Social login + +"social_login_list_title_continue" = "Fortsett med"; +"callbar_return" = "Returner"; +"callbar_only_multiple_paused" = "%@ pausede samtaler"; +"callbar_only_single_paused" = "Pauset samtale"; +"callbar_active_and_multiple_paused" = "1 aktiv samtale (%@) · %@ pausede samtaler"; +"callbar_active_and_single_paused" = "1 aktiv samtale (%@) · 1 pauset samtale"; + +// Call Bar +"callbar_only_single_active" = "Aktiv samtale (%@)"; diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index d193952d4..53182a22a 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -320,7 +320,7 @@ "settings_password_updated" = "Uw wachtwoord is bijgewerkt"; "settings_crypto_device_name" = "Apparaatnaam: "; "settings_crypto_device_id" = "\nApparaats-ID: "; -"settings_crypto_device_key" = "\nApparaatssleutel: "; +"settings_crypto_device_key" = "\nApparaatssleutel:\n"; "settings_crypto_export" = "Sleutels exporteren"; "settings_crypto_blacklist_unverified_devices" = "Alleen naar geverifieerde apparaten versleutelen"; // Room Details @@ -566,7 +566,7 @@ "room_message_reply_to_short_placeholder" = "Stuur een antwoord…"; // String for App Store "store_short_description" = "Veilig en gedecentraliseerd chatten en bellen"; -"store_full_description" = "Communiceer op uw manier.\n\nEen chat-app, onder uw controle en heel flexibel. Element laat u communiceren zoals u dat wilt. Gemaakt voor [matrix] - de standaard voor open, gedecentraliseerde communicatie.\n\nMaak een gratis account aan op matrix.org, verkrijg uw eigen server op https://ems.element.io, of gebruik een andere Matrix-server.\n\nWaarom zou ik voor Element kiezen?\n\n• VOLLEDIGE COMMUNICATIE: maak gesprekken aan rond uw teams, uw vrienden, uw gemeenschap - hoe u maar wilt! Chat, deel bestanden, voeg widgets toe en maak stem- en video-oproepen - allemaal volledig gratis.\n\n• KRACHTIGE INTEGRATIE: gebruik Element met de hulpmiddelen waarmee u vertrouwd bent. Met Element kunt u zelfs chatten met gebruikers en groepen op andere chat-apps.\n\n• PRIVÉ EN VEILIG: houd uw gesprekken geheim. Eind-tot-eind-versleuteling van de bovenste plank zorgt ervoor dat uw privécommunicatie ook privé blijft.\n\n• OPEN, NIET GESLOTEN: vrije software, gebouwd op Matrix. Wees baas over uw eigen gegevens door uw eigen server te gebruiken, of te kiezen voor een andere server die u vertrouwt.\n\n• WAAR U OOK BENT: houd contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten, en online op https://app.element.io."; +"store_full_description" = "Element is een nieuw type messenger en samenwerkings app die:\n\n1. U de controle geeft om uw privacy te behouden\n2. U laat communiceren met iedereen in het Matrix-netwerk, en zelfs daarbuiten door integratie met apps zoals Slack\n3. Beschermt u tegen reclame, datamining, achterdeurtjes en ommuurde netwerken\n4. Beveiligt u door eind-tot-eind versleuteling, met kruislings ondertekenen om anderen te verifiëren\n\nElement is compleet anders dan andere messengers en samenwerkings-apps, omdat het gedecentraliseerd en open source is.\n\nMet Element kunt u zelf hosten - of een host kiezen - zodat u privacy, eigendom en controle heeft over uw gegevens en gesprekken. Het geeft u toegang tot een open netwerk; u zit dus niet vast aan het praten met alleen andere Element-gebruikers. En het is zeer veilig.\n\nElement is hiertoe in staat omdat het werkt op basis van Matrix - de standaard voor open, gedecentraliseerde communicatie. \n\nElement geeft u de controle door u te laten kiezen wie uw gesprekken host. Vanuit de Element app kunt u kiezen om op verschillende manieren te hosten:\n\n1. Neem een gratis account op de publieke server matrix.org\n2. Host het zelf, uw account door draait op uw eigen server\n3. Laat ons het hosten, meld u aan voor een account op een aangepaste server bij het Element Matrix Services hosting platform\n\nWaarom kiest u voor Element?\n\nEIGENAAR VAN UW GEGEVENS: U bepaalt waar uw gegevens en berichten worden bewaard. U bent de eigenaar en heeft de controle, niet een of andere MEGACORP die uw gegevens mijnt of toegang geeft aan derden.\n\nOPEN MESSAGING EN SAMENWERKING: U kunt met iedereen in het Matrix-netwerk chatten, of ze nu Element of een andere Matrix-app gebruiken, en zelfs als ze een ander messaging-systeem gebruiken zoals Slack, IRC of XMPP.\n\nSUPER-VEILIG: Echte eind-tot-eind versleuteling (alleen degenen in de conversatie kunnen berichten ontsleutelen), en kruislings ondertekenen om de apparaten van gespreksdeelnemers te verifiëren.\n\nCOMPLETE COMMUNICATIE: Berichten, spraak- en videogesprekken, bestandsdeling, schermdeling en een heleboel integraties, bots en widgets. Bouw gesprekken, gemeenschappen, blijf in contact en krijg het gedaan.\n\nOVERAL WAAR U BENT: Blijf in contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten en op het web op https://element.io/app."; "auth_login_single_sign_on" = "Aanmelden met enkele aanmelding"; "auth_accept_policies" = "Gelieve het beleid van deze thuisserver te lezen en aanvaarden:"; "auth_autodiscover_invalid_response" = "Ongeldig thuisserverontdekkingsantwoord"; @@ -866,3 +866,587 @@ "auth_email_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen e-mailadres toevoegen om uw wachtwoord in de toekomst opnieuw in te stellen."; "auth_phone_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen telefoonnummer toevoegen om uw wachtwoord in de toekomst opnieuw in te stellen."; "auth_reset_password_error_is_required" = "Geen identiteitsserver ingesteld: voeg er één toe bij server opties om uw wachtwoord te wijzigen."; + +// MARK: - Secrets set up + +// Recovery Key + +"secrets_setup_recovery_key_title" = "Sla uw veiligheidssleutel op"; +"secure_key_backup_setup_intro_use_security_key_info" = "Genereer een veiligheidssleutel, die op een veilige plek opgeslagen kan worden zoals een wachtwoordmanager."; +"secure_key_backup_setup_intro_use_security_key_title" = "Gebruik een veiligheidssleutel"; +"secrets_setup_recovery_passphrase_summary_information" = "Onthoud uw veiligheidswachtwoord. Het kan gebruikt worden voor het ontgrendelen van uw versleutelde berichten en data."; +"secrets_setup_recovery_passphrase_summary_title" = "Sla uw veiligheidswachtwoord op"; +"secrets_setup_recovery_passphrase_confirm_information" = "Voer uw veiligheidswachtwoord opnieuw in om het te bevestigen."; +"secrets_setup_recovery_passphrase_information" = "Voer een veiligheidswachtwoord in die alleen u kent om uw gegevens te beveiligen op uw server."; + +// Recovery passphrase + +"secrets_setup_recovery_passphrase_title" = "Veiligheidswachtwoord instellen"; +"secure_key_backup_setup_intro_use_security_passphrase_info" = "Voer een veiligheidswachtwoord in die alleen u weet, en genereer een veiligheidssleutel voor uw back-up."; +"secure_key_backup_setup_intro_use_security_passphrase_title" = "Gebruik een veiligheidswachtwoord"; +"secrets_setup_recovery_key_storage_alert_message" = "✓ Print het en bewaar het op een veilige plek\n✓ Sla het op een USB-sleutel of back-upschijf op\n✓ Kopieer het naar uw persoonlijke cloud opslag"; +"room_intro_cell_information_multiple_dm_sentence2" = "Alleen u bent in dit gesprek, tenzij u iemand uitnodigd voor dit gesprek."; +"room_intro_cell_information_dm_sentence2" = "Alleen u twee zijn in dit gesprek, niemand anders kan deelnemen."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Dit is het begin van uw directe gesprek met "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " om personen te laten weten waar dit gesprek over gaat."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Voeg een onderwerp toe"; +"room_intro_cell_information_room_with_topic_sentence2" = "Onderwerp: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Dit is het begin van "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Personen toevoegen"; +"room_avatar_view_accessibility_hint" = "Gespreksfoto wijzigen"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "profielfoto"; +"invite_friends_share_text" = "Hoi, start een gesprek met me op %@: %@"; + +// MARK: - Invite friends + +"invite_friends_action" = "Vrienden tot %@ uitnodigen"; +"favourites_empty_view_information" = "U kunt op een paar manieren favorieten maken - de snelste is om een gesprek ingedrukt te houden. Tik op de ster en ze verschijnen hier automatisch om veilig te bewaren."; + +// MARK: - Favourites + +"favourites_empty_view_title" = "Favoriete gesprekken en personen"; +"home_empty_view_information" = "De alles-in-één veilige chat app voor teams, vrienden en organisaties. Klik op de onderstaande + knop om gesprekken te starten met personen en groepen."; + +// MARK: - Home + +"home_empty_view_title" = "Welkom bij %@,\n%@"; +"call_transfer_error_message" = "Oproepdoorschakelen mislukt"; +"call_transfer_error_title" = "Fout"; +"call_transfer_contacts_all" = "Alles"; +"call_transfer_contacts_recent" = "Recent"; +"call_transfer_dialpad" = "Kiestoetsen"; +"call_transfer_users" = "Gebruikers"; + +// MARK: - Call Transfer +"call_transfer_title" = "Doorschakelen"; + +// MARK: - Dial Pad +"dialpad_title" = "Kiestoetsen"; +"room_info_list_section_other" = "Overige"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 persoon"; +"room_info_list_several_members" = "%@ personen"; +"create_room_placeholder_address" = "#testroom:matrix.org"; +"create_room_section_header_address" = "Adres"; +"create_room_show_in_directory" = "Gesprek weergeven in de catalogus"; +"create_room_section_footer_type" = "Mensen kunnen alleen met een uitnodiging deelnemen aan een privégesprek."; +"create_room_type_public" = "Openbaar gesprek"; +"create_room_type_private" = "Privégesprek"; +"create_room_section_header_type" = "Type gesprek"; +"create_room_section_footer_encryption" = "Versleuteling kan achteraf niet worden uitgeschakeld."; +"create_room_enable_encryption" = "Versleuteling inschakelen"; +"create_room_section_header_encryption" = "Gespreksversleuteling"; +"create_room_placeholder_topic" = "Onderwerp"; +"create_room_section_header_topic" = "Onderwerp (optioneel)"; +"create_room_placeholder_name" = "Naam"; +"create_room_section_header_name" = "Naam"; + +// MARK: - Create Room + +"create_room_title" = "Nieuw Gesprek"; +"searchable_directory_search_placeholder" = "Naam of ID"; +"searchable_directory_x_network" = "%@-netwerk"; + +// MARK: - Searchable Directory View Controller + +"searchable_directory_create_new_room" = "Maak een nieuw gesprek"; +"biometrics_cant_unlocked_alert_message_retry" = "Opnieuw proberen"; +"biometrics_cant_unlocked_alert_message_login" = "Log opnieuw in"; +"biometrics_cant_unlocked_alert_message_x" = "Gebruik %@ om te ontgrendelen of log opnieuw in en schakel %@ opnieuw in"; +"biometrics_cant_unlocked_alert_title" = "Kan uw app niet ontgrendelen"; +"biometrics_usage_reason" = "Authenticatie is nodig om toegang te krijgen tot uw app"; +"biometrics_desetup_disable_button_title_x" = "%@ uitschakelen"; +"biometrics_desetup_title_x" = "%@ uitschakelen"; +"biometrics_setup_subtitle" = "Bespaar uzelf tijd"; +"biometrics_setup_enable_button_title_x" = "%@ inschakelen"; +"biometrics_setup_title_x" = "%@ inschakelen"; +"biometrics_settings_enable_x" = "%@ inschakelen"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - Biometrics Protection + +"biometrics_mode_touch_id" = "Touch ID"; +"pin_protection_kick_user_alert_message" = "Te veel fouten, u bent uitgelogd"; +"pin_protection_explanatory" = "Met een PIN beschermt u uw data zoals uw berichten en contacten. Zo heeft alleen u toegang na het invoeren van uw PIN bij het opstarten van de app."; +"pin_protection_not_allowed_pin" = "Om beveiligingsredenen is deze PIN niet beschikbaar. Probeer een andere PIN"; +"pin_protection_settings_change_pin" = "PIN wijzigen"; +"pin_protection_settings_enable_pin" = "PIN inschakelen"; +"pin_protection_settings_enabled_forced" = "PIN ingeschakeld"; +"pin_protection_settings_section_footer" = "Om uw PIN opnieuw in te stellen moet u straks opnieuw inloggen en een nieuwe PIN aanmaken."; +"pin_protection_settings_section_header_x" = "PIN en %@"; +"pin_protection_mismatch_too_many_times_error_message" = "Als u uw PIN bent vergeten, klik op de PIN vergeten-knop."; +"pin_protection_mismatch_error_message" = "Probeer het opnieuw"; +"pin_protection_mismatch_error_title" = "PIN's zijn niet hetzelfde"; +"pin_protection_reset_alert_action_reset" = "Opnieuw instellen"; +"pin_protection_reset_alert_message" = "Om uw PIN opnieuw in te stellen moet u strak opnieuw inloggen en een nieuwe PIN aanmaken"; +"pin_protection_reset_alert_title" = "PIN opnieuw instellen"; +"pin_protection_forgot_pin" = "PIN vergeten"; +"pin_protection_enter_pin" = "Voor uw PIN in"; +"pin_protection_confirm_pin_to_change" = "Bevestig uw PIN om uw PIN te wijzigen"; +"pin_protection_confirm_pin_to_disable" = "Bevestig uw PIN om uw PIN uit te schakelen"; +"pin_protection_confirm_pin" = "Bevestig uw PIN"; +"pin_protection_choose_pin" = "Maak een PIN voor uw veiligheid"; +"pin_protection_choose_pin_welcome_after_register" = "Welkom."; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "Welkom terug."; +"major_update_done_action" = "Ik snap het"; +"major_update_learn_more_action" = "Leer meer"; +"major_update_information" = "We zijn enthousiast om onze nieuwe naam aan te kondigen! Uw app is up-to-date en u bent ingelogd op uw account."; + +// MARK: - Major update + +"major_update_title" = "Riot is nu Element"; +"cross_signing_setup_banner_subtitle" = "Verifieer uw andere apparaat gemakkelijker"; + +// MARK: - Cross-signing + +// Banner + +"cross_signing_setup_banner_title" = "Versleuteling instellen"; +"secrets_reset_authentication_message" = "Geef het wachtwoord van uw account om te bevestigen"; +"secrets_reset_reset_action" = "Opnieuw instellen"; +"secrets_reset_warning_message" = "U zult opnieuw starten zonder geschiedenis, berichten, vertrouwde apparaten en vertrouwde gebruikers."; +"secrets_reset_warning_title" = "Als u alles terugzet"; +"secrets_reset_information" = "Doe dit alleen, wanneer u geen ander apparaat heeft om dit apparaat mee te verifiëren."; + +// MARK: - Secrets reset + +"secrets_reset_title" = "Alles terugzetten"; +"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Wachtwoord bevestigen"; +"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Bevestigen"; +"secrets_setup_recovery_passphrase_validate_action" = "Klaar"; +"secrets_setup_recovery_passphrase_additional_information" = "Gebruik niet het wachtwoord van uw account."; +"secrets_setup_recovery_key_storage_alert_title" = "Bewaar hem op een veilige plaats"; +"secrets_setup_recovery_key_done_action" = "Klaar"; +"secrets_setup_recovery_key_export_action" = "Opslaan"; +"secrets_setup_recovery_key_loading" = "Laden…"; +"secrets_setup_recovery_key_information" = "Bewaar uw Herstelsleutel op een veilige plek. Het kan gebruikt worden voor het ontgrendelen van uw versleutelde berichten en data."; +"secrets_recovery_with_key_invalid_recovery_key_message" = "Verifieer dat u de juiste herstelsleutel heeft ingevoerd."; +"secrets_recovery_with_key_invalid_recovery_key_title" = "Geen toegang tot geheime opslag"; +"secrets_recovery_with_key_recover_action" = "Gebruik sleutel"; +"secrets_recovery_with_key_recovery_key_placeholder" = "Voer de herstelsleutel in"; +"secrets_recovery_with_key_recovery_key_title" = "Invoeren"; +"secrets_recovery_with_key_information_verify_device" = "Gebruik uw herstelsleutel om dit apparaat te verifiëren."; +"secrets_recovery_with_key_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en uw kruislings ondertekenen ID voor het verifiëren van andere sessie door het invoeren van uw Herstelsleutel."; + +// Recover with key + +"secrets_recovery_with_key_title" = "Herstelsleutel"; +"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Verifieer dat u het juiste Herstelwachtwoord heeft ingevoerd."; +"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Geen toegang tot geheime opslag"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = "."; +"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "uw Herstelsleutel gebruiken"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Herstelwachtwoord vergeten? Dan kunt u "; +"secrets_recovery_with_passphrase_recover_action" = "Gebruik Wachtwoord"; +"secrets_recovery_with_passphrase_passphrase_placeholder" = "Voer uw Herstelwachtwoord in"; +"secrets_recovery_with_passphrase_passphrase_title" = "Invoeren"; +"secrets_recovery_with_passphrase_information_verify_device" = "Gebruik uw Herstelwachtwoord om dit apparaat te verifiëren."; +"secrets_recovery_with_passphrase_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en uw kruislings ondertekenen ID voor het verifiëren van andere sessies door het invoeren van uw Herstelwachtwoord."; + +// Recover with passphrase + +"secrets_recovery_with_passphrase_title" = "Herstelwachtwoord"; +"secrets_recovery_reset_action_part_2" = "Alles terugzetten"; + +// MARK: - Secrets recovery + +"secrets_recovery_reset_action_part_1" = "Alle herstelopties vergeten of verloren? "; +"user_verification_session_details_verify_action_other_user" = "Handmatig verifiëren"; +"user_verification_session_details_verify_action_current_user_manually" = "Handmatig middels een tekst"; +"user_verification_session_details_verify_action_current_user" = "Interactief Verifiëren"; +"user_verification_session_details_additional_information_untrusted_current_user" = "Als u zich niet heeft aangemeld bij deze sessie, is uw account wellicht geschonden."; +"user_verification_session_details_additional_information_untrusted_other_user" = "Totdat deze persoon de sessie vertrouwd zijn berichten gelabeld met een waarschuwing. Een alternatief is handmatig verifiëren."; +"user_verification_session_details_information_untrusted_other_user" = " heeft zich in een nieuwe sessie aangemeld:"; +"user_verification_session_details_information_untrusted_current_user" = "Verifieer deze sessie om het als vertrouwd te markeren en het toegang te geven tot versleutelde berichten:"; +"user_verification_session_details_information_trusted_other_user_part2" = " verifieer het:"; +"user_verification_session_details_information_trusted_other_user_part1" = "Deze sessie is vertrouwd voor veilige communicatie omdat "; +"user_verification_session_details_information_trusted_current_user" = "Deze sessie is vertrouwd voor veilige communicatie omdat u het heeft geverifieerd:"; +"user_verification_session_details_untrusted_title" = "Niet vertrouwd"; + +// Session details + +"user_verification_session_details_trusted_title" = "Vertrouwd"; +"user_verification_sessions_list_session_untrusted" = "Niet vertrouwd"; +"user_verification_sessions_list_session_trusted" = "Vertrouwd"; +"user_verification_sessions_list_table_title" = "Sessies"; +"user_verification_sessions_list_information" = "Berichten met deze gebruiker zijn eind-tot-eind versleuteld en kunnen niet door derde partijen gelezen worden."; +"user_verification_sessions_list_user_trust_level_unknown_title" = "Onbekend"; +"user_verification_sessions_list_user_trust_level_warning_title" = "Waarschuwing"; + +// Sessions list + +"user_verification_sessions_list_user_trust_level_trusted_title" = "Vertrouwd"; +"user_verification_start_additional_information" = "Doe dit voor de zekerheid onder vier ogen, of gebruik een andere manier om te communiceren."; +"user_verification_start_waiting_partner" = "Wachten op %@…"; +"user_verification_start_information_part2" = " door een eenmalige code op beide apparaten te controleren."; +"user_verification_start_information_part1" = "Voor extra veiligheid, verifieer "; + +// MARK: - User verification + +// Start + +"user_verification_start_verify_action" = "Verificatie starten"; +"key_verification_scan_confirmation_scanned_device_information" = "Toont het andere apparaat hetzelfde schild?"; +"key_verification_scan_confirmation_scanned_user_information" = "Toont %@ hetzelfde schild?"; + +// Scanned +"key_verification_scan_confirmation_scanned_title" = "Bijna klaar!"; +"key_verification_scan_confirmation_scanning_device_waiting_other" = "Wachten op het andere apparaat…"; +"key_verification_scan_confirmation_scanning_user_waiting_other" = "Wachten op %@…"; + +// MARK: Scan confirmation + +// Scanning +"key_verification_scan_confirmation_scanning_title" = "Bijna klaar! Wachten op bevestiging…"; +"key_verification_verify_qr_code_scan_other_code_success_message" = "De QR-code is gevalideerd."; +"key_verification_verify_qr_code_scan_other_code_success_title" = "Code gevalideerd!"; +"key_verification_verify_qr_code_other_scan_my_code_title" = "Heeft de andere gebruiker de QR-code gescand?"; +"key_verification_verify_qr_code_start_emoji_action" = "Verifiëren met emoji"; +"key_verification_verify_qr_code_cannot_scan_action" = "Scannen niet mogelijk?"; +"key_verification_verify_qr_code_scan_code_action" = "Scan hun code"; +"key_verification_verify_qr_code_emoji_information" = "Verifieer door unieke emoji te vergelijken."; +"key_verification_verify_qr_code_information_other_device" = "Scan de code hieronder om te verifiëren:"; +"key_verification_verify_qr_code_information" = "Scan de code om elkaar veilig te verifiëren."; + +// MARK: QR code + +"key_verification_verify_qr_code_title" = "Verifiëren met scan"; + +// Incoming key verification request + +"key_verification_incoming_request_incoming_alert_message" = "%@ wil verifiëren"; +"key_verification_tile_conclusion_warning_title" = "Niet-vertrouwde aanmelding"; +"key_verification_tile_conclusion_done_title" = "Geverifieerd"; +"key_verification_tile_request_incoming_approval_decline" = "Weigeren"; +"key_verification_tile_request_incoming_approval_accept" = "Aanvaarden"; +"key_verification_tile_request_status_accepted" = "U heeft aanvaard"; +"key_verification_tile_request_status_cancelled" = "%@ heeft geannuleerd"; +"key_verification_tile_request_status_cancelled_by_me" = "U heeft geannuleerd"; +"key_verification_tile_request_status_expired" = "Verlopen"; +"key_verification_tile_request_status_waiting" = "Wachten…"; +"key_verification_tile_request_status_data_loading" = "Gegevens laden…"; +"key_verification_tile_request_outgoing_title" = "Verificatie verstuurd"; + +// Tiles + +"key_verification_tile_request_incoming_title" = "Verificatieverzoek"; +"key_verification_bootstrap_not_setup_message" = "U moet kruislings ondertekenen eerst instellen."; + +// MARK: - Key Verification + +"key_verification_bootstrap_not_setup_title" = "Fout"; +"error_not_supported_on_mobile" = "U kunt dit niet doen vanaf de mobiele %@."; + + +// Generic errors +"error_invite_3pid_with_no_identity_server" = "Voeg een identiteitsserver toe in uw instellingen, om per e-mail uit te kunnen nodigen."; + +// User + +"key_verification_verified_user_information" = "Berichten met deze gebruikers zijn eind-tot-eind versleuteld en kunnen niet door derde partijen gelezen worden."; +"key_verification_verified_this_session_information" = "U kunt nu veilig uw berichten op dit apparaat lezen. Andere gebruikers weten dat zij u kunnen vertrouwen."; +"key_verification_verified_new_session_information" = "U kunt nu veilig uw berichten op uw andere apparaat lezen. Andere gebruikers weten dat zij u kunnen vertrouwen."; +"key_verification_verified_other_session_information" = "U kunt nu veilig uw berichten in uw andere sessie lezen. Andere gebruikers weten dat zij u kunnen vertrouwen."; +"key_verification_verified_new_session_title" = "Nieuwe sessie geverifieerd!"; +"key_verification_manually_verify_device_validate_action" = "Verifiëren"; +"key_verification_manually_verify_device_additional_information" = "Als deze niet overeenkomen, dan wordt deze sessie mogelijk door iemand anders onderschept."; +"key_verification_manually_verify_device_key_title" = "Sessiesleutel"; +"key_verification_manually_verify_device_id_title" = "Sessie-ID"; +"key_verification_manually_verify_device_name_title" = "Sessienaam"; +"key_verification_manually_verify_device_instruction" = "Om te verifiëren dat deze sessie vertrouwd kan worden, contacteert u de eigenaar via een andere methode (bv. persoonlijk of via een telefoontje) en vraagt u hem/haar of de sleutel die hij/zij ziet in zijn/haar Gebruikersinstellingen van deze sessie overeenkomt met de sleutel hieronder:"; + +// MARK: Manually Verify Device + +"key_verification_manually_verify_device_title" = "Handmatig middels een tekst"; +"key_verification_verify_sas_additional_information" = "Gebruik voor de ultieme veiligheid een ander vertrouwd communicatiemiddel of doe dit persoonlijk."; +"key_verification_verify_sas_validate_action" = "Ze komen overeen"; +"key_verification_verify_sas_cancel_action" = "Ze komen niet overeen"; +"key_verification_verify_sas_title_number" = "Vergelijk nummers"; + +// MARK: Verify + +"key_verification_verify_sas_title_emoji" = "Vergelijk de emoji's"; +"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Controleren op andere verificatie mogelijkheden..."; +"device_verification_self_verify_wait_recover_secrets_additional_information" = "Wanneer u geen toegang meer heeft tot een bestaande sessie"; +"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Uw Herstelwachtwoord of -sleutel gebruiken"; +"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Herstelsleutel gebruiken"; +"device_verification_self_verify_wait_additional_information" = "Dit werkt met Element en andere Matrix-apps die kruislings ondertekenen ondersteunen."; +"device_verification_self_verify_wait_information" = "Verifieer deze sessie vanaf een van uw andere sessies, om toegang te krijgen tot de versleutelde berichten.\n\nGebruik de laatste versie van Element op uw andere apparaten:"; +"device_verification_self_verify_wait_new_sign_in_title" = "Verifieer deze aanmelding"; + +// MARK: Self verification wait + +"device_verification_self_verify_wait_title" = "Beveiliging afronden"; +"key_verification_self_verify_unverified_sessions_alert_validate_action" = "Nakijken"; +"key_verification_self_verify_unverified_sessions_alert_message" = "Controleer al uw sessies om zeker te zijn dat uw account & berichten veilig zijn."; + +// Unverified sessions + +"key_verification_self_verify_unverified_sessions_alert_title" = "Kijk na waar u aangemeld bent"; +"key_verification_self_verify_current_session_alert_validate_action" = "Verifiëren"; +"key_verification_self_verify_current_session_alert_message" = "Mogelijk wantrouwen anderen het."; + +// Current session + +"key_verification_self_verify_current_session_alert_title" = "Deze sessie verifiëren"; +"device_verification_self_verify_start_waiting" = "Wachten…"; +"device_verification_self_verify_start_information" = "Gebruik deze sessie om uw nieuwe sessie te verifiëren, waardoor deze laatste toegang verkrijgt tot versleutelde berichten."; +"device_verification_self_verify_start_verify_action" = "Verificatie starten"; +"device_verification_self_verify_alert_validate_action" = "Verifiëren"; +"device_verification_self_verify_alert_message" = "Verifieer de nieuwe aanmelding op uw account: %@"; + +// MARK: Self verification start + +// New login +"device_verification_self_verify_alert_title" = "Nieuwe aanmelding - was u dat?"; +"device_verification_security_advice_number" = "Vergelijk de cijfers en stel vast dat deze in dezelfde volgorde worden weergeven."; +"device_verification_security_advice_emoji" = "Vergelijk de emoji's en stel vast dat deze in dezelfde volgorde worden weergeven."; +"key_verification_user_title" = "Verifieer hen"; +"key_verification_this_session_title" = "Deze sessie verifiëren"; +"key_verification_new_session_title" = "Verifieer uw nieuwe sessie"; + +// MARK: - Device Verification +"key_verification_other_session_title" = "Sessie verifiëren"; +"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Gebruik uw Veilige Back-up"; + +// Recover from private key +"key_backup_recover_from_private_key_info" = "Back-up wordt hersteld…"; +"secure_backup_setup_banner_subtitle" = "Bescherm uzelf tegen toegangsverlies van uw versleutelde berichten en data"; + +// Banner + +"secure_backup_setup_banner_title" = "Veilige Back-up"; +"secure_key_backup_setup_cancel_alert_message" = "Wanneer u nu afbreekt en de toegang tot uw sessies verliest, kunt u de versleutelde berichten en data kwijtraken.\n\nU kunt ook een back-up instellen en uw sleutels beheren in de Instellingen."; + + +// Cancel + +"secure_key_backup_setup_cancel_alert_title" = "Weet u het zeker?"; +"secure_key_backup_setup_existing_backup_error_delete_it" = "Verwijder het"; +"secure_key_backup_setup_existing_backup_error_unlock_it" = "Ontsleutelen"; +"secure_key_backup_setup_existing_backup_error_info" = "Ontgrendel het om de Veilige Back-up te gebruiken of verwijder het om een nieuwe berichten back-up te beginnen in de Veilige Back-up."; +"secure_key_backup_setup_existing_backup_error_title" = "Er bestaat al een back-up voor berichten"; +"secure_key_backup_setup_intro_info" = "Bescherm uzelf tegen het verliezen van uw versleutelde berichten en data door uw versleutelingssleutels te back-uppen op onze server."; + +// MARK: Secure backup setup + +// Intro + +"secure_key_backup_setup_intro_title" = "Veilige Back-up"; +"service_terms_modal_policy_checkbox_accessibility_hint" = "Aanvinken om te aanvaarden %@"; +"service_terms_modal_message_identity_server" = "Aanvaard de gebruikersvoorwaarden van de identiteitsserver (%@), om contacten te vinden."; + +// Service terms - Variant for identity server when displayed out of a context +"service_terms_modal_title_identity_server" = "Contacten ontdekken"; +"service_terms_modal_description_for_identity_server_2" = "Wees vindbaar via telefoonnummer of e-mailadres"; +"service_terms_modal_description_for_identity_server_1" = "Vind anderen via telefoonnummer of e-mailadres"; +"service_terms_modal_decline_button" = "Weigeren"; +"room_widget_permission_room_id_permission" = "Gespreks-ID"; +"room_widget_permission_widget_id_permission" = "Widget-ID"; +"room_widget_permission_theme_permission" = "Uw thema"; +"room_widget_permission_user_id_permission" = "Uw gebruikers-ID"; +"room_widget_permission_avatar_url_permission" = "Uw profielfoto-URL"; +"room_widget_permission_display_name_permission" = "Uw weergavenaam"; +"room_widget_permission_information_title" = "Dit gebruiken kan gegevens delen met %@:\n"; +"room_widget_permission_webview_information_title" = "Dit gebruiken kan cookies toevoegen en gegevens delen met %@:\n"; +"room_widget_permission_creator_info_title" = "Deze widget is toegevoegd door:"; + +// Room widget permissions +"room_widget_permission_title" = "Widget laden"; +"widget_picker_manage_integrations" = "Beheer integraties…"; +"widget_integration_manager_disabled" = "U moet een integratebeheerder inschakelen in uw instellingen"; +"widget_menu_remove" = "Verwijderen voor iedereen"; +"widget_menu_revoke_permission" = "Toegang intrekken voor mij"; +"widget_menu_open_outside" = "Openen in browser"; +"widget_menu_refresh" = "Herladen"; +"bug_report_background_mode" = "Op de achtergrond doorgaan"; +"call_actions_unhold" = "Hervatten"; +"call_no_stun_server_error_use_fallback_button" = "Probeer %@ te gebruiken"; +"call_no_stun_server_error_message_2" = "U kunt ook de publieke server op %@ gebruiken, maar dit zal minder betrouwbaar zijn, en zal uw IP-adres met die server delen. U kunt dit ook beheren in de Instellingen"; +"call_no_stun_server_error_message_1" = "Vraag uw thuisserverbeheerder %@ een TURN-server te configureren teneinde oproepen betrouwbaar te doen werken."; +"call_no_stun_server_error_title" = "Oproep mislukt door verkeerd geconfigureerde server"; +"event_formatter_jitsi_widget_removed_by_you" = "U heeft een VoIP-vergadering verwijderd"; +"event_formatter_jitsi_widget_added_by_you" = "U heeft een VoIP-vergadering toegevoegd"; +"event_formatter_widget_removed_by_you" = "U heeft deze widget verwijderd: %@"; + +// Events formatter with you +"event_formatter_widget_added_by_you" = "U heeft deze widget toegevoegd: %@"; +"event_formatter_call_back" = "Terugbellen"; +"event_formatter_call_you_declined" = "U heeft de oproep afgewezen"; +"event_formatter_call_you_currently_in" = "U bent momenteel in deze oproep"; +"event_formatter_call_has_ended" = "Deze oproep is beëindigd"; +"event_formatter_call_video" = "Video-oproep"; +"event_formatter_call_voice" = "Audio-oproep"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "Versleuteling is hier niet ingeschakeld."; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "Versleuteling is hier ingeschakeld"; +"room_details_advanced_room_id_for_dm" = "ID:"; +"room_details_no_local_addresses_for_dm" = "Dit heeft geen lokaaladres"; +"room_details_access_section_directory_toggle_for_dm" = "Weergeven in publieke groepsgesprekkencatalogus"; +"room_details_access_section_anyone_for_dm" = "Iedereen die de koppeling kent, inclusief gasten"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "Iedereen die de koppeling kent, behalve gasten"; +"room_details_access_section_for_dm" = "Wie mag toegang hebben?"; +"room_details_room_name_for_dm" = "Naam"; +"room_details_photo_for_dm" = "Foto"; +"room_details_title_for_dm" = "Details"; +"identity_server_settings_alert_error_invalid_identity_server" = "%@ is geen geldige identiteitsserver."; +"identity_server_settings_alert_error_terms_not_accepted" = "U moet de voorwaarden van %@ aanvaarden om deze als identiteitsserver in te stellen."; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Verbinding toch verbreken"; +"identity_server_settings_alert_disconnect_still_sharing_3pid" = "U deelt nog persoonlijke gegevens op de identiteitsserver %@.\n\nVoordat u de verbinding verbreekt wordt het u aangeraden uw e-mailadressen en telefoonnummers van de identiteitsserver te verwijderen."; +"identity_server_settings_alert_disconnect_button" = "Verbinding verbreken"; +"identity_server_settings_alert_disconnect" = "Wilt u de verbinding met de identiteitsserver %@ verbreken?"; +"identity_server_settings_alert_disconnect_title" = "Verbinding met identiteitsserver verbreken"; +"identity_server_settings_alert_change" = "Verbinding met identiteitsserver %1$@ verbreken en in plaats daarvan verbinden met %2$@?"; +"identity_server_settings_alert_change_title" = "Identiteitsserver wisselen"; +"identity_server_settings_alert_no_terms" = "De door u gekozen identiteitsserver heeft geen dienstvoorwaarden. Ga alleen door, wanneer u de eigenaar van de server vertrouwd."; +"identity_server_settings_alert_no_terms_title" = "De identiteitsserver heeft geen dienstvoorwaarden"; +"identity_server_settings_disconnect" = "Verbinding verbreken"; +"identity_server_settings_disconnect_info" = "De verbinding met uw identiteitsserver verbreken zal ertoe leiden dat u niet door andere gebruikers gevonden zal kunnen worden, en dat u anderen niet via e-mail of telefoon zal kunnen uitnodigen."; +"identity_server_settings_change" = "Wijzigen"; +"identity_server_settings_add" = "Toevoegen"; +"identity_server_settings_place_holder" = "Voer een identiteitsserver in"; +"identity_server_settings_no_is_description" = "U gebruikt momenteel geen identiteitsserver. Voeg er hierboven één toe om bekenden te kunnen vinden en voor hen vindbaar te zijn."; +"identity_server_settings_description" = "U gebruikt momenteel %@ om gevonden te kunnen worden en bestaande contacten te ontdekken."; + +// Identity server settings +"identity_server_settings_title" = "Identiteitsserver"; + +// AuthenticatedSessionViewControllerFactory +"authenticated_session_flow_not_supported" = "Deze app ondersteunt de verificatiemethode op uw homeserver niet."; +"manage_session_sign_out" = "Deze sessie afmelden"; +"manage_session_not_trusted" = "Niet vertrouwd"; +"manage_session_trusted" = "Door u vertrouwd"; +"manage_session_name" = "Sessienaam"; +"manage_session_info" = "SESSIE INFO"; + +// Manage session +"manage_session_title" = "Beheer sessie"; +"security_settings_user_password_description" = "Bevestig uw identiteit door uw accountwachtwoord in te voeren"; +"security_settings_coming_soon" = "Sorry. Deze actie is nog niet beschikbaar in Element iOS. Gebruik een andere Matrix-app om het in te stellen. Element iOS zal het dan wel gebruiken."; +"security_settings_complete_security_alert_message" = "U moet de beveiliging van uw huidige sessie nog afronden."; +"security_settings_complete_security_alert_title" = "Beveiliging afronden"; +"security_settings_blacklist_unverified_devices_description" = "Verifieer alle sessies van een gebruiker om deze als vertrouwd te markeren en berichten naar te zenden."; +"security_settings_blacklist_unverified_devices" = "Verzend nooit berichten naar niet-vertrouwde sessies"; +"security_settings_advanced" = "GEAVANCEERD"; +"security_settings_export_keys_manually" = "Exporteer sleutels handmatig"; +"security_settings_cryptography" = "CRYPTOGRAFIE"; +"security_settings_crosssigning_complete_security" = "Beveiliging afronden"; +"security_settings_crosssigning_reset" = "Kruislings ondertekenen resetten"; +"security_settings_crosssigning_bootstrap" = "Kruislings ondertekenen instellen"; +"security_settings_crosssigning_info_ok" = "Kruislings ondertekenen is ingeschakeld."; +"security_settings_crosssigning_info_trusted" = "Kruislings ondertekenen is ingeschakeld. U kunt andere personen en sessies verifiëren met kruislings ondertekenen, maar u kunt dit nog niet vanaf deze sessie doordat de versleutelingssleutel ontbreekt. Rond de beveiliging van deze sessie af."; +"security_settings_crosssigning_info_exists" = "Uw account heeft een kruislings ondertekenen ID, maar is nog niet geverifieerd door deze sessie. Rond de beveiliging van deze sessie af."; +"security_settings_crosssigning_info_not_bootstrapped" = "Kruislings ondertekenen is nog niet ingesteld."; +"security_settings_crosssigning" = "KRUISLINGS ONDERTEKENEN"; +"security_settings_backup" = "BERICHTENBACK-UP"; +"security_settings_secure_backup_delete" = "Verwijderen"; +"security_settings_secure_backup_synchronise" = "Synchroniseren"; +"security_settings_secure_backup_setup" = "Instellen"; +"security_settings_secure_backup_description" = "Een waarborg voor toegang tot uw versleutelde berichten & data door de versleutelingssleutels op te slaan op uw server."; +"security_settings_secure_backup" = "VEILIGE BACK-UP"; +"security_settings_crypto_sessions_description_2" = "Als u deze inlog niet herkent, verander uw wachtwoord en reset uw Veilige Back-up."; +"security_settings_crypto_sessions_loading" = "Sessies laden…"; +"security_settings_crypto_sessions" = "MIJN SESSIES"; + +// Security settings +"security_settings_title" = "Beveiliging"; +"settings_show_NSFW_public_rooms" = "NSFW openbare gesprekken weergeven"; +"settings_identity_server_no_is_description" = "U gebruikt momenteel geen identiteitsserver. Voeg er hierboven één toe om bekenden te kunnen vinden en voor hen vindbaar te zijn."; +"settings_identity_server_no_is" = "Geen identiteitsserver geconfigureerd"; +"settings_identity_server_description" = "Met de hierboven ingestelde identiteitsserver kan u uw contacten vinden en bent u vindbaar voor uw contacten."; +"settings_discovery_three_pid_details_enter_sms_code_action" = "SMS-activeringscode invoeren"; +"settings_discovery_three_pid_details_cancel_email_validation_action" = "E-mailbevestiging afbreken"; +"settings_discovery_three_pid_details_revoke_action" = "Intrekken"; +"settings_discovery_three_pid_details_share_action" = "Delen"; +"settings_discovery_three_pid_details_information_phone_number" = "Beheer de voorkeuren voor dit telefoonnummer, dat andere gebruikers kunnen gebruiken om u te vinden en u uit te nodigen tot gesprekken. Telefoonnummers toevoegen of verwijderen in Accounts."; +"settings_discovery_three_pid_details_title_phone_number" = "Beheer telefoonnummer"; +"settings_discovery_three_pid_details_information_email" = "Beheer de voorkeuren voor dit e-mailadres, dat andere gebruikers kunnen gebruiken om u te vinden en u uit te nodigen tot gesprekken. E-mailadressen toevoegen of verwijderen in Accounts."; +"settings_discovery_three_pid_details_title_email" = "E-mail beheren"; +"settings_discovery_error_message" = "Er is een fout opgetreden. Probeer het opnieuw."; +"settings_discovery_three_pids_management_information_part3" = "."; +"settings_discovery_three_pids_management_information_part2" = "Gebruikersinstellingen"; +"settings_discovery_three_pids_management_information_part1" = "Beheer e-mailadressen en telefoonnummers die andere gebruikers kunnen gebruiken om u te vinden en u uit te nodigen voor een gesprekken. E-mailadressen of telefoonnummers toevoegen of verwijderen van deze lijst kan in "; +"settings_discovery_terms_not_signed" = "Aanvaard de gebruikersvoorwaarden van de identiteitsserver (%@) om vindbaar te zijn op e-mailadres of telefoonnummer."; +"settings_discovery_no_identity_server" = "U gebruikt momenteel geen identiteitsserver. Om door de u bekende contacten vindbaar te zijn, voeg er een toe."; +"settings_devices_description" = "De publieke naam van een sessie is zichtbaar voor de personen waarmee u communiceert"; +"settings_add_3pid_invalid_password_message" = "Ongeldig wachtwoord"; +"settings_add_3pid_password_message" = "Geef uw wachtwoord om verder te gaan"; +"settings_add_3pid_password_title_msidsn" = "Telefoonnummer toevoegen"; +"settings_add_3pid_password_title_email" = "E-mailadres toevoegen"; +"settings_integrations_allow_description" = "Gebruik een integratiebeheerder om bots, bruggen, widgets en stickerpakketten te beheren.\n\nIntegratiebeheerders ontvangen configuratiedata en kunnen widgets aanpassen, gespreksuitnodigingen versturen en bestuursniveaus instellen namens u."; +"settings_integrations_allow_button" = "Beheer integraties"; +"settings_calls_stun_server_fallback_description" = "Sta de terugvalserver voor oproepbijstand %@ toe wanneer uw homeserver er geen aanbiedt (uw IP-adres wordt gedeeld gedurende een oproep)."; +"settings_calls_stun_server_fallback_button" = "Terugvalserver voor oproepen toestaan"; +"settings_security" = "BEVEILIGING"; +"settings_three_pids_management_information_part3" = "."; +"settings_three_pids_management_information_part2" = "Ontdekken"; +"settings_three_pids_management_information_part1" = "Beheer hier de e-mailadressen en telefoonnummers die u kunt gebruiken om zich aan te melden, of om uw account te herstellen. Controleer wie u vinden kan in "; +"settings_integrations" = "INTEGRATIES"; +"settings_identity_server_settings" = "IDENTITEITSSERVER"; +"settings_discovery_settings" = "ONTDEKKEN"; +"external_link_confirmation_message" = "Deze koppeling %@ brengt u naar een andere website: %@\n\nWeet u zeker dat u door wilt gaan?"; +"external_link_confirmation_title" = "Controleer deze koppeling"; +"room_open_dialpad" = "Kiestoetsen"; +"room_place_voice_call" = "Audio-oproep"; +"room_event_action_delete_confirmation_message" = "Weet u zeker dat u alle niet verzonden berichten wilt verwijderen?"; +"room_event_action_delete_confirmation_title" = "Niet verzonden berichten verwijderen"; +"room_unsent_messages_cancel_message" = "Weet u zeker dat u alle niet verzonden berichten in dit gesprek wilt verwijderen?"; +"room_unsent_messages_cancel_title" = "Niet verzonden berichten verwijderen"; +"room_member_power_level_short_custom" = "Aangepast"; +"room_member_power_level_short_moderator" = "Mod"; +"room_member_power_level_short_admin" = "Beheerder"; +"room_member_power_level_custom_in" = "Aangepast (%@) in %@"; +"room_member_power_level_moderator_in" = "Moderator in %@"; +"room_member_power_level_admin_in" = "Beheerder in %@"; +"room_participants_security_information_room_encrypted_for_dm" = "Berichten zijn hier eind-tot-eind versleuteld.\n\nUw berichten zijn met een digitale sleutel beveiligd, alleen u en de ontvanger hebben de unieke sleutels om deze berichten te ontgrendelen."; +"room_participants_security_information_room_encrypted" = "Berichten in dit gesprek zijn eind-tot-eind versleuteld.\n\nUw berichten zijn met een digitale sleutel beveiligd, alleen u en de ontvanger hebben de unieke sleutels om deze berichten te ontgrendelen."; +"room_participants_security_information_room_not_encrypted_for_dm" = "Berichten zijn hier niet eind-tot-eind versleuteld."; +"room_participants_security_information_room_not_encrypted" = "Berichten in dit gesprek zijn niet eind-tot-eind versleuteld."; +"room_participants_security_loading" = "Laden…"; +"room_participants_action_security_status_loading" = "Laden…"; +"room_participants_action_security_status_warning" = "Waarschuwing"; +"room_participants_action_security_status_complete_security" = "Complete beveiliging"; +"room_participants_action_security_status_verify" = "Verifiëren"; +"room_participants_action_security_status_verified" = "Geverifieerd"; +"room_participants_action_section_security" = "Beveiliging"; +"room_participants_filter_room_members_for_dm" = "Deelnemers filteren"; +"room_participants_leave_prompt_msg_for_dm" = "Weet u zeker dat u het gesprek wilt verlaten?"; +"room_participants_leave_prompt_title_for_dm" = "Verlaten"; +"contacts_address_book_no_identity_server" = "Geen identiteitsserver geconfigureerd"; +"rooms_empty_view_information" = "Groepsgesprekken zijn geschikt voor alle gesprekken, privé of publiek. Klik op de + om de bestaande groepen te verkennen of maak een nieuwe."; +"rooms_empty_view_title" = "Gesprekken"; +"people_empty_view_information" = "Veilig communiceren met iedereen. Druk op + om personen toe te voegen."; +"people_empty_view_title" = "Personen"; +"social_login_button_title_sign_up" = "Registreren met %@"; +"social_login_button_title_sign_in" = "Aanmelden met %@"; +"social_login_button_title_continue" = "Doorgaan met %@"; +"social_login_list_title_sign_up" = "Of"; +"social_login_list_title_sign_in" = "Of"; + +// Social login + +"social_login_list_title_continue" = "Doorgaan met"; +"callbar_return" = "Terug"; +"callbar_only_multiple_paused" = "%@ oproepen in de wacht"; +"callbar_only_single_paused" = "Oproep in de wacht"; +"callbar_active_and_multiple_paused" = "1 oproep actief (%@) · %@ oproepen in de wacht"; +"callbar_active_and_single_paused" = "1 oproep actief (%@) · 1 oproep in de wacht"; + +// Call Bar +"callbar_only_single_active" = "Oproep actief (%@)"; +"less" = "Minder"; +"more" = "Meer"; +"switch" = "Wissel"; +"joined" = "Toegetreden"; +"store_promotional_text" = "Privacy-beschermende chat- en samenwerkingsapp, op een open netwerk. Gedecentraliseerd, zodat u de controle hebt. Geen datamining, geen achterdeurtjes en geen toegang voor derden."; diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index a2582a618..b94a62387 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -210,8 +210,8 @@ "room_message_short_placeholder" = "Digite uma mensagem…"; "room_message_reply_to_short_placeholder" = "Digite sua resposta…"; "room_offline_notification" = "A conectividade com o servidor foi perdida."; -"room_unsent_messages_notification" = "Mensagens não enviadas. %@ ou %@ agora?"; -"room_unsent_messages_unknown_devices_notification" = "Mensagem não enviada devido à presença de sessões desconhecidas. %@ ou %@ agora?"; +"room_unsent_messages_notification" = "Falha ao enviar mensagens."; +"room_unsent_messages_unknown_devices_notification" = "Mensagem não enviada devido à presença de sessões desconhecidas."; "room_ongoing_conference_call" = "Chamada em grupo em andamento. Junte-se como %@ ou %@."; "room_ongoing_conference_call_with_close" = "Chamada em grupo em andamento. Junte-se como %@ ou %@. %@ isto."; "room_ongoing_conference_call_close" = "Fechar"; @@ -861,7 +861,7 @@ "settings_labs_message_reaction" = "Adicionar reações em mensagens"; "settings_add_3pid_password_title_msidsn" = "Adicionar número de telefone"; "settings_add_3pid_password_message" = "Para continuar, por favor, digite sua senha"; -"settings_add_3pid_invalid_password_message" = "Senha inválida"; +"settings_add_3pid_invalid_password_message" = "Credenciais inválidas"; "settings_key_backup_button_connect" = "Autorize esta sessão a fazer o backup de chaves"; "settings_discovery_no_identity_server" = "No momento, você não está usando um servidor de identidade. Para descobrir e ser descoberto pelos contatos existentes, adicione um abaixo."; "settings_discovery_error_message" = "Um erro ocorreu. Por favor, tente novamente mais tarde."; @@ -1260,9 +1260,61 @@ "social_login_button_title_sign_up" = "Registrar-se com %@"; "social_login_button_title_sign_in" = "Entrar com %@"; "social_login_button_title_continue" = "Continuar com %@"; -"social_login_list_title_sign_up" = "Ou registrar-se com"; -"social_login_list_title_sign_in" = "Ou entrar com"; +"social_login_list_title_sign_up" = "Ou"; +"social_login_list_title_sign_in" = "Ou"; // Social login "social_login_list_title_continue" = "Continuar com"; +"room_avatar_view_accessibility_hint" = "Alterar a imagem da sala"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "imagem"; +"call_transfer_contacts_all" = "Todos"; +"call_transfer_contacts_recent" = "Recente"; +"call_transfer_users" = "Pessoas"; +"event_formatter_call_has_ended" = "Essa chamada foi encerrada"; +"room_intro_cell_information_multiple_dm_sentence2" = "Somente vocês estão nesta conversa, ao menos até que convidem alguém para participar."; +"room_intro_cell_information_dm_sentence2" = "Apenas vocês dois/duas estão nesta conversa, ninguém mais pode entrar."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Este é o início de sua conversa com "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " para que as pessoas saibam do que se trata essa sala."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Adicionar uma descrição"; +"room_intro_cell_information_room_with_topic_sentence2" = "Descrição: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Este é o começo de "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Adicionar pessoas"; +"call_transfer_error_message" = "Falha ao transferir a chamada"; +"call_transfer_error_title" = "Erro"; +"call_transfer_dialpad" = "Teclado de discagem"; + +// MARK: - Call Transfer +"call_transfer_title" = "Transferir"; + +// MARK: - Dial Pad +"dialpad_title" = "Teclado de discagem"; +"call_actions_unhold" = "Retomar"; +"event_formatter_call_back" = "Ligar de volta"; +"event_formatter_call_you_declined" = "Você recusou esta chamada"; +"event_formatter_call_you_currently_in" = "Você está nesta chamada"; +"event_formatter_call_video" = "Chamada de vídeo"; +"event_formatter_call_voice" = "Chamada de voz"; +"settings_show_NSFW_public_rooms" = "Exibir salas públicas com conteúdo sensível"; +"room_open_dialpad" = "Teclado de discagem"; +"room_place_voice_call" = "Chamada de voz"; +"room_event_action_delete_confirmation_message" = "Tem certeza de que deseja excluir esta mensagem não enviada?"; +"room_event_action_delete_confirmation_title" = "Excluir mensagem não enviada"; +"room_unsent_messages_cancel_message" = "Tem certeza de que deseja excluir todas as mensagens não enviadas nesta sala?"; +"room_unsent_messages_cancel_title" = "Excluir mensagens não enviadas"; +"callbar_return" = "Retornar"; +"callbar_only_multiple_paused" = "%@ chamadas pausadas"; +"callbar_only_single_paused" = "Chamada pausada"; +"callbar_active_and_multiple_paused" = "1 chamada em andamento (%@) · %@ chamadas pausadas"; +"callbar_active_and_single_paused" = "1 chamada em andamento (%@) · 1 chamada pausada"; + +// Call Bar +"callbar_only_single_active" = "Chamada em andamento (%@)"; diff --git a/Riot/Assets/sv.lproj/Vector.strings b/Riot/Assets/sv.lproj/Vector.strings index 5da224c27..00dcf0e4c 100644 --- a/Riot/Assets/sv.lproj/Vector.strings +++ b/Riot/Assets/sv.lproj/Vector.strings @@ -340,7 +340,7 @@ "settings_add_3pid_password_title_email" = "Lägg till e-postadress"; "settings_add_3pid_password_title_msidsn" = "Lägg till telefonnummer"; "settings_add_3pid_password_message" = "För att fortsätta, ange ditt lösenord"; -"settings_add_3pid_invalid_password_message" = "Ogiltigt lösenord"; +"settings_add_3pid_invalid_password_message" = "Ogiltiga uppgifter"; "settings_crypto_export" = "Exportera nycklar"; "settings_crypto_blacklist_unverified_devices" = "Kryptera endast till verifierade sessioner"; "settings_deactivate_my_account" = "Inaktivera mitt konto"; @@ -438,7 +438,7 @@ "room_participants_security_information_room_encrypted" = "Meddelanden i det här rummet är totalsträckskrypterade.\n\nDina meddelanden är säkrade med lås och bara du och mottagaren har de unika nycklarna för att låsa upp dem."; "room_accessiblity_scroll_to_bottom" = "Scrolla till botten"; "room_do_not_have_permission_to_post" = "Du har inte behörighet att posta till det här rummet"; -"room_unsent_messages_notification" = "Meddelanden skickades inte. %@ eller %@ nu?"; +"room_unsent_messages_notification" = "Meddelanden misslyckades att skickas."; "room_conference_call_no_power" = "Du behöver behörighet för att hantera gruppsamtal i det här rummet"; "room_prompt_resend" = "Skicka alla igen"; "room_accessibility_call" = "Ring"; @@ -641,7 +641,7 @@ "group_section" = "GEMENSKAPER"; "directory_search_fail" = "Misslyckades att hämta data"; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Ingen identitetsserver är konfigurerad så du kan inte starta en chatt med en kontakt med en e-postadress."; -"room_unsent_messages_unknown_devices_notification" = "Meddelandet skickades inte eftersom okända sessioner var närvarande. %@ eller %@ nu?"; +"room_unsent_messages_unknown_devices_notification" = "Meddelandet misslyckades att skickas eftersom okända sessioner var närvarande."; "room_resend_unsent_messages" = "Skicka oskickade meddelanden igen"; "room_warning_about_encryption" = "Totalsträckskryptering är i beta, och kanske inte är pålitligt.\n\nDu bör inte ännu lita på att den säkrar data.\n\nEnheter kommer inte att kunna avkryptera historik från innan de gick med i rummet.\n\nKrypterade meddelanden kommer inte vara synliga på klienter som inte ännu stöder kryptering."; "room_resource_limit_exceeded_message_contact_1" = " Vänligen "; @@ -1228,9 +1228,61 @@ "social_login_button_title_sign_up" = "Skapa konto med %@"; "social_login_button_title_sign_in" = "Logga in med %@"; "social_login_button_title_continue" = "Fortsätt med %@"; -"social_login_list_title_sign_up" = "Eller registrera med"; -"social_login_list_title_sign_in" = "Eller logga in med"; +"social_login_list_title_sign_up" = "Eller"; +"social_login_list_title_sign_in" = "Eller"; // Social login "social_login_list_title_continue" = "Fortsätt med"; +"room_intro_cell_information_multiple_dm_sentence2" = "Bara ni är i den här konversationen, om inte nån av er bjuder in nån att gå med."; +"room_intro_cell_information_dm_sentence2" = "Bara ni två är i den här konversationen, ingen annan kan gå med."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Det här är början på ditt direktmeddelande med "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " för att låta folk veta vad rummet handlar om."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Lägg till ett ämne"; +"room_intro_cell_information_room_with_topic_sentence2" = "Ämne: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Detta är början på "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Lägg till personer"; +"room_avatar_view_accessibility_hint" = "Byt rumsavatar"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "avatar"; +"call_transfer_error_message" = "Samtalsöverföring misslyckades"; +"call_transfer_error_title" = "Fel"; +"call_transfer_contacts_all" = "Alla"; +"call_transfer_contacts_recent" = "Nyliga"; +"call_transfer_dialpad" = "Knappsats"; +"call_transfer_users" = "Användare"; + +// MARK: - Call Transfer +"call_transfer_title" = "Överför"; + +// MARK: - Dial Pad +"dialpad_title" = "Knappsats"; +"call_actions_unhold" = "Återuppta"; +"event_formatter_call_back" = "Ring tillbaka"; +"event_formatter_call_you_declined" = "Du avslog det här samtalet"; +"event_formatter_call_you_currently_in" = "Du är för närvarande i det här samtalet"; +"event_formatter_call_has_ended" = "Det här samtalet har avslutats"; +"event_formatter_call_video" = "Videosamtal"; +"event_formatter_call_voice" = "Röstsamtal"; +"settings_show_NSFW_public_rooms" = "Visa NSFW offentliga rum"; +"room_open_dialpad" = "Knappsats"; +"room_place_voice_call" = "Röstsamtal"; +"room_event_action_delete_confirmation_message" = "Är du säker på att du vill radera det här oskickade meddelandet?"; +"room_event_action_delete_confirmation_title" = "Radera oskickat meddelande"; +"room_unsent_messages_cancel_message" = "Är du säker på att du vill radera alla oskickade meddelanden i det här rummet?"; +"room_unsent_messages_cancel_title" = "Radera oskickade meddelanden"; +"callbar_return" = "Återgå"; +"callbar_only_multiple_paused" = "%@ pausade samtal"; +"callbar_only_single_paused" = "Pausat samtal"; +"callbar_active_and_multiple_paused" = "1 aktivt samtal (%@) · %@ pausade samtal"; +"callbar_active_and_single_paused" = "1 aktivt samtal (%@) · 1 pausat samtal"; + +// Call Bar +"callbar_only_single_active" = "Aktivt samtal (%@)"; diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings index 56ac63b7b..0eb951189 100644 --- a/Riot/Assets/uk.lproj/Vector.strings +++ b/Riot/Assets/uk.lproj/Vector.strings @@ -165,11 +165,11 @@ "client_android_name" = "Element Android"; "store_promotional_text" = "Додаток для чату та сумісної роботи, що зберігає конфіденційність у відкритій мережі. Децентралізований, щоб надати вам контроль над даними. Без обробки даних, без бекдорів, без доступу для третіх сторін."; "settings_three_pids_management_information_part3" = "."; -"settings_three_pids_management_information_part1" = "Керування адресами електронної пошти чи номерами телефонів, які ви можете використовувати для входу або відновлення акаунту. Контролюйте хто і як може вас знайти "; +"settings_three_pids_management_information_part1" = "Керуйте звідси адресами е-пошти чи номерами телефонів, які можна застосовувати для входу або відновлення облікового запису. Контролюйте хто і як може вас знайти "; "contacts_address_book_no_identity_server" = "Сервер ідентифікації не налаштований"; "auth_autodiscover_invalid_response" = "Неправильна відповідь виявлення домашнього сервера"; "settings_key_backup" = "РЕЗЕРВНА КОПІЯ КЛЮЧІВ"; -"settings_deactivate_account" = "ДЕАКТИВУВАТИ АКАУНТ"; +"settings_deactivate_account" = "ДЕАКТИВУВАТИ ОБЛІКОВИЙ ЗАПИС"; "group_section" = "СПІЛЬНОТИ"; // Groups tab @@ -268,8 +268,8 @@ "people_empty_view_title" = "Люди"; "social_login_button_title_sign_up" = "Приєднатися через %@"; "social_login_button_title_sign_in" = "Увійти через %@"; -"social_login_list_title_sign_up" = "Або зареєструватися через"; -"social_login_list_title_sign_in" = "Або увійти через"; +"social_login_list_title_sign_up" = "Або"; +"social_login_list_title_sign_in" = "Або"; "settings_discovery_three_pid_details_revoke_action" = "Відкликати"; "settings_discovery_three_pid_details_share_action" = "Поділитися"; "room_event_action_share" = "Поділитися"; @@ -282,3 +282,9 @@ "room_event_action_more" = "Більше"; "more" = "Більше"; "joined" = "Долучається"; +"secrets_setup_recovery_key_export_action" = "Зберегти"; +"room_event_action_save" = "Зберегти"; +"room_event_action_delete" = "Видалити"; +"security_settings_secure_backup_delete" = "Видалити"; +"security_settings_secure_backup_synchronise" = "Синхронізувати"; +"security_settings_secure_backup_setup" = "Налаштувати"; From d62af868443bf497e6c6a15342cccc2a4d4aba9b Mon Sep 17 00:00:00 2001 From: Element Translate Bot Date: Wed, 24 Mar 2021 14:45:34 +0100 Subject: [PATCH 015/140] Translated using Weblate (Spanish) (#4142) Currently translated at 100.0% (6 of 6 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/es/ Co-authored-by: Ricardo Co-authored-by: Weblate --- Riot/Assets/es.lproj/InfoPlist.strings | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/es.lproj/InfoPlist.strings b/Riot/Assets/es.lproj/InfoPlist.strings index d1bc05247..0a79c4758 100644 --- a/Riot/Assets/es.lproj/InfoPlist.strings +++ b/Riot/Assets/es.lproj/InfoPlist.strings @@ -2,4 +2,6 @@ "NSCameraUsageDescription" = "La cámara se utiliza para tomar fotos y vídeos, realizar llamadas de vídeo."; "NSPhotoLibraryUsageDescription" = "La biblioteca de fotos se utiliza para enviar fotos y vídeos."; "NSMicrophoneUsageDescription" = "El micrófono se utiliza para tomar vídeos, realizar llamadas."; -"NSContactsUsageDescription" = "Para mostrarte cuáles de tus contactos ya utilizan Element o Matrix, podemos enviar las direcciones de correo electrónico y números telefónicos de tu agenda de contactos a tu Servidor de Identidad de Matrix. New Vector no almacena estos datos ni los utiliza para ningún otro propósito. Para obtener más información, por favor consulta la página de política de privacidad en los ajustes de la aplicación."; +"NSContactsUsageDescription" = "Para mostrarte cuáles de tus contactos ya utilizan Matrix, Element puede enviar las direcciones de correo electrónico y números telefónicos de tu agenda de contactos a tu Servidor de Identidad de Matrix. En los casos que se puede, tu información personal se cifra antes de ser enviada - por favor consulta la política de privacidad de tu Servidor de Identidad."; +"NSFaceIDUsageDescription" = "Face ID se usa para acceder a tu aplicación."; +"NSCalendarsUsageDescription" = "Mostrar tus reuniones en la aplicación."; From 42a5862b21d8894ee1d77d6c91f477b85994a35a Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 24 Mar 2021 16:51:51 +0100 Subject: [PATCH 016/140] version++ --- CHANGES.rst | 5 ++++- Podfile | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 0451ab993..a37276553 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -Changes to be released in next version +Changes in 1.2.7 (2021-03-24) ================================================= ✨ Features @@ -25,6 +25,9 @@ Changes to be released in next version Others * +Improvements: + * Upgrade MatrixKit version ([v0.14.6](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.14.6)). + Changes in 1.2.6 (2021-03-11) ================================================= diff --git a/Podfile b/Podfile index b8a686acb..4b19feccf 100644 --- a/Podfile +++ b/Podfile @@ -11,7 +11,7 @@ use_frameworks! # - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixKitVersion = '= 0.14.5' +$matrixKitVersion = '= 0.14.6' # $matrixKitVersion = :local # $matrixKitVersion = {'develop' => 'develop'} From 8d82527f1b3f3681a70bf63d85e6a4bb1f94e672 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 24 Mar 2021 17:30:46 +0100 Subject: [PATCH 017/140] finish version++ --- Podfile.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 1353afc3f..c3b2e1c20 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -55,28 +55,28 @@ PODS: - MatomoTracker (7.4.1): - MatomoTracker/Core (= 7.4.1) - MatomoTracker/Core (7.4.1) - - MatrixKit (0.14.5): + - MatrixKit (0.14.6): - Down (~> 0.10.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.14.5) - - MatrixSDK (= 0.18.5) - - MatrixKit/Core (0.14.5): + - MatrixKit/Core (= 0.14.6) + - MatrixSDK (= 0.18.6) + - MatrixKit/Core (0.14.6): - Down (~> 0.10.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.18.5) - - MatrixSDK (0.18.5): - - MatrixSDK/Core (= 0.18.5) - - MatrixSDK/Core (0.18.5): + - MatrixSDK (= 0.18.6) + - MatrixSDK (0.18.6): + - MatrixSDK/Core (= 0.18.6) + - MatrixSDK/Core (0.18.6): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - OLMKit (~> 3.2.2) - Realm (= 10.7.2) - - MatrixSDK/JingleCallStack (0.18.5): + - MatrixSDK/JingleCallStack (0.18.6): - JitsiMeetSDK (= 3.2.0) - MatrixSDK/Core - OLMKit (3.2.2): @@ -115,7 +115,7 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.4.1) - - MatrixKit (= 0.14.5) + - MatrixKit (= 0.14.6) - MatrixSDK - MatrixSDK/JingleCallStack - OLMKit @@ -186,8 +186,8 @@ SPEC CHECKSUMS: LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb - MatrixKit: f77c5aa1a236331665d3b1f25ed37ed8758eb23f - MatrixSDK: 013859281629b8cccd3a8af1dec48f36335c058c + MatrixKit: 0bf9eb5a4375d829f7d8daf2b0995f630468b825 + MatrixSDK: 4437d3c4299b06954809e2eaa96f9193703e920e OLMKit: 20d1c564033a1ae7148f8f599378d4c798363905 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: e523da9ade306c5ae87e85dc09fdef148d3e1cc1 @@ -199,6 +199,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 442355a7d44d6f0b26a287702404a221cffb03f5 +PODFILE CHECKSUM: 44dae827997fc5fc1a07fabc00a4870eb94a9956 COCOAPODS: 1.10.1 From d58cfe748d4c5b56911bedea843d6ff066523a5b Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 24 Mar 2021 17:30:55 +0100 Subject: [PATCH 018/140] Prepare for new sprint --- CHANGES.rst | 24 ++++++++++++++++++++++++ Config/AppIdentifiers.xcconfig | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a37276553..1258b137c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,27 @@ +Changes to be released in next version +================================================= + +✨ Features + * + +🙌 Improvements + * + +🐛 Bugfix + * + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * + Changes in 1.2.7 (2021-03-24) ================================================= diff --git a/Config/AppIdentifiers.xcconfig b/Config/AppIdentifiers.xcconfig index d290d67fe..ebcc71705 100644 --- a/Config/AppIdentifiers.xcconfig +++ b/Config/AppIdentifiers.xcconfig @@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector APPLICATION_SCHEME = element // Version -MARKETING_VERSION = 1.2.7 -CURRENT_PROJECT_VERSION = 1.2.7 +MARKETING_VERSION = 1.2.8 +CURRENT_PROJECT_VERSION = 1.2.8 // Team From 0dbae5acc2d805a1929622949645d1c85feb7084 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 24 Mar 2021 22:17:09 +0100 Subject: [PATCH 019/140] Composer update - UI enhancements - composer max height - unread messages on scroll to bottom button - changed input toolbar background - new missed discussions notifications - Edit a message mode - Reply to a message mode - support for landscape mode --- .../input_close_icon.imageset/Contents.json | 26 ++++++ .../input_close_icon.png | Bin 0 -> 324 bytes .../input_close_icon@2x.png | Bin 0 -> 429 bytes .../input_close_icon@3x.png | Bin 0 -> 528 bytes .../input_edit_icon.imageset/Contents.json | 26 ++++++ .../input_edit_icon.png | Bin 0 -> 304 bytes .../input_edit_icon@2x.png | Bin 0 -> 465 bytes .../input_edit_icon@3x.png | Bin 0 -> 635 bytes .../input_reply_icon.imageset/Contents.json | 26 ++++++ .../input_reply_icon.png | Bin 0 -> 299 bytes .../input_reply_icon@2x.png | Bin 0 -> 463 bytes .../input_reply_icon@3x.png | Bin 0 -> 604 bytes Riot/Assets/en.lproj/Vector.strings | 2 + Riot/Generated/Images.swift | 3 + Riot/Generated/Strings.swift | 8 ++ Riot/Modules/Room/RoomViewController.m | 75 ++++++++++++---- .../Views/InputToolbar/RoomInputToolbarView.h | 17 ++++ .../Views/InputToolbar/RoomInputToolbarView.m | 80 ++++++++++++++++-- .../InputToolbar/RoomInputToolbarView.xib | 55 ++++++++++-- Riot/Modules/Room/Views/Title/RoomTitleView.h | 9 ++ Riot/Modules/Room/Views/Title/RoomTitleView.m | 26 ++++++ .../Room/Views/Title/RoomTitleView.xib | 24 +++++- 22 files changed, 346 insertions(+), 31 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/input_edit_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/input_edit_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/input_edit_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@3x.png diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/Contents.json new file mode 100644 index 000000000..9c70622e2 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "input_close_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "input_close_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "input_close_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon.png b/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b78911642f1cbb888630b6f3da5ca78ca6cc90fe GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?3oVGw3ym^DWND9BhG z*=8)x>^8vnk>WYYLn#(mrC z{_OX$_1hwlBF)|JC*D1#P7Q3FJN$?+PPzKw93(z z4ayHLUrsC)l$o|YQaZosz&WQQJ1Q*2-%nq7WkHrBUuu|W;lzbb0@>oc(_YEUk_x!x z@jd>k&(ub*16SPcx@Y`9QskL>LZardO}U}#mux5WTbC~9s1T!W=zVx*ja93d-`?GV$ZYSMhX zm$84zk}bdY`zekMuu+j};+?CB4=p1vgHExZXA`#}jQP>&7~GCefSBR+_)ZA^rH!7J z3Vs3NBwHl#N|88t!a&Vi^H~Z)bsAe?duc&Tk>ue?WQFdn?z3WpR6&OuK20~gMMeMl ze)xukhw37#6<{S8c%`68f`!)#swB*UkA*i1N+pY6;3z?v1PgcJfXJ5SN2_1Jfce61 zA7FY#Q$g{E{^J35)8+Ag_b~eWc>k{J=M=a*7V2YU6nJ*#l*h=Z@GMvfYXhf9SX($& zvJ{-%1bqhlg#xdV7-RRshtbT<*KQFN?h>leEO)zhOk7$xxO(bJr95aEsUCedV59N} XDJ>Vpn|mMs00000NkvXXu0mjfd55!5 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Input/input_close_icon.imageset/input_close_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f628586d3ca0d868cbed613cbdbca89d7a96c42 GIT binary patch literal 528 zcmV+r0`L8aP)ccmr<$H;^N614)b<#GH5CQ!n!H?o!Xs8CfH5q z4Anrk{>yBd9>qYm0=abHP?QnmGY&#fNR0_a;UO>~C_EI#7lnt!_@H+B(1cIB)R-() z4-SgqqPVxdF%n?vP^x6#4rs=8`J{T#JF_yrQ(=lI{g}Se-?0*r8bFgK#Q6g`Ro0zu Sg~f&d0000H?p}L9rJOUJoASmLHGh^kR8tF!TKB(>#Y9Sd>bqPO;32I{G{| zF+GQ4ikBTn;VRi_X2t*b*ST74baN=-Tyf=G_RTj|X?oeoyr(MFT&`x{Ydd+?LAM}& z+xPg*@~Y3wKD9YW|1gwW&mH`fB_PvXdc(hc#fyBU5{_|jv6P;2xxi@NE^$nm??t200009a7bBm000&x z000&x0ZCFM@Bjb+0drDELIAGL9O(c600d`2O+f$vv5yPkq z0x=YaU;i9{Bh1nz9AR#NCqPahh=VavDFI_lz-hdIcmrLzCAl4(yIOFlH=x5*a6apDs&5nPC zU;B!b)(`$a90IVy4j@QBLx9|{kFK9pZa)!e(`fx#&NVYFDTXUQtJMCPNFys;mU9Ht zEek72olt4zgbhC@2K#rD;bL12uO=jspBun&dY#C>>PRi&BoVL!wk_<5v_X`50YVN! zg^sQ5bETF@NV5mO`+!RF$6$Mqjte( z-?irIPzsSl0JOL%X!=6KR4m1L27&w>R8QPQs39i^E4$Q_q3XGc(AE{kwq|`$P6&0d zSEL*3^!7ARP_{$3ST(pbB>?jk*5>O+BTlB1box00000NkvXX Hu0mjf)2F-X literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/input_edit_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Input/input_edit_icon.imageset/input_edit_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..4baa61fd8429df16a98d1e990851c704f788cc90 GIT binary patch literal 635 zcmV->0)+jEP)0K=o$z z4!#{89AX&;&cpwHHp_%F1NAT}ky4*Pbp2v1HgW6r-O|@D2cIv-JUCLI&ept=7S}L8 z6Tb%sYCP?}WpFCofZNgYR+tnkoPp+(&Njd`lpWW8fh`XG?M{o$wY~WvuMF|e!v1TqoQh)y+j*0P&z&DSOLtYVhEMmQu7j89B z-;P$aQbQY@Vb;34TYD&=#6BRsonZ6_+u_2*?cUDj00lLbfmZl3etRRM3M)LlzZWtf zd9BzE7nkrv14dIRbvC2#5}s&44w$rcAIjnK0FE_nfT?``@oX@Uwf}1!3((Xq@Ca9h z`h&oGa=-hoz0>_X9WJX#E|c(#mWINGE+=zKs#%s)GQe1o#|;_Ruv~p?JbpC{e52z% zf3M)}Y<>}H^1AB%fnScK)~X&cMz|cY=lSD61*hx2zS5JNRIn^DPo(JIcV0Z){|)ke V{3A8Nk>>ya002ovPDHLkV1n7x807!} literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/Contents.json new file mode 100644 index 000000000..5cbd96db1 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "input_reply_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "input_reply_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "input_reply_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon.png b/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..20bc5c0059f8b112baf04572a3983ef91cd0dbb8 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&k&H|6fVg?3oVGw3ym^DWND9BhG z)x=DLSW8ML_ zbpcIw5*JO>jtKnY=qjZ~t!=iI9JKaX)TbyiIly zc5_LcQ*hur$ zMwP3Dhqii1CcoMee{b#WrWb7-H-B#M`k_B_MQPmo{4-njZf6WrXs})AT_k)~hA%wU sbn&u9+-vT6`xi`n$Mjf`r}+i*Lavbczf^o$fqr4|boFyt=akR{0MLJNh5!Hn literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@2x.png b/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4d45eb912dcf1b24a09912563835575c2e230d91 GIT binary patch literal 463 zcmV;=0WkiFP)Pmt zgS?K31Vuh+rG5VY?9ME}hQCIpEn2o?ly|GI<-O|r^V7o%^}Xta87JXL~~QFG4Ic-XN<$(2HUA3m~W zDI87xgOCaqLGgY>gClk7XZ`KrMYA2-kv!5k?ceh3A$MKjQKff%JOd5&R?kF0Cm4{b zM4xP_Ob3_E8b@^pev+k_SSMWrGz3pW>ML@A=h3wv|3MxTZ>#YA{)W~dY2rz=LBq&C za>H&hlR?DffaJmi4VE3=QmI(Z3c7=Aat|4x1)4$0AgpGf!{o@NC;Y_jD=urkZF-sN zsJFT`1aXs`=a1%+q{_&Sm$iUj;tPYKG0Bger1*ya!6)Khn36FX@Am)z002ovPDHLk FV1iB8$4LMH literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Input/input_reply_icon.imageset/input_reply_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d9999c5e342a87869ac75da19277fb2a9f9469a2 GIT binary patch literal 604 zcmV-i0;BzjP)I2|f_5l2r1|UNc2ox0n0xkTPu6z>y4=Y?FwakO4CZ zP09ceK#vOY2{Is7C`?9kz1|jw9%KL}lSzN>#0o7#CQ@iwGND3#nH1=m)-_-1xMzFM zalrwh`q8am3{N2w$aA=}el6-=R77BvQGq(tA5{k6U-s=^h>Qq(SQ9rDrr4W#S?oWF zA6XQ(FD|hLh})y5fu1%lw z3q?tN|HvvNfv7hoRD>i#ekt1+>SR?LaVUWyjD)2KVN-hwf_*WK2z5m6$GUYo!DXWymA` z)rKsE{!R&6y_l~}E@d?tXJs^(<|rdV_si6NnUty$knuy%?aM?Te^bkla(I_1=^ String { + return VectorL10n.tr("Vector", "room_message_replying_to", p1) + } /// Send a message… internal static var roomMessageShortPlaceholder: String { return VectorL10n.tr("Vector", "room_message_short_placeholder") diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 153708745..8c6be6078 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -155,8 +155,8 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo // Missed discussions badge NSUInteger missedDiscussionsCount; NSUInteger missedHighlightCount; - UIBarButtonItem *missedDiscussionsButton; UILabel *missedDiscussionsBadgeLabel; + UIView *missedDiscussionsDotView; // Potential encryption details view. EncryptionInfoView *encryptionInfoView; @@ -446,10 +446,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo self.previewHeaderContainer.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - missedDiscussionsBadgeLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor; - missedDiscussionsBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; - missedDiscussionsBadgeLabel.backgroundColor = [UIColor clearColor]; - // Check the table view style to select its bg color. self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.bubblesTableView.separatorColor = ThemeService.shared.theme.lineBreakColor; @@ -714,6 +710,19 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinator { + if ([self.titleView isKindOfClass:RoomTitleView.class]) + { + RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView; + if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) + { + [roomTitleView updateLayoutForOrientation:UIInterfaceOrientationPortrait]; + } + else + { + [roomTitleView updateLayoutForOrientation:UIInterfaceOrientationLandscapeLeft]; + } + } + // Hide the expanded header or the preview in case of iPad and iPhone 6 plus. // On these devices, the display mode of the splitviewcontroller may change during screen rotation. // It may correspond to an overlay mode in portrait and a side-by-side mode in landscape. @@ -1135,7 +1144,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)setKeyboardHeight:(CGFloat)keyboardHeight { [super setKeyboardHeight:keyboardHeight]; - + + self.inputToolbarView.maxHeight = round(([UIScreen mainScreen].bounds.size.height - keyboardHeight) * 0.7); + // Make the activity indicator follow the keyboard // At runtime, this creates a smooth animation CGPoint activityIndicatorCenter = self.activityIndicator.center; @@ -1213,6 +1224,14 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo titleView.delegate = self; titleView.mxRoom = self.roomDataSource.room; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:titleView]; + + if ([titleView isKindOfClass:RoomTitleView.class]) + { + RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView; + missedDiscussionsBadgeLabel = roomTitleView.missedDiscussionsBadgeLabel; + missedDiscussionsDotView = roomTitleView.dotView; + [roomTitleView updateLayoutForOrientation:[UIApplication sharedApplication].statusBarOrientation]; + } [self updateViewControllerAppearanceOnRoomDataSourceState]; @@ -1305,6 +1324,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)setShowMissedDiscussionsBadge:(BOOL)showMissedDiscussionsBadge { missedDiscussionsBadgeLabel.hidden = !showMissedDiscussionsBadge; + missedDiscussionsDotView.hidden = !showMissedDiscussionsBadge; } - (void)setScrollToBottomHidden:(BOOL)scrollToBottomHidden @@ -1418,8 +1438,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self.roomDataSource.room.summary setRoomAvatarImageIn:userPictureView]; } - missedDiscussionsBadgeLabel = ((RoomTitleView*)self.titleView).missedDiscussionsBadgeLabel; - [self refreshMissedDiscussionsCount:YES]; } @@ -1468,11 +1486,28 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } } -- (void)setInputToolBarSendMode:(RoomInputToolbarViewSendMode)sendMode +- (void)setInputToolBarSendMode:(RoomInputToolbarViewSendMode)sendMode forEventWithId:(NSString *)eventId { if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:[RoomInputToolbarView class]]) { RoomInputToolbarView *roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView; + if (eventId) + { + MXEvent *event = [self.roomDataSource eventWithEventId:eventId]; + MXRoomMember * roomMember = [self.roomDataSource.roomState.members memberWithUserId:event.sender]; + if (roomMember) + { + roomInputToolbarView.eventSenderDisplayName = roomMember.displayname; + } + else + { + roomInputToolbarView.eventSenderDisplayName = event.sender; + } + } + else + { + roomInputToolbarView.eventSenderDisplayName = nil; + } roomInputToolbarView.sendMode = sendMode; } } @@ -3161,7 +3196,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)selectEventWithId:(NSString*)eventId inputToolBarSendMode:(RoomInputToolbarViewSendMode)inputToolBarSendMode showTimestamp:(BOOL)showTimestamp { - [self setInputToolBarSendMode:inputToolBarSendMode]; + [self setInputToolBarSendMode:inputToolBarSendMode forEventWithId:eventId]; customizedRoomDataSource.showBubbleDateTimeOnSelection = showTimestamp; customizedRoomDataSource.selectedEventId = eventId; @@ -3172,7 +3207,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)cancelEventSelection { - [self setInputToolBarSendMode:RoomInputToolbarViewSendModeSend]; + [self setInputToolBarSendMode:RoomInputToolbarViewSendModeSend forEventWithId:nil]; if (currentAlert) { @@ -3627,6 +3662,11 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self showMediaPickerAnimated:YES]; } +- (void)roomInputToolbarViewDidTapCancel:(MXKRoomInputToolbarView*)toolbarView +{ + [self cancelEventSelection]; +} + #pragma mark - RoomParticipantsViewControllerDelegate - (void)roomParticipantsViewController:(RoomParticipantsViewController *)roomParticipantsViewController mention:(MXRoomMember*)member @@ -4467,16 +4507,15 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo - (void)refreshMissedDiscussionsCount:(BOOL)force { // Ignore this action when no room is displayed - if (!self.roomDataSource || !missedDiscussionsBadgeLabel) + if (!self.roomDataSource || !missedDiscussionsBadgeLabel + || [UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPhone + || ([[UIScreen mainScreen] nativeBounds].size.height > 2532 && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))) { + self.showMissedDiscussionsBadge = NO; return; } - if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPhone) - { - missedDiscussionsBadgeLabel.text = nil; - return; - } + self.showMissedDiscussionsBadge = YES; NSUInteger highlightCount = 0; NSUInteger missedCount = [[AppDelegate theDelegate].masterTabBarController missedDiscussionsCount]; @@ -4523,7 +4562,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo missedDiscussionsBadgeLabel.text = [NSString stringWithFormat:@"%tu", missedCount]; } - missedDiscussionsBadgeLabel.textColor = highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.tintColor; + missedDiscussionsDotView.alpha = highlightCount == 0 ? 0 : 1; } else { diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h index c7f984803..e5559e9fe 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h @@ -59,6 +59,13 @@ typedef enum : NSUInteger */ - (void)roomInputToolbarViewDidTapMediaLibrary:(MXKRoomInputToolbarView*)toolbarView; +/** + Tells the delegate that the user wants to cancel the current edition / reply. + + @param toolbarView the room input toolbar view + */ +- (void)roomInputToolbarViewDidTapCancel:(MXKRoomInputToolbarView*)toolbarView; + @end /** @@ -84,11 +91,21 @@ typedef enum : NSUInteger @property (weak, nonatomic) IBOutlet UIImageView *inputTextBackgroundView; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputContextViewHeightConstraint; +@property (weak, nonatomic) IBOutlet UIImageView *inputContextImageView; +@property (weak, nonatomic) IBOutlet UILabel *inputContextLabel; +@property (weak, nonatomic) IBOutlet UIButton *inputContextButton; + /** Tell whether the filled data will be sent encrypted. NO by default. */ @property (nonatomic) BOOL isEncryptionEnabled; +/** + Sender of the event being edited / replied. + */ +@property (nonatomic, strong) NSString *eventSenderDisplayName; + /** Destination of the message in the composer. */ diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 80c070485..dfceba978 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -27,6 +27,8 @@ #import "WidgetManager.h" #import "IntegrationManagerViewController.h" +const double RoomInputToolbarViewContextBarHeight = 30; + @interface RoomInputToolbarView() { // The intermediate action sheet @@ -61,7 +63,8 @@ [super awakeFromNib]; _sendMode = RoomInputToolbarViewSendModeSend; - + self.inputContextViewHeightConstraint.constant = 0; + [self.rightInputToolbarButton setTitle:nil forState:UIControlStateNormal]; [self.rightInputToolbarButton setTitle:nil forState:UIControlStateHighlighted]; @@ -113,6 +116,10 @@ else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) { [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal]; } + + self.inputContextImageView.tintColor = ThemeService.shared.theme.textSecondaryColor; + self.inputContextLabel.textColor = ThemeService.shared.theme.textSecondaryColor; + self.inputContextButton.tintColor = ThemeService.shared.theme.textSecondaryColor; } #pragma mark - @@ -132,30 +139,77 @@ - (void)setSendMode:(RoomInputToolbarViewSendMode)sendMode { + RoomInputToolbarViewSendMode previousMode = _sendMode; _sendMode = sendMode; [self updatePlaceholder]; - [self updateToolbarButtonLabel]; + [self updateToolbarButtonLabelWithPreviousMode: previousMode]; } -- (void)updateToolbarButtonLabel +- (void)updateToolbarButtonLabelWithPreviousMode:(RoomInputToolbarViewSendMode)previousMode { UIImage *buttonImage; + double updatedHeight = self.mainToolbarHeightConstraint.constant; + switch (_sendMode) { case RoomInputToolbarViewSendModeReply: buttonImage = [UIImage imageNamed:@"send_icon"]; + self.inputContextImageView.image = [UIImage imageNamed:@"input_reply_icon"]; + self.inputContextLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_message_replying_to", @"Vector", nil), self.eventSenderDisplayName]; + + self.inputContextViewHeightConstraint.constant = RoomInputToolbarViewContextBarHeight; + updatedHeight += RoomInputToolbarViewContextBarHeight; + self->growingTextView.maxHeight -= RoomInputToolbarViewContextBarHeight; break; case RoomInputToolbarViewSendModeEdit: buttonImage = [UIImage imageNamed:@"save_icon"]; + self.inputContextImageView.image = [UIImage imageNamed:@"input_edit_icon"]; + self.inputContextLabel.text = NSLocalizedStringFromTable(@"room_message_editing", @"Vector", nil); + + self.inputContextViewHeightConstraint.constant = RoomInputToolbarViewContextBarHeight; + updatedHeight += RoomInputToolbarViewContextBarHeight; + self->growingTextView.maxHeight -= RoomInputToolbarViewContextBarHeight; break; default: buttonImage = [UIImage imageNamed:@"send_icon"]; + + if (previousMode != _sendMode) + { + updatedHeight -= RoomInputToolbarViewContextBarHeight; + self->growingTextView.maxHeight += RoomInputToolbarViewContextBarHeight; + } + self.inputContextViewHeightConstraint.constant = 0; break; } - + [self.rightInputToolbarButton setImage:buttonImage forState:UIControlStateNormal]; + + if (self.maxHeight && updatedHeight > self.maxHeight) + { + growingTextView.maxHeight -= updatedHeight - self.maxHeight; + updatedHeight = self.maxHeight; + } + + if (updatedHeight < self.mainToolbarMinHeightConstraint.constant) + { + updatedHeight = self.mainToolbarMinHeightConstraint.constant; + } + + if (self.mainToolbarHeightConstraint.constant != updatedHeight) + { + [UIView animateWithDuration:.3 animations:^{ + self.mainToolbarHeightConstraint.constant = updatedHeight; + [self layoutIfNeeded]; + + // Update toolbar superview + if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:heightDidChanged:completion:)]) + { + [self.delegate roomInputToolbarView:self heightDidChanged:updatedHeight completion:nil]; + } + }]; + } } - (void)updatePlaceholder @@ -213,6 +267,16 @@ self.placeholder = placeholder; } +#pragma mark - Actions + +- (IBAction)cancelAction:(id)sender +{ + if ([self.delegate respondsToSelector:@selector(roomInputToolbarViewDidTapCancel:)]) + { + [self.delegate roomInputToolbarViewDidTapCancel:self]; + } +} + #pragma mark - HPGrowingTextView delegate - (BOOL)growingTextView:(HPGrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text @@ -237,8 +301,14 @@ - (void)growingTextView:(HPGrowingTextView *)hpGrowingTextView willChangeHeight:(float)height { // Update height of the main toolbar (message composer) - CGFloat updatedHeight = height + (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant); + CGFloat updatedHeight = height + (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant) + self.inputContextViewHeightConstraint.constant; + if (self.maxHeight && updatedHeight > self.maxHeight) + { + hpGrowingTextView.maxHeight -= updatedHeight - self.maxHeight; + updatedHeight = self.maxHeight; + } + if (updatedHeight < self.mainToolbarMinHeightConstraint.constant) { updatedHeight = self.mainToolbarMinHeightConstraint.constant; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib index c8ac8203d..fbc52e9f1 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib @@ -31,23 +31,62 @@ - + + + + + + + + + + + + + + + + + + + + + + - + - + + + - + + - + @@ -88,6 +127,10 @@ + + + + @@ -102,6 +145,8 @@ + + diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.h b/Riot/Modules/Room/Views/Title/RoomTitleView.h index a96cb2d26..9769d3999 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.h @@ -40,6 +40,10 @@ @property (weak, nonatomic) IBOutlet UILabel *missedDiscussionsBadgeLabel; @property (weak, nonatomic) IBOutlet UILabel *typingLabel; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *displayNameCenterYConstraint; +@property (weak, nonatomic) IBOutlet UIView *dotView; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedDiscussionsBadgeLabelLeadingConstraint; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureViewHeightConstraint; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureViewWidthConstraint; /** The room preview data may be used when mxRoom instance is not available @@ -61,4 +65,9 @@ */ - (void)reportTapGesture:(UITapGestureRecognizer*)tapGestureRecognizer; +/** + update the layout of the title view according to the target orientation + */ +- (void)updateLayoutForOrientation:(UIInterfaceOrientation)orientation; + @end diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index b9ae630f6..37390bd80 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -47,6 +47,8 @@ [tap setDelegate:self]; [self.titleMask addGestureRecognizer:tap]; self.titleMask.userInteractionEnabled = YES; + self.dotView.layer.masksToBounds = YES; + self.dotView.layer.cornerRadius = CGRectGetMidX(self.dotView.bounds); } } @@ -85,6 +87,8 @@ self.backgroundColor = UIColor.clearColor; self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? ThemeService.shared.theme.textPrimaryColor : ThemeService.shared.theme.textSecondaryColor); self.typingLabel.textColor = ThemeService.shared.theme.textSecondaryColor; + self.dotView.backgroundColor = ThemeService.shared.theme.warningColor; + self.missedDiscussionsBadgeLabel.textColor = ThemeService.shared.theme.tintColor; } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -133,6 +137,28 @@ } } +- (void)updateLayoutForOrientation:(UIInterfaceOrientation)orientation +{ + if (UIInterfaceOrientationIsLandscape(orientation)) + { + self.missedDiscussionsBadgeLabel.font = [UIFont systemFontOfSize:10]; + self.missedDiscussionsBadgeLabelLeadingConstraint.constant = -24; + self.pictureViewWidthConstraint.constant = 28; + self.pictureViewHeightConstraint.constant = 28; + self.displayNameTextField.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + self.typingLabel.font = [UIFont systemFontOfSize:10]; + } + else + { + self.missedDiscussionsBadgeLabel.font = [UIFont systemFontOfSize:15]; + self.missedDiscussionsBadgeLabelLeadingConstraint.constant = -32; + self.pictureViewWidthConstraint.constant = 32; + self.pictureViewHeightConstraint.constant = 32; + self.displayNameTextField.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium]; + self.typingLabel.font = [UIFont systemFontOfSize:12]; + } +} + - (void)setTypingNotificationString:(NSString *)typingNotificationString { if (typingNotificationString.length > 0) diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.xib b/Riot/Modules/Room/Views/Title/RoomTitleView.xib index 0fbeea444..8280083bd 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.xib +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.xib @@ -4,6 +4,7 @@ + @@ -14,11 +15,19 @@ + + + + + + + + @@ -89,6 +104,9 @@ - + + + + From cf8117329e5e1e3b386898ca00b2a50b4628a8df Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 24 Mar 2021 23:16:27 +0100 Subject: [PATCH 020/140] Explore typing notifications inspired by web - Update for dark mode --- .../Views/BubbleCells/RoomTypingBubbleCell.swift | 12 ++++-------- .../Room/Views/BubbleCells/RoomTypingBubbleCell.xib | 8 +------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift index 60f9cb98e..b69541f88 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift @@ -36,20 +36,16 @@ class RoomTypingBubbleCell: UITableViewCell { // MARK: - Lifecycle - override func awakeFromNib() { - super.awakeFromNib() - - additionalUsersLabel?.textColor = ThemeService.shared().theme.textSecondaryColor - dotsView?.highlightedDotColor = ThemeService.shared().theme.textTertiaryColor - dotsView?.dotColor = ThemeService.shared().theme.tabBarUnselectedItemTintColor - } - override func prepareForReuse() { super.prepareForReuse() for pictureView in userPictureViews { pictureView.removeFromSuperview() } + + additionalUsersLabel?.textColor = ThemeService.shared().theme.textSecondaryColor + dotsView?.highlightedDotColor = ThemeService.shared().theme.textTertiaryColor + dotsView?.dotColor = ThemeService.shared().theme.textSecondaryColor } override func layoutSubviews() { diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.xib b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.xib index ec01f9b08..5cd15a92d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.xib +++ b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.xib @@ -4,7 +4,6 @@ - @@ -25,7 +24,7 @@ - + @@ -46,9 +45,4 @@ - - - - - From 65c67ea52b6f40cfc8baf07eaa34b452aeb5bb6d Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 25 Mar 2021 10:26:15 +0100 Subject: [PATCH 021/140] Explore typing notifications inspired by web - generated strings updated --- Riot/Generated/Strings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index dd05e41f8..0d5515a5a 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1514,7 +1514,7 @@ internal enum VectorL10n { internal static var identityServerSettingsDisconnect: String { return VectorL10n.tr("Vector", "identity_server_settings_disconnect") } - /// Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone. + /// Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone. internal static var identityServerSettingsDisconnectInfo: String { return VectorL10n.tr("Vector", "identity_server_settings_disconnect_info") } From 7fb8dc95abf5dde39084ed330d1ff3cb523395f6 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 25 Mar 2021 11:53:45 +0100 Subject: [PATCH 022/140] Explore typing notifications inspired by web - bug fixing --- Riot/Modules/Room/DataSources/RoomDataSource.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 880f6dc65..210f27c93 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -275,6 +275,8 @@ if (self.currentTypingUsers.count == 0) { + self.typingCellIndex = -1; + // we may have changed the number of bubbles in this block, consider that change return bubbles.count; } From 9bc478f6343f56c5e508a1afadf43720a1d050bd Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 25 Mar 2021 22:15:18 +0100 Subject: [PATCH 023/140] Switching composer between text mode & action mode --- .../Room/Actions/Contents.json | 6 + .../action_camera.imageset/Contents.json | 26 +++ .../action_camera.imageset/action_camera.png | Bin 0 -> 469 bytes .../action_camera@2x.png | Bin 0 -> 780 bytes .../action_camera@3x.png | Bin 0 -> 1118 bytes .../action_file.imageset/Contents.json | 26 +++ .../action_file.imageset/action_file.png | Bin 0 -> 653 bytes .../action_file.imageset/action_file@2x.png | Bin 0 -> 1269 bytes .../action_file.imageset/action_file@3x.png | Bin 0 -> 1845 bytes .../Contents.json | 26 +++ .../action_media_library.png | Bin 0 -> 519 bytes .../action_media_library@2x.png | Bin 0 -> 851 bytes .../action_media_library@3x.png | Bin 0 -> 1238 bytes .../action_sticker.imageset/Contents.json | 26 +++ .../action_sticker.png | Bin 0 -> 582 bytes .../action_sticker@2x.png | Bin 0 -> 1050 bytes .../action_sticker@3x.png | Bin 0 -> 1457 bytes Riot/Generated/Images.swift | 4 + Riot/Generated/Strings.swift | 2 +- Riot/Modules/Room/RoomViewController.m | 219 ++++++++++-------- .../Views/InputToolbar/RoomActionItem.swift | 30 +++ .../Views/InputToolbar/RoomActionsBar.swift | 129 +++++++++++ .../Views/InputToolbar/RoomInputToolbarView.h | 36 +-- .../Views/InputToolbar/RoomInputToolbarView.m | 135 ++++------- .../InputToolbar/RoomInputToolbarView.xib | 12 + 25 files changed, 467 insertions(+), 210 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/action_media_library.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/action_media_library@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/action_media_library@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@3x.png create mode 100644 Riot/Modules/Room/Views/InputToolbar/RoomActionItem.swift create mode 100644 Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift diff --git a/Riot/Assets/Images.xcassets/Room/Actions/Contents.json b/Riot/Assets/Images.xcassets/Room/Actions/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Actions/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/Contents.json new file mode 100644 index 000000000..aec39f6e4 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "action_camera.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "action_camera@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "action_camera@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera.png b/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera.png new file mode 100644 index 0000000000000000000000000000000000000000..799e2c02a34e0e95981ca836b05eb11146523f1d GIT binary patch literal 469 zcmV;`0V@89P)(3s!#c*;}R93a_= z+9S8fUHeN2@P&2%!yW{@>MjtJ1F_HFLV=)&o}{Z(jN1%4tYofuiSjlgSjc7TF%VC_tsnc z>X@5tVBBJ(s}ow&U=O19u(xRm?dyQMPIEDN;f#*TqLmp)Nz)=4;_31SN?hDwiUnZ00000 LNkvXXu0mjfO-#xO literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera@2x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_camera.imageset/action_camera@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..191b388f9587a3ecb24cbb846a02a88fff45975e GIT binary patch literal 780 zcmV+n1M~ceP))kBx-q1IYGk-+DNpBr{oPatpuE)TkR~g#%6kR=(|TLg^E@pjES9fAblZSPQ83J_Jb`_fS0Z*NHss zuSNA%1Pe4QNz!2r?!g7165tac;UuEYt}GpU4T;0VGFrebP_WVn9c+W@}$=_ekOn;B0nMJpmW)We6=aRGoAtoxa1A+{rvd_1(-76yAVBK^t@rmk$`nWTZGvVQ8qJ$; zzkcu%Ez+t$SD!uVl0qLX!UpM^TlWWOiPi+N%PP^PaN;Crmwc?k>!Y+cL<=aigw{od z_Qi3;Yo^#nOSED^&M8~#c?CK0K!soCX)i~^gtL5T{kOdi5mkofs`an6?g}Rmv1Yzu zU!S63YM0o?^Svz<&(}FIpCSG7tu);9gZ$eoi3gL+o-}@{hbQH06P#whe_@50E?r7d>@@pbX^6NK3Cm%ga2u-*(T&N|={#uJ5$G~d z(xA0s^>e`sRKrZgYMU@)zyTd&Z2mY)?7}ciIHa#go31ToI(&9lmX9-K9?p>H9Gm_TgI&f9eH7LBtc+h03?5K;o=MQ9Gu z5MdBx?w$}pN}%IKmew?G|Hei^k_f|w8QtBQW#%_a% zY!6F0>A1J4r9Z5{By+^7|Ir8 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/Contents.json new file mode 100644 index 000000000..63ec74393 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "action_file.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "action_file@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "action_file@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file.png b/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file.png new file mode 100644 index 0000000000000000000000000000000000000000..0d944b128424028f710a5f0b169375c475bc561d GIT binary patch literal 653 zcmV;80&@L{P)f8zenJf`o&3bDvOKq|zItC!l%a0g8KrniDiPpdx8O zjdzC~Z(JPPsonB~Ixn`@_V@4nJ39;TzlVT3gd6R<3Kjz*(FX!g4^1`b2+`g?_g|m? zlYoYMQYDeT^@{I=fEb1C=S2{15vy>Tk^+DBA`nW_M*2+9PLiu({-4GIdAJ~oExg>A zZw4p)?&9SrCMCAgED(FQ7AV5ey3{s=D_&<}P_V96;9<1i&fwaDlPb9RZntgjXxdnS z;i#nXoZxWY4SaydrSCXHRN_;LS9I7&;4hq9hR?b|-((}toNs$k9-d!#+y3>jR=|lq z^fEXR9c1w9F-702;0u%``$_`N*PU0OXly`gd)^%l^Mb~z(XhDi4FB!Fn-+PZ=%u#c z^cueTHe|RFWPin0^UjoN(J`tt$+D@gs-;zkPpbr0)?? zNOvhghphn=p#|22`+Mv2d+$NZ9%!LqJ{zcsl0bS|Q4(=)U-wf}c%?uV&hc(vABnwX nW%1rf7n>{?U-+XK?oIpweW0!btEzG400000NkvXXu0mjf4U{R% literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@2x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4f4522ab7be943bcede71985f74aa89bd17c54af GIT binary patch literal 1269 zcmVqHdC&x}(E>5?k!AUmL}fJEHh*OnDDT|pCx7V*^N3DHzayMo)hf?HmJ;@lOqtbi=R zA_+oVdk*I~b?}Tm_BbEqf&8Va$z{d>q`aTDzj^0+trs=ml|MR=7>)?KRWfz*QP$djwR@A2c`s)`-M>Bog?AOc5~v8< z^EVeyMUy1FfcE|C%Zl));wT=4;aP<&mz!1-PUn> zOh`Pj&EJXvHh3k`dMDGu2nPCyXxZl0V8g2W!?y(AF@|IKdAm5HETL+(r$~kAp{8x_ zMm@mrprE6VBIWe(3s-nn(C!7Ub2s9FhCgaVKm{rnKB9v3-2^HquGA?B1gr6D8^G`? z3VjN^1O1cL;8{ZGHv+|$3`pQ{gYfl-s}B9svJPb~Yj3o23=n+N75>#vR|jPkl@+%e zAV=o)iZa(q1~5Eji443zd`iQ!hw8r$eQF6F_f+`%{=*MlD1wjM4Q!;x`Fc>G$_6Cx zV5ByNm)@Tmd>k98&Qqa0%DX1jjkCO7Nh#=+EyGF%l)(q>evq2?nDLN+31s29=-ogL z{QU6z21?{?fDN7-upIbYBdKxgK^DHB`7!F1T;SvDx=bp9pT0itl+80eQ~)0ke6Ofi zs%*fz@Z2`ny!qEU{BT66(G2KH?M9-~I*<#c)L?e_Z68YD*~nSSNYA{--aquA6sNl6I|deDRr94N_t?6W*Gkc8@=d*gRDzP7%t~sQtHE# zb>IU7J`>nNXr3*Sb33iM6wO>O?vvLg6}y|N*o_Ej87lLX4kw`(IaOg+Q7fUXLH@zz z8>6T3yoE=2CskDR((q=Zm%vvIY-a<)FkCJvIyLy9^Fg=%Fhn}f$*IJ6Yu1BJW+l4; zs6OZes+GK=cwiToW{I4Xn%|`w`-m#C8z973dn@HxvWz$$_~4cA8Wh1-2<%nsfz<%Y z#T=OFyWCJJTvld2HTHP76rX1<4GEGn&sDQhRTXxldFPaL%-8>;eK7z>S+f#|dr!_z z*MX0(0>wYxprZ9?7A;pJc&kX>=$q|^+32mK()|FRDDXKw7;OV-LK)^qI<&dxBFAyT z26MKOHT)8l>}J3>49{}fkuBP4!N(oW6*5m|m%0f#KOb0l0^Xa;$x#7q(g&{l+$yT{ zfa7_IbSbdUz|9-{Jm9ugo8PP(tTwImgr?ztPnpGQQOZ1GkE9yEApS!fD^EV{!R+0( fz<1hdr-l9j#u{U2?FBcK00000NkvXXu0mjf6f$98 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@3x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_file.imageset/action_file@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..13ed744fc0e4e92f638233252e53fda390e53e23 GIT binary patch literal 1845 zcmV-52g>+~P)x*`WdL>haq^MF5Bw?6vTre2#FC8zLA2jT@#Xx!;t$sMTmM3 z1U>1#SHwWaftcIqGY~tU7q|8y2WFa}#GD}70|6^g5RA*t=l13fIAUfAN=zz_x{^T? zN)APj*hQINDkZ@%E z6ypcDI)R9pT0vuS)SnI07%AZ_@}kwt_Ai0?I&al=Jarw`&|X7`oiDGpIzYh85JVvd zSI7CwjTInW&q`9?6{1N2Oyx* z6+|azvvhKBZe>R;!|6k6bgOIyWs@TV!C_fP&ZFPoHfrB^N^h2Z7inUQdUy9g&Annc z-4A(0)`Ti4R-bft_muQtDGg*0^0=+5$kW6sC)?x9Z&Tkml4DaKUGuBbSJ3e7*(6dr zImu`V%_zP?vO8cwlJCgqSdr5*k76gT$!DnqWxYLDa>ihcS;e!lJPTHlO$JI-TLnjy zLJ;lkC9>VQCzrt^)B4wR-gJY-{Z+P(R0TN*rxi4MNG*zxV~aKva!`S+f*b_d2h~5m zTLI%k>Qnfl(T1P~l&(OgL0>_P>4m2x;)LtzqZ1&fUxfmh2FV9meGg|V=k1@5G~=_I zfd;dfrjC>b$;4t2w)9-e;Jm$YbbtJG$Vt)w8SN!=E2kgw+IrD_iZm0GrZz1*OCPcO zDmytNp{oPt8&T#QJvWkrX#ggm66a@2HT9xgwz}v*BZ$Ly+T+Z-ul5;zRW>sX+y6^nYIPSS zyf+_V6Yu78nfnlJr3WR_;eN$3awMvW1)zycVHo1EYcs1sEr=n)2TGgd0!9@7^j*@d zi$(kzEEV~v^jOPFPLc*JmXjlq2vU9Q9s}06cY?_l+#(2DGxfiAdj_qip~Uw$<11Pw zE0kTAoj?-vAka4YxyOG>9}|&Whn%qOL!>k!O*v8#P!mOcBv30Q?T0Y32>@r3Z2J&t z38X&K6$Oc)WHTfdhZ+bGZKsb77B}{llO(ryt4bit06B`O<*(hruDr<_s(tC>iquZB z^Ibgv7_SLuIA&JKL68;2;l^y=q$aAarT^U2KY#qkyC&553l_yslSw&K<1bE3?HJk@ zS*j-o;Uu}%Pj?SZ8nDi&oE7cS>F1lqhp)1f-izJX$ zz_~A0KYhQX?lNopn$uSykr?K|w!K$2d2*6DAqUh0byQKhojp>X0Ouzn6#vv}wP5U{ zk_}Qd-eewoCQ)m$6En=rOX`%mB6sWA=8sCpl*mEkE>`h|U2>hgz#M5>(*X&hrKWhshC4wTw@wF&kUmo~ituogoHG$p$Z@|AXv$nOT6p4yG=Sf`@Aq-~pfkdI%ZE;nZ?_-vlUl7X^Ay02qk&wAvX+ zn=hRdya@#Xfp?cSSNtXv2O~@1*FZ#Hq*x*Aik49pXAkr-Ol-HcuqOvk_a@`eT_>uxQz@IUCV=5PpI2hL zGg>Fks?MN9dy)hC0x*8FZo@osM0+J(u28E!f~LTah^%%L+fI{)Vs9J1c9|wM$6Iu9 z2)huFn4PG7}pW~efNXU1I&m1c+WvW0ZYx=V*H6T;A7;56nKThS8d{B<(Xb6dA;6#2oB{kBd;n=4o!Mxh`y{Dtr=>y}MZZ+p{yXvj97GJZ@NA=ksrub;j`&7^?$94T{C0-*CYz zy}919q6S3@crm!@qCf*m0KG)xR`2xI_N{9y)8sv(M1%xX2On#Wuzx`bK>_;oxIOf@ z@!%lGu?;9G?s^Qs!=vC8looO(0r;9xH7GB&U;~H$oC+ue5r&Lme|baZ!H~?C)lxh{ zp#TTZrY9ZK*J4%&7vur8K^hTCObCVOP5zy{%UFMJpwIVv9OK3Ct98Ex@iN@iY6BbG67?3 z`Ovgv5+MEf^!S}2ujk7EG)xA)S@V1sNFYEonwgD$Q7oOE0w@V!wa`_!AxoC1-|kaBC)2NF<(}bVeGj zA^N04$eF@Y3D?!WZtGMU=|PSZo(oBnqV40Gyi7_-GB;_Qe|AkO2NBAu5_i%2fhMKA ztm2v!pxg&%ir%HD3(=P_vqtaI6t=wRoi-sXRb@^_Z(l-~h;;%i?}E`T2^6qO2oJ(0 z6*jT302DXgB~=GbpMCwHM1(XcKpyxKY#1CDO6Cx`N!vSb!(HVX`$2nGlX`BTK;#}7 z?&smM;P&Pd8VO~P#x^s^Ecmyvej*R~$|NFc@{-tNR<~O0RE#WT?;M~tfK(@C{ouLS djvYJh`3o?@GrUq}Bh>%^002ovPDHLkV1l}-Yz_bb literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/action_media_library@3x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_media_library.imageset/action_media_library@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2dfd074ab0b731e1eb15eb1e57d0eac22426c876 GIT binary patch literal 1238 zcmV;{1S$K8P)f8deH)w|dOjr4mx=dw;8{L8U+l@D`p3oUyWUO!*Wt8=eY`y;Kcx^)v7ao({HZ zAW|Ikl*t7Op#Wy%0%D8utSj;fv{kd0A_j7Qb2ORccOmxxRpu9)O`}7YK#e>Q-u1*J-$;-+C*x29v3VMyEh7 z4De%b<#S`)V7Ic-viQI;O(abMVMmrAx^L=-L9_f)gfux!o@|G87O4%$&)^5~xo;gI?qpq=ZZv zhM_>>N}w)c33RKWLKns`6j;rQ$z?X1&r0;2>2k*?`j%a)@JM979wbffda1VfSSDvo z!OS-~z>hHH=-a4@B02BFX-D72m0U;B_p}mTBm0A7^nEYkO%?AwdFl9{!-Con+b!6W*mDkr=9z;eg95|95jS3yi!THQeQ1sG@Ir*DKYtYJmhh z8}m=)s8<=Y0=Wg*?E%G~O~x%nqHA$wCkPAp6kb!expUm_3%jd z=E;T|jGO786`(x$q_e%yYC!Z43*6md-At(&YFfyk(WRyHDd?v2ePVr@LL!Ail=oSg z{Rp=bCyk0bvI!k6el`caqa?@WIXO8wIXUL=54DWl7jMf|&;S4c07*qoM6N<$g3o0> A;Q#;t literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/Contents.json new file mode 100644 index 000000000..adf12f0d6 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "action_sticker.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "action_sticker@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "action_sticker@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker.png b/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker.png new file mode 100644 index 0000000000000000000000000000000000000000..cb7a04d3fedd7a64764e1531e27487662a2119e5 GIT binary patch literal 582 zcmV-M0=fN(P)dYxl00==P#{sCeR7<~H>LYJ9)pj5k`ubh3! zVCm|h1n4vY*n{a9BMc@PskGp7=kOR%oo5gid?0QucN(>{Nlc0#)tESdFJQz@9{%r? z$71g+T{kvOs0s7HwB9dN+i%0M6k!eK1yxguBVq8e`j;x16EC8ulrUg`HTWhJ!_dGT zMj8F-U6Bqm+?fA+=?zk91vULOGAjuKb3+b3foZf;*Le)Wd=O5%&xOwug68sIb+;vh z#mjx)SzK6?mD`0n>dpb@BFvY=af2RYIb^1-{%W-?m7+;YrkQjb(zm#fxs0AssN6CW{HaNQP2ekUN+ z@|54}$?8qDZDbK2F|dcixCIj($nG$T;p)-tl|j+VNj@S zGeI3@kVQPzz?u|y0wZD4WxiUkAh9o3V%5zmo(Xvg{<&(Lo8O6yy-twjBlL@S21JM0 Uvtx15!TpF literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@2x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..13a2b75119e96e2c5819dbaa3eea71b33b314557 GIT binary patch literal 1050 zcmV+#1m*jQP)~;JRlSFEMQUp$ROgiAY{a=pGPH^;4?Q*#R88DOq`T9v-L2Hwg*m@Eh8(Y5`Eg|=t*0v2PNoBx;aCeUs zY(X}hrZpt70dw_Z?Qy82@OTt92&~*#JGCT}5*aX8KRU_K>qfMo>h)rIJHhy9IAlC> zzXCxCMgSsQ2$Ys%Z97q81;jvkZhchZ86qgQ9TtN~1KMGOP=ryV9X5A%bP_deU#fA?Ua-cuI#3Kmo>!lM`}2Y(IpCkmtD-7{7QXuavtN_MveF zI^Ms62|};JYtt$iSD@qliNba7jpvU!gb?1sgn>eAn%)l>z*!|sM(q2^ceM3kSOHan z357rf&ZD3K0vBL>@FvxD12p&r4=HySfmrfSkb$otEM!;aMB?Zor^dNY>)vZL-+#1C zgI@kPEQ%Zy34_iJNS!@9`mO(DohthvTM1Ep0k<{BszfGigOG;zo>ja~$M>cDQ@t5d z_#+ZV274V=?-oB?3>r1_{h-kOe`dysN~uQ_LS(muXEm*0jCbp5(i@a?Gayjup#w-4 zEp#_b^Gz$j7H4RHS^Q&Nty7k*CqI&Dex5va-dr|s@PGjXbb){c$OsM_zj!{7Jmqo0 z66q*XYX5e5w-WZb2u{Fr$Oyjqoz)-nv-RUO6i|=T6o?Yf1PsuNIdGH3hiw1NXMcTK z0Y#^=X2%fE1PthO%!Yr&2~p|2)Stt@tRFs`cqXzlce}K+ zr8i&$VxoLuhb|fqtSrPcv3jF9l&f5HKt^OGo{41u?}zJm$EuKlV0*^TQ zF?q98Ue5`4UgzI6|BAS-+xO&Af>xhHJd^3qtnHqX?i^4~H14dOA@ivzQ>Mh>A1bBE UH10O~g#Z8m07*qoM6N<$f+`HqF#rGn literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@3x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_sticker.imageset/action_sticker@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d000e8f4c8ab95168d1c282536f38a7922870313 GIT binary patch literal 1457 zcmV;i1y1^jP)Sy0`|8_!v@R{{KgK? zdxK5LNG3sn9OVxQVHsu+L^!=cXEjU6r4|(A8y?R5-!{xPF6X6gT1lw{)kw|+*S4IM zG(~2rB+X%U4E2#Cv^51EXkrozS{Uvf%xcbwg9w%vPWBEUA&Ek4{^a*H{*hNuV-WP_ zd2j2`{Cq=dn0KP^IBBn#CT-&oQ_A0g`pXeob5iXaVl;y0-|zPU=@{-2T-bI^Cb?!K z2q|%Ln{|T8v;k8E$;=$?M`+!K=Zv4;TP#xrnVPO6Chsja2YtG7eSmumSJ>ajRoJm3 zXzcraxaau(P3$T}tRTyVr*O|f+xj8)@u&xa?t}LKfp37gFpC^PzVFv=zLge56gi4w zLQHqy8$qk_!>Grc$e*%s3F?JML?izCx2z-rS@Qj@u;C_UOWUxBO0y7L;`2Ik+=_Xx zk%HvOxR{!CT%Iz#=C7l)y)h{k2{1C9L?-F^lRc?_+AxFg+RlhSyh0m>6P%dG+Aw33 zDQ1EL^}y2_cCVfcj2F7{q6UJ9yArB<-FxXm1c+vzw#|USB*OtW7&jq>Mp5vxxeM+umsRr)_wM96|gkcv$-O zs?V=Ix|||svgb%?wP69ZAn9vpEy;fBZjk6Y2(;|#s$jZ7u7p+G8T0Rd>$4bMSLRwR zMX~l#&eo2}xsg*1P1Y%tk0%M)i^)0CmjkqTeLVT75t7IeB1e#g=t9Y*v|P%gu2w+; zCjXc#=MJPKsT?741lhJdf>I$juFerTS@s^Kkt0M33f4!EE7y`BjnAVV3&N@bIYR7; zA}RP2N+7suMbstI?#{9~D~lWU3<&^e3zY04nO#{ACrS7U^l_SIoDksdyjT${! z+TD4`5vKOVWFImV2!~f_u@;OTgjAa`^O7S>6%>5B1&$)lFGpd=l^%B>)$`>iM=6)H!<3lr{QD?*N7yg$fBU+R>6@3bKuT1F%d zucG7##)7==OIJg_p+=TWXF`sX`RFN9j*w^*=T&cT$hqMU$O+Wpg3z$#RJ0r+@h;cP z$G>a@eWx6_+qe3BT*K6vdKq$rRQseYbh=XDK}M8Pp@R4Wh!s?p93hn;sjzKcx5-0N zQp%Jgq`ncurrentAlert = nil; + } + + }]]; + + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"yes"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + if (weakSelf) + { + typeof(self) self = weakSelf; + self->currentAlert = nil; + + // Show the sticker picker settings screen + IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] + initForMXSession:self.roomDataSource.mxSession + inRoom:self.roomDataSource.roomId + screen:[IntegrationManagerViewController screenForWidget:kWidgetTypeStickerPicker] + widgetId:nil]; + + [self presentViewController:modularVC animated:NO completion:nil]; + } + }]]; + + [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"]; + [self presentViewController:currentAlert animated:YES completion:nil]; + } +} + +- (void)roomInputToolbarViewDidTapFileUpload +{ + MXKDocumentPickerPresenter *documentPickerPresenter = [MXKDocumentPickerPresenter new]; + documentPickerPresenter.delegate = self; + + NSArray *allowedUTIs = @[MXKUTI.data]; + [documentPickerPresenter presentDocumentPickerWith:allowedUTIs from:self animated:YES completion:nil]; + + self.documentPickerPresenter = documentPickerPresenter; +} + #pragma mark - Dialpad - (void)openDialpad @@ -3321,80 +3445,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; } -#pragma mark - RoomInputToolbarViewDelegate - -- (void)roomInputToolbarViewPresentStickerPicker:(MXKRoomInputToolbarView*)toolbarView -{ - // Search for the sticker picker widget in the user account - Widget *widget = [[WidgetManager sharedManager] userWidgets:self.roomDataSource.mxSession ofTypes:@[kWidgetTypeStickerPicker]].firstObject; - - if (widget) - { - // Display the widget - [widget widgetUrl:^(NSString * _Nonnull widgetUrl) { - - StickerPickerViewController *stickerPickerVC = [[StickerPickerViewController alloc] initWithUrl:widgetUrl forWidget:widget]; - - stickerPickerVC.roomDataSource = self.roomDataSource; - - [self.navigationController pushViewController:stickerPickerVC animated:YES]; - } failure:^(NSError * _Nonnull error) { - - NSLog(@"[RoomVC] Cannot display widget %@", widget); - [[AppDelegate theDelegate] showErrorAsAlert:error]; - }]; - } - else - { - // The Sticker picker widget is not installed yet. Propose the user to install it - __weak typeof(self) weakSelf = self; - - [currentAlert dismissViewControllerAnimated:NO completion:nil]; - - NSString *alertMessage = [NSString stringWithFormat:@"%@\n%@", - NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert", @"Vector", nil), - NSLocalizedStringFromTable(@"widget_sticker_picker_no_stickerpacks_alert_add_now", @"Vector", nil) - ]; - - currentAlert = [UIAlertController alertControllerWithTitle:nil message:alertMessage preferredStyle:UIAlertControllerStyleAlert]; - - [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"no"] - style:UIAlertActionStyleCancel - handler:^(UIAlertAction * action) - { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; - - [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"yes"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) - { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - // Show the sticker picker settings screen - IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] - initForMXSession:self.roomDataSource.mxSession - inRoom:self.roomDataSource.roomId - screen:[IntegrationManagerViewController screenForWidget:kWidgetTypeStickerPicker] - widgetId:nil]; - - [self presentViewController:modularVC animated:NO completion:nil]; - } - }]]; - - [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCStickerPickerAlert"]; - [self presentViewController:currentAlert animated:YES completion:nil]; - } -} - #pragma mark - VoIP - (void)placeCallWithVideo:(BOOL)video @@ -3641,27 +3691,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } } -- (void)roomInputToolbarViewDidTapFileUpload:(MXKRoomInputToolbarView *)toolbarView -{ - MXKDocumentPickerPresenter *documentPickerPresenter = [MXKDocumentPickerPresenter new]; - documentPickerPresenter.delegate = self; - - NSArray *allowedUTIs = @[MXKUTI.data]; - [documentPickerPresenter presentDocumentPickerWith:allowedUTIs from:self animated:YES completion:nil]; - - self.documentPickerPresenter = documentPickerPresenter; -} - -- (void)roomInputToolbarViewDidTapCamera:(MXKRoomInputToolbarView*)toolbarView -{ - [self showCameraControllerAnimated:YES]; -} - -- (void)roomInputToolbarViewDidTapMediaLibrary:(MXKRoomInputToolbarView*)toolbarView -{ - [self showMediaPickerAnimated:YES]; -} - - (void)roomInputToolbarViewDidTapCancel:(MXKRoomInputToolbarView*)toolbarView { [self cancelEventSelection]; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomActionItem.swift b/Riot/Modules/Room/Views/InputToolbar/RoomActionItem.swift new file mode 100644 index 000000000..e22f9bda5 --- /dev/null +++ b/Riot/Modules/Room/Views/InputToolbar/RoomActionItem.swift @@ -0,0 +1,30 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 UIKit + +@objcMembers +@objc class RoomActionItem: NSObject { + var image: UIImage! + var action: (() -> Void)! + + init(image: UIImage, andAction action: @escaping () -> Void) { + super.init() + + self.image = image + self.action = action + } +} diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift new file mode 100644 index 000000000..7f4bdcb98 --- /dev/null +++ b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift @@ -0,0 +1,129 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 UIKit + +@objcMembers +@objc class RoomActionsBar: UIScrollView { + // MARK: - Properties + + var itemSpacing: CGFloat = 20 { + didSet { + self.setNeedsLayout() + } + } + + var actionItems: Array = [] { + didSet { + var actionButtons: Array = [] + for (index, item) in actionItems.enumerated() { + let button = UIButton(type: .custom) + button.setImage(item.image, for: .normal) + button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside) + button.tintColor = ThemeService.shared().theme.tintColor + button.tag = index + actionButtons.append(button) + addSubview(button) + } + self.actionButtons = actionButtons + self.lastBounds = .zero + self.setNeedsLayout() + } + } + + private var actionButtons: Array = [] { + willSet { + for button in actionButtons { + button.removeFromSuperview() + } + } + } + + private var lastBounds = CGRect.zero + + // MARK: - Lifecycle + + override init(frame: CGRect) { + super.init(frame: frame) + self.showsHorizontalScrollIndicator = false + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.showsHorizontalScrollIndicator = false + } + + override func layoutSubviews() { + super.layoutSubviews() + + guard lastBounds != self.bounds else { + return + } + + lastBounds = self.bounds + + var currentX: CGFloat = 0 + for button in actionButtons { + button.frame = CGRect(x: currentX, y: 0, width: self.bounds.height, height: self.bounds.height) + currentX = button.frame.maxX + itemSpacing + } + + self.contentSize = CGSize(width: currentX - itemSpacing, height: self.bounds.height) + } + + // MARK: - Business methods + + func customizeViewRendering() { + for button in actionButtons { + button.tintColor = ThemeService.shared().theme.tintColor + } + } + + func animate(showIn: Bool, completion: ((Bool) -> Void)? = nil) { + if showIn { + for button in actionButtons { + button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) + } + for (index, button) in actionButtons.enumerated() { + UIView.animate(withDuration: 0.32, delay: 0.05 * Double(index), usingSpringWithDamping: 0.5, initialSpringVelocity: 7, options: .curveEaseInOut) { + button.transform = CGAffineTransform.identity + } completion: { (finished) in + completion?(finished) + } + } + } else { + for (index, button) in actionButtons.enumerated() { + UIView.animate(withDuration: 0.2, delay: 0.05 * Double(index), options: .curveEaseInOut) { + button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) + } completion: { (finished) in + completion?(finished) + } + } + } + } + + // MARK: - Private methods + + @objc private func buttonAction(_ sender: UIButton) { + if let action = actionItems[sender.tag].action { + action() + } + } + + private func setupView() { + self.showsHorizontalScrollIndicator = false + } +} diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h index e5559e9fe..b2ad883b8 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h @@ -18,6 +18,8 @@ #import "MediaPickerViewController.h" +@class RoomActionsBar; + /** Destination of the message in the composer */ @@ -31,34 +33,6 @@ typedef enum : NSUInteger @protocol RoomInputToolbarViewDelegate -/** - Tells the delegate that the user wants to display the sticker picker. - - @param toolbarView the room input toolbar view. - */ -- (void)roomInputToolbarViewPresentStickerPicker:(MXKRoomInputToolbarView*)toolbarView; - -/** - Tells the delegate that the user wants to send external files. - - @param toolbarView the room input toolbar view - */ -- (void)roomInputToolbarViewDidTapFileUpload:(MXKRoomInputToolbarView*)toolbarView; - -/** - Tells the delegate that the user wants to take photo or video with camera. - - @param toolbarView the room input toolbar view - */ -- (void)roomInputToolbarViewDidTapCamera:(MXKRoomInputToolbarView*)toolbarView; - -/** - Tells the delegate that the user wants to show media library. - - @param toolbarView the room input toolbar view - */ -- (void)roomInputToolbarViewDidTapMediaLibrary:(MXKRoomInputToolbarView*)toolbarView; - /** Tells the delegate that the user wants to cancel the current edition / reply. @@ -95,6 +69,7 @@ typedef enum : NSUInteger @property (weak, nonatomic) IBOutlet UIImageView *inputContextImageView; @property (weak, nonatomic) IBOutlet UILabel *inputContextLabel; @property (weak, nonatomic) IBOutlet UIButton *inputContextButton; +@property (weak, nonatomic) IBOutlet RoomActionsBar *actionsBar; /** Tell whether the filled data will be sent encrypted. NO by default. @@ -111,4 +86,9 @@ typedef enum : NSUInteger */ @property (nonatomic) RoomInputToolbarViewSendMode sendMode; +/** + YES if action menu is opened. NO otherwise + */ +@property (nonatomic, getter=isActionMenuOpened) BOOL actionMenuOpened; + @end diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index dfceba978..cb3a55146 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -120,6 +120,7 @@ const double RoomInputToolbarViewContextBarHeight = 30; self.inputContextImageView.tintColor = ThemeService.shared.theme.textSecondaryColor; self.inputContextLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.inputContextButton.tintColor = ThemeService.shared.theme.textSecondaryColor; + [self.actionsBar customizeViewRendering]; } #pragma mark - @@ -142,6 +143,7 @@ const double RoomInputToolbarViewContextBarHeight = 30; RoomInputToolbarViewSendMode previousMode = _sendMode; _sendMode = sendMode; + self.actionMenuOpened = NO; [self updatePlaceholder]; [self updateToolbarButtonLabelWithPreviousMode: previousMode]; } @@ -329,92 +331,7 @@ const double RoomInputToolbarViewContextBarHeight = 30; { if (button == self.attachMediaButton) { - // Check whether media attachment is supported - if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:presentViewController:)]) - { - // Ask the user the kind of the call: voice or video? - actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; - - __weak typeof(self) weakSelf = self; - - [actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_camera", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->actionSheet = nil; - - [self.delegate roomInputToolbarViewDidTapCamera:self]; - } - }]]; - - - [actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_photo_or_video", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->actionSheet = nil; - - [self.delegate roomInputToolbarViewDidTapMediaLibrary:self]; - } - - }]]; - - if (BuildSettings.allowSendingStickers) - { - [actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_sticker", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->actionSheet = nil; - - [self.delegate roomInputToolbarViewPresentStickerPicker:self]; - } - - }]]; - } - - [actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_file", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->actionSheet = nil; - - [self.delegate roomInputToolbarViewDidTapFileUpload:self]; - } - }]]; - - [actionSheet addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] - style:UIAlertActionStyleCancel - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->actionSheet = nil; - } - - }]]; - - [actionSheet popoverPresentationController].sourceView = self.attachMediaButton; - [actionSheet popoverPresentationController].sourceRect = self.attachMediaButton.bounds; - [self.window.rootViewController presentViewController:actionSheet animated:YES completion:nil]; - } - else - { - NSLog(@"[RoomInputToolbarView] Attach media is not supported"); - } + self.actionMenuOpened = !self.isActionMenuOpened; } [super onTouchUpInside:button]; @@ -443,9 +360,55 @@ const double RoomInputToolbarViewContextBarHeight = 30; self.rightInputToolbarButton.alpha = 0; self.messageComposerContainerTrailingConstraint.constant = 12; } + [self layoutIfNeeded]; } +#pragma mark - properties + +- (void)setActionMenuOpened:(BOOL)actionMenuOpened +{ + if (_actionMenuOpened != actionMenuOpened) + { + _actionMenuOpened = actionMenuOpened; + + if (_actionMenuOpened) { + self.actionsBar.hidden = NO; + [self.actionsBar animateWithShowIn:_actionMenuOpened completion:nil]; + } + else + { + [self.actionsBar animateWithShowIn:_actionMenuOpened completion:^(BOOL finished) { + self.actionsBar.hidden = YES; + }]; + } + + [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.45 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self.attachMediaButton.transform = actionMenuOpened ? CGAffineTransformMakeRotation(M_PI * 3 / 4) : CGAffineTransformIdentity; + } completion:^(BOOL finished) { + }]; + + [UIView animateWithDuration:.2 delay:_actionMenuOpened ? 0 : .1 options:UIViewAnimationOptionCurveEaseIn animations:^{ + self->messageComposerContainer.alpha = actionMenuOpened ? 0 : 1; + self.rightInputToolbarButton.alpha = self->growingTextView.text.length == 0 || actionMenuOpened ? 0 : 1; + } completion:^(BOOL finished) { + }]; + + [UIView animateWithDuration:.3 animations:^{ + if (actionMenuOpened) + { + self.mainToolbarHeightConstraint.constant = self.mainToolbarMinHeightConstraint.constant; + } + else + { + [self->growingTextView refreshHeight]; + } + [self layoutIfNeeded]; + [self.delegate roomInputToolbarView:self heightDidChanged:self.mainToolbarHeightConstraint.constant completion:nil]; + }]; + } +} + #pragma mark - Clipboard - Handle image/data paste from general pasteboard - (void)paste:(id)sender diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib index fbc52e9f1..e99b0ef66 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib @@ -27,6 +27,14 @@ + @@ -105,11 +113,14 @@ + + + @@ -125,6 +136,7 @@ + From 15f2f14ee720c2cd3cddd34132218fc63d236cc1 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 26 Mar 2021 11:18:05 +0100 Subject: [PATCH 024/140] Switching composer between text mode & action mode - Deselect text if user taps action button to avoid overlaps --- Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index cb3a55146..a0b5aceb8 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -372,6 +372,8 @@ const double RoomInputToolbarViewContextBarHeight = 30; { _actionMenuOpened = actionMenuOpened; + self->growingTextView.internalTextView.selectedTextRange = nil; + if (_actionMenuOpened) { self.actionsBar.hidden = NO; [self.actionsBar animateWithShowIn:_actionMenuOpened completion:nil]; From b8b58b472728e65ca7dd3dc3c299167cf35f025c Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 26 Mar 2021 12:56:56 +0100 Subject: [PATCH 025/140] Unit tests are broken - xcodegen target file updated --- RiotTests/Debug.xcconfig | 20 ++++++++++++++++++++ RiotTests/Release.xcconfig | 20 ++++++++++++++++++++ RiotTests/target.yml | 20 +++++++++++++++++--- 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 RiotTests/Debug.xcconfig create mode 100644 RiotTests/Release.xcconfig diff --git a/RiotTests/Debug.xcconfig b/RiotTests/Debug.xcconfig new file mode 100644 index 000000000..be053c75b --- /dev/null +++ b/RiotTests/Debug.xcconfig @@ -0,0 +1,20 @@ +// +// Copyright 2020 Vector Creations Ltd +// +// 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. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Pods/Target Support Files/Pods-RiotTests/Pods-RiotTests.debug.xcconfig" diff --git a/RiotTests/Release.xcconfig b/RiotTests/Release.xcconfig new file mode 100644 index 000000000..5a62ed9cd --- /dev/null +++ b/RiotTests/Release.xcconfig @@ -0,0 +1,20 @@ +// +// Copyright 2020 Vector Creations Ltd +// +// 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. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Pods/Target Support Files/Pods-RiotTests/Pods-RiotTests.release.xcconfig" diff --git a/RiotTests/target.yml b/RiotTests/target.yml index 83cd4c55e..fa2288a2e 100644 --- a/RiotTests/target.yml +++ b/RiotTests/target.yml @@ -33,15 +33,19 @@ targets: dependencies: - target: Riot + configFiles: + Debug: Debug.xcconfig + Release: Release.xcconfig + settings: base: BUNDLE_LOADER: $(TEST_HOST) FRAMEWORK_SEARCH_PATHS: $(SDKROOT)/Developer/Library/Frameworks $(inherited) - INFOPLIST_FILE: Info.plist + INFOPLIST_FILE: RiotTests/Info.plist LD_RUNPATH_SEARCH_PATHS: $(inherited) @executable_path/Frameworks @loader_path/Frameworks PRODUCT_BUNDLE_IDENTIFIER: org.matrix.$(PRODUCT_NAME:rfc1034identifier) PRODUCT_NAME: RiotTests - SWIFT_OBJC_BRIDGING_HEADER: RiotTests-Bridging-Header.h + SWIFT_OBJC_BRIDGING_HEADER: RiotTests/RiotTests-Bridging-Header.h TEST_HOST: $(BUILT_PRODUCTS_DIR)/Riot.app/Riot configs: Debug: @@ -49,4 +53,14 @@ targets: PROVISIONING_PROFILE: $(RIOT_PROVISIONING_PROFILE) PROVISIONING_PROFILE_SPECIFIER: $(RIOT_PROVISIONING_PROFILE_SPECIFIER) - sources: . + sources: + - path: . + - path: ../Config/Configurable.swift + - path: ../Config/BuildSettings.swift + - path: ../Config/AppConfiguration.swift + - path: ../Config/CommonConfiguration.swift + - path: ../Riot/Categories/Bundle.swift + - path: ../Riot/Generated/InfoPlist.swift + - path: ../Riot/Managers/Settings/RiotSettings.swift + - path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift + - path: ../Riot/Managers/KeyValueStorage/ From aeac807686edfd2cd6d00c1f7db1c120f01ef9c6 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 26 Mar 2021 13:06:38 +0100 Subject: [PATCH 026/140] Updated CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 1258b137c..8dffc4bff 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,7 +8,7 @@ Changes to be released in next version * 🐛 Bugfix - * + * Xcodegen: Unit tests are broken (#4152). ⚠️ API Changes * From 4cd2212b107054efb83d9dc7c5ab2c25f564115e Mon Sep 17 00:00:00 2001 From: RainSlide Date: Thu, 25 Mar 2021 15:00:47 +0000 Subject: [PATCH 027/140] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (6 of 6 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/InfoPlist.strings | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/zh_Hans.lproj/InfoPlist.strings b/Riot/Assets/zh_Hans.lproj/InfoPlist.strings index 4e2b4662c..b548711be 100644 --- a/Riot/Assets/zh_Hans.lproj/InfoPlist.strings +++ b/Riot/Assets/zh_Hans.lproj/InfoPlist.strings @@ -2,5 +2,6 @@ "NSCameraUsageDescription" = "摄像头权限用于拍摄照片、录制视频或进行视频聊天。"; "NSPhotoLibraryUsageDescription" = "照片库访问权限用于发送图片与视频。"; "NSMicrophoneUsageDescription" = "麦克风权限用于录制视频或进行通话。"; -"NSContactsUsageDescription" = "为了发现已在使用Matrix的联系人,Element可以把你地址簿里的邮箱地址和电话号码发送到你所选择的Matrix身份认证服务器。如果支持的话,个人数据在发送前会被哈希处理–请检查你的身份认证服务器的隐私条款以获取详细信息。"; +"NSContactsUsageDescription" = "为了发现已在使用 Matrix 的联系人,Element 可以把你地址簿里的邮箱地址和电话号码发送到你所选择的 Matrix 身份认证服务器。如果支持的话,个人数据在发送前会被哈希处理——请检查你的身份认证服务器的隐私政策以获取详细信息。"; "NSCalendarsUsageDescription" = "在此应用中查看你计划的会议。"; +"NSFaceIDUsageDescription" = "Face ID 权限用于访问您的应用。"; From ee9aa1714c3e77c092d1b9047a837772ec3c1f39 Mon Sep 17 00:00:00 2001 From: RainSlide Date: Thu, 25 Mar 2021 15:02:48 +0000 Subject: [PATCH 028/140] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (33 of 33 strings) Translation: Element iOS/Element iOS (Push) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-push/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/Localizable.strings | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/zh_Hans.lproj/Localizable.strings b/Riot/Assets/zh_Hans.lproj/Localizable.strings index aea281b69..7ff0fb738 100644 --- a/Riot/Assets/zh_Hans.lproj/Localizable.strings +++ b/Riot/Assets/zh_Hans.lproj/Localizable.strings @@ -1,5 +1,5 @@ /* New message from a specific person, not referencing a room */ -"MSG_FROM_USER" = "%@发送了一条消息"; +"MSG_FROM_USER" = "%@ 发送了一条消息"; /* New message from a specific person in a named room */ "MSG_FROM_USER_IN_ROOM" = "%@ 在 %@ 发送了消息"; /* New message from a specific person, not referencing a room. Content included. */ @@ -27,11 +27,11 @@ /* Multiple unread messages from three people */ "MSGS_FROM_THREE_USERS" = "%@ 条未读消息 (来自 %@、%@ 和 %@)"; /* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */ -"MSGS_FROM_TWO_PLUS_USERS" = "%@ 条未读消息 (来自 %@、%@ 及更多)"; +"MSGS_FROM_TWO_PLUS_USERS" = "%@ 条未读消息 (来自 %@、%@ 与其他)"; /* Multiple messages in two rooms */ "MSGS_IN_TWO_ROOMS" = "%@ 条未读消息 (来自聊天室 %@ 和 %@)"; /* Look, stuff's happened, alright? Just open the app. */ -"MSGS_IN_TWO_PLUS_ROOMS" = "%@ 条未读消息 (来自聊天室 %@、%@ 和更多)"; +"MSGS_IN_TWO_PLUS_ROOMS" = "%@ 条未读消息 (来自 %@、%@ 与其他)"; /* A user has invited you to a chat */ "USER_INVITE_TO_CHAT" = "%@ 邀请您加入私聊"; /* A user has invited you to an (unamed) group chat */ @@ -54,4 +54,16 @@ "MSG_FROM_USER_IN_ROOM_TITLE" = "%@(来自 %@)"; /* Sticker from a specific person, not referencing a room. */ "STICKER_FROM_USER" = "%@发送了一张贴图"; -"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@想要验证"; +"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ 想要验证"; +"MESSAGE_PROTECTED" = "未读消息"; + +/* New message indicator on a room */ +"MESSAGE_IN_X" = "%@ 中的消息"; + +/* New message indicator from a DM */ +"MESSAGE_FROM_X" = "来自 %@ 的消息"; + +/** Notification messages **/ + +/* New message indicator on unknown room */ +"MESSAGE" = "消息"; From ca28199205c607a7468a33a4b5f3cdd12258322f Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 26 Mar 2021 17:07:59 +0100 Subject: [PATCH 029/140] version++ --- CHANGES.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8dffc4bff..cb519d96a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -Changes to be released in next version +Changes in 1.2.8 (2021-03-26) ================================================= ✨ Features @@ -22,6 +22,9 @@ Changes to be released in next version Others * +Improvements: + + Changes in 1.2.7 (2021-03-24) ================================================= From 2ce557773a4ed164fa59812013d73af47c15b2bc Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 26 Mar 2021 17:23:39 +0100 Subject: [PATCH 030/140] finish version++ From cd7d533edd16da6c54db60fdb03fb7c40d2edabf Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 26 Mar 2021 17:23:48 +0100 Subject: [PATCH 031/140] Prepare for new sprint --- CHANGES.rst | 24 ++++++++++++++++++++++++ Config/AppIdentifiers.xcconfig | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cb519d96a..09d797340 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,27 @@ +Changes to be released in next version +================================================= + +✨ Features + * + +🙌 Improvements + * + +🐛 Bugfix + * + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * + Changes in 1.2.8 (2021-03-26) ================================================= diff --git a/Config/AppIdentifiers.xcconfig b/Config/AppIdentifiers.xcconfig index ebcc71705..9c0a99957 100644 --- a/Config/AppIdentifiers.xcconfig +++ b/Config/AppIdentifiers.xcconfig @@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector APPLICATION_SCHEME = element // Version -MARKETING_VERSION = 1.2.8 -CURRENT_PROJECT_VERSION = 1.2.8 +MARKETING_VERSION = 1.2.9 +CURRENT_PROJECT_VERSION = 1.2.9 // Team From 286faff5ea6a3183f450bfeb3f59d7aaf9fa09a4 Mon Sep 17 00:00:00 2001 From: jelv Date: Thu, 25 Mar 2021 11:08:22 +0000 Subject: [PATCH 032/140] Translated using Weblate (Dutch) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ --- Riot/Assets/nl.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 53182a22a..9f0ecb1a4 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -1312,7 +1312,7 @@ "identity_server_settings_alert_no_terms" = "De door u gekozen identiteitsserver heeft geen dienstvoorwaarden. Ga alleen door, wanneer u de eigenaar van de server vertrouwd."; "identity_server_settings_alert_no_terms_title" = "De identiteitsserver heeft geen dienstvoorwaarden"; "identity_server_settings_disconnect" = "Verbinding verbreken"; -"identity_server_settings_disconnect_info" = "De verbinding met uw identiteitsserver verbreken zal ertoe leiden dat u niet door andere gebruikers gevonden zal kunnen worden, en dat u anderen niet via e-mail of telefoon zal kunnen uitnodigen."; +"identity_server_settings_disconnect_info" = "De verbinding met uw identiteitsserver verbreken zal ertoe leiden dat u niet door andere mensen gevonden zal kunnen worden, en dat u anderen niet via e-mail of telefoon zal kunnen uitnodigen."; "identity_server_settings_change" = "Wijzigen"; "identity_server_settings_add" = "Toevoegen"; "identity_server_settings_place_holder" = "Voer een identiteitsserver in"; From f1352a4681116b937b938ae1a40b18434922693d Mon Sep 17 00:00:00 2001 From: RainSlide Date: Thu, 25 Mar 2021 16:36:07 +0000 Subject: [PATCH 033/140] Translated using Weblate (Chinese (Simplified)) Currently translated at 92.2% (1094 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/Vector.strings | 237 ++++++++++++++++++----- 1 file changed, 185 insertions(+), 52 deletions(-) diff --git a/Riot/Assets/zh_Hans.lproj/Vector.strings b/Riot/Assets/zh_Hans.lproj/Vector.strings index 46cf235d1..65d372752 100644 --- a/Riot/Assets/zh_Hans.lproj/Vector.strings +++ b/Riot/Assets/zh_Hans.lproj/Vector.strings @@ -11,7 +11,7 @@ "continue" = "继续"; "create" = "新建"; "start" = "开始"; -"leave" = "退出"; +"leave" = "离开"; "remove" = "移除"; "invite" = "邀请"; "retry" = "重试"; @@ -27,7 +27,7 @@ "voice" = "语音"; "video" = "视频"; "active_call" = "当前通话"; -"active_call_details" = "当前通话 (%@)"; +"active_call_details" = "当前通话(%@)"; "later" = "稍后再说"; "rename" = "重命名"; // Authentication @@ -47,7 +47,7 @@ "auth_phone_placeholder" = "手机号码"; "auth_repeat_password_placeholder" = "重复密码"; "auth_repeat_new_password_placeholder" = "确认您的新密码"; -"auth_invalid_login_param" = "无效的用户名和/或密码"; +"auth_invalid_login_param" = "用户名和/或密码无效"; "auth_invalid_user_name" = "用户名只能包含字母、数字、短横(-)与下划线(_)"; "auth_invalid_password" = "密码太短(至少 6 个字符)"; "auth_invalid_email" = "这不像是一个有效的邮箱地址"; @@ -142,8 +142,8 @@ "room_participants_add_participant" = "添加参加者"; "room_participants_one_participant" = "1 个参加者"; "room_participants_multi_participants" = "%d 个参加者"; -"room_participants_leave_prompt_title" = "退出聊天室"; -"room_participants_leave_prompt_msg" = "您确定要退出此聊天室吗?"; +"room_participants_leave_prompt_title" = "离开聊天室"; +"room_participants_leave_prompt_msg" = "您确定要离开此聊天室吗?"; "room_participants_remove_prompt_title" = "确认"; "room_participants_remove_prompt_msg" = "您确定要将 %@ 从此聊天室里移除?"; "room_participants_remove_third_party_invite_msg" = "在 API 实现之前还不支持移除第三方邀请"; @@ -165,18 +165,18 @@ "room_participants_action_section_devices" = "会话"; "room_participants_action_section_other" = "选项"; "room_participants_action_invite" = "邀请"; -"room_participants_action_leave" = "退出此聊天室"; +"room_participants_action_leave" = "离开此聊天室"; "room_participants_action_remove" = "从此聊天室移除"; "room_participants_action_ban" = "从此聊天室封禁"; "room_participants_action_unban" = "解封"; "room_participants_action_ignore" = "隐藏此用户的所有信息"; "room_participants_action_unignore" = "显示此用户的所有信息"; "room_participants_action_set_default_power_level" = "重置到正常用户"; -"room_participants_action_set_moderator" = "使其成为主持人"; +"room_participants_action_set_moderator" = "使其成为协管员"; "room_participants_action_set_admin" = "使其成为管理员"; "room_participants_action_start_new_chat" = "发起新的聊天"; -"room_participants_action_start_voice_call" = "开始语音通话"; -"room_participants_action_start_video_call" = "开始视频通话"; +"room_participants_action_start_voice_call" = "发起语音通话"; +"room_participants_action_start_video_call" = "发起视频通话"; "room_participants_action_mention" = "提及"; // Chat "room_jump_to_first_unread" = "跳到第一条未读信息"; @@ -185,7 +185,7 @@ "room_one_user_is_typing" = "%@ 正在输入…"; "room_two_users_are_typing" = "%@ 和 %@ 正在输入…"; "room_many_users_are_typing" = "%@、%@ 和 %@ 正在输入…"; -"room_message_placeholder" = "发送消息(非加密)…"; +"room_message_placeholder" = "发送消息(未加密)…"; "encrypted_room_message_placeholder" = "发送加密消息…"; "room_message_short_placeholder" = "发送消息…"; "room_offline_notification" = "到服务器的连接已经丢失。"; @@ -252,7 +252,7 @@ "settings_labs" = "实验室"; "settings_devices" = "会话"; "settings_cryptography" = "加密"; -"settings_sign_out" = "退出"; +"settings_sign_out" = "离开"; "settings_sign_out_confirmation" = "你确定?"; "settings_sign_out_e2e_warn" = "您将丢失所有端对端加密密钥。这意味着在此设备上您将再也无法阅读已加密聊天室里的旧消息。"; "settings_profile_picture" = "档案图片"; @@ -326,7 +326,7 @@ "room_details_history_section_prompt_msg" = "改成谁都可以阅读历史只会应用于此聊天室未来的消息。已经存在的历史消息的可见性将不会改变。"; "room_details_new_address" = "添加新地址"; "room_details_new_address_placeholder" = "添加新地址(例如 #foo%@)"; -"room_details_addresses_invalid_address_prompt_title" = "无效的别名格式"; +"room_details_addresses_invalid_address_prompt_title" = "别名格式无效"; "room_details_addresses_invalid_address_prompt_msg" = "%@ 不是一个有效的别名格式"; "room_details_addresses_disable_main_address_prompt_title" = "主地址警告"; "room_details_addresses_disable_main_address_prompt_msg" = "您没有指定主地址。此聊天室的默认主地址会随机选取"; @@ -413,7 +413,7 @@ // Events formatter "event_formatter_member_updates" = "%tu 的成员身份变化"; "auth_home_server_placeholder" = "URL(例如 https://matrix.org)"; -"auth_identity_server_placeholder" = "网址(例如 https://vector.im)"; +"auth_identity_server_placeholder" = "URL(例如 https://vector.im)"; "contacts_user_directory_section" = "用户目录"; "contacts_user_directory_offline_section" = "用户目录(离线)"; "room_ongoing_conference_call_with_close" = "收到会议通话。以 %@ 或 %@.%@ 加入。"; @@ -454,8 +454,8 @@ "group_home_multi_rooms_format" = "%tu 个聊天室"; // Group participants "group_participants_add_participant" = "添加成员"; -"group_participants_leave_prompt_title" = "退出群组"; -"group_participants_leave_prompt_msg" = "你确定要退出此群组吗?"; +"group_participants_leave_prompt_title" = "离开群组"; +"group_participants_leave_prompt_msg" = "你确定要离开此群组吗?"; "group_participants_remove_prompt_title" = "选项"; "group_participants_remove_prompt_msg" = "你确定要从此群组中移除 %@ 吗?"; "group_participants_invite_prompt_title" = "选项"; @@ -477,7 +477,7 @@ "widget_integration_room_not_recognised" = "无法识别此房间。"; "widget_integration_positive_power_level" = "权限级别必须是整数。"; "widget_integration_must_be_in_room" = "您不在此聊天室中。"; -"e2e_room_key_request_start_verification" = "开始验证……"; +"e2e_room_key_request_start_verification" = "开始验证…"; "e2e_room_key_request_share_without_verifying" = "在不验证的情况下分享"; "e2e_room_key_request_ignore_request" = "忽略请求"; "room_event_action_kick_prompt_reason" = "移除此用户的原因"; @@ -527,20 +527,20 @@ "room_resource_usage_limit_reached_message_contact_3" = " 以提高限制。"; // String for App Store "store_short_description" = "安全、去中心化的聊天及 VoIP 应用"; -"store_full_description" = "沟通,由你掌控。\n\n一个聊天应用,由你掌控且完全灵活。Element 让你以你的方式沟通。为 [matrix] - 开放、去中心化的沟通而打造。\n\n获取一个免费的 matrix.org 账号,在 https://ems.element.io 获取一个你自己的服务器,或者使用其他 Matrix 服务器。\n\n为什么选择 Element?\n\n完整的沟通:围绕你的团队、你的朋友、你的社区创建聊天室 - 随你喜欢!聊天、分享文件、添加插件和语音视频通话 - 全部免费。\n\n强大的集成度:通过你了解和喜欢的工具来使用 Element 。你甚至可以在 Element 上与其他聊天应用的用户和群组聊天。\n\n隐私和安全:保守你对话的秘密。最先进的端到端加密技术可确保私密通信保持私密性。\n\n开放,而非封闭:开源,基于 Matrix。通过自己开设的服务器来拥有你自己的数据,或者选择你信赖的服务器。\n\n随处可及:在你所有的设备和线上页面 https://app.element.io 上通过完整的历史信息同步让你随处可及。"; +"store_full_description" = "Element 是一种新型的通讯与协作应用:\n\n1. 使您可以掌控您的隐私\n2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯\n3. 保护您免受广告,大数据挖掘和封闭服务的侵害\n4. 通过端到端加密保证安全,通过交叉签名验证其他人\n\nElement 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。\n\nElement 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。\n\nElement 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。\n\n通过让您选择由谁来托管您的会话,Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:\n\n1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的上千个公共服务器中选择\n2. 在您自己的硬件上运行服务器,自托管您的会话\n3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户\n\n为什么选择 Element?\n\n掌控您的数据:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。\n\n开放通讯与协作:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 Slack,IRC 或 XMPP。\n\n超级安全:支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。\n\n完善的通讯方式:消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和小挂件。建立房间与社区,保持联系并完成工作。\n\n随时随地:消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。"; "auth_accept_policies" = "请查看并接受此主页服务器的服务条款:"; "room_replacement_information" = "这个聊天室已被替换,不再有效。"; "settings_flair" = "在允许的地方显示个性徽章"; "settings_key_backup" = "密钥备份"; "settings_key_backup_info" = "消息已被端对端安全加密。只有您和持有密钥的接收方可以阅读这些消息。"; -"settings_key_backup_info_checking" = "检查中……"; +"settings_key_backup_info_checking" = "正在检查…"; "settings_key_backup_info_none" = "您的密钥未从此会话备份。"; "settings_key_backup_info_signout_warning" = "在登出账号之前把此会话关联到密钥备份以免丢失仅在此设备上的所有密钥。"; "settings_key_backup_info_version" = "密钥备份版本:%@"; "settings_key_backup_info_algorithm" = "算法:%@"; "settings_key_backup_info_valid" = "此会话正在备份密钥。"; "settings_key_backup_info_not_valid" = "此会话未在备份你的密钥,但你的确一个有可以恢复和继续添加的现有备份。"; -"settings_key_backup_info_progress" = "%@ 个密钥备份中……"; +"settings_key_backup_info_progress" = "正在备份 %@ 个密钥…"; "settings_key_backup_info_progress_done" = "所有密钥都已备份"; "settings_key_backup_info_trust_signature_unknown" = "备份具有一个 ID:%@ 的会话的签名"; "settings_key_backup_info_trust_signature_valid" = "备份具有此会话的一个有效签名"; @@ -558,8 +558,8 @@ "room_details_fail_to_update_room_direct" = "此聊天室的直接标记更新失败"; "event_formatter_jitsi_widget_removed" = "VoIP 会议已被 %@ 移除"; "room_does_not_exist" = "%@ 聊天室不存在"; -"call_incoming_voice" = "来电……"; -"call_incoming_video" = "视频通话来电……"; +"call_incoming_voice" = "收到来电…"; +"call_incoming_video" = "收到视频通话…"; // Key backup wrong version "e2e_key_backup_wrong_version_title" = "新建密钥备份"; "e2e_key_backup_wrong_version" = "一个新的安全消息密钥备份已被删除。\n\n如果这不是您的操作,请在设置中设定一个新的密码。"; @@ -591,7 +591,7 @@ "rerequest_keys_alert_message" = "请在另一台可以解密消息的设备上启动Element,这样它就可以将密钥发送到此会话。"; "key_backup_setup_title" = "密钥备份"; "key_backup_setup_skip_alert_title" = "您确定吗?"; -"key_backup_setup_skip_alert_message" = "如果您退出或丢失设备,可能会丢失安全消息。"; +"key_backup_setup_skip_alert_message" = "如果您登出或丢失设备,可能会丢失安全消息。"; "key_backup_setup_skip_alert_skip_action" = "跳过"; "key_backup_setup_intro_title" = "永不丢失加密消息"; "key_backup_setup_intro_info" = "加密聊天室中的消息使用端到端加密进行保护。 只有您和拥有密钥的收件人才能阅读这些消息。\n\n安全备份密钥以避免丢失密钥。"; @@ -659,7 +659,7 @@ "sign_out_key_backup_in_progress_alert_cancel_action" = "等待"; "auth_login_single_sign_on" = "使用单点登录方式登入"; "room_message_unable_open_link_error_message" = "无法打开链接。"; -"auth_autodiscover_invalid_response" = "无效的主服务器探测响应"; +"auth_autodiscover_invalid_response" = "主服务器探测响应无效"; "close" = "关闭"; // Accessibility "accessibility_checkbox_label" = "多选框"; @@ -670,7 +670,7 @@ "auth_phone_is_required" = "未设置身份认证服务器,所以你不能添加电话号码来重设你的密码。"; "auth_forgot_password_error_no_configured_identity_server" = "未设置身份认证服务器:添加服务器以重设你的密码。"; "auth_reset_password_error_is_required" = "未设置身份认证服务器:在服务器选项中添加以便重设你的密码。"; -"auth_softlogout_signed_out" = "你已经登出"; +"auth_softlogout_signed_out" = "你已登出"; "auth_softlogout_sign_in" = "登录"; "auth_softlogout_reason" = "你的主服务器(%1$@)管理员已将你的账号%2$@(%3$@)登出。"; "auth_softlogout_recover_encryption_keys" = "登录以恢复单独保存在此设备上的加密密钥。你需要它们才能阅读任何设备上的安全消息。"; @@ -682,7 +682,7 @@ "auth_softlogout_clear_data_sign_out_msg" = "你确定希望清空所有当前保存在此设备上数据吗?再次登录可以获取你的账号数据和消息。"; "auth_softlogout_clear_data_sign_out" = "登出"; // Errors -"error_user_already_logged_in" = "看上去你试图连接另一个主服务器。你想要登出吗?"; +"error_user_already_logged_in" = "您似乎正在尝试连接另一个主服务器。您想要登出吗?"; "room_creation_error_invite_user_by_email_without_identity_server" = "未设置身份认证服务器,所以你不能用邮箱添加参与者。"; "contacts_address_book_no_identity_server" = "未设置身份认证服务器"; "room_participants_remove_third_party_invite_prompt_msg" = "你确定想撤回这个邀请吗?"; @@ -691,9 +691,9 @@ "room_participants_action_security_status_verified" = "已验证"; "room_participants_action_security_status_verify" = "验证"; "room_participants_action_security_status_warning" = "警告"; -"room_participants_security_loading" = "载入中……"; -"room_participants_security_information_room_not_encrypted" = "本聊天室中的消息不是端到端加密的。"; -"room_participants_security_information_room_encrypted" = "本聊天室中的消息是端到端加密的。\n\n你的消息被加锁保护,并且只有你和收信人有唯一的解密密钥。"; +"room_participants_security_loading" = "正在载入…"; +"room_participants_security_information_room_not_encrypted" = "此聊天室中的消息未经端对端加密。"; +"room_participants_security_information_room_encrypted" = "本聊天室中的消息已被端对端加密。\n\n您的消息受加密保护,并且只有您和消息接收者拥有唯一解密密钥。"; "room_accessiblity_scroll_to_bottom" = "滚动到底部"; "room_event_action_reply" = "回复"; "room_event_action_edit" = "编辑"; @@ -731,7 +731,7 @@ "settings_add_3pid_password_title_email" = "添加邮箱地址"; "settings_add_3pid_password_title_msidsn" = "添加电话号码"; "settings_add_3pid_password_message" = "请填写你的密码以继续"; -"settings_add_3pid_invalid_password_message" = "无效密码"; +"settings_add_3pid_invalid_password_message" = "验证信息无效"; "settings_key_backup_button_connect" = "关联此会话到密钥备份"; "settings_devices_description" = "会话的公开名字会对你联络的人可见"; "settings_discovery_no_identity_server" = "你现在没有在用身份认证服务器。想要被你认识的现有联系人发现,请添加。"; @@ -754,7 +754,7 @@ // Security settings "security_settings_title" = "安全"; "security_settings_crypto_sessions" = "我的会话"; -"security_settings_crypto_sessions_loading" = "载入会话中……"; +"security_settings_crypto_sessions_loading" = "正在载入会话…"; "security_settings_crypto_sessions_description" = "信任会话以给与获得端到端加密的消息的权限。如果你没有认出某个会话,请更改你的登录密码并且重设你用于消息备的消息密码。"; "security_settings_backup" = "消息备份"; "security_settings_advanced" = "高级"; @@ -775,14 +775,14 @@ "identity_server_settings_place_holder" = "输入身份认证服务器"; "identity_server_settings_add" = "添加"; "identity_server_settings_change" = "更改"; -"identity_server_settings_disconnect_info" = "从你的身份认证服务器断开连接意味着你不会被其他用户所发现并且不会被其他人通过邮箱或者电话邀请。"; +"identity_server_settings_disconnect_info" = "从你的身份认证服务器断开连接意味着你无法被其他用户所发现,并且不会被其他人通过邮箱或者电话邀请。"; "identity_server_settings_disconnect" = "断开连接"; "identity_server_settings_alert_no_terms_title" = "身份认证服务器没有服务条款"; "identity_server_settings_alert_no_terms" = "你所选择的身份认证服务器并没有任何服务条款。请仅当你信任此服务器所有人时再继续。"; "identity_server_settings_alert_change_title" = "更改身份认证服务器"; -"identity_server_settings_alert_change" = "断开身份认证服务器%1$@的连接,而连接到%2$@?"; +"identity_server_settings_alert_change" = "断开与身份认证服务器 %1$@ 的连接,转而连接到 %2$@?"; "identity_server_settings_alert_disconnect_title" = "断开连接身份认证服务器"; -"identity_server_settings_alert_disconnect" = "断开到身份认证服务器%@的连接?"; +"identity_server_settings_alert_disconnect" = "断开到身份认证服务器 %@ 的连接?"; "identity_server_settings_alert_disconnect_button" = "断开连接"; "identity_server_settings_alert_disconnect_still_sharing_3pid" = "你仍在身份认证服务器%@分享你的个人数据。\n\n我们建议你在断开连接前从此身份认证服务器删除你的邮箱地址和电话号码。"; "identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "仍然断开连接"; @@ -810,7 +810,7 @@ "widget_integration_manager_disabled" = "你需要在设置中打开“集成管理器”"; // Widget Picker "widget_picker_title" = "集成"; -"widget_picker_manage_integrations" = "管理集成……"; +"widget_picker_manage_integrations" = "管理集成…"; // Room widget permissions "room_widget_permission_title" = "载入小插件"; "room_widget_permission_creator_info_title" = "这个小插件的添加者是:"; @@ -849,13 +849,13 @@ "device_verification_incoming_description_2" = "验证此会话将标记它为已信任,而且同伴也会标记你的会话为已信任。"; // MARK: Start "device_verification_start_title" = "比较一段短文字来验证"; -"device_verification_start_wait_partner" = "等待同伴接受……"; +"device_verification_start_wait_partner" = "正在等待同伴接受…"; "device_verification_start_use_legacy" = "啥都没出现?并非所有客户端都支持交互式验证。使用旧的验证方法。"; "device_verification_start_verify_button" = "开始验证"; "device_verification_start_use_legacy_action" = "使用老式验证"; "device_verification_verify_title_emoji" = "通过确认以下emoji表情出现在同伴的屏幕上来验证此会话"; "device_verification_verify_title_number" = "通过确认以下数字出现在同伴的屏幕上来验证此会话"; -"device_verification_verify_wait_partner" = "等待同伴确认……"; +"device_verification_verify_wait_partner" = "正在等待同伴确认…"; "key_verification_verify_user_title_emoji" = "通过确认以下唯一的emoji表情,以同样顺序,出现在同伴的屏幕上来验证此用户。"; "key_verification_verify_user_title_number" = "通过确认以下数字,以同样顺序,出现在同伴的屏幕上来验证此用户。"; "device_verification_verified_title" = "已验证!"; @@ -949,8 +949,8 @@ "error_not_supported_on_mobile" = "你不能从移动版%@中进行此操作。"; "key_verification_tile_request_incoming_title" = "验证请求"; "key_verification_tile_request_outgoing_title" = "验证已发送"; -"key_verification_tile_request_status_data_loading" = "数据载入中……"; -"key_verification_tile_request_status_waiting" = "等待中……"; +"key_verification_tile_request_status_data_loading" = "正在载入数据…"; +"key_verification_tile_request_status_waiting" = "正在等待…"; "key_verification_tile_request_status_expired" = "已过期"; "key_verification_tile_request_status_cancelled_by_me" = "您已取消"; "key_verification_tile_request_status_cancelled" = "%@已取消"; @@ -963,7 +963,7 @@ "user_verification_start_verify_action" = "开始验证"; "user_verification_start_information_part1" = "为了额外的安全性,请验证: "; "user_verification_start_information_part2" = " 检查在你的两个设备上的一次性代码。"; -"user_verification_start_waiting_partner" = "等待%@……"; +"user_verification_start_waiting_partner" = "正在等待 %@…"; "user_verification_start_additional_information" = "为了安全,请当面或者使用其他通信方式进行此操作。"; "user_verification_sessions_list_user_trust_level_trusted_title" = "已信任"; "user_verification_sessions_list_user_trust_level_warning_title" = "警告"; @@ -989,16 +989,16 @@ "client_ios_name" = "Element iOS版"; "client_android_name" = "Element 安卓版"; "room_participants_action_security_status_complete_security" = "完整安全性"; -"room_participants_action_security_status_loading" = "加载中……"; -"room_member_power_level_admin_in" = "在 %@ 的管理员"; -"room_member_power_level_moderator_in" = "在 %@ 的主持人"; -"room_member_power_level_short_admin" = "管理员"; -"room_member_power_level_short_moderator" = "主持人"; +"room_participants_action_security_status_loading" = "正在加载…"; +"room_member_power_level_admin_in" = "管理员(%@)"; +"room_member_power_level_moderator_in" = "协管员(%@)"; +"room_member_power_level_short_admin" = "管理"; +"room_member_power_level_short_moderator" = "协管"; "security_settings_crosssigning" = "交叉签名"; "security_settings_crosssigning_info_not_bootstrapped" = "交叉签名还没有被设置。"; "security_settings_crosssigning_info_exists" = "您的帐户有一个交叉签名身份,但是还没有被这个会话信任。完全安全的会话。"; "skip" = "跳过"; -"room_member_power_level_custom_in" = "自定义(%@) 到%@"; +"room_member_power_level_custom_in" = "自定义(%@)(%@)"; "room_member_power_level_short_custom" = "自定义"; "security_settings_crosssigning_info_trusted" = "已启用交叉签名。您可以基于交叉签名信任其他用户和其他会话,但不能从此会话交叉签名,因为它没有交叉签名私钥。此会话完全安全。"; "security_settings_crosssigning_info_ok" = "交叉签名还没有被设置。"; @@ -1008,7 +1008,7 @@ "security_settings_cryptography" = "加密"; "security_settings_complete_security_alert_title" = "绝对安全"; "security_settings_complete_security_alert_message" = "您应该先完成当前会话的安全防护。"; -"security_settings_coming_soon" = "对不起。这个操作在Element iOS版本上还不可用。请使用另一个Matrix客户端来设置它。Elment iOS会使用它。"; +"security_settings_coming_soon" = "对不起。这个操作在 Element iOS 版本上还不可用。请使用另一个 Matrix 客户端来设置它。Elment iOS 会沿用其他客户端的设置。"; // Recover from private key "key_backup_recover_from_private_key_info" = "备份恢复中…"; // MARK: - Device Verification @@ -1023,7 +1023,7 @@ "device_verification_self_verify_alert_validate_action" = "验证"; "device_verification_self_verify_start_verify_action" = "开始验证"; "device_verification_self_verify_start_information" = "使用此会话验证您的新会话,并授予其访问加密信息的权限。"; -"device_verification_self_verify_start_waiting" = "等待中……"; +"device_verification_self_verify_start_waiting" = "正在等待…"; "key_verification_self_verify_current_session_alert_title" = "验证此会话"; "key_verification_self_verify_current_session_alert_message" = "其他用户可能不信任它。"; "key_verification_self_verify_current_session_alert_validate_action" = "验证"; @@ -1104,12 +1104,145 @@ "switch" = "开关"; "joined" = "已加入"; "store_promotional_text" = "在开放网络上保护隐私的聊天和协作应用程序。分散权力让你掌控一切。没有数据挖掘,没有后门,也没有第三方访问。"; -"social_login_button_title_sign_up" = "以 %@ 方式登录"; -"social_login_button_title_sign_in" = "以 %@ 方式登录"; -"social_login_button_title_continue" = "继续 %@ 以其他方式登录"; -"social_login_list_title_sign_in" = "利用社交媒体登录"; -"social_login_list_title_sign_up" = "利用社交媒体注册"; +"social_login_button_title_sign_up" = "使用 %@ 注册"; +"social_login_button_title_sign_in" = "使用 %@ 登录"; +"social_login_button_title_continue" = "使用 %@ 继续"; +"social_login_list_title_sign_in" = "或"; +"social_login_list_title_sign_up" = "或"; // Social login "social_login_list_title_continue" = "以其他方式登录"; +"security_settings_secure_backup_delete" = "删除"; +"security_settings_secure_backup_synchronise" = "同步"; +"security_settings_secure_backup_setup" = "设置"; +"security_settings_secure_backup_description" = "通过在您的服务器上备份加密密钥,防止失去对加密信息和数据的访问。"; +"security_settings_crypto_sessions_description_2" = "如果您未曾发起登录,请更改密码并重置安全备份。"; +"settings_show_NSFW_public_rooms" = "显示 NSFW 公共聊天室"; +"external_link_confirmation_message" = "此链接 %@ 会将您带至另一个网站:%@\n\n是否前往?"; +"external_link_confirmation_title" = "双击此链接"; +"room_open_dialpad" = "拨号键盘"; +"room_place_voice_call" = "语音通话"; +"room_event_action_delete_confirmation_message" = "您确定要删除这条未发送的消息吗?"; +"room_event_action_delete_confirmation_title" = "删除未发送的消息"; +"room_unsent_messages_cancel_message" = "您确定要删除此聊天室中所有未发送的消息吗?"; +"room_unsent_messages_cancel_title" = "删除未发送的消息"; +"room_participants_security_information_room_encrypted_for_dm" = "这里的消息已被端对端加密。\n\n您的消息受加密保护,并且只有您和消息接收者拥有唯一解密密钥。"; +"room_participants_security_information_room_not_encrypted_for_dm" = "此处的消息未经端对端加密。"; +"room_participants_filter_room_members_for_dm" = "筛选成员"; +"room_participants_leave_prompt_msg_for_dm" = "您确定要离开吗?"; +"room_participants_leave_prompt_title_for_dm" = "离开"; +"callbar_active_and_multiple_paused" = "1 个进行中通话(%@)· %@ 个已暂停通话"; +"callbar_active_and_single_paused" = "1 个进行中通话(%@)· 1 个已暂停通话"; + +// Call Bar +"callbar_only_single_active" = "进行中通话(%@)"; +"callbar_only_multiple_paused" = "%@ 个已暂停通话"; +"callbar_only_single_paused" = "已暂停通话"; +"callbar_return" = "返回"; +"room_intro_cell_information_room_sentence1_part3" = "。 "; +"room_intro_cell_information_dm_sentence1_part3" = "。 "; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "添加话题"; +"room_intro_cell_information_room_with_topic_sentence2" = "话题:%@"; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "添加人员"; +"room_avatar_view_accessibility_hint" = "修改聊天室头像"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "头像"; + +// MARK: - Invite friends + +"invite_friends_action" = "邀请好友至 %@"; + +// MARK: - Favourites + +"favourites_empty_view_title" = "收藏聊天室与对话"; + +// MARK: - Home + +"home_empty_view_title" = "欢迎使用 %@,\n%@"; +"call_transfer_error_message" = "呼叫转移失败"; +"call_transfer_error_title" = "错误"; +"call_transfer_contacts_all" = "全部"; +"call_transfer_contacts_recent" = "最近"; +"call_transfer_dialpad" = "拨号键盘"; +"call_transfer_users" = "用户"; + +// MARK: - Call Transfer +"call_transfer_title" = "转移"; + +// MARK: - Dial Pad +"dialpad_title" = "拨号键盘"; +"room_info_list_section_other" = "其他"; +"create_room_section_footer_encryption" = "加密一经启用,便无法禁用。"; +"create_room_placeholder_address" = "#testroom:matrix.org"; +"create_room_section_header_address" = "聊天室地址"; +"create_room_section_header_type" = "聊天室类型"; +"create_room_enable_encryption" = "启用加密"; +"create_room_section_header_encryption" = "聊天室加密"; +"create_room_placeholder_topic" = "话题"; +"create_room_section_header_topic" = "聊天室话题(可选)"; +"create_room_placeholder_name" = "名称"; +"create_room_section_header_name" = "聊天室名称"; + +// MARK: - Create Room + +"create_room_title" = "新聊天室"; +"searchable_directory_search_placeholder" = "名称或 ID"; +"searchable_directory_x_network" = "%@ 网络"; + +// MARK: - Searchable Directory View Controller + +"searchable_directory_create_new_room" = "创建新聊天室"; +"biometrics_cant_unlocked_alert_message_retry" = "重试"; +"biometrics_desetup_disable_button_title_x" = "禁用 %@"; +"biometrics_desetup_title_x" = "禁用 %@"; +"biometrics_setup_enable_button_title_x" = "启用 %@"; +"biometrics_setup_title_x" = "启用 %@"; +"biometrics_settings_enable_x" = "启用 %@"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - Biometrics Protection + +"biometrics_mode_touch_id" = "Touch ID"; +"pin_protection_mismatch_error_message" = "请再试一次"; +"pin_protection_reset_alert_action_reset" = "重置"; +"pin_protection_choose_pin_welcome_after_register" = "欢迎。"; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "欢迎回来。"; +"major_update_learn_more_action" = "了解更多"; + +// MARK: - Major update + +"major_update_title" = "Riot 现已成为 Element"; +"secrets_reset_reset_action" = "重置"; +"secrets_setup_recovery_passphrase_summary_title" = "保存您的安全密语"; +"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "确认安全密语"; +"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "确认"; +"secrets_setup_recovery_passphrase_additional_information" = "不要使用你的账号密码。"; +"secrets_setup_recovery_passphrase_validate_action" = "完成"; + +// Recovery passphrase + +"secrets_setup_recovery_passphrase_title" = "设置安全密语"; +"secrets_setup_recovery_key_done_action" = "完成"; +"secrets_setup_recovery_key_export_action" = "保存"; +"secrets_setup_recovery_key_loading" = "正在加载…"; + +// MARK: - Secrets set up + +// Recovery Key + +"secrets_setup_recovery_key_title" = "保存您的安全密钥"; +"room_info_list_several_members" = "%@ 位成员"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 位成员"; +"security_settings_secure_backup" = "安全备份"; From 28e34873a382bd85876b817042fdf58420abc3f1 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Wed, 24 Mar 2021 16:31:34 +0000 Subject: [PATCH 034/140] Translated using Weblate (Albanian) Currently translated at 99.6% (1182 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 77 ++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index e6057953a..b8ea07cc1 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -476,7 +476,7 @@ "room_participants_remove_third_party_invite_msg" = "Heqja e ftesave nga palë të treta nuk mbulohet ende, derisa të kihet API"; "room_participants_invite_malformed_id" = "ID e keqformuar. Duhet të jetë një adresë email ose ID Matrix, si '@localpart:domain'"; "room_participants_action_ban" = "Dëboje nga kjo dhomë"; -"room_unsent_messages_unknown_devices_notification" = "Mesazhi s’u dërgua, për shkak të pranisë së sesioneve të panjohur. %@ ose %@ tani?"; +"room_unsent_messages_unknown_devices_notification" = "Mesazhi s’u dërgua, për shkak të pranisë së sesioneve të panjohur."; "room_ongoing_conference_call" = "Thirrje konference që po zhvillohet. Merrni pjesë si %@ ose %@."; "room_ongoing_conference_call_with_close" = "Thirrje konference që po zhvillohet. Merrni pjesë si %@ ose %@. %@."; "room_conference_call_no_power" = "Ju duhen leje për të administruar thirrje konferencë në këtë dhomë"; @@ -853,7 +853,7 @@ "settings_add_3pid_password_title_email" = "Shtoni adresë email"; "settings_add_3pid_password_title_msidsn" = "Shtoni numër telefoni"; "settings_add_3pid_password_message" = "Që të vazhdohet, ju lutemi, jepni fjalëkalimin tuaj"; -"settings_add_3pid_invalid_password_message" = "Fjalëkalim i pavlefshëm"; +"settings_add_3pid_invalid_password_message" = "Kredenciale të pavlefshme"; "settings_devices_description" = "Emri publik i një sesioni është i dukshëm për persona me të cilët komunikoni"; "settings_discovery_no_identity_server" = "S’po përdorni ndonjë shërbyes identitetesh. Që të jeni i zbulueshëm nga kontakte ekzistuese që njihni, shtoni një të tillë."; "settings_discovery_terms_not_signed" = "Pajtohuni me Kushtet e Shërbimit të Shërbyesit të Identiteteve që t’i lejoni vetes të jeni i zbulueshëm përmes adrese email ose numri telefoni."; @@ -1266,3 +1266,76 @@ "rooms_empty_view_title" = "Dhoma"; "people_empty_view_information" = "Fjalosuni në mënyrë të sigurt me këdo. Prekni + që të filloni të shtoni persona."; "people_empty_view_title" = "Njerëz"; +"room_intro_cell_information_multiple_dm_sentence2" = "Në këtë bisedë jeni vetëm ju, veç nëse cilido prej jush fton dikë tjetër të vijë."; +"room_intro_cell_information_dm_sentence2" = "Në këtë bisedë gjenden vetëm ju të dy, s’mund të vijë tjetërkush."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Ky është fillimi i mesazhit tuaj të drejtpërdrejtë me "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " që t’u bëni me dije njerëzve se për çfarë është kjo dhomë."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Shtoni një temë"; +"room_intro_cell_information_room_with_topic_sentence2" = "Temë: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Ky është fillimi i "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Shtoni persona"; +"room_avatar_view_accessibility_hint" = "Ndryshoni avatar dhome"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "avatar"; +"invite_friends_share_text" = "Hej, bisedoni me mua në %@: %@"; + +// MARK: - Invite friends + +"invite_friends_action" = "Ftoni shokë te %@"; +"call_transfer_error_message" = "S’u arrit të shpërngulej thirrje"; +"call_transfer_error_title" = "Gabim"; +"call_transfer_contacts_all" = "Krejt"; +"call_transfer_contacts_recent" = "Së fundi"; +"call_transfer_dialpad" = "Numërator"; +"call_transfer_users" = "Përdorues"; + +// MARK: - Call Transfer +"call_transfer_title" = "Shpërngule"; + +// MARK: - Dial Pad +"dialpad_title" = "Numërator"; +"pin_protection_settings_change_pin" = "Ndryshoni PIN-in"; +"pin_protection_confirm_pin_to_change" = "Ripohoni PIN-in që të ndryshohet PIN"; +"secrets_recovery_with_key_recovery_key_title" = "Jepeni"; +"secrets_recovery_with_passphrase_passphrase_title" = "Jepeni"; +"bug_report_background_mode" = "Vazhdo në prapaskenë"; +"call_actions_unhold" = "Rimerre"; +"event_formatter_call_back" = "Ktheji thirrjen"; +"event_formatter_call_you_declined" = "Hodhët poshtë këtë thirrje"; +"event_formatter_call_you_currently_in" = "Gjendeni në këtë thirrje"; +"event_formatter_call_has_ended" = "Kjo thirrje ka përfunduar"; +"event_formatter_call_video" = "Thirrje video"; +"event_formatter_call_voice" = "Thirrje audio"; +"security_settings_crosssigning_reset" = "Rikthe te parazgjedhjet cross-signing"; +"security_settings_crosssigning" = "CROSS-SIGNING"; +"settings_show_NSFW_public_rooms" = "Shfaq dhoma publike NSFW"; +"room_open_dialpad" = "Numërator"; +"room_place_voice_call" = "Thirrje audio"; +"room_event_action_delete_confirmation_message" = "Jeni i sigurt se doni të fshihet ky mesazh i padërguar?"; +"room_event_action_delete_confirmation_title" = "Fshi mesazh të padërguar"; +"room_unsent_messages_cancel_message" = "Jeni i sigurt se doni të fshihen krejt mesazhet e padërguar në këtë dhomë?"; +"room_unsent_messages_cancel_title" = "Fshi mesazhet e padërguar"; +"social_login_button_title_sign_up" = "Regjistrohuni me %@"; +"social_login_button_title_sign_in" = "Hyni me %@"; +"social_login_button_title_continue" = "Vazhdo me %@"; +"social_login_list_title_sign_up" = "Ose"; +"social_login_list_title_sign_in" = "Ose"; + +// Social login + +"social_login_list_title_continue" = "Vazhdoni me"; +"callbar_return" = "Rimerre"; +"callbar_only_multiple_paused" = "%@ thirrje të ndalura"; +"callbar_only_single_paused" = "Thirrje e ndalur"; +"callbar_active_and_multiple_paused" = "1 thirrje aktive (%@) · %@ thirrje të ndalura"; +"callbar_active_and_single_paused" = "1 thirrje aktive (%@) · 1 thirrje e ndalur"; + +// Call Bar +"callbar_only_single_active" = "Thirrje aktive (%@)"; From 32768b6f4b56ce2a8c40c41d26d0fcfbb5a4a1e1 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Wed, 24 Mar 2021 20:42:24 +0000 Subject: [PATCH 035/140] Translated using Weblate (Ukrainian) Currently translated at 21.6% (257 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ --- Riot/Assets/uk.lproj/Vector.strings | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings index 0eb951189..667094056 100644 --- a/Riot/Assets/uk.lproj/Vector.strings +++ b/Riot/Assets/uk.lproj/Vector.strings @@ -288,3 +288,13 @@ "security_settings_secure_backup_delete" = "Видалити"; "security_settings_secure_backup_synchronise" = "Синхронізувати"; "security_settings_secure_backup_setup" = "Налаштувати"; +"people_empty_view_information" = "Безпечно спілкуйтеся з будь-ким. Торкніться +, щоб додати співрозмовників."; +"callbar_return" = "Повернути"; +"callbar_only_multiple_paused" = "%@ викликів у очікуванні"; +"callbar_only_single_paused" = "Виклики в очікуванні"; +"callbar_active_and_multiple_paused" = "1 активний виклик (%@) · %@ викликів у очікуванні"; +"callbar_active_and_single_paused" = "1 активний виклик (%@) · 1 виклик в очікуванні"; + +// Call Bar +"callbar_only_single_active" = "Активний виклик (%@)"; +"switch" = "Перемкнути"; From 0927154b023b85d5e5b94ad75dbcf5cb606ab52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 24 Mar 2021 15:13:39 +0000 Subject: [PATCH 036/140] Translated using Weblate (Estonian) Currently translated at 100.0% (1186 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ --- Riot/Assets/et.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index f150ffbcf..e97d22d99 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -559,7 +559,7 @@ "identity_server_settings_place_holder" = "Sisesta isikutuvastusserver"; "identity_server_settings_add" = "Lisa"; "identity_server_settings_change" = "Muuda"; -"identity_server_settings_disconnect_info" = "Isikutuvastusserveri kasutamise lõpetamine tähendab, et sa ei ole leitav teiste kasutajate poolt ega sulle ei saa telefoninumbri või e-posti aadressi alusel kutset saata. Küll aga saab kutset saata Matrix'i kasutajatunnuse alusel."; +"identity_server_settings_disconnect_info" = "Isikutuvastusserveri kasutamise lõpetamine tähendab, et sa ei ole leitav nende kasutajate poolt, kes tahavad sulle telefoninumbri või e-posti aadressi alusel kutset saata. Küll aga saab alati kutset saata Matrix'i kasutajatunnuse alusel."; "room_details_history_section_prompt_msg" = "Kui muudad seda, kes saavad selle jututoa ajalugu lugeda, siis kehtib see vaid tulevaste sõnumite kohta. Senise ajaloo nähtavus sellega ei muutu."; // Read Receipts "read_receipts_list" = "Lugemisteatiste loend"; From 99dda6e3ebf767178af07448c8e403e00d43b2d1 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Sat, 27 Mar 2021 07:51:51 +0100 Subject: [PATCH 037/140] Switching composer between text mode & action mode - Fixed: if you start typing while the new attachment sending mode is on, the send button appears --- .../Room/Views/InputToolbar/RoomInputToolbarView.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index a0b5aceb8..5997ce8bb 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -350,6 +350,8 @@ const double RoomInputToolbarViewContextBarHeight = 30; - (void)updateSendButtonWithMessage:(NSString *)textMessage { + self.actionMenuOpened = NO; + if (textMessage.length) { self.rightInputToolbarButton.alpha = 1; @@ -372,7 +374,13 @@ const double RoomInputToolbarViewContextBarHeight = 30; { _actionMenuOpened = actionMenuOpened; - self->growingTextView.internalTextView.selectedTextRange = nil; + if (self->growingTextView.internalTextView.selectedRange.length > 0) + { + NSRange range = self->growingTextView.internalTextView.selectedRange; + range.location = range.location + range.length; + range.length = 0; + self->growingTextView.internalTextView.selectedRange = range; + } if (_actionMenuOpened) { self.actionsBar.hidden = NO; From 55b47da61b6e103229e0c3f8f1fcdbfce4f2638e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexia=20=C5=ACerner?= Date: Sun, 28 Mar 2021 20:49:29 +0000 Subject: [PATCH 038/140] Translated using Weblate (Esperanto) Currently translated at 98.9% (1174 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/eo/ --- Riot/Assets/eo.lproj/Vector.strings | 226 +++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/eo.lproj/Vector.strings b/Riot/Assets/eo.lproj/Vector.strings index 2a7d6d0fd..7ae1f4577 100644 --- a/Riot/Assets/eo.lproj/Vector.strings +++ b/Riot/Assets/eo.lproj/Vector.strings @@ -128,8 +128,8 @@ "room_conference_call_no_power" = "Vi bezonas permeson administri grupvokojn en ĉi tiu ĉambro"; "room_ongoing_conference_call_close" = "Fermi"; "room_ongoing_conference_call" = "Daŭranta grupa voko. Aliĝi kiel %@ aŭ %@."; -"room_unsent_messages_unknown_devices_notification" = "Mesaĝoj ne sendiĝis pro ĉeesto de nekonataj salutaĵoj. Ĉu %@ aŭ %@ nun?"; -"room_unsent_messages_notification" = "Mesaĝoj ne sendiĝis. Ĉu %@ aŭ %@ nun?"; +"room_unsent_messages_unknown_devices_notification" = "Mesaĝoj ne sendiĝis pro ĉeesto de nekonataj salutaĵoj."; +"room_unsent_messages_notification" = "Mesaĝoj ne sendiĝis."; "room_offline_notification" = "Konekto al la servilo perdiĝis."; "room_accessiblity_scroll_to_bottom" = "Moviĝi ĝis planko"; "encrypted_room_message_placeholder" = "Sendi mesaĝon ĉifritan…"; @@ -964,7 +964,7 @@ //"settings_join_leave_rooms" = "When people join or leave rooms"; //"settings_call_invitations" = "Call invitations"; -"settings_enable_callkit" = ""; +"settings_enable_callkit" = "Integraj vokoj"; "settings_ui_theme_picker_title" = "Elektu haŭton"; "settings_ui_theme_black" = "Nigra"; "settings_ui_theme_dark" = "Malluma"; @@ -1075,3 +1075,223 @@ "room_resource_limit_exceeded_message_contact_3" = " por ke vi daŭre uzu la servilon."; "room_resource_limit_exceeded_message_contact_2_link" = "kontaktu vian serviladministranton"; "room_resource_limit_exceeded_message_contact_1" = " Bonvole "; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence2" = "Sole la paro de vi ĉeestas ĉi tiu ĉambro, neniu alia povas eniri."; +"room_intro_cell_information_multiple_dm_sentence2" = "Sole vi ĉeestas ĉi tiu ĉambro, krom se oni invitas aliulon."; +"device_verification_security_advice_emoji" = "Komparu la unikajn bildosignojn, certigante, ke ili aperas samorde."; +"key_verification_user_title" = "Kontrolu ĝin"; +"key_verification_this_session_title" = "Kontrolu ĉi tiun salutaĵon"; +"key_verification_new_session_title" = "Kontrolu vian novan salutaĵon"; + +// MARK: - Device Verification +"key_verification_other_session_title" = "Kontrolu salutaĵon"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Mi atendos"; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Mi ne volas miajn ĉifritajn mesaĝojn"; +"sign_out_key_backup_in_progress_alert_title" = "Savkopiado progresas. Se vi adiaŭos nun, vi perdos aliron al viaj ĉifritaj mesaĝoj."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Savkopii"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Adiaŭi"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Vi perdos aliron al viaj ĉifritaj mesaĝoj, se vi ne savkopios viajn ŝlosilojn antaŭ adiaŭo."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Vi perdos viajn ĉifritajn mesaĝojn"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Mi ne volas miajn ĉifritajn mesaĝojn"; +"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Ekuzi sekuran savkopiadon"; +"sign_out_non_existing_key_backup_alert_title" = "Vi perdos aliron al viaj ĉifritaj mesaĝoj se vi nun adiaŭos"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Adiaŭi"; + +// MARK: Sign out warning + +"sign_out_existing_key_backup_alert_title" = "Ĉu vi certe volas adiaŭi?"; +"key_backup_recover_done_action" = "Finite"; + +// Success + +"key_backup_recover_success_info" = "Savkopio rehaviĝis!"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Ĉu vi perdis vian rehavan ŝlosilon? Vi povas agordi novan per la Agordoj."; +"key_backup_recover_from_recovery_key_recover_action" = "Malŝlosi historion"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Enigu rehavan ŝlosilon"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Enigu"; + +// Recover from recovery key + +"key_backup_recover_from_recovery_key_info" = "Uzu vian rehavan ŝlosilon por malŝlosi vian historion de sekuraj mesaĝoj"; +"large_badge_value_k_format" = "%.1fK"; +"image_picker_action_library" = "Elekti el vidaŭdaĵujo"; +"media_picker_library" = "Vidaŭdaĵujo"; +"room_details_advanced_section" = "Altnivelaj"; +"room_details_banned_users_section" = "Forbaritaj uzantoj"; +"room_details_flair_invalid_id_prompt_msg" = "%@ ne estas valida identigilo por komunumo"; +"room_details_flair_invalid_id_prompt_title" = "Nevalida formo"; +"room_details_new_flair_placeholder" = "Aldoni novan identigilon de komunumo (ekz. +io%@)"; +"room_details_flair_section" = "Montri insignon por komunumoj"; +"room_details_addresses_disable_main_address_prompt_msg" = "Vi havos neniun specifitan ĉefan adreson. La implicita ĉefadreso por ĉi tiu ĉambro elektiĝos hazarde"; +"room_details_access_section_for_dm" = "Kiu rajtas aliri ĉi tion?"; +"room_details_access_section" = "Kiu rajtas aliri ĉi tiun ĉambron?"; +"room_details_direct_chat" = "Rekta babilo"; +"room_details_mute_notifs" = "Silentigi sciigojn"; +"room_details_low_priority_tag" = "Malalta prioritato"; +"room_details_favourite_tag" = "Elstarigita"; +"room_details_topic" = "Temo"; +"room_details_room_name_for_dm" = "Nomo"; +"room_details_room_name" = "Nomo de ĉambro"; +"room_details_photo_for_dm" = "Bildo"; +"room_details_photo" = "Bildo de ĉambro"; +"room_details_settings" = "Agordoj"; +"room_details_files" = "Alŝutoj"; +"room_details_people" = "Ĉambranoj"; +"room_details_title_for_dm" = "Detaloj"; + + +// Room Details +"room_details_title" = "Detaloj pri ĉambro"; +"identity_server_settings_alert_error_invalid_identity_server" = "%@ ne estas valida identiga servilo."; +"identity_server_settings_alert_error_terms_not_accepted" = "Vi devas akcepti la uzokondiĉojn de %@, por uzi ĝin kiel identiga servilo."; +"identity_server_settings_alert_disconnect" = "Ĉu malkonektu de la identiga servilo %@?"; +"identity_server_settings_alert_disconnect_title" = "Malkonektu identigan servilon"; +"identity_server_settings_alert_change" = "Ĉu malkonektu de identiga servilo %1$@ kaj anstataŭe konektu al %@$A?"; +"identity_server_settings_alert_change_title" = "Ŝanĝu identigan servilon"; +"identity_server_settings_alert_no_terms" = "Via elektita identiga servilo ne havas uzokondiĉojn. Daŭrigu nur se vi fidas la posedanton de tiu servilo."; +"identity_server_settings_alert_no_terms_title" = "Identiga servilo ne havas uzokondiĉojn"; +"identity_server_settings_disconnect" = "Malkonekti"; +"identity_server_settings_disconnect_info" = "Malkonektinte de via identiga servilo, vi ne troviĝus al aliaj uzantoj per, nek povos inviti uzantojn per, retpoŝtadresoj aŭ telefonnumeroj."; +"identity_server_settings_change" = "Ŝanĝi"; +"identity_server_settings_add" = "Aldoni"; +"identity_server_settings_place_holder" = "Enigu identigan servilon"; +"identity_server_settings_no_is_description" = "Vi nun ne uzas identigan servilon. Por troviĝi de kaj trovi jamajn kontaktojn, aldonu tian servilon ĉi-supre."; +"identity_server_settings_description" = "Vi uzas %@ por trovi kaj troviĝi de jamaj kontaktoj, kiujn vi konas."; + +// Identity server settings +"identity_server_settings_title" = "Identiga Servilo"; + +// AuthenticatedSessionViewControllerFactory +"authenticated_session_flow_not_supported" = "Ĉi tiu programo ne subtenas la identigan metodon de via hejmservilo."; +"manage_session_sign_out" = "Adiaŭi al ĉi tiu salutaĵo"; +"manage_session_not_trusted" = "Nefidataj"; +"manage_session_trusted" = "Fidataj de vi"; +"manage_session_name" = "Nomo de salutaĵo"; +"manage_session_info" = "INFORMOJ DE SALUTAĴO"; + +// Manage session +"manage_session_title" = "Administru salutaĵon"; +"security_settings_user_password_description" = "Konfirmi vian identon per enigo de via pasvorto"; +"security_settings_coming_soon" = "Bedaŭron. Ĉi tiu funkcio ne jam estas subtenata por Element iOS. Bonvolu uzi alian Matrix klienton por agordi ĝin. Element iOS sekvos ĝin."; +"security_settings_complete_security_alert_message" = "Vi kompletigu sekurigon je ĉi tiu salutaĵo unue."; +"security_settings_complete_security_alert_title" = "Kompletigi sekurigon"; +"security_settings_blacklist_unverified_devices_description" = "Kontroli ĉiujn salutaĵojn de uzanto, por marki ilin fidata kaj sendi mesaĝojn al ĝi."; +"security_settings_blacklist_unverified_devices" = "Neniam sendi mesaĝojn al nefidatajn salutaĵojn"; +"security_settings_advanced" = "ALTNIVELAJ"; +"security_settings_export_keys_manually" = "Elporti ŝlosilojn permane"; +"security_settings_cryptography" = "KRIPTOGRAFIO"; +"security_settings_crosssigning_complete_security" = "Kompletigi sekurigon"; +"security_settings_crosssigning_reset" = "Restarigi delegan subskribadon"; +"security_settings_crosssigning_bootstrap" = "Praŝargi delegan subskribadon"; +"security_settings_crosssigning_info_ok" = "Delega subskribado estas ŝaltita."; +"security_settings_crosssigning_info_trusted" = "Delega subskribado estas ŝaltita. Vi povas fidi aliajn uzantojn kaj viajn salutaĵojn per delegaj subskriboj, sed vi ne povas delege subskribi de ĉi tiu salutaĵo, ĉar mankas al ĝi ŝlosiloj privataj por delegaj subskriboj."; +"security_settings_crosssigning_info_exists" = "Via konto havas identon de delega subskribado, sed ne jam estas fidata de ĉi tiu salutaĵo. Kompletigu la sekurigon de ĉi tiu salutaĵo."; +"security_settings_crosssigning_info_not_bootstrapped" = "Delega subskribado ne jam agordiĝis."; +"security_settings_crosssigning" = "DELEGAJ SUBSKRIBOJ"; +"security_settings_backup" = "SAVKOPIADO DE MESAĜOJ"; +"security_settings_secure_backup_delete" = "Forigi"; +"security_settings_secure_backup_synchronise" = "Speguli"; +"security_settings_secure_backup_setup" = "Agordi"; +"security_settings_secure_backup_description" = "Malhelpu perdon de aliro al ĉifritaj mesaĝoj kaj datumoj per savkopiado de ĉifraj ŝlosiloj al via servilo."; +"security_settings_secure_backup" = "SAVKOPIADO"; +"security_settings_crypto_sessions_description_2" = "Se vi ne konas salutaĵojn, ŝanĝu vian pasvorton kaj restarigu savkopiadon."; +"security_settings_crypto_sessions_loading" = "Enlegante salutaĵojn…"; +"security_settings_crypto_sessions" = "MIAJ SALUTAĴOJ"; + +// Security settings +"security_settings_title" = "Sekureco"; +"settings_show_NSFW_public_rooms" = "Montru publikajn ĉambrojn konsternajn"; +"settings_identity_server_no_is_description" = "Vi uzas neniun identigan servilon. Por trovi kaj troviĝi de jamaj kontaktoj, kiujn vi konas, aldonu servilon supre."; +"settings_identity_server_no_is" = "Neniu identiga servilo estas agordita"; +"settings_identity_server_description" = "Uzante la identigan servilon supre agorditan, vi povas trovi kaj troviĝi de jamaj kontaktoj, kiujn vi konas."; +"settings_discovery_three_pid_details_enter_sms_code_action" = "Enigu SMS aktivigan kodon"; +"settings_discovery_three_pid_details_cancel_email_validation_action" = "Nuligi retpoŝtan kontrolon"; +"settings_discovery_three_pid_details_revoke_action" = "Senvalidigi"; +"settings_discovery_three_pid_details_share_action" = "Kunhavigi"; +"settings_discovery_three_pid_details_information_phone_number" = "Agordu ĉi tiun telefonnumeron, per kiu aliaj uzantoj povas trovi kaj inviti vin al ĉambroj. Aldonu aŭ forigu telefonnumerojn ĉe Kontoj."; +"settings_discovery_three_pid_details_title_phone_number" = "Agordu telefonnumeron"; +"settings_discovery_three_pid_details_information_email" = "Agordu ĉi tiun retpoŝtadreson, per kiu aliaj uzantoj povas trovi kaj inviti vin al ĉambroj. Aldonu aŭ forigu retpoŝtadresojn ĉe Kontoj."; +"settings_discovery_three_pid_details_title_email" = "Agordu retpoŝtadreson"; +"settings_discovery_error_message" = "Eraris iel. Bonvolu reprovi."; +"settings_discovery_three_pids_management_information_part3" = "."; +"settings_discovery_three_pids_management_information_part2" = "Agordoj de uzanto"; +"settings_discovery_three_pids_management_information_part1" = "Agordu la retpoŝtadresojn kaj telefonnumerojn per kiuj aliaj uzantoj povas trovi kaj inviti vin al ĉambroj. Aldonu aŭ forigu retpoŝtadresojn aŭ telefonnumerojn de ĉi tiu listo en "; +"settings_discovery_terms_not_signed" = "Konsentu la uzokondiĉojn de la identiga servilo (%@) por trovebligi vin per retpoŝtadreso aŭ telefonnumero."; +"settings_discovery_no_identity_server" = "Vi nun ne uzas identigan servilon. Por trovi kaj troviĝi de jamaj kontaktoj, kiujn vi konas, aldonu servilon."; +"settings_devices_description" = "Prezenta nomo de salutaĵo videblas al personoj kunbabilataj"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Ĉu vi certas? Vi perdos aliron al viaj ĉifritaj mesaĝoj, se vi ne savkopios viajn ŝlosilojn."; +"settings_key_backup_delete_confirmation_prompt_title" = "Forigi savkopion"; +"settings_key_backup_button_connect" = "Konekti ĉi tiu salutaĵo savkopionte"; +"settings_key_backup_button_delete" = "Forigi savkopion"; +"settings_key_backup_button_restore" = "Rehavigi per savkopio"; +"settings_key_backup_button_create" = "Komenci savkopiojn"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Savkopio havas nevalidan subskribon de %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Savkopio havas nevalidan subskribon de %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Savkopio havas subskribon de %@"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Savkopio havas validan subskribon de %@"; +"settings_key_backup_info_trust_signature_valid" = "Savkopio havas validan subskribon de ĉi salutaĵo"; +"settings_key_backup_info_trust_signature_unknown" = "Savkopio havas subskribon de salutaĵo kun la identigilo: %@"; +"settings_key_backup_info_progress_done" = "Ĉiuj ŝlosiloj estas savkopiitaj"; +"settings_key_backup_info_progress" = "Savkopiante %@ ŝlosilojn…"; +"settings_key_backup_info_not_valid" = "Ĉi tiu salutaĵo ne savkopias viajn ŝlosilojn, sed vi havas restantan kopion kiun vi povas alreveni kaj uzi ekde nun."; +"settings_key_backup_info_valid" = "Ĉi tiu salutaĵo savkopias viajn ŝlosilojn."; +"settings_key_backup_info_algorithm" = "Algoritmo: %@"; +"settings_key_backup_info_version" = "Savkopia Versio: %@"; +"settings_key_backup_info_signout_warning" = "Konektu ĉi tiun salutaĵon savkopie antaŭ ol vi adiaŭas, por eviti la perdiĝon de ŝlosiloj nurlokaj."; +"settings_key_backup_info_none" = "Viaj ŝlosiloj estas nesavkopiataj por ĉi tiu salutaĵo."; +"settings_key_backup_info_checking" = "Kontrolante…"; +"settings_key_backup_info" = "Mesaĝoj en ĉifritaj ĉambroj estas sekurigitaj per tutvoja ĉifrado. Nur vi kaj la adresato(j) havas la ŝlosilojn por malĉifri tiujn ĉi mesaĝojn."; +"settings_deactivate_my_account" = "Malŝalti mian konton"; +"settings_crypto_blacklist_unverified_devices" = "Ĉifri nur al kontrolitaj salutaĵoj"; +"settings_crypto_export" = "Elporti ŝlosilojn"; +"settings_crypto_device_key" = "\nŜlosilo de salutaĵo:\n"; +"settings_crypto_device_id" = "\nIdentigilo de salutaĵo: "; +"settings_crypto_device_name" = "Nomo de salutaĵo: "; +"settings_add_3pid_invalid_password_message" = "Nevalida pasvorto"; +"settings_add_3pid_password_message" = "Por daŭrigi, bonvolu enigi vian pasvorton"; +"settings_add_3pid_password_title_msidsn" = "Aldoni telefonnumeron"; +"settings_add_3pid_password_title_email" = "Aldoni retpoŝtadreson"; +"settings_password_updated" = "Via pasvorto ĝisdatiĝis"; +"settings_fail_to_update_password" = "Eraris ĝisdatigante pasvorton"; +"settings_confirm_password" = "Konfirmu pasvorton"; +"settings_global_settings_info" = "Ĉieaj sciigoj uzeblas per via retkliento %@"; +"settings_fail_to_update_profile" = "Eraris ĝisdatigante profilon"; +"room_open_dialpad" = "Ciferilo"; +"room_place_voice_call" = "Voĉvoko"; +"room_event_action_delete_confirmation_message" = "Ĉu vi certas, ke vi volas forigi ĉi tiun nesenditan mesaĝon?"; +"room_event_action_delete_confirmation_title" = "Forigi nesenditan mesaĝon"; +"room_ongoing_conference_call_with_close" = "Daŭranta grupa voko. Aliĝi kiel %@ aŭ %@. %@."; +"room_unsent_messages_cancel_message" = "Ĉu vi certas, ke vi volas forigi ĉiujn nesenditajn mesaĝojn en ĉi tiu ĉambro?"; +"room_unsent_messages_cancel_title" = "Forigi nesenditajn mesaĝojn"; +"room_member_power_level_short_moderator" = "Reg"; +"room_participants_security_loading" = "Enlegante…"; +"room_participants_action_security_status_loading" = "Enlegante…"; +"room_participants_filter_room_members_for_dm" = "Filtri ĉambranojn"; +"room_participants_add_participant" = "Aldoni partoprenanton"; +"contacts_user_directory_offline_section" = "KATALOGO DE UZANTOJ (nefunkcia)"; +"contacts_address_book_permission_denied" = "Vi ne permesis al Element aliri viajn lokajn kontaktojn"; +"rooms_empty_view_information" = "Ĉambroj taŭgas por ajna grupbabilo, privata aŭ publika. Premu la + por trovi ekzistantaj ĉambroj, aŭ fari novajn."; +"rooms_empty_view_title" = "Ĉambroj"; +"people_empty_view_information" = "Sekure babili kun iu ajn.Premu la + por inviti personojn."; +"people_empty_view_title" = "Homoj"; +"social_login_button_title_sign_up" = "Registriĝi per %@"; +"social_login_button_title_sign_in" = "Saluti per %@"; +"social_login_button_title_continue" = "Saluti per %@"; +"social_login_list_title_sign_up" = "Aŭ registriĝi per"; +"social_login_list_title_sign_in" = "Aŭ saluti per"; + +// Social login + +"social_login_list_title_continue" = "Saluti per"; +"callbar_return" = "Reveni"; +"callbar_only_multiple_paused" = "%@ paŭzigitaj vokoj"; +"callbar_only_single_paused" = "Paŭzigita voko"; +"callbar_active_and_multiple_paused" = "1 aktiva voko (%@) · %@ paŭzigitaj vokoj"; +"callbar_active_and_single_paused" = "1 aktiva voko (%@) · 1 paŭzigita voko"; + +// Call Bar +"callbar_only_single_active" = "Aktiva voko (%@)"; +"less" = "Malpli"; +"more" = "Pli"; +"switch" = "Baskuli"; +"store_promotional_text" = "Privatecgardanta babila kaj kunlabora programo, uzanta malferman reton. Ĝi estas malcentra, do vi estas la stiranto. Neniu datumamasanto nek kaŝenirejo."; From eb3b2631bde278a99b52031c8bd378fb93c03f42 Mon Sep 17 00:00:00 2001 From: Tirifto Date: Sun, 28 Mar 2021 20:48:55 +0000 Subject: [PATCH 039/140] Translated using Weblate (Esperanto) Currently translated at 98.9% (1174 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/eo/ --- Riot/Assets/eo.lproj/Vector.strings | 178 ++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/Riot/Assets/eo.lproj/Vector.strings b/Riot/Assets/eo.lproj/Vector.strings index 7ae1f4577..90ecb7d1f 100644 --- a/Riot/Assets/eo.lproj/Vector.strings +++ b/Riot/Assets/eo.lproj/Vector.strings @@ -1295,3 +1295,181 @@ "more" = "Pli"; "switch" = "Baskuli"; "store_promotional_text" = "Privatecgardanta babila kaj kunlabora programo, uzanta malferman reton. Ĝi estas malcentra, do vi estas la stiranto. Neniu datumamasanto nek kaŝenirejo."; +"room_intro_cell_information_room_with_topic_sentence2" = "Temo: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Ĉi tio estas la komenco de "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Aldoni personojn"; +"room_avatar_view_accessibility_hint" = "Ŝanĝi bildon de ĉambro"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "bildo de ĉambro"; +"invite_friends_share_text" = "Saluton! Parolu kun mi per %@: %@"; + +// MARK: - Invite friends + +"invite_friends_action" = "Inviti amikojn al %@"; +"favourites_empty_view_information" = "Vi povas elstarigi kelkmaniere – plej rapide estas simple premi kaj teni. Tuŝetu la stelon por aperigi la elstarigaton ĉi tie."; + +// MARK: - Favourites + +"favourites_empty_view_title" = "Elstarigitaj ĉambroj kaj personoj"; +"home_empty_view_information" = "La ĉionhava sekura babililo por skipoj, amikoj, kaj organizaĵoj. Tuŝetu la ĉi-suban butonon + por aldoni personojn kaj ĉambrojn."; + +// MARK: - Home + +"home_empty_view_title" = "bonvenu al %@,\n%@"; +"call_transfer_error_title" = "Eraro"; +"call_transfer_contacts_all" = "Ĉiuj"; +"call_transfer_contacts_recent" = "Freŝdataj"; +"call_transfer_users" = "Uzantoj"; +"pin_protection_settings_change_pin" = "Ŝanĝi personan identigan numeron"; +"pin_protection_confirm_pin_to_change" = "Konfirmu personan identigan numeron por ĝin ŝanĝi"; +"key_verification_bootstrap_not_setup_message" = "Vi devas praŝargi delegan subskribadon unue."; +"error_not_supported_on_mobile" = "Vi ne povas tion fari per %@ je portebla aparato."; + +// Unverified sessions + +"key_verification_self_verify_unverified_sessions_alert_title" = "Kontrolu, kie vi salutis"; +"device_verification_incoming_description_1" = "Kontrolu ĉi tiun salutaĵon por marki ĝin fidata. Fidi salutaĵojn de kunuloj helpos vin resti pli trankvila kiam vi sendas tutvoje ĉifritajn mesaĝojn."; + +// Mark: Incoming +"device_verification_incoming_title" = "Envena kontrolpeto"; +"device_verification_error_cannot_load_device" = "Ne povas enlegi informojn pri salutaĵo."; +"device_verification_cancelled_by_me" = "La kontrolo nuliĝis. Kialo: %@"; +"device_verification_cancelled" = "La aliulo nuligis la kontrolon."; +"device_verification_security_advice_number" = "Komparu la numerojn, certigante, ke ili aperas samorde."; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "uzi vian rehavan ŝlosilon"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Ĉu vi ne konas vian rehavan pasfrazon? Vi povas "; +"key_backup_recover_from_passphrase_recover_action" = "Malŝlosi historion"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Enigu pasfrazon"; +"key_backup_recover_from_passphrase_passphrase_title" = "Enigu"; + +// Recover from passphrase + +"key_backup_recover_from_passphrase_info" = "Uzu vian rehavan pasfrazon por malŝlosi vian historion de sekuraj mesaĝoj"; + +// Recover from private key +"key_backup_recover_from_private_key_info" = "Rehavante savkopion…"; +"key_backup_recover_invalid_recovery_key" = "Ne povis malĉifri savkopion per tiu ĉi ŝlosilo: bonvolu kontroli, ke vi enigis la ĝustan rehavan ŝlosilon."; +"key_backup_recover_invalid_recovery_key_title" = "Malakordo de rehava ŝlosilo"; +"key_backup_recover_invalid_passphrase" = "Ne povis malĉifri savkopion per ĉi tiu pasfrazo: bonvolu kontroli, ĉu vi ĝuste enigis la rehavan pasfrazon."; +"key_backup_recover_invalid_passphrase_title" = "Malĝusta rehava pasfrazo"; + +// MARK: Key backup recover + +"key_backup_recover_title" = "Sekuraj mesaĝoj"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Mi faris kopion"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Fari kopion"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Rehava ŝlosilo"; + +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Viaj ŝlosiloj estas savkopiataj.\n\nFaru kopion de tiu ĉi rehava ŝlosilo kaj bone ĝin sekurigu."; +"key_backup_setup_success_from_passphrase_done_action" = "Finite"; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Konservi rehavan ŝlosilon"; + +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Viaj ŝlosiloj estas savkopiataj.\n\nVia rehava ŝlosilo estas formo de asekuro – vi povas ĝin uzi por rehavi aliron al viaj ĉifritaj mesaĝoj, se vi forgesos vian pasfrazon.\n\nTenu vian rehavan ŝlosilon en loko tre sekura, kiel ekzemple administrilo de pasvortoj (aŭ sekurkesto)."; + +// Success + +"key_backup_setup_success_title" = "Sukceso!"; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Altnivele) Agordi per rehava ŝlosilo"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Aŭ sekurigu vian savkopion per rehava ŝlosilo, konservante ĝin en sekura loko."; +"key_backup_setup_passphrase_set_passphrase_action" = "Agordi pasfrazon"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Pasfrazoj ne akordas"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Bonege!"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Konfirmu pasfrazon"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Konfirmi"; +"key_backup_setup_passphrase_passphrase_invalid" = "Provu aldoni vorton"; +"key_backup_setup_passphrase_passphrase_title" = "Enigi"; + +// Passphrase + +"key_backup_setup_passphrase_title" = "Sekurigu vian savkopion per pasfrazo"; +"key_backup_setup_intro_manual_export_info" = "(Altnivele)"; +"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Konektu ĉi tiun aparaton al savkopio de ŝlosiloj"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Ekuzu savkopiadon de ŝlosiloj"; + + +// MARK: Key backup setup + +"key_backup_setup_title" = "Savkopiado de ŝlosiloj"; + +// MARK: Secure backup setup + +// Intro + +"secure_key_backup_setup_intro_title" = "Sekura savkopiado"; +"room_widget_permission_information_title" = "Uzado povas havigi datumojn al %@:\n"; +"room_widget_permission_webview_information_title" = "Uzado povas meti kuketojn kaj havigi datumojn al %@:\n"; +"bug_report_background_mode" = "Daŭrigi fone"; +"e2e_key_backup_wrong_version" = "Nova savkopio de ŝlosiloj de sekuraj mesaĝoj troviĝis.\n\nSe vi ne faris ĝin, agordu novan pasfrazon per la Agordoj."; + +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Nova savkopio de ŝlosiloj"; +"call_actions_unhold" = "Daŭrigi"; +"photo_library_access_not_granted" = "%@ ne havas permeson aliri la fotujon; bonvolu ŝanĝi agordojn de privateco"; +"event_formatter_call_back" = "Revoki"; +"event_formatter_call_you_declined" = "Vi rifuzis ĉi tiun vokon"; +"event_formatter_call_you_currently_in" = "Vi nun partoprenas ĉi tiun vokon"; +"event_formatter_call_has_ended" = "Ĉi tiu voko finiĝis"; +"event_formatter_call_video" = "Vidvoko"; +"event_formatter_call_voice" = "Voĉvoko"; + +// Media picker +"media_picker_title" = "Vidaŭdaĵoj"; +"room_details_set_main_address" = "Agordi kiel ĉefadreson"; +"room_details_save_changes_prompt" = "Ĉu vi volas konservi ŝanĝojn?"; +"room_details_fail_to_enable_encryption" = "Malsukcesis ŝalti ĉifradon en ĉi tiu ĉambro"; +"room_details_fail_to_update_room_direct" = "Malsukcesis ĝisdatigi la rektan markon de ĉi tiu ĉambro"; +"room_details_fail_to_update_room_communities" = "Malsukcesis ĝisdatigi la ritalajn komunumojn"; +"room_details_fail_to_update_room_canonical_alias" = "Malsukcesis ĝisdatigi la ĉefadreson"; +"room_details_fail_to_remove_room_aliases" = "Malsukcesis forigi la adresojn de ĉambro"; +"room_details_fail_to_add_room_aliases" = "Malsukcesis aldoni novajn adresojn de ĉambro"; +"room_details_fail_to_update_history_visibility" = "Malsukcesis ĝisdatigi videblecon de la historio"; +"room_details_fail_to_update_room_directory_visibility" = "Malsukcesis ĝisdatigi videblecon en la katalogo de ĉambroj"; +"room_details_fail_to_update_room_join_rule" = "Malsukcesis ĝisdatigi la regulon pri aliĝoj"; +"room_details_fail_to_update_room_guest_access" = "Malsukcesis ĝisdatigi aliron de gastoj al la ĉambro"; +"room_details_fail_to_update_topic" = "Malsukcesis ĝisdatigi la temon"; +"room_details_fail_to_update_room_name" = "Malsukcesis ĝisdatigi la nomon de ĉambro"; +"room_details_fail_to_update_avatar" = "Malsukcesis ĝisdatigi la bildon de ĉambro"; +"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Ĉifri nur por kontrolitaj salutaĵoj"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "Ĉifrado ne estas ŝaltita ĉi tie."; +"room_details_advanced_e2e_encryption_disabled" = "Ĉifrado ne estas ŝaltita en ĉi tiu ĉambro."; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "Ĉifrado estas ŝaltita ĉi tie"; +"room_details_advanced_e2e_encryption_enabled" = "Ĉifrado estas ŝaltita en ĉi tiu ĉambro"; +"room_details_advanced_enable_e2e_encryption" = "Ŝalti ĉifradon (averto: ne eblas malŝalti!)"; +"room_details_advanced_room_id_for_dm" = "Identigilo:"; +"room_details_advanced_room_id" = "Identigilo de ĉambro:"; +"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Vi ankoraŭ kunhavigas personajn informojn per la identiga servilo %@.\n\nNi rekomendas, ke vi forigu viajn retpoŝtadresojn kaj telefonnumerojn de la identiga servilo, antaŭ malkonekto."; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Malkonekti malgraŭe"; +"identity_server_settings_alert_disconnect_button" = "Malkonekti"; +"room_details_addresses_disable_main_address_prompt_title" = "Averto je la ĉefadreso"; +"room_details_addresses_invalid_address_prompt_msg" = "%@ ne estas valida formo por kromnomo"; +"room_details_addresses_invalid_address_prompt_title" = "Nevalido formo de kromnomo"; +"room_details_new_address_placeholder" = "Aldoni novan adreson (ekz. #io%@)"; +"room_details_new_address" = "Aldoni novan adreson"; +"room_details_no_local_addresses_for_dm" = "Ĉi tio ne havas lokajn adresojn"; +"room_details_no_local_addresses" = "Ĉi tiu ĉambro ne havas lokajn adresojn"; +"room_details_addresses_section" = "Adresoj"; +"room_details_history_section_prompt_msg" = "Ŝanĝoj al legebleco de historio nur aplikiĝos al venontaj mesaĝoj en ĉi tiu ĉambro. La videbleco de jama historio restos senŝanĝe."; +"room_details_history_section_prompt_title" = "Averto de privateco"; +"room_details_history_section_members_only_since_joined" = "Nur ĉambranoj (ekde sia aliĝo)"; +"room_details_history_section_members_only_since_invited" = "Nur ĉambranoj (ekde sia invitiĝo)"; +"room_details_history_section_members_only" = "Nur ĉambranoj (ekde ĉi tiu elekto)"; +"room_details_history_section_anyone" = "Ĉiu ajn"; +"room_details_history_section" = "Kiu rajtas legi historion?"; +"room_details_access_section_directory_toggle_for_dm" = "Listigi en katalogo de ĉambroj"; +"room_details_access_section_directory_toggle" = "Listigi ĉi tiun ĉambron en la katalogo de ĉambroj"; +"room_details_access_section_no_address_warning" = "Por ligi al ĉambro, ĝi bezonas adreson"; +"room_details_access_section_anyone_for_dm" = "Ĉiu, kiu konas la ligilon, inkluzive gastojn"; +"room_details_access_section_anyone" = "Ĉiu, kiu konas la ligilon de la ĉambro, inkluzive gastojn"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "Ĉiu, kiu konas la ligilon, krom gastoj"; +"room_details_access_section_anyone_apart_from_guest" = "Ĉiu, kiu konas la ligilon de la ĉambro, krom gastoj"; +"room_details_access_section_invited_only" = "Nur personoj, kiuj invitiĝis"; +"store_full_description" = "Element estas nova speco de mesaĝilo kaj kunlabora aplikaĵo, kiu:\n\n1. Stirigas vin por konservi vian privatecon\n2. Lasas vin komuniki kun ĉiu en la reto de Matrix, kaj eĉ ekstere, per kuniĝo kun aliaj aplikaĵoj, kiel ekzemple Slack\n3. Protektas vin de reklamoj, datumkolektado, kaŝenirejoj, kaj muritaj ĝardenoj\n4. Sekurigas vin per tutvoja ĉifrado, kun delegaj subskriboj por kontroli aliulojn\n\nElement tute malsamas de aliaj mesaĝiloj kaj kunlaboriloj, ĉar ĝi estas federa kaj malfermitkoda.\n\nElement lasas vin gastigi vin mem – aŭ elekti alian gastiganton – por ke vi havu privatecon, regon kaj kontrolon de viaj datumoj kaj interparoloj. Ĝi donas al vi aliron al malfermita reto, por ke via komunikado ne limiĝu al nur aliaj uzantoj de Element. Kaj ĝi estas tre sekura.\n\nElement povas fari ĉi ĉion, ĉar ĝi funkcias per Matrix – publika normo por malfermita, sencentra komunikado. \n\n\nElement lasas vi elekti, kiu gastigos viajn interparolojn. Per la aplikaĵo Element, vi povas elekti diversajn specojn de gastigado:\n\n1. Akiri senpagan konton ĉe la publika servilo matrix.org\n2. Memgastiĝi per via propra servilo ĉe via propra aparato\n3. Registriĝi ĉe propra servilo per simpla pagaliĝo al la gastiga platformo «Element Matrix Services»\n\nKial Element?\n\nPOSEDU VIAJN DATUMOJN: Vi decidu, kie vi tenu viajn datumojn kaj mesaĝojn. Vi posedas kaj regas ilin, ne iu granda komerca firmao, kiu kolektas viajn datumojn aŭ donas aliron al aliuloj.\n\nMALFERMAJ MESAĜADO KAJ KUNLABORADO: Vi povas babili kun ĉiu alia en la reto de Matrix, ĉu ĝi uzas Elementon aŭ alian aplikaĵon de Matrix, kaj eĉ se ĝi uzas tute alian mesaĝilon, kiel ekzemple Slack, IRC, aŭ XMPP.\n\nTRE SEKURA: Vera tutvoja ĉifrado (nur la interparolantoj povas malĉifri siajn mesaĝojn), kaj delegaj subskriboj por kontroli la aparatojn de partoprenantoj.\n\nSENMANKA KOMUNIKADO: Mesaĝoj, voĉvokoj kaj vidvokoj, havigado de dosieroj, ekrano, kaj multaj diversaj kunigoj, robotoj kaj fenestraĵoj. Kreu ĉambrojn, komunumojn, komuniku kaj kunlaboru.\n\nĈIE KUN VI: Tenu vin ĝisdata per historio de mesaĝoj plene spegulita trans ĉiuj viaj aparatoj, kaj sur la reto per https://app.element.io."; From dcc5b9cccb3f563817b74d71d175d204905c82ff Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 29 Mar 2021 22:26:03 +0200 Subject: [PATCH 040/140] Explore typing notifications inspired by web - prevent timeline from going up and down by keeping the space allocated for the typing notification --- Riot/Modules/Room/DataSources/RoomDataSource.m | 4 ++-- Riot/Modules/Room/RoomViewController.m | 17 +++++++++++++++-- .../BubbleCells/RoomTypingBubbleCell.swift | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 210f27c93..8cef6f9b2 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -273,7 +273,7 @@ [self updateStatusInfo]; } - if (self.currentTypingUsers.count == 0) + if (!self.currentTypingUsers) { self.typingCellIndex = -1; @@ -285,7 +285,7 @@ return bubbles.count + 1; } - if (self.currentTypingUsers.count == 0) + if (!self.currentTypingUsers) { self.typingCellIndex = -1; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index abac470da..6e5173a6f 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4109,9 +4109,22 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (needsUpdate) { + BOOL needsReload = roomDataSource.currentTypingUsers == nil; roomDataSource.currentTypingUsers = typingUsers; - [self.bubblesTableView reloadData]; - if (self.isScrollToBottomHidden) + if (needsReload) + { + [self.bubblesTableView reloadData]; + } + else + { + NSInteger count = [self.roomDataSource tableView:self.bubblesTableView numberOfRowsInSection:0]; + NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:count - 1 inSection:0]; + [self.bubblesTableView reloadRowsAtIndexPaths:@[lastIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + } + + if (self.isScrollToBottomHidden + && !self.bubblesTableView.isDragging + && !self.bubblesTableView.isDecelerating) { NSInteger count = [self.roomDataSource tableView:self.bubblesTableView numberOfRowsInSection:0]; if (count) diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift index b69541f88..0fdbc7a8e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift @@ -51,6 +51,8 @@ class RoomTypingBubbleCell: UITableViewCell { override func layoutSubviews() { super.layoutSubviews() + self.dotsView?.isHidden = userPictureViews.count == 0 + guard userPictureViews.count > 0 else { return } From 5c1b741ad43e5d7e74e026364b7c044f13dd8268 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 29 Mar 2021 23:04:01 +0200 Subject: [PATCH 041/140] Composer update - UI enhancements - Fixed red dot misplacement in the header --- Riot/Modules/Room/Views/Title/RoomTitleView.h | 2 ++ Riot/Modules/Room/Views/Title/RoomTitleView.m | 6 +++++- Riot/Modules/Room/Views/Title/RoomTitleView.xib | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.h b/Riot/Modules/Room/Views/Title/RoomTitleView.h index 9769d3999..d4295093f 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.h @@ -44,6 +44,8 @@ @property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedDiscussionsBadgeLabelLeadingConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureViewHeightConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *pictureViewWidthConstraint; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *dotViewCenterXConstraint; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *dotViewCenterYConstraint; /** The room preview data may be used when mxRoom instance is not available diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 37390bd80..6a338590e 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -147,6 +147,8 @@ self.pictureViewHeightConstraint.constant = 28; self.displayNameTextField.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; self.typingLabel.font = [UIFont systemFontOfSize:10]; + self.dotViewCenterXConstraint.constant = 3; + self.dotViewCenterYConstraint.constant = -2; } else { @@ -156,7 +158,9 @@ self.pictureViewHeightConstraint.constant = 32; self.displayNameTextField.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium]; self.typingLabel.font = [UIFont systemFontOfSize:12]; - } + self.dotViewCenterXConstraint.constant = 0; + self.dotViewCenterYConstraint.constant = -1; + } } - (void)setTypingNotificationString:(NSString *)typingNotificationString diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.xib b/Riot/Modules/Room/Views/Title/RoomTitleView.xib index 8280083bd..0d6fc7ca1 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.xib +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.xib @@ -71,7 +71,7 @@ - + @@ -92,6 +92,8 @@ + + From 2c83494d223069ca1f9d1bae02432829368e1539 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 29 Mar 2021 23:45:47 +0200 Subject: [PATCH 042/140] Switching composer between text mode & action mode - Fixed: The final frames of the appearance animation of the new composer buttons are missing --- Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift index 7f4bdcb98..0cf11e292 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift +++ b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift @@ -77,6 +77,7 @@ import UIKit var currentX: CGFloat = 0 for button in actionButtons { + button.transform = CGAffineTransform.identity button.frame = CGRect(x: currentX, y: 0, width: self.bounds.height, height: self.bounds.height) currentX = button.frame.maxX + itemSpacing } @@ -98,7 +99,7 @@ import UIKit button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) } for (index, button) in actionButtons.enumerated() { - UIView.animate(withDuration: 0.32, delay: 0.05 * Double(index), usingSpringWithDamping: 0.5, initialSpringVelocity: 7, options: .curveEaseInOut) { + UIView.animate(withDuration: 0.38, delay: 0.05 * Double(index), usingSpringWithDamping: 0.5, initialSpringVelocity: 7, options: .curveEaseInOut) { button.transform = CGAffineTransform.identity } completion: { (finished) in completion?(finished) @@ -106,7 +107,7 @@ import UIKit } } else { for (index, button) in actionButtons.enumerated() { - UIView.animate(withDuration: 0.2, delay: 0.05 * Double(index), options: .curveEaseInOut) { + UIView.animate(withDuration: 0.3, delay: 0.05 * Double(index), options: .curveEaseInOut) { button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) } completion: { (finished) in completion?(finished) From bce89d5ab45aee34cd9f2b56c46d85a301e87014 Mon Sep 17 00:00:00 2001 From: zer0-x <1rn0kmrwo@relay.firefox.com> Date: Sun, 28 Mar 2021 09:52:10 +0000 Subject: [PATCH 043/140] Translated using Weblate (Arabic) Currently translated at 8.6% (102 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ar/ --- Riot/Assets/ar.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/ar.lproj/Vector.strings b/Riot/Assets/ar.lproj/Vector.strings index bdf811f06..fa1146281 100644 --- a/Riot/Assets/ar.lproj/Vector.strings +++ b/Riot/Assets/ar.lproj/Vector.strings @@ -118,3 +118,4 @@ "store_full_description" = "Element هُوَ نَوعٌ جَديدٌ مِن تَطبيقاتِ المُراسَلَة وَالتَّعَاوُن الَّذي:\n\n1. يَمنَحُكَ التَّحَكُّم فِي لِلحِفاظِ عَلَى خُصُوصِيَّتِك\n2. يُتيحُ لَكَ التَّواصُلُ مَعَ أيّ شَخص عَلَى شَبَكَةِ Matrix ، وَحَتَّى خارِجَهَا مِن خِلال التَّكامُل مَعَ التَّطبيقات مِثل Slack\n3. يَحميكَ مِنَ الإعلانات، التَّنقيبُ عَنِ البَيانات، الأبوابُ الخَلفِيَّة وَعَمَلِيَّاتُ الحَدائِقِ المُسَوَّرَة\n4. يُؤمِنُكَ مِن خِلاِل تَعمِيَةِ النِّهايَة-إلى-النِّهايَة، مَعَ التَّوقيعِ المُتَبادَلِ لِلتَحَقُّقِ مِنَ الآخَرَين\n\nيَختَلِفُ Element تَمامًا عَن تَطبيقاتِ المُراسَلَةِ وَالتَّعاوُن الأُخرَى لأنَّهُ لا مَركَزي وَمَفتُوح المَصدَر.\n\nيُتيحُ لَكَ Element إمكانيةُ الاِستِضافَة الذّاتيَّة -أو اِختيارُ مُضيف- بِحَيث تَتَمَتَّع بِالخُصُوصِيَّة وَالمُلكيَّة وَالتَّحَكُّم فِي بَيانَاتك وَمُحَادَثاتك. يُتيحُ لَكَ الوُصُول إلى شَبَكَة مَفتُوحَة؛ لِذَلِكَ لا يَقتَصِرُ الأمر عَلَى التَّحدُث إلى مُستَخدِمي Element الآخَرين فَقَط. كَما اَنهُ آمِنٌ لِلغايَة.\n\nإنَّ Element قادِرٌ عَلَى إتاحَةِ كُلِ ذَلِك لِأنَهُ يَعمَلُ عَلَى Matrix -مِعيار التَّواصُل المَفتُوح اللَّامَركَزي.\n\nإنَّ Element يَمنَحُكَ زِمَامَ التَّحَكُم مِن خِلال السَّماح لَك بِاختيار مَن يَستَضيفُ المُحادَثاتِ الخَاصَّةِ بِك. مِن تَطبيقِ Element يُمكِنُكَ اِختيار الاِستِضافَة بِطُرُقٍ مُختَلِفَة:\n\n1. الحُصُول عَلَى حِساب مَجانيّ عَلَى الخادِم العَامّ matrix.org\n2. اِستِضافَة حِسابك بِنَفسِك عَن طَريق تَشغيل خادِم عَلَى أجهِزَتِكَ الخَاصَّة\n3. التَّسجيل لِلحُصُولِ عَلَى حِساب عَلَى خادِم مُخصص بمُجرد الاِشتِراك فِي مِنَصَّة اِستِضافَة Element Matrix Services\n\nلِمَاذَا تَختارُ Element؟\n\nتَملَّك بَياناتَك: أنتَ مَن تُقرر أين تَحتَفِظ ببياناتك ورسائلك. أنت تمتلكها وتتحكم فيها، وليس بعض الشركات الكُبرى الإحتكارية التي تُنقِّب عن بياناتك أو تُتيح الوصول إلى أطراف ثالثة.\n\n\nتَراسُل وَتَعَاوُن مَفتُوح يُمكِنُكَ مُحادَثَة أي شَخص آخَر عَلَى شَبَكَة Matrix، سَواءً كانُوا يَستَخدِمُونَ Element أو تَطبيقُ Matrix آخَر، وَحَتّى إذا كانُوا يَستَخدِمُونَ نِظامَ مُراسلةٍ مُختَلِف مِثل Slack أو IRC أو XMPP.\n\nالأمان-الخارِق: تَعميَة حَقيقيَة مِنَ النِّهايَة إلى النِّهايَة (فَقَط أطراف المُحادَثَة مَن يُمكِنَهُم فَكّ تَعميَة الرَّسائِل)، وَالتَّوقِيع المُتَبادَل لِلتحقق من أجهزة المُشاركين في المُحادثة.\n\nالتواصل الكامل: المُراسلة، المُكالمات الصوتية والمرئية، مُشاركة الملفات، مُشاركة الشاشة، مجموعة كاملة وكبيرة من عمليات التكامُل، الروبوتات والأدوات. بناء الغُرف، المُجتمعات، ابق على اتصال وأنجز المهام.\n\nأين ما كُنت: ابق على اتصال أينما كنت مع سجل الرسائل المتزامن بالكامل عبر جميع أجهزتك وفي الويب على https://app.element.io."; // String for App Store "store_short_description" = "مُحادَثَةٌ/VoIP آمنةٌ لَا مَركَزِيَّة"; +"auth_missing_email" = "عنوان البريد ناقص"; From d242b9f5908bfbfc43dde9a98c03ffda64ee1eab Mon Sep 17 00:00:00 2001 From: libexus Date: Mon, 29 Mar 2021 15:16:49 +0000 Subject: [PATCH 044/140] Translated using Weblate (German) Currently translated at 99.6% (1182 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index a2fe5d961..5b4213b72 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -755,7 +755,7 @@ "widget_integrations_server_failed_to_connect" = "Verbindung zum Integrationsserver fehlgeschlagen"; "device_verification_security_advice" = "Für maximale Sicherheit empfehlen wir, dies persönlich zu tun oder ein anderes vertrauenswürdiges Kommunikationsmittel zu verwenden"; "device_verification_incoming_description_1" = "Überprüfe diese Sitzung, um sie als vertrauenswürdig zu markieren. Sitzungen von Partnern zu vertrauen gibt dir zusätzliche Sicherheit bei der Verwendung von Ende-zu-Ende verschlüsselten Nachrichten."; -"device_verification_incoming_description_2" = "Wenn du diese Sitzung verifizierst, wird es sie vertrauenswürdig und für dein Gegenüber als vertrauenswürdig gekennzeichnet."; +"device_verification_incoming_description_2" = "Wenn du diese Sitzung verifizierst, wird sie für dich und für dein Gegenüber als vertrauenswürdig gekennzeichnet."; // MARK: Start "device_verification_start_title" = "Verifizieren durch Vergleichen eines kurzen Textes"; "device_verification_start_wait_partner" = "Warten auf Annahme durch Partner…"; @@ -1058,7 +1058,7 @@ "key_verification_other_session_title" = "Sitzung verifizieren"; "key_verification_new_session_title" = "Neue Sitzung verifizieren"; "key_verification_this_session_title" = "Verifiziere diese Sitzung"; -"device_verification_security_advice_emoji" = "Vergleiche die einzigartigen Emoji und stell sicher, dass sie in derselben Reihenfolge angezeigt werden."; +"device_verification_security_advice_emoji" = "Vergleiche die einzigartigen Emojis und kontrolliere, dass sie in derselben Reihenfolge angezeigt werden."; "device_verification_security_advice_number" = "Vergleiche die Zahlen und stell sicher, dass sie in derselben Reihenfolge angezeigt werden."; "key_verification_self_verify_current_session_alert_title" = "Verifiziere diese Sitzung"; "key_verification_self_verify_current_session_alert_message" = "Andere Benutzer vertrauen ihr vielleicht nicht."; From 6cc65e4fb4842ab4fec67321c9fb40b1d688210a Mon Sep 17 00:00:00 2001 From: RainSlide Date: Sun, 28 Mar 2021 15:16:45 +0000 Subject: [PATCH 045/140] Translated using Weblate (Chinese (Simplified)) Currently translated at 92.2% (1094 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/Vector.strings | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Riot/Assets/zh_Hans.lproj/Vector.strings b/Riot/Assets/zh_Hans.lproj/Vector.strings index 65d372752..858143d2f 100644 --- a/Riot/Assets/zh_Hans.lproj/Vector.strings +++ b/Riot/Assets/zh_Hans.lproj/Vector.strings @@ -466,13 +466,13 @@ "group_participants_invited_section" = "已邀请"; // Group rooms "group_rooms_filter_rooms" = "过滤社区聊天室"; -"event_formatter_widget_added" = "小部件 %@ 已被 %@ 添加"; -"event_formatter_widget_removed" = "小部件 %@ 已被 %@ 移除"; +"event_formatter_widget_added" = "挂件 %@ 已被 %@ 添加"; +"event_formatter_widget_removed" = "挂件 %@ 已被 %@ 移除"; "do_not_ask_again" = "不再询问"; "call_already_displayed" = "正在通话。"; // Widget Integration Manager "widget_integration_need_to_be_able_to_invite" = "你需要有邀请用户的权限才能进行此操作。"; -"widget_integration_unable_to_create" = "无法创建小部件。"; +"widget_integration_unable_to_create" = "无法创建挂件。"; "widget_integration_failed_to_send_request" = "发送请求失败。"; "widget_integration_room_not_recognised" = "无法识别此房间。"; "widget_integration_positive_power_level" = "权限级别必须是整数。"; @@ -489,8 +489,8 @@ "group_invitation_format" = "%@ 邀请您加入此社区"; "group_participants_invite_malformed_id" = "ID 格式错误。一个 Matrix ID 看起来应该像是 “@localpart:domain”"; // Widget -"widget_no_power_to_manage" = "你需要相关权限以管理此聊天室的小部件"; -"widget_creation_failure" = "小部件创建失败"; +"widget_no_power_to_manage" = "你需要相关权限以管理此聊天室的挂件"; +"widget_creation_failure" = "挂件创建失败"; // Room key request dialog "e2e_room_key_request_title" = "密钥共享请求"; "room_recents_server_notice_section" = "系统警告"; @@ -527,7 +527,7 @@ "room_resource_usage_limit_reached_message_contact_3" = " 以提高限制。"; // String for App Store "store_short_description" = "安全、去中心化的聊天及 VoIP 应用"; -"store_full_description" = "Element 是一种新型的通讯与协作应用:\n\n1. 使您可以掌控您的隐私\n2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯\n3. 保护您免受广告,大数据挖掘和封闭服务的侵害\n4. 通过端到端加密保证安全,通过交叉签名验证其他人\n\nElement 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。\n\nElement 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。\n\nElement 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。\n\n通过让您选择由谁来托管您的会话,Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:\n\n1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的上千个公共服务器中选择\n2. 在您自己的硬件上运行服务器,自托管您的会话\n3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户\n\n为什么选择 Element?\n\n掌控您的数据:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。\n\n开放通讯与协作:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 Slack,IRC 或 XMPP。\n\n超级安全:支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。\n\n完善的通讯方式:消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和小挂件。建立房间与社区,保持联系并完成工作。\n\n随时随地:消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。"; +"store_full_description" = "Element 是一种新型的通讯与协作应用:\n\n1. 使您可以掌控您的隐私\n2. 使您与 Matrix 网络中的任何人交流,甚至可以通过集成功能与如 Slack 之类的其他应用通讯\n3. 保护您免受广告,大数据挖掘和封闭服务的侵害\n4. 通过端到端加密保证安全,通过交叉签名验证其他人\n\nElement 与其他通讯与协作应用完全不同,因为它是去中心化且开源的。\n\nElement 允许您自托管——或者选择托管商——因此,您能拥有数据和会话的隐私权,所有权和控制权。它允许您访问开放网络;因此,您可以与 Element 用户以外的人交流。并且它非常安全。\n\nElement 之所以可以做到这些,是因为它在 Matrix 上运行——开放,去中心化通讯的标准。\n\n通过让您选择由谁来托管您的会话,Element 让您掌控一切。在 Element 应用中,您可以选择不同的托管方式:\n\n1. 在由 Matrix 开发者托管的 matrix.org 公共服务器上获取免费帐户,或从志愿者托管的上千个公共服务器中选择\n2. 在您自己的硬件上运行服务器,自托管您的会话\n3. 通过订阅 Element Matrix Services 托管平台,简单地在自定义服务器上注册账户\n\n为什么选择 Element?\n\n掌控您的数据:您来决定存放您的数据和消息的位置。拥有并控制它的是您,而不是挖掘您的数据或与第三方分享的巨型企业。\n\n开放通讯与协作:您可以与 Matrix 网络中的任何人聊天,不论他们使用 Element 还是其他 Matrix 应用,甚至/即使他们在使用不同的通讯系统,例如 Slack,IRC 或 XMPP。\n\n超级安全:支持真正的端到端加密(仅有会话中的人可以解密消息),还有能够验证会话参与方的设备的交叉签名。\n\n完善的通讯方式:消息,语音和视频通话,文件共享,屏幕共享和大量集成功能,机器人和挂件。建立房间与社区,保持联系并完成工作。\n\n随时随地:消息历史可在您的全部设备和 https://app.element.io 网页端之间完全同步,无论您在哪里,都可以保持联系。"; "auth_accept_policies" = "请查看并接受此主页服务器的服务条款:"; "room_replacement_information" = "这个聊天室已被替换,不再有效。"; "settings_flair" = "在允许的地方显示个性徽章"; From bb130d82263cb8efa856a9287b02e2fbf200a848 Mon Sep 17 00:00:00 2001 From: Tirifto Date: Sun, 28 Mar 2021 21:11:20 +0000 Subject: [PATCH 046/140] Translated using Weblate (Esperanto) Currently translated at 99.8% (1184 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/eo/ --- Riot/Assets/eo.lproj/Vector.strings | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/eo.lproj/Vector.strings b/Riot/Assets/eo.lproj/Vector.strings index 90ecb7d1f..4b7604cde 100644 --- a/Riot/Assets/eo.lproj/Vector.strings +++ b/Riot/Assets/eo.lproj/Vector.strings @@ -305,7 +305,7 @@ "auth_untrusted_id_server" = "La identiga servilo ne estas fidata"; "auth_phone_is_required" = "Neniu identiga servilo estas agordita, do vi ne povas agordi telefonnumeron por laŭbezona rehavo de konto."; "auth_email_is_required" = "Neniu identiga servilo estas agordita, do vi ne povas agordi retpoŝtadreson por laŭbezona rehavo de konto."; -"auth_phone_in_use" = "Ĉi tiu telefonnumero jam estas uzata."; +"auth_phone_in_use" = "Ĉi tiu telefonnumero jam estas uzata"; "auth_email_in_use" = "Ĉi tiu retpoŝtadreso jam estas uzata"; "auth_add_email_phone_message_2" = "Agordu retpoŝtadreson por rehavo de konto. Uzu poste retpoŝtadreson aŭ telefonon por esti laŭplaĉe trovebla de personoj, kiuj vin konas."; "auth_add_phone_message_2" = "Agordu telefonon, por via (laŭplaĉa) trovebleco de personoj, kiuj vin konas."; @@ -313,7 +313,7 @@ "joined" = "Aliĝita"; "device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Uzi rehavajn pasfrazon aŭ ŝlosilon"; "device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Uzi rehavan ŝlosilon"; -"device_verification_self_verify_wait_additional_information" = "Ĉi tio funkcias por Element kaj aliaj klientoj kapablaj je delegaj subskriboj"; +"device_verification_self_verify_wait_additional_information" = "Ĉi tio funkcias por Element kaj aliaj klientoj kapablaj je delegaj subskriboj."; "device_verification_self_verify_wait_information" = "Kontrolu ĉi tiun saluton per unu el viaj aliaj salutaĵoj, dononte al ĝi aliron al ĉifritaj mesaĝoj.\n\nUzu la plej freŝan version de Element per viaj aliaj aparatoj:"; "device_verification_self_verify_wait_new_sign_in_title" = "Kontrolu ĉi tiun saluton"; @@ -1077,7 +1077,7 @@ "room_resource_limit_exceeded_message_contact_1" = " Bonvole "; "room_intro_cell_information_dm_sentence1_part3" = ". "; "room_intro_cell_information_dm_sentence2" = "Sole la paro de vi ĉeestas ĉi tiu ĉambro, neniu alia povas eniri."; -"room_intro_cell_information_multiple_dm_sentence2" = "Sole vi ĉeestas ĉi tiu ĉambro, krom se oni invitas aliulon."; +"room_intro_cell_information_multiple_dm_sentence2" = "Sole vi ĉeestas ĉi tiun ĉambron, krom se oni invitas aliulon."; "device_verification_security_advice_emoji" = "Komparu la unikajn bildosignojn, certigante, ke ili aperas samorde."; "key_verification_user_title" = "Kontrolu ĝin"; "key_verification_this_session_title" = "Kontrolu ĉi tiun salutaĵon"; @@ -1473,3 +1473,9 @@ "room_details_access_section_anyone_apart_from_guest" = "Ĉiu, kiu konas la ligilon de la ĉambro, krom gastoj"; "room_details_access_section_invited_only" = "Nur personoj, kiuj invitiĝis"; "store_full_description" = "Element estas nova speco de mesaĝilo kaj kunlabora aplikaĵo, kiu:\n\n1. Stirigas vin por konservi vian privatecon\n2. Lasas vin komuniki kun ĉiu en la reto de Matrix, kaj eĉ ekstere, per kuniĝo kun aliaj aplikaĵoj, kiel ekzemple Slack\n3. Protektas vin de reklamoj, datumkolektado, kaŝenirejoj, kaj muritaj ĝardenoj\n4. Sekurigas vin per tutvoja ĉifrado, kun delegaj subskriboj por kontroli aliulojn\n\nElement tute malsamas de aliaj mesaĝiloj kaj kunlaboriloj, ĉar ĝi estas federa kaj malfermitkoda.\n\nElement lasas vin gastigi vin mem – aŭ elekti alian gastiganton – por ke vi havu privatecon, regon kaj kontrolon de viaj datumoj kaj interparoloj. Ĝi donas al vi aliron al malfermita reto, por ke via komunikado ne limiĝu al nur aliaj uzantoj de Element. Kaj ĝi estas tre sekura.\n\nElement povas fari ĉi ĉion, ĉar ĝi funkcias per Matrix – publika normo por malfermita, sencentra komunikado. \n\n\nElement lasas vi elekti, kiu gastigos viajn interparolojn. Per la aplikaĵo Element, vi povas elekti diversajn specojn de gastigado:\n\n1. Akiri senpagan konton ĉe la publika servilo matrix.org\n2. Memgastiĝi per via propra servilo ĉe via propra aparato\n3. Registriĝi ĉe propra servilo per simpla pagaliĝo al la gastiga platformo «Element Matrix Services»\n\nKial Element?\n\nPOSEDU VIAJN DATUMOJN: Vi decidu, kie vi tenu viajn datumojn kaj mesaĝojn. Vi posedas kaj regas ilin, ne iu granda komerca firmao, kiu kolektas viajn datumojn aŭ donas aliron al aliuloj.\n\nMALFERMAJ MESAĜADO KAJ KUNLABORADO: Vi povas babili kun ĉiu alia en la reto de Matrix, ĉu ĝi uzas Elementon aŭ alian aplikaĵon de Matrix, kaj eĉ se ĝi uzas tute alian mesaĝilon, kiel ekzemple Slack, IRC, aŭ XMPP.\n\nTRE SEKURA: Vera tutvoja ĉifrado (nur la interparolantoj povas malĉifri siajn mesaĝojn), kaj delegaj subskriboj por kontroli la aparatojn de partoprenantoj.\n\nSENMANKA KOMUNIKADO: Mesaĝoj, voĉvokoj kaj vidvokoj, havigado de dosieroj, ekrano, kaj multaj diversaj kunigoj, robotoj kaj fenestraĵoj. Kreu ĉambrojn, komunumojn, komuniku kaj kunlaboru.\n\nĈIE KUN VI: Tenu vin ĝisdata per historio de mesaĝoj plene spegulita trans ĉiuj viaj aparatoj, kaj sur la reto per https://app.element.io."; +"directory_server_all_native_rooms" = "Ĉiuj ĉambroj, propraj al Matrix"; +"call_transfer_error_message" = "Malsukcesis transdono de voko"; + +// MARK: - Call Transfer +"call_transfer_title" = "Transdono"; +"room_intro_cell_information_dm_sentence1_part1" = "Ĉi tie komencas historio de viaj rektaj mesaĝoj kun "; From 3da3ecd45c42ead75650a0b065a60c64f9c4ee06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexia=20=C5=ACerner?= Date: Sun, 28 Mar 2021 20:57:51 +0000 Subject: [PATCH 047/140] Translated using Weblate (Esperanto) Currently translated at 99.8% (1184 of 1186 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/eo/ --- Riot/Assets/eo.lproj/Vector.strings | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Riot/Assets/eo.lproj/Vector.strings b/Riot/Assets/eo.lproj/Vector.strings index 4b7604cde..71c9a87a2 100644 --- a/Riot/Assets/eo.lproj/Vector.strings +++ b/Riot/Assets/eo.lproj/Vector.strings @@ -1479,3 +1479,7 @@ // MARK: - Call Transfer "call_transfer_title" = "Transdono"; "room_intro_cell_information_dm_sentence1_part1" = "Ĉi tie komencas historio de viaj rektaj mesaĝoj kun "; +"call_transfer_dialpad" = "Ciferplato"; + +// MARK: - Dial Pad +"dialpad_title" = "Ciferplato"; From 550c4033ea14cff4cf8e171a8534c1716819271f Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 31 Mar 2021 19:04:00 +0200 Subject: [PATCH 048/140] Make the application settings more configurable --- Config/BuildSettings.swift | 2 + Riot/Generated/Strings.swift | 2 +- Riot/Managers/Settings/RiotSettings.swift | 27 ++++++ .../Security/SecurityViewController.m | 83 +++++++++++-------- .../Modules/Settings/SettingsViewController.m | 29 +++++-- 5 files changed, 101 insertions(+), 42 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index d06d29747..df69674d0 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -109,6 +109,8 @@ final class BuildSettings: NSObject { // MARK: - Legal URLs + + // Note: Set empty strings to hide the related entry in application settings static let applicationCopyrightUrlString = "https://element.io/copyright" static let applicationPrivacyPolicyUrlString = "https://element.io/privacy" static let applicationTermsConditionsUrlString = "https://element.io/terms-of-service" diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 218303eaf..5de375e70 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1514,7 +1514,7 @@ internal enum VectorL10n { internal static var identityServerSettingsDisconnect: String { return VectorL10n.tr("Vector", "identity_server_settings_disconnect") } - /// Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone. + /// Disconnecting from your identity server will mean you won’t be discoverable by other users and be able to invite others by email or phone. internal static var identityServerSettingsDisconnectInfo: String { return VectorL10n.tr("Vector", "identity_server_settings_disconnect_info") } diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 5627d7369..7dbbc84d7 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -37,6 +37,9 @@ final class RiotSettings: NSObject { static let hideReviewSessionsAlert = "hideReviewSessionsAlert" static let matrixApps = "matrixApps" static let showNSFWPublicRooms = "showNSFWPublicRooms" + static let accountManagedExternally = "accountManagedExternally" + static let inviteFriendsNotAllowed = "inviteFriendsNotAllowed" + static let callsSettingsManagedExternally = "callsSettingsManagedExternally" } static let shared = RiotSettings() @@ -212,4 +215,28 @@ final class RiotSettings: NSObject { defaults.set(newValue, forKey: UserDefaultsKeys.matrixApps) } } + + var inviteFriendsNotAllowed: Bool { + get { + return defaults.bool(forKey: UserDefaultsKeys.inviteFriendsNotAllowed) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.inviteFriendsNotAllowed) + } + } + + var accountManagedExternally: Bool { + get { + return defaults.bool(forKey: UserDefaultsKeys.accountManagedExternally) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.accountManagedExternally) + } + } + + var callsSettingsManagedExternally: Bool { + get { + return defaults.bool(forKey: UserDefaultsKeys.callsSettingsManagedExternally) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.callsSettingsManagedExternally) + } + } } diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index 291a02d73..48dfc2e87 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -329,41 +329,53 @@ TableViewSectionsDelegate> // Crypto sessions section - Section *sessionsSection = [Section sectionWithTag:SECTION_CRYPTO_SESSIONS]; - - sessionsSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_crypto_sessions", @"Vector", nil); - - NSUInteger sessionsSectionRowsCount; - - if (self.showLoadingDevicesInformation) + if (!RiotSettings.shared.accountManagedExternally) { - sessionsSectionRowsCount = 2; - } else { - sessionsSectionRowsCount = devicesArray.count + 1; - } + Section *sessionsSection = [Section sectionWithTag:SECTION_CRYPTO_SESSIONS]; + + sessionsSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_crypto_sessions", @"Vector", nil); + + NSUInteger sessionsSectionRowsCount; + + if (self.showLoadingDevicesInformation) + { + sessionsSectionRowsCount = 2; + } + else + { + sessionsSectionRowsCount = devicesArray.count + 1; + } - [sessionsSection addRowsWithCount:sessionsSectionRowsCount]; - - [sections addObject:sessionsSection]; + [sessionsSection addRowsWithCount:sessionsSectionRowsCount]; + + [sections addObject:sessionsSection]; + } // Secure backup - - Section *secureBackupSection = [Section sectionWithTag:SECTION_SECURE_BACKUP]; - secureBackupSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_secure_backup", @"Vector", nil); - - [secureBackupSection addRowsWithCount:[self numberOfRowsInSecureBackupSection]]; - - [sections addObject:secureBackupSection]; + if (!RiotSettings.shared.accountManagedExternally) + { + Section *secureBackupSection = [Section sectionWithTag:SECTION_SECURE_BACKUP]; + secureBackupSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_secure_backup", @"Vector", nil); + + [secureBackupSection addRowsWithCount:[self numberOfRowsInSecureBackupSection]]; + + [sections addObject:secureBackupSection]; + } // Cryptograhpy - Section *cryptograhpySection = [Section sectionWithTag:SECTION_CRYPTOGRAPHY]; - cryptograhpySection.headerTitle = NSLocalizedStringFromTable(@"security_settings_cryptography", @"Vector", nil); - - [cryptograhpySection addRowsWithCount:CRYPTOGRAPHY_COUNT]; - - [sections addObject:cryptograhpySection]; + if (!RiotSettings.shared.accountManagedExternally) + { + Section *cryptograhpySection = [Section sectionWithTag:SECTION_CRYPTOGRAPHY]; + cryptograhpySection.headerTitle = NSLocalizedStringFromTable(@"security_settings_cryptography", @"Vector", nil); + + [cryptograhpySection addRowWithTag:CRYPTOGRAPHY_INFO]; + + [cryptograhpySection addRowWithTag:CRYPTOGRAPHY_EXPORT]; + + [sections addObject:cryptograhpySection]; + } #ifdef CROSS_SIGNING_AND_BACKUP_DEV @@ -389,13 +401,16 @@ TableViewSectionsDelegate> // Advanced - Section *advancedSection = [Section sectionWithTag:SECTION_ADVANCED]; - advancedSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_advanced", @"Vector", nil); - - [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES]; - [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES_DESCRIPTION]; - - [sections addObject:advancedSection]; + if (!RiotSettings.shared.accountManagedExternally) + { + Section *advancedSection = [Section sectionWithTag:SECTION_ADVANCED]; + advancedSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_advanced", @"Vector", nil); + + [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES]; + [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES_DESCRIPTION]; + + [sections addObject:advancedSection]; + } // Update sections diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index fdac6daff..923c6717d 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -300,7 +300,10 @@ TableViewSectionsDelegate> Section *sectionUserSettings = [Section sectionWithTag:SECTION_TAG_USER_SETTINGS]; [sectionUserSettings addRowWithTag:USER_SETTINGS_PROFILE_PICTURE_INDEX]; [sectionUserSettings addRowWithTag:USER_SETTINGS_DISPLAYNAME_INDEX]; - [sectionUserSettings addRowWithTag:USER_SETTINGS_CHANGE_PASSWORD_INDEX]; + if (!RiotSettings.shared.accountManagedExternally) + { + [sectionUserSettings addRowWithTag:USER_SETTINGS_CHANGE_PASSWORD_INDEX]; + } if (BuildSettings.settingsScreenShowUserFirstName) { [sectionUserSettings addRowWithTag:USER_SETTINGS_FIRST_NAME_INDEX]; @@ -332,8 +335,10 @@ TableViewSectionsDelegate> { [sectionUserSettings addRowWithTag:USER_SETTINGS_THREEPIDS_INFORMATION_INDEX]; } - - [sectionUserSettings addRowWithTag:USER_SETTINGS_INVITE_FRIENDS_INDEX]; + if (!RiotSettings.shared.inviteFriendsNotAllowed) + { + [sectionUserSettings addRowWithTag:USER_SETTINGS_INVITE_FRIENDS_INDEX]; + } sectionUserSettings.headerTitle = NSLocalizedStringFromTable(@"settings_user_settings", @"Vector", nil); [tmpSections addObject:sectionUserSettings]; @@ -352,7 +357,8 @@ TableViewSectionsDelegate> sectionNotificationSettings.headerTitle = NSLocalizedStringFromTable(@"settings_notifications_settings", @"Vector", nil); [tmpSections addObject:sectionNotificationSettings]; - if (BuildSettings.allowVoIPUsage && BuildSettings.stunServerFallbackUrlString) + if (BuildSettings.allowVoIPUsage && BuildSettings.stunServerFallbackUrlString + && !RiotSettings.shared.callsSettingsManagedExternally) { Section *sectionCalls = [Section sectionWithTag:SECTION_TAG_CALLS]; [sectionCalls addRowWithTag:CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX]; @@ -432,9 +438,18 @@ TableViewSectionsDelegate> Section *sectionOther = [Section sectionWithTag:SECTION_TAG_OTHER]; [sectionOther addRowWithTag:OTHER_VERSION_INDEX]; [sectionOther addRowWithTag:OTHER_OLM_VERSION_INDEX]; - [sectionOther addRowWithTag:OTHER_COPYRIGHT_INDEX]; - [sectionOther addRowWithTag:OTHER_TERM_CONDITIONS_INDEX]; - [sectionOther addRowWithTag:OTHER_PRIVACY_INDEX]; + if (BuildSettings.applicationCopyrightUrlString.length) + { + [sectionOther addRowWithTag:OTHER_COPYRIGHT_INDEX]; + } + if (BuildSettings.applicationTermsConditionsUrlString.length) + { + [sectionOther addRowWithTag:OTHER_TERM_CONDITIONS_INDEX]; + } + if (BuildSettings.applicationPrivacyPolicyUrlString.length) + { + [sectionOther addRowWithTag:OTHER_PRIVACY_INDEX]; + } [sectionOther addRowWithTag:OTHER_THIRD_PARTY_INDEX]; [sectionOther addRowWithTag:OTHER_SHOW_NSFW_ROOMS_INDEX]; From 13aded46b93b802de7f2aa0a3754c288f29566eb Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 1 Apr 2021 07:55:04 +0200 Subject: [PATCH 049/140] Updated CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 09d797340..49117bff7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,7 @@ Changes to be released in next version * 🙌 Improvements - * + * Make the application settings more configurable (#4171) 🐛 Bugfix * From 9b4cb2f94f21d6baabbbe61898861ef73a8a3048 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 1 Apr 2021 14:16:06 +0200 Subject: [PATCH 050/140] Make the application settings more configurable - Update after review --- Config/BuildSettings.swift | 12 +- Riot/Managers/Settings/RiotSettings.swift | 127 ++++++++++++++++-- Riot/Modules/Application/LegacyAppDelegate.m | 4 + .../Security/SecurityViewController.m | 83 +++++++----- .../Modules/Settings/SettingsViewController.m | 21 ++- 5 files changed, 192 insertions(+), 55 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index df69674d0..5612061e0 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -227,7 +227,17 @@ final class BuildSettings: NSObject { static let settingsScreenAllowChangingCrashUsageDataSettings: Bool = true static let settingsScreenAllowBugReportingManually: Bool = true static let settingsScreenAllowDeactivatingAccount: Bool = true - + static let settingsScreenShowChangePassword:Bool = true + static let settingsScreenShowInviteFriends:Bool = true + static let settingsScreenShowEnableStunServerFallback: Bool = true + static let settingsSecurityScreenShowSessions:Bool = true + static let settingsSecurityScreenShowSetupBackup:Bool = true + static let settingsSecurityScreenShowRestoreBackup:Bool = true + static let settingsSecurityScreenShowDeleteBackup:Bool = true + static let settingsSecurityScreenShowCryptographyInfo:Bool = true + static let settingsSecurityScreenShowCryptographyExport:Bool = true + static let settingsSecurityScreenShowAdvancedUnverifiedDevices:Bool = true + // MARK: - Timeline settings static let roomInputToolbarCompressionMode = MXKRoomInputToolbarCompressionModePrompt diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 7dbbc84d7..014f4502d 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -37,9 +37,16 @@ final class RiotSettings: NSObject { static let hideReviewSessionsAlert = "hideReviewSessionsAlert" static let matrixApps = "matrixApps" static let showNSFWPublicRooms = "showNSFWPublicRooms" - static let accountManagedExternally = "accountManagedExternally" - static let inviteFriendsNotAllowed = "inviteFriendsNotAllowed" - static let callsSettingsManagedExternally = "callsSettingsManagedExternally" + static let settingsScreenShowChangePassword = "settingsScreenShowChangePassword" + static let settingsScreenShowInviteFriends = "settingsScreenShowInviteFriends" + static let settingsScreenShowEnableStunServerFallback = "settingsScreenShowEnableStunServerFallback" + static let settingsSecurityScreenShowSessions = "settingsSecurityScreenShowSessions" + static let settingsSecurityScreenShowSetupBackup = "settingsSecurityScreenShowSetupBackup" + static let settingsSecurityScreenShowRestoreBackup = "settingsSecurityScreenShowRestoreBackup" + static let settingsSecurityScreenShowDeleteBackup = "settingsSecurityScreenShowDeleteBackup" + static let settingsSecurityScreenShowCryptographyInfo = "settingsSecurityScreenShowCryptographyInfo" + static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport" + static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices" } static let shared = RiotSettings() @@ -54,6 +61,19 @@ final class RiotSettings: NSObject { // MARK: - Public + func reset() { + defaults.removeObject(forKey: UserDefaultsKeys.settingsScreenShowChangePassword) + defaults.removeObject(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) + defaults.removeObject(forKey: UserDefaultsKeys.settingsScreenShowEnableStunServerFallback) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) + defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) + } + // MARK: Servers var homeserverUrlString: String { @@ -216,27 +236,106 @@ final class RiotSettings: NSObject { } } - var inviteFriendsNotAllowed: Bool { + // MARK: General Settings + + var settingsScreenShowChangePassword: Bool { get { - return defaults.bool(forKey: UserDefaultsKeys.inviteFriendsNotAllowed) + guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowChangePassword) != nil else { + return BuildSettings.settingsScreenShowChangePassword + } + return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowChangePassword) } set { - defaults.set(newValue, forKey: UserDefaultsKeys.inviteFriendsNotAllowed) + defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowChangePassword) } } - - var accountManagedExternally: Bool { + var settingsScreenShowInviteFriends: Bool { get { - return defaults.bool(forKey: UserDefaultsKeys.accountManagedExternally) + guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) != nil else { + return BuildSettings.settingsScreenShowInviteFriends + } + return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) } set { - defaults.set(newValue, forKey: UserDefaultsKeys.accountManagedExternally) + defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) } } - - var callsSettingsManagedExternally: Bool { + var settingsScreenShowEnableStunServerFallback: Bool { get { - return defaults.bool(forKey: UserDefaultsKeys.callsSettingsManagedExternally) + guard defaults.object(forKey: UserDefaultsKeys.settingsScreenShowInviteFriends) != nil else { + return BuildSettings.settingsScreenShowEnableStunServerFallback + } + return defaults.bool(forKey: UserDefaultsKeys.settingsScreenShowEnableStunServerFallback) } set { - defaults.set(newValue, forKey: UserDefaultsKeys.callsSettingsManagedExternally) + defaults.set(newValue, forKey: UserDefaultsKeys.settingsScreenShowEnableStunServerFallback) + } + } + var settingsSecurityScreenShowSessions: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions) != nil else { + return BuildSettings.settingsSecurityScreenShowSessions + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowSessions) + } + } + var settingsSecurityScreenShowSetupBackup: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup) != nil else { + return BuildSettings.settingsSecurityScreenShowSetupBackup + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowSetupBackup) + } + } + var settingsSecurityScreenShowRestoreBackup: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup) != nil else { + return BuildSettings.settingsSecurityScreenShowRestoreBackup + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowRestoreBackup) + } + } + var settingsSecurityScreenShowDeleteBackup: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup) != nil else { + return BuildSettings.settingsSecurityScreenShowDeleteBackup + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowDeleteBackup) + } + } + var settingsSecurityScreenShowCryptographyInfo: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) != nil else { + return BuildSettings.settingsSecurityScreenShowCryptographyInfo + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) + } + } + var settingsSecurityScreenShowCryptographyExport: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) != nil else { + return BuildSettings.settingsSecurityScreenShowCryptographyExport + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) + } + } + var settingsSecurityScreenShowAdvancedUnverifiedDevices: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) != nil else { + return BuildSettings.settingsSecurityScreenShowAdvancedUnverifiedDevices + } + return defaults.bool(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) } } } diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 4c4ff28f3..501021ddc 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2136,6 +2136,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [self logoutSendingRequestServer:YES completion:^(BOOL isLoggedOut) { if (completion) { + if (isLoggedOut) + { + [RiotSettings.shared reset]; + } completion (YES); } }]; diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index 48dfc2e87..c087bdfb6 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -329,7 +329,7 @@ TableViewSectionsDelegate> // Crypto sessions section - if (!RiotSettings.shared.accountManagedExternally) + if (RiotSettings.shared.settingsSecurityScreenShowSessions) { Section *sessionsSection = [Section sectionWithTag:SECTION_CRYPTO_SESSIONS]; @@ -353,30 +353,36 @@ TableViewSectionsDelegate> // Secure backup - if (!RiotSettings.shared.accountManagedExternally) + Section *secureBackupSection = [Section sectionWithTag:SECTION_SECURE_BACKUP]; + secureBackupSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_secure_backup", @"Vector", nil); + + [secureBackupSection addRowsWithCount:[self numberOfRowsInSecureBackupSection]]; + + if (secureBackupSection.rows.count) { - Section *secureBackupSection = [Section sectionWithTag:SECTION_SECURE_BACKUP]; - secureBackupSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_secure_backup", @"Vector", nil); - - [secureBackupSection addRowsWithCount:[self numberOfRowsInSecureBackupSection]]; - [sections addObject:secureBackupSection]; } // Cryptograhpy - if (!RiotSettings.shared.accountManagedExternally) + Section *cryptograhpySection = [Section sectionWithTag:SECTION_CRYPTOGRAPHY]; + cryptograhpySection.headerTitle = NSLocalizedStringFromTable(@"security_settings_cryptography", @"Vector", nil); + + if (RiotSettings.shared.settingsSecurityScreenShowCryptographyInfo) { - Section *cryptograhpySection = [Section sectionWithTag:SECTION_CRYPTOGRAPHY]; - cryptograhpySection.headerTitle = NSLocalizedStringFromTable(@"security_settings_cryptography", @"Vector", nil); - [cryptograhpySection addRowWithTag:CRYPTOGRAPHY_INFO]; - - [cryptograhpySection addRowWithTag:CRYPTOGRAPHY_EXPORT]; - - [sections addObject:cryptograhpySection]; } + if (RiotSettings.shared.settingsSecurityScreenShowCryptographyExport) + { + [cryptograhpySection addRowWithTag:CRYPTOGRAPHY_EXPORT]; + } + + if (cryptograhpySection.rows.count) + { + [sections addObject:cryptograhpySection]; + } + #ifdef CROSS_SIGNING_AND_BACKUP_DEV // Cross-Signing @@ -401,17 +407,20 @@ TableViewSectionsDelegate> // Advanced - if (!RiotSettings.shared.accountManagedExternally) + Section *advancedSection = [Section sectionWithTag:SECTION_ADVANCED]; + advancedSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_advanced", @"Vector", nil); + + if (RiotSettings.shared.settingsSecurityScreenShowAdvancedUnverifiedDevices) { - Section *advancedSection = [Section sectionWithTag:SECTION_ADVANCED]; - advancedSection.headerTitle = NSLocalizedStringFromTable(@"security_settings_advanced", @"Vector", nil); - [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES]; [advancedSection addRowWithTag:ADVANCED_BLACKLIST_UNVERIFIED_DEVICES_DESCRIPTION]; - + } + + if (advancedSection.rows.count) + { [sections addObject:advancedSection]; } - + // Update sections self.tableViewSections.sections = sections; @@ -868,28 +877,36 @@ TableViewSectionsDelegate> - (void)refreshSecureBackupSectionData { MXRecoveryService *recoveryService = self.mainSession.crypto.recoveryService; + NSMutableArray *secureBackupSectionState = [NSMutableArray new]; if (recoveryService.hasRecovery) { - secureBackupSectionState = @[ - @(SECURE_BACKUP_RESTORE), - @(SECURE_BACKUP_DELETE), - @(SECURE_BACKUP_DESCRIPTION), - //@(SECURE_BACKUP_MANAGE_MANUALLY), - ]; + if (RiotSettings.shared.settingsSecurityScreenShowRestoreBackup) + { + [secureBackupSectionState addObject:@(SECURE_BACKUP_RESTORE)]; + } + if (RiotSettings.shared.settingsSecurityScreenShowDeleteBackup) + { + [secureBackupSectionState addObject:@(SECURE_BACKUP_DELETE)]; + } } else { - secureBackupSectionState = @[ - @(SECURE_BACKUP_SETUP), - @(SECURE_BACKUP_DESCRIPTION), - //@(SECURE_BACKUP_MANAGE_MANUALLY), - ]; + if (RiotSettings.shared.settingsSecurityScreenShowSetupBackup) + { + [secureBackupSectionState addObject:@(SECURE_BACKUP_SETUP)]; + } } + if (secureBackupSectionState.count) + { + [secureBackupSectionState addObject:@(SECURE_BACKUP_DESCRIPTION)]; + } + #ifdef CROSS_SIGNING_AND_BACKUP_DEV - secureBackupSectionState = [@[@(SECURE_BACKUP_INFO)] arrayByAddingObjectsFromArray:secureBackupSectionState]; + [secureBackupSectionState addObject:@(SECURE_BACKUP_INFO)]; #endif + self->secureBackupSectionState = secureBackupSectionState; } - (NSUInteger)secureBackupSectionEnumForRow:(NSUInteger)row diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 923c6717d..12adb0364 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -300,7 +300,7 @@ TableViewSectionsDelegate> Section *sectionUserSettings = [Section sectionWithTag:SECTION_TAG_USER_SETTINGS]; [sectionUserSettings addRowWithTag:USER_SETTINGS_PROFILE_PICTURE_INDEX]; [sectionUserSettings addRowWithTag:USER_SETTINGS_DISPLAYNAME_INDEX]; - if (!RiotSettings.shared.accountManagedExternally) + if (RiotSettings.shared.settingsScreenShowChangePassword) { [sectionUserSettings addRowWithTag:USER_SETTINGS_CHANGE_PASSWORD_INDEX]; } @@ -335,7 +335,7 @@ TableViewSectionsDelegate> { [sectionUserSettings addRowWithTag:USER_SETTINGS_THREEPIDS_INFORMATION_INDEX]; } - if (!RiotSettings.shared.inviteFriendsNotAllowed) + if (RiotSettings.shared.settingsScreenShowInviteFriends) { [sectionUserSettings addRowWithTag:USER_SETTINGS_INVITE_FRIENDS_INDEX]; } @@ -357,14 +357,21 @@ TableViewSectionsDelegate> sectionNotificationSettings.headerTitle = NSLocalizedStringFromTable(@"settings_notifications_settings", @"Vector", nil); [tmpSections addObject:sectionNotificationSettings]; - if (BuildSettings.allowVoIPUsage && BuildSettings.stunServerFallbackUrlString - && !RiotSettings.shared.callsSettingsManagedExternally) + if (BuildSettings.allowVoIPUsage && BuildSettings.stunServerFallbackUrlString) { Section *sectionCalls = [Section sectionWithTag:SECTION_TAG_CALLS]; - [sectionCalls addRowWithTag:CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX]; - [sectionCalls addRowWithTag:CALLS_STUN_SERVER_FALLBACK_DESCRIPTION_INDEX]; sectionCalls.headerTitle = NSLocalizedStringFromTable(@"settings_calls_settings", @"Vector", nil); - [tmpSections addObject:sectionCalls]; + + if (RiotSettings.shared.settingsScreenShowEnableStunServerFallback) + { + [sectionCalls addRowWithTag:CALLS_ENABLE_STUN_SERVER_FALLBACK_INDEX]; + [sectionCalls addRowWithTag:CALLS_STUN_SERVER_FALLBACK_DESCRIPTION_INDEX]; + } + + if (sectionCalls.rows.count) + { + [tmpSections addObject:sectionCalls]; + } } if (BuildSettings.settingsScreenShowDiscoverySettings) From a5526415fbe53f4c3a170dc171395ee41a7e07d2 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 1 Apr 2021 15:02:43 +0200 Subject: [PATCH 051/140] Enable / disable external friends invite --- Config/BuildSettings.swift | 2 ++ Riot/Managers/Settings/RiotSettings.swift | 15 +++++++++++++++ .../Contacts/DataSources/ContactsDataSource.m | 2 +- Riot/Modules/StartChat/StartChatViewController.m | 6 ++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 5612061e0..ef6fc2a87 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -195,6 +195,8 @@ final class BuildSettings: NSObject { static let allowLocalContactsAccess: Bool = true + static let allowInviteExernalUsers: Bool = true + // MARK: - Feature Specifics /// Not allowed pin codes. User won't be able to select one of the pin in the list. diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 014f4502d..a984eda88 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -47,6 +47,7 @@ final class RiotSettings: NSObject { static let settingsSecurityScreenShowCryptographyInfo = "settingsSecurityScreenShowCryptographyInfo" static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport" static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices" + static let allowInviteExernalUsers = "allowInviteExernalUsers" } static let shared = RiotSettings() @@ -72,6 +73,7 @@ final class RiotSettings: NSObject { defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyInfo) defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowCryptographyExport) defaults.removeObject(forKey: UserDefaultsKeys.settingsSecurityScreenShowAdvancedUnverifiedDevices) + defaults.removeObject(forKey: UserDefaultsKeys.allowInviteExernalUsers) } // MARK: Servers @@ -236,6 +238,19 @@ final class RiotSettings: NSObject { } } + // MARK: Features + + var allowInviteExernalUsers: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.allowInviteExernalUsers) != nil else { + return BuildSettings.allowInviteExernalUsers + } + return defaults.bool(forKey: UserDefaultsKeys.allowInviteExernalUsers) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.allowInviteExernalUsers) + } + } + // MARK: General Settings var settingsScreenShowChangePassword: Bool { diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 72d2e4616..dea3437ff 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -499,7 +499,7 @@ if (section == searchInputSection) { - count = 1; + count = RiotSettings.shared.allowInviteExernalUsers ? 1 : 0; } else if (section == filteredLocalContactsSection && !(shrinkedSectionsBitMask & CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE)) { diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index eb35cd1fb..421ac343e 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -133,6 +133,12 @@ - (void)setupInviteFriendsHeaderView { + if (!RiotSettings.shared.allowInviteExernalUsers) + { + self.contactsTableView.tableHeaderView = nil; + return; + } + InviteFriendsHeaderView *inviteFriendsHeaderView = [InviteFriendsHeaderView instantiate]; inviteFriendsHeaderView.delegate = self; self.contactsTableView.tableHeaderView = inviteFriendsHeaderView; From b23579ca305bc8a3dccea6ae8925af9da192e4d1 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 2 Apr 2021 10:09:04 +0200 Subject: [PATCH 052/140] Update Riot/Modules/Room/RoomViewController.m Co-authored-by: manuroe --- Riot/Modules/Room/RoomViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 8c6be6078..9bd047643 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1495,7 +1495,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { MXEvent *event = [self.roomDataSource eventWithEventId:eventId]; MXRoomMember * roomMember = [self.roomDataSource.roomState.members memberWithUserId:event.sender]; - if (roomMember) + if (roomMember.displayname.length) { roomInputToolbarView.eventSenderDisplayName = roomMember.displayname; } From e26acaaffbafc2c589aa876eed5c23e0a0c8fd8a Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 2 Apr 2021 11:49:02 +0200 Subject: [PATCH 053/140] Updated CHANGES.rst --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 8855e8f83..6c1534a28 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,7 @@ Changes to be released in next version 🙌 Improvements * Make the application settings more configurable (#4171) + * Enable / disable external friends invite (#4173) 🐛 Bugfix * From 16937adc62a168eff42e9306072efcb51e7bceb4 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Fri, 2 Apr 2021 15:54:21 +0200 Subject: [PATCH 054/140] Possibility to lock some room creation parameters from settings --- CHANGES.rst | 1 + Config/BuildSettings.swift | 17 +++++ Riot/Managers/Settings/RiotSettings.swift | 22 +++++++ .../EnterNewRoomDetailsViewController.swift | 62 +++++++++++-------- .../EnterNewRoomDetailsViewModel.swift | 3 +- 5 files changed, 79 insertions(+), 26 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8855e8f83..846f03166 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,7 @@ Changes to be released in next version 🙌 Improvements * Make the application settings more configurable (#4171) + * Possibility to lock some room creation parameters from settings (#4181) 🐛 Bugfix * diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 5612061e0..57285d9eb 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -241,6 +241,23 @@ final class BuildSettings: NSObject { // MARK: - Timeline settings static let roomInputToolbarCompressionMode = MXKRoomInputToolbarCompressionModePrompt + // MARK: - Room Creation Screen + + enum ForcedEncryptionMode: String { + case none = "none" + case disabled = "disabled" + case enabled = "enabled" + } + + enum ForcedRoomType: String { + case none = "none" + case privateRoom = "privateRoom" + case publicRoom = "publicRoom" + } + + static let roomCreationScreenForcedEncryptionMode: ForcedEncryptionMode = .none + static let roomCreationScreenForcedRoomType: ForcedRoomType = .none + // MARK: - Room Settings Screen static let roomSettingsScreenShowLowPriorityOption: Bool = true diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 014f4502d..f2b43fa5f 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -47,6 +47,8 @@ final class RiotSettings: NSObject { static let settingsSecurityScreenShowCryptographyInfo = "settingsSecurityScreenShowCryptographyInfo" static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport" static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices" + static let roomCreationScreenForcedEncryptionMode = "roomCreationScreenForcedEncryptionMode" + static let roomCreationScreenForcedRoomType = "roomCreationScreenForcedRoomType" } static let shared = RiotSettings() @@ -236,6 +238,26 @@ final class RiotSettings: NSObject { } } + // MARK: - Room Creation Screen + + var roomCreationScreenForcedEncryptionMode: BuildSettings.ForcedEncryptionMode { + get { + let rawValue = defaults.string(forKey: UserDefaultsKeys.roomCreationScreenForcedEncryptionMode) ?? BuildSettings.roomCreationScreenForcedEncryptionMode.rawValue + return BuildSettings.ForcedEncryptionMode(rawValue: rawValue) ?? .none + } set { + defaults.set(newValue.rawValue, forKey: UserDefaultsKeys.roomCreationScreenForcedEncryptionMode) + } + } + + var roomCreationScreenForcedRoomType: BuildSettings.ForcedRoomType { + get { + let rawValue = defaults.string(forKey: UserDefaultsKeys.roomCreationScreenForcedRoomType) ?? BuildSettings.roomCreationScreenForcedRoomType.rawValue + return BuildSettings.ForcedRoomType(rawValue: rawValue) ?? .none + } set { + defaults.set(newValue.rawValue, forKey: UserDefaultsKeys.roomCreationScreenForcedRoomType) + } + } + // MARK: General Settings var settingsScreenShowChangePassword: Bool { diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift index 7ec1cf9e8..5e0dc933e 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift @@ -113,39 +113,51 @@ final class EnterNewRoomDetailsViewController: UIViewController { rows: [row_2_0], footer: nil) - let row_3_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.isEncrypted, onValueChanged: { (theSwitch) in - self.viewModel.roomCreationParameters.isEncrypted = theSwitch.isOn - }), text: VectorL10n.createRoomEnableEncryption, accessoryType: .none) { - // no-op - } - let section3 = Section(header: VectorL10n.createRoomSectionHeaderEncryption, - rows: [row_3_0], - footer: VectorL10n.createRoomSectionFooterEncryption) - - let row_4_0 = Row(type: .default, text: VectorL10n.createRoomTypePrivate, accessoryType: viewModel.roomCreationParameters.isPublic ? .none : .checkmark) { - self.viewModel.roomCreationParameters.isPublic = false - self.updateSections() - } - let row_4_1 = Row(type: .default, text: VectorL10n.createRoomTypePublic, accessoryType: viewModel.roomCreationParameters.isPublic ? .checkmark : .none) { - self.viewModel.roomCreationParameters.isPublic = true - self.updateSections() - // scroll bottom to show user new fields - DispatchQueue.main.async { - self.mainTableView.scrollToRow(at: IndexPath(row: 0, section: 6), at: .bottom, animated: true) + var section3: Section? + if RiotSettings.shared.roomCreationScreenForcedEncryptionMode == .none { + let row_3_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.isEncrypted, onValueChanged: { (theSwitch) in + self.viewModel.roomCreationParameters.isEncrypted = theSwitch.isOn + }), text: VectorL10n.createRoomEnableEncryption, accessoryType: .none) { + // no-op } + section3 = Section(header: VectorL10n.createRoomSectionHeaderEncryption, + rows: [row_3_0], + footer: VectorL10n.createRoomSectionFooterEncryption) + } + + var section4: Section? + if RiotSettings.shared.roomCreationScreenForcedRoomType == .none { + let row_4_0 = Row(type: .default, text: VectorL10n.createRoomTypePrivate, accessoryType: viewModel.roomCreationParameters.isPublic ? .none : .checkmark) { + self.viewModel.roomCreationParameters.isPublic = false + self.updateSections() + } + let row_4_1 = Row(type: .default, text: VectorL10n.createRoomTypePublic, accessoryType: viewModel.roomCreationParameters.isPublic ? .checkmark : .none) { + self.viewModel.roomCreationParameters.isPublic = true + self.updateSections() + // scroll bottom to show user new fields + DispatchQueue.main.async { + self.mainTableView.scrollToRow(at: IndexPath(row: 0, section: 6), at: .bottom, animated: true) + } + } + section4 = Section(header: VectorL10n.createRoomSectionHeaderType, + rows: [row_4_0, row_4_1], + footer: VectorL10n.createRoomSectionFooterType) } - let section4 = Section(header: VectorL10n.createRoomSectionHeaderType, - rows: [row_4_0, row_4_1], - footer: VectorL10n.createRoomSectionFooterType) var tmpSections: [Section] = [ section0, section1, - section2, - section3, - section4 + section2 ] + if let section3 = section3 { + tmpSections.append(section3) + } + + if let section4 = section4 { + tmpSections.append(section4) + } + if viewModel.roomCreationParameters.isPublic { let row_5_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.showInDirectory, onValueChanged: { (theSwitch) in self.viewModel.roomCreationParameters.showInDirectory = theSwitch.isOn diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift index 37ed2bed9..b4f919239 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift @@ -39,7 +39,8 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType { init(session: MXSession) { self.session = session - roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() + roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() && RiotSettings.shared.roomCreationScreenForcedEncryptionMode != .disabled + roomCreationParameters.isPublic = RiotSettings.shared.roomCreationScreenForcedRoomType == .publicRoom } deinit { From ef7347f0bcdb749b3b59995873785745edaaebf0 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Sat, 3 Apr 2021 00:03:57 +0200 Subject: [PATCH 055/140] Switching composer between text mode & action mode - Tweaked animation speed --- Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift | 8 +++++--- .../Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift index 0cf11e292..3f78b9cb3 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift +++ b/Riot/Modules/Room/Views/InputToolbar/RoomActionsBar.swift @@ -99,7 +99,7 @@ import UIKit button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) } for (index, button) in actionButtons.enumerated() { - UIView.animate(withDuration: 0.38, delay: 0.05 * Double(index), usingSpringWithDamping: 0.5, initialSpringVelocity: 7, options: .curveEaseInOut) { + UIView.animate(withDuration: 0.3, delay: 0.05 * Double(index), usingSpringWithDamping: 0.45, initialSpringVelocity: 11, options: .curveEaseInOut) { button.transform = CGAffineTransform.identity } completion: { (finished) in completion?(finished) @@ -107,10 +107,12 @@ import UIKit } } else { for (index, button) in actionButtons.enumerated() { - UIView.animate(withDuration: 0.3, delay: 0.05 * Double(index), options: .curveEaseInOut) { + UIView.animate(withDuration: 0.25, delay: 0.05 * Double(index), options: .curveEaseInOut) { button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height) } completion: { (finished) in - completion?(finished) + if index == self.actionButtons.count - 1 { + completion?(finished) + } } } } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 5997ce8bb..c76bbd038 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -201,7 +201,7 @@ const double RoomInputToolbarViewContextBarHeight = 30; if (self.mainToolbarHeightConstraint.constant != updatedHeight) { - [UIView animateWithDuration:.3 animations:^{ + [UIView animateWithDuration:.15 animations:^{ self.mainToolbarHeightConstraint.constant = updatedHeight; [self layoutIfNeeded]; From 90412e33937d15068a573a240ff036c816a131bc Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 6 Apr 2021 10:47:54 +0200 Subject: [PATCH 056/140] Possibility to lock some room creation parameters from settings - Update after review --- Config/BuildSettings.swift | 18 ++----- Riot/Managers/Settings/RiotSettings.swift | 49 ++++++++++++++----- .../EnterNewRoomDetailsViewController.swift | 4 +- .../EnterNewRoomDetailsViewModel.swift | 4 +- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 57285d9eb..0d46526d1 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -243,20 +243,10 @@ final class BuildSettings: NSObject { // MARK: - Room Creation Screen - enum ForcedEncryptionMode: String { - case none = "none" - case disabled = "disabled" - case enabled = "enabled" - } - - enum ForcedRoomType: String { - case none = "none" - case privateRoom = "privateRoom" - case publicRoom = "publicRoom" - } - - static let roomCreationScreenForcedEncryptionMode: ForcedEncryptionMode = .none - static let roomCreationScreenForcedRoomType: ForcedRoomType = .none + static let roomCreationScreenAllowEncryptionConfiguration: Bool = true + static let roomCreationScreenEncryptionEnabled: Bool = true + static let roomCreationScreenAllowRoomTypeConfiguration: Bool = true + static let roomCreationScreenRoomIsPublic: Bool = false // MARK: - Room Settings Screen diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index f2b43fa5f..314541939 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -47,8 +47,10 @@ final class RiotSettings: NSObject { static let settingsSecurityScreenShowCryptographyInfo = "settingsSecurityScreenShowCryptographyInfo" static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport" static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices" - static let roomCreationScreenForcedEncryptionMode = "roomCreationScreenForcedEncryptionMode" - static let roomCreationScreenForcedRoomType = "roomCreationScreenForcedRoomType" + static let roomCreationScreenAllowEncryptionConfiguration = "roomCreationScreenAllowEncryptionConfiguration" + static let roomCreationScreenEncryptionEnabled = "roomCreationScreenEncryptionEnabled" + static let roomCreationScreenAllowRoomTypeConfiguration = "roomCreationScreenAllowRoomTypeConfiguration" + static let roomCreationScreenRoomIsPublic = "roomCreationScreenRoomIsPublic" } static let shared = RiotSettings() @@ -239,22 +241,45 @@ final class RiotSettings: NSObject { } // MARK: - Room Creation Screen - - var roomCreationScreenForcedEncryptionMode: BuildSettings.ForcedEncryptionMode { + + var roomCreationScreenAllowEncryptionConfiguration: Bool { get { - let rawValue = defaults.string(forKey: UserDefaultsKeys.roomCreationScreenForcedEncryptionMode) ?? BuildSettings.roomCreationScreenForcedEncryptionMode.rawValue - return BuildSettings.ForcedEncryptionMode(rawValue: rawValue) ?? .none + guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration) != nil else { + return BuildSettings.roomCreationScreenAllowEncryptionConfiguration + } + return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration) } set { - defaults.set(newValue.rawValue, forKey: UserDefaultsKeys.roomCreationScreenForcedEncryptionMode) + defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration) } } - - var roomCreationScreenForcedRoomType: BuildSettings.ForcedRoomType { + var roomCreationScreenEncryptionEnabled: Bool { get { - let rawValue = defaults.string(forKey: UserDefaultsKeys.roomCreationScreenForcedRoomType) ?? BuildSettings.roomCreationScreenForcedRoomType.rawValue - return BuildSettings.ForcedRoomType(rawValue: rawValue) ?? .none + guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) != nil else { + return BuildSettings.roomCreationScreenEncryptionEnabled + } + return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) } set { - defaults.set(newValue.rawValue, forKey: UserDefaultsKeys.roomCreationScreenForcedRoomType) + defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) + } + } + var roomCreationScreenAllowRoomTypeConfiguration: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration) != nil else { + return BuildSettings.roomCreationScreenAllowRoomTypeConfiguration + } + return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenAllowRoomTypeConfiguration) + } + } + var roomCreationScreenRoomIsPublic: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic) != nil else { + return BuildSettings.roomCreationScreenRoomIsPublic + } + return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenRoomIsPublic) } } diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift index 5e0dc933e..d177dcd52 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift @@ -114,7 +114,7 @@ final class EnterNewRoomDetailsViewController: UIViewController { footer: nil) var section3: Section? - if RiotSettings.shared.roomCreationScreenForcedEncryptionMode == .none { + if RiotSettings.shared.roomCreationScreenAllowEncryptionConfiguration { let row_3_0 = Row(type: .withSwitch(isOn: viewModel.roomCreationParameters.isEncrypted, onValueChanged: { (theSwitch) in self.viewModel.roomCreationParameters.isEncrypted = theSwitch.isOn }), text: VectorL10n.createRoomEnableEncryption, accessoryType: .none) { @@ -126,7 +126,7 @@ final class EnterNewRoomDetailsViewController: UIViewController { } var section4: Section? - if RiotSettings.shared.roomCreationScreenForcedRoomType == .none { + if RiotSettings.shared.roomCreationScreenAllowRoomTypeConfiguration { let row_4_0 = Row(type: .default, text: VectorL10n.createRoomTypePrivate, accessoryType: viewModel.roomCreationParameters.isPublic ? .none : .checkmark) { self.viewModel.roomCreationParameters.isPublic = false self.updateSections() diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift index b4f919239..709623c18 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift @@ -39,8 +39,8 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType { init(session: MXSession) { self.session = session - roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() && RiotSettings.shared.roomCreationScreenForcedEncryptionMode != .disabled - roomCreationParameters.isPublic = RiotSettings.shared.roomCreationScreenForcedRoomType == .publicRoom + roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() && RiotSettings.shared.roomCreationScreenEncryptionEnabled + roomCreationParameters.isPublic = RiotSettings.shared.roomCreationScreenRoomIsPublic } deinit { From 57517d6aacdde49d839db13d8351d3460831b818 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 6 Apr 2021 10:51:07 +0200 Subject: [PATCH 057/140] Possibility to lock some room creation parameters from settings - Update after review --- Config/BuildSettings.swift | 2 +- Riot/Managers/Settings/RiotSettings.swift | 12 ++++++------ .../EnterNewRoomDetailsViewModel.swift | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 0d46526d1..100bf20ee 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -244,7 +244,7 @@ final class BuildSettings: NSObject { // MARK: - Room Creation Screen static let roomCreationScreenAllowEncryptionConfiguration: Bool = true - static let roomCreationScreenEncryptionEnabled: Bool = true + static let roomCreationScreenRoomIsEncrypted: Bool = true static let roomCreationScreenAllowRoomTypeConfiguration: Bool = true static let roomCreationScreenRoomIsPublic: Bool = false diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 314541939..13910303d 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -48,7 +48,7 @@ final class RiotSettings: NSObject { static let settingsSecurityScreenShowCryptographyExport = "settingsSecurityScreenShowCryptographyExport" static let settingsSecurityScreenShowAdvancedUnverifiedDevices = "settingsSecurityScreenShowAdvancedBlacklistUnverifiedDevices" static let roomCreationScreenAllowEncryptionConfiguration = "roomCreationScreenAllowEncryptionConfiguration" - static let roomCreationScreenEncryptionEnabled = "roomCreationScreenEncryptionEnabled" + static let roomCreationScreenRoomIsEncrypted = "roomCreationScreenRoomIsEncrypted" static let roomCreationScreenAllowRoomTypeConfiguration = "roomCreationScreenAllowRoomTypeConfiguration" static let roomCreationScreenRoomIsPublic = "roomCreationScreenRoomIsPublic" } @@ -252,14 +252,14 @@ final class RiotSettings: NSObject { defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenAllowEncryptionConfiguration) } } - var roomCreationScreenEncryptionEnabled: Bool { + var roomCreationScreenRoomIsEncrypted: Bool { get { - guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) != nil else { - return BuildSettings.roomCreationScreenEncryptionEnabled + guard defaults.object(forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted) != nil else { + return BuildSettings.roomCreationScreenRoomIsEncrypted } - return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) + return defaults.bool(forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted) } set { - defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenEncryptionEnabled) + defaults.set(newValue, forKey: UserDefaultsKeys.roomCreationScreenRoomIsEncrypted) } } var roomCreationScreenAllowRoomTypeConfiguration: Bool { diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift index 709623c18..a9a48bdde 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift @@ -39,7 +39,7 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType { init(session: MXSession) { self.session = session - roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() && RiotSettings.shared.roomCreationScreenEncryptionEnabled + roomCreationParameters.isEncrypted = session.vc_isE2EByDefaultEnabledByHSAdmin() && RiotSettings.shared.roomCreationScreenRoomIsEncrypted roomCreationParameters.isPublic = RiotSettings.shared.roomCreationScreenRoomIsPublic } From 96408aea02782b2b0c820c8ec5a285ae2b79bec4 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 6 Apr 2021 13:09:30 +0200 Subject: [PATCH 058/140] Limit typing notifications timeline jumps --- Riot/Modules/Room/DataSources/RoomDataSource.h | 2 ++ Riot/Modules/Room/DataSources/RoomDataSource.m | 4 ++++ Riot/Modules/Room/RoomViewController.m | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.h b/Riot/Modules/Room/DataSources/RoomDataSource.h index ced9e687a..d4ec45c91 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.h +++ b/Riot/Modules/Room/DataSources/RoomDataSource.h @@ -98,6 +98,8 @@ success:(void(^)(void))success failure:(void(^)(NSError*))failure; +- (void)resetTypingNotification; + @end @protocol RoomDataSourceDelegate diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 8cef6f9b2..2122a398d 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -950,6 +950,10 @@ }]; } +- (void)resetTypingNotification { + self.currentTypingUsers = nil; +} + #pragma - Accessibility - (void)setupAccessibilityForCell:(MXKRoomBubbleTableViewCell *)cell withCellData:(RoomBubbleCellData*)cellData diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 6e5173a6f..9ac281f7d 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -511,6 +511,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo [self refreshRoomInputToolbar]; } + // Reset typing notification in order to remove the allocated space + if ([self.roomDataSource isKindOfClass:RoomDataSource.class]) + { + [((RoomDataSource*)self.roomDataSource) resetTypingNotification]; + } + [self listenTypingNotifications]; [self listenCallNotifications]; [self listenWidgetNotifications]; @@ -1338,6 +1344,17 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo _scrollToBottomHidden = scrollToBottomHidden; } + if (!_scrollToBottomHidden && [self.roomDataSource isKindOfClass:RoomDataSource.class]) + { + RoomDataSource *roomDataSource = (RoomDataSource *) self.roomDataSource; + if (roomDataSource.currentTypingUsers && !roomDataSource.currentTypingUsers.count) + { + [roomDataSource resetTypingNotification]; + NSInteger count = [roomDataSource tableView:self.bubblesTableView numberOfRowsInSection:0]; + [self.bubblesTableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:count inSection:0]] withRowAnimation:UITableViewRowAnimationNone]; + } + } + [UIView animateWithDuration:.2 animations:^{ self.scrollToBottomBadgeLabel.alpha = (scrollToBottomHidden || !self.scrollToBottomBadgeLabel.text) ? 0 : 1; self.scrollToBottomButton.alpha = scrollToBottomHidden ? 0 : 1; From f222f468104aca0690f10685fd8e3ca67f2f4485 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 6 Apr 2021 14:32:25 +0200 Subject: [PATCH 059/140] Consider displaying names in typing notifications --- Riot/Assets/en.lproj/Vector.strings | 2 ++ Riot/Generated/Strings.swift | 4 +++ .../BubbleCells/RoomTypingBubbleCell.swift | 26 +++++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 40ab6cd46..6b58da5c1 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -406,6 +406,8 @@ Tap the + to start adding people."; "external_link_confirmation_title" = "Double-check this link"; "external_link_confirmation_message" = "The link %@ is taking you to another site: %@\n\nAre you sure you want to continue?"; +"room_multiple_typing_notification" = "%@ and others"; + // Unknown devices "unknown_devices_alert_title" = "Room contains unknown sessions"; "unknown_devices_alert" = "This room contains unknown sessions which have not been verified.\nThis means there is no guarantee that the sessions belong to the users they claim to.\nWe recommend you go through the verification process for each session before continuing, but you can resend the message without verifying if you prefer."; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 0d5515a5a..ab9947434 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2938,6 +2938,10 @@ internal enum VectorL10n { internal static var roomMessageUnableOpenLinkErrorMessage: String { return VectorL10n.tr("Vector", "room_message_unable_open_link_error_message") } + /// %@ and others + internal static func roomMultipleTypingNotification(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_multiple_typing_notification", p1) + } /// %d new message internal static func roomNewMessageNotification(_ p1: Int) -> String { return VectorL10n.tr("Vector", "room_new_message_notification", p1) diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift index 0fdbc7a8e..ae06ed057 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift @@ -32,10 +32,17 @@ class RoomTypingBubbleCell: UITableViewCell { // MARK: - members private var userPictureViews: Array = Array() - private var typingUsers: Array = Array() // MARK: - Lifecycle + override func awakeFromNib() { + super.awakeFromNib() + + additionalUsersLabel?.textColor = ThemeService.shared().theme.textSecondaryColor + dotsView?.highlightedDotColor = ThemeService.shared().theme.textTertiaryColor + dotsView?.dotColor = ThemeService.shared().theme.textSecondaryColor + } + override func prepareForReuse() { super.prepareForReuse() @@ -97,7 +104,22 @@ class RoomTypingBubbleCell: UITableViewCell { self.contentView.addSubview(pictureView) } - additionalUsersLabel?.text = typingUsers.count <= 4 ? nil : "+\(typingUsers.count - 4)" + switch typingUsers.count { + case 0: + additionalUsersLabel?.text = nil + case 1: + additionalUsersLabel?.text = firstUserNameFor(typingUsers) + default: + additionalUsersLabel?.text = VectorL10n.roomMultipleTypingNotification(firstUserNameFor(typingUsers) ?? "") + } self.setNeedsLayout() } + + private func firstUserNameFor(_ typingUsers: Array) -> String? { + guard let firstUser = typingUsers.first else { + return nil + } + + return firstUser.displayname.isEmptyOrNil ? firstUser.userId : firstUser.displayname + } } From 88cf035fe6271ef7267cf871c9b860c2c021726e Mon Sep 17 00:00:00 2001 From: Hivaa Date: Wed, 7 Apr 2021 04:51:25 +0000 Subject: [PATCH 060/140] Added translation using Weblate (Persian) --- Riot/Assets/fa.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/fa.lproj/Vector.strings diff --git a/Riot/Assets/fa.lproj/Vector.strings b/Riot/Assets/fa.lproj/Vector.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/fa.lproj/Vector.strings @@ -0,0 +1 @@ + From 0a5e16965cd91c41777be29fe242e0c8c59601b7 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 7 Apr 2021 09:32:57 +0200 Subject: [PATCH 061/140] Switching composer between text mode & action mode - Tweaked animation speed --- Riot/Modules/Room/RoomViewController.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 87f9f09a8..99d67c067 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -286,6 +286,8 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo { [super finalizeInit]; + self.resizeComposerAnimationDuration = 0.15; + // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; self.rageShakeManager = [RageShakeManager sharedManager]; From fb5dca4c24ce5619412ab9f1a28939fd21a5177d Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 7 Apr 2021 10:28:35 +0200 Subject: [PATCH 062/140] Switching composer between text mode & action mode - Tweaked animation speed --- Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index c76bbd038..aef222b14 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -393,7 +393,7 @@ const double RoomInputToolbarViewContextBarHeight = 30; }]; } - [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.45 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseIn animations:^{ + [UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.45 initialSpringVelocity:7 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.attachMediaButton.transform = actionMenuOpened ? CGAffineTransformMakeRotation(M_PI * 3 / 4) : CGAffineTransformIdentity; } completion:^(BOOL finished) { }]; From eb9678e30beba5b7ad37ce7b747e7e0938a82fda Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 7 Apr 2021 11:14:08 +0200 Subject: [PATCH 063/140] Crash in [RoomViewController setupActions] --- Riot/Modules/Room/RoomViewController.m | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 99d67c067..6a14a78c2 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1702,6 +1702,10 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo } - (void)setupActions { + if (![self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + return; + } + RoomInputToolbarView *roomInputView = ((RoomInputToolbarView *) self.inputToolbarView); __weak typeof(self) weakSelf = self; roomInputView.actionsBar.actionItems = @[ @@ -1709,7 +1713,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (weakSelf) { typeof(self) self = weakSelf; - roomInputView.actionMenuOpened = NO; + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } [self showCameraControllerAnimated:YES]; } }], @@ -1717,7 +1723,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (weakSelf) { typeof(self) self = weakSelf; - roomInputView.actionMenuOpened = NO; + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } [self showMediaPickerAnimated:YES]; } }], @@ -1725,7 +1733,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (weakSelf) { typeof(self) self = weakSelf; - roomInputView.actionMenuOpened = NO; + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } [self roomInputToolbarViewPresentStickerPicker]; } }], @@ -1733,7 +1743,9 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo if (weakSelf) { typeof(self) self = weakSelf; - roomInputView.actionMenuOpened = NO; + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } [self roomInputToolbarViewDidTapFileUpload]; } }], From 8433048451a66ea02059da5f111be15217229d0f Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 7 Apr 2021 12:26:51 +0200 Subject: [PATCH 064/140] Crash in [RoomViewController refreshTypingNotification] --- .../Modules/Room/DataSources/TypingUserInfo.h | 34 ++++++++++++++ .../Modules/Room/DataSources/TypingUserInfo.m | 46 +++++++++++++++++++ Riot/Modules/Room/RoomViewController.m | 15 +++++- .../BubbleCells/RoomTypingBubbleCell.swift | 8 ++-- Riot/SupportingFiles/Riot-Bridging-Header.h | 1 + 5 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 Riot/Modules/Room/DataSources/TypingUserInfo.h create mode 100644 Riot/Modules/Room/DataSources/TypingUserInfo.m diff --git a/Riot/Modules/Room/DataSources/TypingUserInfo.h b/Riot/Modules/Room/DataSources/TypingUserInfo.h new file mode 100644 index 000000000..54914dc6e --- /dev/null +++ b/Riot/Modules/Room/DataSources/TypingUserInfo.h @@ -0,0 +1,34 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TypingUserInfo : NSObject + +@property (nonatomic, strong) NSString *userId; +@property (nonatomic, strong, nullable) NSString *displayName; +@property (nonatomic, strong, nullable) NSString *avatarUrl; + +- (instancetype) initWithMember:(MXRoomMember*)member; + +- (instancetype) initWithUserId:(NSString*)userId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Riot/Modules/Room/DataSources/TypingUserInfo.m b/Riot/Modules/Room/DataSources/TypingUserInfo.m new file mode 100644 index 000000000..fa59cde01 --- /dev/null +++ b/Riot/Modules/Room/DataSources/TypingUserInfo.m @@ -0,0 +1,46 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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 "TypingUserInfo.h" + +@implementation TypingUserInfo + +- (instancetype) initWithMember:(MXRoomMember*)member +{ + self = [self initWithUserId:member.userId]; + + if (self) + { + self.displayName = member.displayname; + self.avatarUrl = member.avatarUrl; + } + + return self; +} + +- (instancetype) initWithUserId:(NSString*)userId +{ + self = [super init]; + + if (self) + { + self.userId = userId; + } + + return self; +} + +@end diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index e3379981e..e7c07ec93 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -124,6 +124,8 @@ #import "SettingsViewController.h" #import "SecurityViewController.h" +#import "TypingUserInfo.h" + #import "Riot-Swift.h" NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNotification"; @@ -4134,8 +4136,17 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo for (NSUInteger i = 0 ; i < currentTypingUsers.count ; i++) { NSString *userId = currentTypingUsers[i]; MXRoomMember* member = [self.roomDataSource.roomState.members memberWithUserId:userId]; - [typingUsers addObject:member]; - needsUpdate = needsUpdate || member.userId != ((MXRoomMember *) roomDataSource.currentTypingUsers[i]).userId; + TypingUserInfo *userInfo; + if (member) + { + userInfo = [[TypingUserInfo alloc] initWithMember: member]; + } + else + { + userInfo = [[TypingUserInfo alloc] initWithUserId: userId]; + } + [typingUsers addObject:userInfo]; + needsUpdate = needsUpdate || userInfo.userId != ((MXRoomMember *) roomDataSource.currentTypingUsers[i]).userId; } if (needsUpdate) diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift index ae06ed057..551dca621 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomTypingBubbleCell.swift @@ -82,7 +82,7 @@ class RoomTypingBubbleCell: UITableViewCell { // MARK: - Business methods - func updateTypingUsers(_ typingUsers: Array, mediaManager: MXMediaManager) { + func updateTypingUsers(_ typingUsers: Array, mediaManager: MXMediaManager) { for pictureView in userPictureViews { pictureView.removeFromSuperview() } @@ -97,7 +97,7 @@ class RoomTypingBubbleCell: UITableViewCell { pictureView.layer.masksToBounds = true pictureView.layer.cornerRadius = pictureView.bounds.midX - let defaultavatarImage = AvatarGenerator.generateAvatar(forMatrixItem: user.userId, withDisplayName: user.displayname) + let defaultavatarImage = AvatarGenerator.generateAvatar(forMatrixItem: user.userId, withDisplayName: user.displayName) pictureView.setImageURI(user.avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: pictureView.bounds.size, with: MXThumbnailingMethodCrop, previewImage: defaultavatarImage, mediaManager: mediaManager) userPictureViews.append(pictureView) @@ -115,11 +115,11 @@ class RoomTypingBubbleCell: UITableViewCell { self.setNeedsLayout() } - private func firstUserNameFor(_ typingUsers: Array) -> String? { + private func firstUserNameFor(_ typingUsers: Array) -> String? { guard let firstUser = typingUsers.first else { return nil } - return firstUser.displayname.isEmptyOrNil ? firstUser.userId : firstUser.displayname + return firstUser.displayName.isEmptyOrNil ? firstUser.userId : firstUser.displayName } } diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index f8ff71ea5..7daa40759 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -31,3 +31,4 @@ #import "AuthFallBackViewController.h" #import "CallViewController.h" #import "MatrixContactsDataSource.h" +#import "TypingUserInfo.h" From e31707d97113415b29b21fe8bf26d30ef94e9d1a Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 7 Apr 2021 13:11:07 +0200 Subject: [PATCH 065/140] too much vertical whitespace when replying --- .../Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- .../Room/Views/InputToolbar/RoomInputToolbarView.xib | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index aef222b14..ec9afdc99 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -27,7 +27,7 @@ #import "WidgetManager.h" #import "IntegrationManagerViewController.h" -const double RoomInputToolbarViewContextBarHeight = 30; +const double RoomInputToolbarViewContextBarHeight = 20; @interface RoomInputToolbarView() { diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib index e99b0ef66..403a83a59 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.xib @@ -45,16 +45,16 @@ - +