Merge branch 'release/1.2.6/master'

This commit is contained in:
manuroe 2021-03-11 14:25:41 +01:00
commit 792e792426
100 changed files with 1570 additions and 602 deletions

View file

@ -1,3 +1,31 @@
Changes in 1.2.6 (2021-03-11)
=================================================
✨ Features
* Improve the status of send messages (sending, sent, received, failed) (#4014)
* Retrying & deleting failed messages (#4013)
🙌 Improvements
*
🐛 Bugfix
*
⚠️ API Changes
*
🗣 Translations
*
🧱 Build
*
Others
*
Improvements:
* Upgrade MatrixKit version ([v0.14.5](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.14.5)).
Changes in 1.2.5 (2021-03-03) Changes in 1.2.5 (2021-03-03)
================================================= =================================================

View file

@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector
APPLICATION_SCHEME = element APPLICATION_SCHEME = element
// Version // Version
MARKETING_VERSION = 1.2.5 MARKETING_VERSION = 1.2.6
CURRENT_PROJECT_VERSION = 1.2.5 CURRENT_PROJECT_VERSION = 1.2.6
// Team // Team

View file

@ -130,7 +130,10 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0) xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0) xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3) xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-brew (0.1.1)
fastlane-plugin-versioning (0.4.4) fastlane-plugin-versioning (0.4.4)
fastlane-plugin-xcodegen (1.0.0)
fastlane-plugin-brew (~> 0.1.1)
ffi (1.13.1) ffi (1.13.1)
fourflusher (2.3.1) fourflusher (2.3.1)
fuzzy_match (2.0.4) fuzzy_match (2.0.4)
@ -245,6 +248,7 @@ DEPENDENCIES
cocoapods (~> 1.10.0) cocoapods (~> 1.10.0)
fastlane fastlane
fastlane-plugin-versioning fastlane-plugin-versioning
fastlane-plugin-xcodegen
xcode-install xcode-install
BUNDLED WITH BUNDLED WITH

View file

@ -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 # - `{ {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 # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
$matrixKitVersion = '= 0.14.4' $matrixKitVersion = '= 0.14.5'
# $matrixKitVersion = :local # $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'} # $matrixKitVersion = {'develop' => 'develop'}

View file

@ -55,28 +55,28 @@ PODS:
- MatomoTracker (7.2.2): - MatomoTracker (7.2.2):
- MatomoTracker/Core (= 7.2.2) - MatomoTracker/Core (= 7.2.2)
- MatomoTracker/Core (7.2.2) - MatomoTracker/Core (7.2.2)
- MatrixKit (0.14.4): - MatrixKit (0.14.5):
- Down (~> 0.9.3) - Down (~> 0.9.3)
- DTCoreText (~> 1.6.23) - DTCoreText (~> 1.6.23)
- HPGrowingTextView (~> 1.1) - HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13) - libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.14.4) - MatrixKit/Core (= 0.14.5)
- MatrixSDK (= 0.18.4) - MatrixSDK (= 0.18.5)
- MatrixKit/Core (0.14.4): - MatrixKit/Core (0.14.5):
- Down (~> 0.9.3) - Down (~> 0.9.3)
- DTCoreText (~> 1.6.23) - DTCoreText (~> 1.6.23)
- HPGrowingTextView (~> 1.1) - HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13) - libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.18.4) - MatrixSDK (= 0.18.5)
- MatrixSDK (0.18.4): - MatrixSDK (0.18.5):
- MatrixSDK/Core (= 0.18.4) - MatrixSDK/Core (= 0.18.5)
- MatrixSDK/Core (0.18.4): - MatrixSDK/Core (0.18.5):
- AFNetworking (~> 4.0.0) - AFNetworking (~> 4.0.0)
- GZIP (~> 1.3.0) - GZIP (~> 1.3.0)
- libbase58 (~> 0.1.4) - libbase58 (~> 0.1.4)
- OLMKit (~> 3.2.2) - OLMKit (~> 3.2.2)
- Realm (= 10.1.4) - Realm (= 10.1.4)
- MatrixSDK/JingleCallStack (0.18.4): - MatrixSDK/JingleCallStack (0.18.5):
- JitsiMeetSDK (= 3.1.0) - JitsiMeetSDK (= 3.1.0)
- MatrixSDK/Core - MatrixSDK/Core
- OLMKit (3.2.2): - OLMKit (3.2.2):
@ -115,7 +115,7 @@ DEPENDENCIES:
- KeychainAccess (~> 4.2.1) - KeychainAccess (~> 4.2.1)
- KTCenterFlowLayout (~> 1.3.1) - KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.2.2) - MatomoTracker (~> 7.2.2)
- MatrixKit (= 0.14.4) - MatrixKit (= 0.14.5)
- MatrixSDK - MatrixSDK
- MatrixSDK/JingleCallStack - MatrixSDK/JingleCallStack
- OLMKit - OLMKit
@ -186,8 +186,8 @@ SPEC CHECKSUMS:
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
Logging: beeb016c9c80cf77042d62e83495816847ef108b Logging: beeb016c9c80cf77042d62e83495816847ef108b
MatomoTracker: a59ec4da0f580be57bdc6baa708a71a86532a832 MatomoTracker: a59ec4da0f580be57bdc6baa708a71a86532a832
MatrixKit: fad56170110b7248cfdd5bf210f944c6fad04162 MatrixKit: f77c5aa1a236331665d3b1f25ed37ed8758eb23f
MatrixSDK: d2cb905cf6afa5df63c5a76f7678456723923af5 MatrixSDK: 013859281629b8cccd3a8af1dec48f36335c058c
OLMKit: 20d1c564033a1ae7148f8f599378d4c798363905 OLMKit: 20d1c564033a1ae7148f8f599378d4c798363905
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
Realm: 80f4fb2971ccb9adc27a47d0955ae8e533a7030b Realm: 80f4fb2971ccb9adc27a47d0955ae8e533a7030b
@ -199,6 +199,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: c98fd507efbe607a5821e154e941210a093f54f9 PODFILE CHECKSUM: e2cd2613ad0fe9313fc917b2c277836f16a6fbc3
COCOAPODS: 1.10.0 COCOAPODS: 1.10.0

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "error_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "error_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "error_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,6 +1,6 @@
{ {
"info" : { "info" : {
"version" : 1, "author" : "xcode",
"author" : "xcode" "version" : 1
} }
} }

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "error_message_tick.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "error_message_tick@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "error_message_tick@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "room_activities_retry.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "room_activities_retry@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "room_activities_retry@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "sending_message_tick.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "sending_message_tick@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "sending_message_tick@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "sent_message_tick.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "sent_message_tick@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "sent_message_tick@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "room_context_menu_delete.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "room_context_menu_delete@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "room_context_menu_delete@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "room_context_menu_retry.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "room_context_menu_retry@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "room_context_menu_retry@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,9 @@
"NSContactsUsageDescription" = "لاِكتِشاف جِهات الاِتِّصال الَّتي تَستَخدِمُ Matrix بِالفِعل، يُمكِنُ لِـElement إرسَال عَناوين البَريد الإلِكتُرونيّ وأرقام الهَواتِف الَّتي في دَفتَرِ العَناوين الخاصِّ بِك إلى خادِمِ هُويَّة Matrix المُختار. يَتِّمُ تَجزِئة البَياناتِ الشَّخصيَّة قَبلَ إرسالِها حَيثُما كانَت مَدعُومَة - يُرجى مُراجَعَة سياسَة الخُصُوصيَّة الخاصَّة بِخادِم الهُويَّة لِلحُصُولِ عَلَى المَزيدِ مِنَ التَّفاصيل.";
"NSFaceIDUsageDescription" = "يُستخدَم الـFace ID لِلوُصُول إلى التَّطبيق الخاصّ بِك.";
"NSCalendarsUsageDescription" = "اطَّلِع عَلَى اِجتِماعاتِك المُجَدوَلَة في التَّطبيق.";
"NSMicrophoneUsageDescription" = "المِيكرُوفُون يُستَخدَم لاِلتِقاط المَقاطِع المَرئيَّة وإجراء المُكالَمات.";
// Permissions usage explanations
"NSCameraUsageDescription" = "تُستَخدَم الكاميرا لاِلتِقاط الصُّوَر، المَقاطِع المَرئيَّة وإجراءُ مُكالَمَةٍ مَرئيَّة.";
"NSPhotoLibraryUsageDescription" = "مَكتَبَة الصُّوَر تُستَخدَم لإرسال الصُّوَر وَالمَقاطِع المَرئيَّة.";

View file

@ -0,0 +1,113 @@
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "العُضو %@ في %@";
/** Single, unencrypted messages (where we can include the content */
/* New message from a specific person, not referencing a room. Content included. */
"MSG_FROM_USER_WITH_CONTENT" = "العُضو %@: %@";
/* New action message from a specific person, not referencing a room. */
"ACTION_FROM_USER" = "* %@ %@";
/** Key verification **/
"KEY_VERIFICATION_REQUEST_FROM_USER" = "إنَّ %@ يُريدُ التَّحَقُّق";
/* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "مُكالَمَة مَرئيَّة جَماعِيَّة مِن %@: %@";
/* Incoming named voice conference invite from a specific person */
"VOICE_CONF_NAMED_FROM_USER" = "مُحادَثَة جَماعِيَّة مِن %@: '%@'";
/* Incoming unnamed video conference invite from a specific person */
"VIDEO_CONF_FROM_USER" = "مُكالَمَة مَرئيَّة جَماعِيَّة مِن %@";
/* Incoming unnamed voice conference invite from a specific person */
"VOICE_CONF_FROM_USER" = "مُحادَثَة جَماعِيَّة مِن %@";
/* Incoming one-to-one video call */
"VIDEO_CALL_FROM_USER" = "مُكالَمَة مَرئيَّة مِن %@";
/** Calls **/
/* Incoming one-to-one voice call */
"VOICE_CALL_FROM_USER" = "مُكالَمَة مِن %@";
/* A user has invited you to a named room */
"USER_INVITE_TO_NAMED_ROOM" = "لَقَد دَعاكَ %@ إلى %@";
/* A user has invited you to an (unamed) group chat */
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "لَقَد دَعاكَ %@ إلى مُحادَثَة جَماعِيَّة";
/** Invites **/
/* A user has invited you to a chat */
"USER_INVITE_TO_CHAT" = "لَقَد دَعاكَ %@ إلى مُحادَثَة";
/* Look, stuff's happened, alright? Just open the app. */
"MSGS_IN_TWO_PLUS_ROOMS" = "عَدَد %@ رِسالَة جَديدَة في %@، %@ وَأُخرَى";
/* Multiple messages in two rooms */
"MSGS_IN_TWO_ROOMS" = "عَدَد %@ رِسالَة جَديدَة في %@ وَ %@";
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
"MSGS_FROM_TWO_PLUS_USERS" = "عَدَد %@ رِسالَة جَديدَة مِن %@، %@ وَآخرُون";
/* Multiple unread messages from three people */
"MSGS_FROM_THREE_USERS" = "عَدَد %@ رِسالَة جَديدَة مِن %@، %@ وَ %@";
/* Multiple unread messages from two people */
"MSGS_FROM_TWO_USERS" = "عَدَد %@ رِسالَة جَديدَة مِن %@ وَ %@";
/* Multiple unread messages from a specific person, not referencing a room */
"MSGS_FROM_USER" = "عَدَد %@ رِسالَة جَديدَة في %@";
/** Coalesced messages **/
/* Multiple unread messages in a room */
"UNREAD_IN_ROOM" = "عَدَد %@ رِسالَة جَديدَة في %@";
"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" = "رِسالة";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "لَقَد أرسَلَ %@ مُلصَق";
/* A single unread message */
"SINGLE_UNREAD" = "أنتَ قَد اِستَلَمتَ رِسالَة";
/* A single unread message in a room */
"SINGLE_UNREAD_IN_ROOM" = "أنتَ قَد اِستَلَمتَ رِسالَة في %@";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "لَقَد نَشَرَ %@ صُّورَة %@ في %@";
/** Image Messages **/
/* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "لَقَد أرسَلَ %@ صُّورة %@";
/* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "العُضو %@: * %@ %@";
/* New message from a specific person in a named room. Content included. */
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "العُضو %@ في %@: %@";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "لَقَد نَشَرَ %@ في %@";
/** Single, end-to-end encrypted messages (ie. we don't know what they say) */
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "لَقَد أرسَلَ %@ رِسالة";

View file

@ -209,8 +209,8 @@
"encrypted_room_message_placeholder" = "Изпрати шифровано съобщение…"; "encrypted_room_message_placeholder" = "Изпрати шифровано съобщение…";
"room_message_short_placeholder" = "Изпрати съобщение…"; "room_message_short_placeholder" = "Изпрати съобщение…";
"room_offline_notification" = "Връзката със сървъра е изгубена."; "room_offline_notification" = "Връзката със сървъра е изгубена.";
"room_unsent_messages_notification" = "Съобщенията не са изпратени. %@ или %@?"; "room_unsent_messages_notification" = "Съобщенията не са изпратени.";
"room_unsent_messages_unknown_devices_notification" = "Съобщението не е изпратено поради наличието на непознати сесии. %@ или %@?"; "room_unsent_messages_unknown_devices_notification" = "Съобщението не е изпратено поради наличието на непознати сесии.";
"room_ongoing_conference_call" = "Текущ групов разговор. Присъедини се с %@ или %@."; "room_ongoing_conference_call" = "Текущ групов разговор. Присъедини се с %@ или %@.";
"room_ongoing_conference_call_with_close" = "Текущ групов разговор. Присъедини се с %@ или %@. %@ го."; "room_ongoing_conference_call_with_close" = "Текущ групов разговор. Присъедини се с %@ или %@. %@ го.";
"room_ongoing_conference_call_close" = "Затвори"; "room_ongoing_conference_call_close" = "Затвори";

View file

@ -204,8 +204,8 @@
"encrypted_room_message_placeholder" = "Envia un missatge encriptat…"; "encrypted_room_message_placeholder" = "Envia un missatge encriptat…";
"room_message_short_placeholder" = "Envia un missatge…"; "room_message_short_placeholder" = "Envia un missatge…";
"room_offline_notification" = "S'ha perdut la connexió amb el servidor."; "room_offline_notification" = "S'ha perdut la connexió amb el servidor.";
"room_unsent_messages_notification" = "Missatges no enviats. %@ o %@ ara?"; "room_unsent_messages_notification" = "Missatges no enviats.";
"room_unsent_messages_unknown_devices_notification" = "El missatge no s'ha enviat perquè hi ha presents dispositius desconeguts. %@ o %@ ara?"; "room_unsent_messages_unknown_devices_notification" = "El missatge no s'ha enviat perquè hi ha presents dispositius desconeguts.";
"room_ongoing_conference_call" = "Conferència en curs. Unir-te com a %@ o %@."; "room_ongoing_conference_call" = "Conferència en curs. Unir-te com a %@ o %@.";
"room_ongoing_conference_call_with_close" = "Conferència en curs. Unir-te com a %@ o %@. %@."; "room_ongoing_conference_call_with_close" = "Conferència en curs. Unir-te com a %@ o %@. %@.";
"room_ongoing_conference_call_close" = "Tancar"; "room_ongoing_conference_call_close" = "Tancar";

View file

@ -237,8 +237,8 @@
"room_message_short_placeholder" = "Anfon neges…"; "room_message_short_placeholder" = "Anfon neges…";
"room_message_reply_to_short_placeholder" = "Anfon ateb…"; "room_message_reply_to_short_placeholder" = "Anfon ateb…";
"room_offline_notification" = "Collwyd cysylltedd â'r gweinydd."; "room_offline_notification" = "Collwyd cysylltedd â'r gweinydd.";
"room_unsent_messages_notification" = "Negeseuon heb eu hanfon. %@ neu %@ rwan?"; "room_unsent_messages_notification" = "Negeseuon heb eu hanfon.";
"room_unsent_messages_unknown_devices_notification" = "Ni anfonwyd neges oherwydd bod sesiynau anhysbys yn bresennol. %@ neu %@ rwan?"; "room_unsent_messages_unknown_devices_notification" = "Ni anfonwyd neges oherwydd bod sesiynau anhysbys yn bresennol.";
"room_ongoing_conference_call" = "Galwad gynhadledd ar y gweill. Ymunwch fel %@ neu %@."; "room_ongoing_conference_call" = "Galwad gynhadledd ar y gweill. Ymunwch fel %@ neu %@.";
"room_ongoing_conference_call_with_close" = "Galwad gynhadledd ar y gweill. Ymunwch fel %@ neu %@. %@ o."; "room_ongoing_conference_call_with_close" = "Galwad gynhadledd ar y gweill. Ymunwch fel %@ neu %@. %@ o.";
"room_ongoing_conference_call_close" = "Cau"; "room_ongoing_conference_call_close" = "Cau";

View file

@ -4,4 +4,4 @@
"NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet, um Videos aufzunehmen sowie Gespräche zu führen."; "NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet, um Videos aufzunehmen sowie Gespräche zu führen.";
"NSContactsUsageDescription" = "Element kann E-Mail-Adressen und Telefonnummern aus deinem Adressbuch zu deinem Matrix-Identitätsserver schicken, um Kontakte zu finden, die bereits Matrix verwenden. Wenn verfügbar, werden persönliche Daten vor dem Versand gehasht. Für weitere Informationen schaue bitte in die Datenschutzerklärung deines Identitätsservers."; "NSContactsUsageDescription" = "Element kann E-Mail-Adressen und Telefonnummern aus deinem Adressbuch zu deinem Matrix-Identitätsserver schicken, um Kontakte zu finden, die bereits Matrix verwenden. Wenn verfügbar, werden persönliche Daten vor dem Versand gehasht. Für weitere Informationen schaue bitte in die Datenschutzerklärung deines Identitätsservers.";
"NSCalendarsUsageDescription" = "Sieh dir deine geplanten Meetings in der App an."; "NSCalendarsUsageDescription" = "Sieh dir deine geplanten Meetings in der App an.";
"NSFaceIDUsageDescription" = "Face ID wird zum Zugriff auf deine App verwendet."; "NSFaceIDUsageDescription" = "Face-ID wird zum Zugriff auf deine App verwendet.";

View file

@ -157,8 +157,8 @@
"encrypted_room_message_placeholder" = "Verschlüsselte Nachricht…"; "encrypted_room_message_placeholder" = "Verschlüsselte Nachricht…";
"room_message_short_placeholder" = "Sende eine Nachricht…"; "room_message_short_placeholder" = "Sende eine Nachricht…";
"room_offline_notification" = "Verbindung zum Server wurde unterbrochen."; "room_offline_notification" = "Verbindung zum Server wurde unterbrochen.";
"room_unsent_messages_notification" = "Nachrichten wurden nicht gesendet. Jetzt %@ oder %@?"; "room_unsent_messages_notification" = "Nachrichten wurden nicht gesendet.";
"room_unsent_messages_unknown_devices_notification" = "Nachrichten wurden nicht gesendet, da unbekannte Sitzungen vorhanden waren. Jetzt %@ oder %@?"; "room_unsent_messages_unknown_devices_notification" = "Nachrichten wurden nicht gesendet, da unbekannte Sitzungen vorhanden waren.";
"room_prompt_resend" = "alle erneut senden"; "room_prompt_resend" = "alle erneut senden";
"room_prompt_cancel" = "alles abbrechen"; "room_prompt_cancel" = "alles abbrechen";
"room_resend_unsent_messages" = "Ungesendete Nachrichten erneut senden"; "room_resend_unsent_messages" = "Ungesendete Nachrichten erneut senden";

View file

@ -328,8 +328,10 @@ Tap the + to start adding people.";
"room_message_short_placeholder" = "Send a message…"; "room_message_short_placeholder" = "Send a message…";
"room_message_reply_to_short_placeholder" = "Send a reply…"; "room_message_reply_to_short_placeholder" = "Send a reply…";
"room_offline_notification" = "Connectivity to the server has been lost."; "room_offline_notification" = "Connectivity to the server has been lost.";
"room_unsent_messages_notification" = "Messages not sent. %@ or %@ now?"; "room_unsent_messages_notification" = "Messages failed to send.";
"room_unsent_messages_unknown_devices_notification" = "Message not sent due to unknown sessions being present. %@ or %@ now?"; "room_unsent_messages_unknown_devices_notification" = "Message failed to send due to unknown sessions being present.";
"room_unsent_messages_cancel_title" = "Delete unsent messages";
"room_unsent_messages_cancel_message" = "Are you sure you want to delete all unsent messages in this room?";
"room_ongoing_conference_call" = "Ongoing conference call. Join as %@ or %@."; "room_ongoing_conference_call" = "Ongoing conference call. Join as %@ or %@.";
"room_ongoing_conference_call_with_close" = "Ongoing conference call. Join as %@ or %@. %@ it."; "room_ongoing_conference_call_with_close" = "Ongoing conference call. Join as %@ or %@. %@ it.";
"room_ongoing_conference_call_close" = "Close"; "room_ongoing_conference_call_close" = "Close";
@ -354,6 +356,8 @@ Tap the + to start adding people.";
"room_event_action_save" = "Save"; "room_event_action_save" = "Save";
"room_event_action_resend" = "Resend"; "room_event_action_resend" = "Resend";
"room_event_action_delete" = "Delete"; "room_event_action_delete" = "Delete";
"room_event_action_delete_confirmation_title" = "Delete unsent message";
"room_event_action_delete_confirmation_message" = "Are you sure you want to delete this unsent message?";
"room_event_action_cancel_send" = "Cancel Send"; "room_event_action_cancel_send" = "Cancel Send";
"room_event_action_cancel_download" = "Cancel Download"; "room_event_action_cancel_download" = "Cancel Download";
"room_event_action_view_encryption" = "Encryption Information"; "room_event_action_view_encryption" = "Encryption Information";
@ -1592,14 +1596,14 @@ Tap the + to start adding people.";
"room_intro_cell_add_participants_action" = "Add people"; "room_intro_cell_add_participants_action" = "Add people";
"room_intro_cell_information_room_sentence1_part1" = "This is the begining of "; "room_intro_cell_information_room_sentence1_part1" = "This is the beginning of ";
"room_intro_cell_information_room_sentence1_part3" = ". "; "room_intro_cell_information_room_sentence1_part3" = ". ";
"room_intro_cell_information_room_with_topic_sentence2" = "Topic: %@"; "room_intro_cell_information_room_with_topic_sentence2" = "Topic: %@";
"room_intro_cell_information_room_without_topic_sentence2_part1" = "Add a topic"; "room_intro_cell_information_room_without_topic_sentence2_part1" = "Add a topic";
"room_intro_cell_information_room_without_topic_sentence2_part2" = " to let people know what this room is about."; "room_intro_cell_information_room_without_topic_sentence2_part2" = " to let people know what this room is about.";
"room_intro_cell_information_dm_sentence1_part1" = "This is the begining of your direct message with "; "room_intro_cell_information_dm_sentence1_part1" = "This is the beginning of your direct message with ";
"room_intro_cell_information_dm_sentence1_part3" = ". "; "room_intro_cell_information_dm_sentence1_part3" = ". ";
"room_intro_cell_information_dm_sentence2" = "Only the two of you are in this conversation, no one else can join."; "room_intro_cell_information_dm_sentence2" = "Only the two of you are in this conversation, no one else can join.";

View file

@ -1 +1,9 @@
"NSFaceIDUsageDescription" = "Identigilo de vizaĝo uziĝas por aliri vian aplikaĵon.";
"NSCalendarsUsageDescription" = "Vidu viajn planitajn renkontiĝojn en la aplikaĵo.";
"NSContactsUsageDescription" = "Por trovi kontaktojn, kiuj jam estas ĉe Matrix, Element povas sendi retpoŝtadresojn kaj telefonnumerojn el via adresaro al via elektita identigila servilo de Matrix. Kiam eblas, personaj datumoj estas haketitaj antaŭ forsendo bonvolu kontroli la politikon pri privateco de via identiga servilo por pliaj detaloj.";
"NSMicrophoneUsageDescription" = "La mikrofono estas uzata por filmi, kaj ankaŭ por voki.";
"NSPhotoLibraryUsageDescription" = "La fotujo estas uzata por sendi fotojn kaj filmojn.";
// Permissions usage explanations
"NSCameraUsageDescription" = "La filmilo estas uzata por foti kaj filmi, kaj ankaŭ por vidvoki.";

View file

@ -216,8 +216,8 @@
"room_message_short_placeholder" = "Enviar un mensaje…"; "room_message_short_placeholder" = "Enviar un mensaje…";
"room_message_reply_to_short_placeholder" = "Enviar una respuesta…"; "room_message_reply_to_short_placeholder" = "Enviar una respuesta…";
"room_offline_notification" = "Se perdió la conexión con el servidor."; "room_offline_notification" = "Se perdió la conexión con el servidor.";
"room_unsent_messages_notification" = "Los mensajes no se enviaron. ¿%@ o %@ ahora?"; "room_unsent_messages_notification" = "Los mensajes no se enviaron.";
"room_unsent_messages_unknown_devices_notification" = "No se envió el mensaje debido a dispositivos desconocidos presentes. ¿%@ o %@ ahora?"; "room_unsent_messages_unknown_devices_notification" = "No se envió el mensaje debido a dispositivos desconocidos presentes.";
"room_recents_server_notice_section" = "ALERTAS DE SISTEMA"; "room_recents_server_notice_section" = "ALERTAS DE SISTEMA";
"room_ongoing_conference_call" = "Llamada de conferencia en curso. Unirse con %@ o %@."; "room_ongoing_conference_call" = "Llamada de conferencia en curso. Unirse con %@ o %@.";
"room_ongoing_conference_call_with_close" = "Llamada de conferencia en curso. Unirse con %@ o %@. %@ la."; "room_ongoing_conference_call_with_close" = "Llamada de conferencia en curso. Unirse con %@ o %@. %@ la.";

View file

@ -242,8 +242,8 @@
"room_message_short_placeholder" = "Saada sõnum…"; "room_message_short_placeholder" = "Saada sõnum…";
"room_message_reply_to_short_placeholder" = "Saada vastus…"; "room_message_reply_to_short_placeholder" = "Saada vastus…";
"room_offline_notification" = "Ühendus sinu serveriga on katkenud."; "room_offline_notification" = "Ühendus sinu serveriga on katkenud.";
"room_unsent_messages_notification" = "Sõnumid pole saadetud. %@ või %@ nüüd?"; "room_unsent_messages_notification" = "Sõnumid pole saadetud.";
"room_unsent_messages_unknown_devices_notification" = "Kuna leidub tundmatuid sessioone, siis sõnumid pole saadetud. %@ või %@ nüüd?"; "room_unsent_messages_unknown_devices_notification" = "Kuna leidub tundmatuid sessioone, siis sõnumid pole saadetud.";
"room_ongoing_conference_call" = "Konverentsikõne on käsil. Liitu kas %@ või %@."; "room_ongoing_conference_call" = "Konverentsikõne on käsil. Liitu kas %@ või %@.";
"room_ongoing_conference_call_with_close" = "Konverentsikõne on käsil. Liitu kas %@ või %@. %@ seda."; "room_ongoing_conference_call_with_close" = "Konverentsikõne on käsil. Liitu kas %@ või %@. %@ seda.";
"room_ongoing_conference_call_close" = "Sulge"; "room_ongoing_conference_call_close" = "Sulge";

View file

@ -286,8 +286,8 @@
"room_two_users_are_typing" = "%@ eta %@ idazten ari dira…"; "room_two_users_are_typing" = "%@ eta %@ idazten ari dira…";
"room_many_users_are_typing" = "%@, %@, eta beste batzuk idazten ari dira…"; "room_many_users_are_typing" = "%@, %@, eta beste batzuk idazten ari dira…";
"room_message_short_placeholder" = "Bidali mezu bat…"; "room_message_short_placeholder" = "Bidali mezu bat…";
"room_unsent_messages_notification" = "Bidali gabeko mezuak daude. %@ edo %@ orain?"; "room_unsent_messages_notification" = "Bidali gabeko mezuak daude.";
"room_unsent_messages_unknown_devices_notification" = "Mezua ez da bidali saio ezezagunak daudelako. %@ edo %@ orain?"; "room_unsent_messages_unknown_devices_notification" = "Mezua ez da bidali saio ezezagunak daudelako.";
"room_ongoing_conference_call" = "Konferentzia deia abioan. Elkartu %@ edo %@ erabiliz."; "room_ongoing_conference_call" = "Konferentzia deia abioan. Elkartu %@ edo %@ erabiliz.";
"room_event_action_more" = "Gehiago"; "room_event_action_more" = "Gehiago";
"room_event_action_save" = "Gorde"; "room_event_action_save" = "Gorde";

View file

@ -1,7 +1,7 @@
// Permissions usage explanations // Permissions usage explanations
"NSCameraUsageDescription" = "L'appareil photo est utilisé pour prendre des photos et des vidéos et pour passer des appels vidéo."; "NSCameraUsageDescription" = "Lappareil photo est utilisé pour prendre des photos, des vidéos et pour passer des appels vidéo.";
"NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos."; "NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos.";
"NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels."; "NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels.";
"NSContactsUsageDescription" = "Pour découvrir vos contacts qui utilisent déjà Matrix, Element peut envoyer les adresses e-mail et les numéros de téléphone de votre carnet dadresse à votre serveur didentité Matrix. Si votre serveur didentité le prend en charge, les données personnelles sont hachées avant lenvoi  vérifiez sa politique de vie privée pour plus de détails."; "NSContactsUsageDescription" = "Pour découvrir vos contacts qui utilisent déjà Matrix, Element peut envoyer les adresses e-mail et les numéros de téléphone de votre carnet dadresse à votre serveur didentité Matrix. Si votre serveur didentité le prend en charge, les données personnelles sont hachées avant lenvoi  vérifiez sa politique de confidentialité pour plus de détails.";
"NSCalendarsUsageDescription" = "Voir vos rendez-vous prévus dans lapplication."; "NSCalendarsUsageDescription" = "Voir vos rendez-vous dans lapplication.";
"NSFaceIDUsageDescription" = "Face ID est utilisé pour accéder à votre application."; "NSFaceIDUsageDescription" = "Face ID est utilisé pour accéder à votre application.";

View file

@ -3,13 +3,13 @@
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ a posté dans %@"; "MSG_FROM_USER_IN_ROOM" = "%@ a posté dans %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
"MSG_FROM_USER_WITH_CONTENT" = "%@ : %@"; "MSG_FROM_USER_WITH_CONTENT" = "%@ : %@";
/* New message from a specific person in a named room. Content included. */ /* New message from a specific person in a named room. Content included. */
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@ dans %@ : %@"; "MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@ dans %@ : %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"ACTION_FROM_USER" = "* %@ %@"; "ACTION_FROM_USER" = "* %@ %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@ : * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@ : * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ a envoyé une image %@"; "IMAGE_FROM_USER" = "%@ a envoyé une image %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
@ -27,11 +27,11 @@
/* Multiple unread messages from three people */ /* Multiple unread messages from three people */
"MSGS_FROM_THREE_USERS" = "%@ nouveaux messages de %@, %@ et %@"; "MSGS_FROM_THREE_USERS" = "%@ nouveaux messages de %@, %@ et %@";
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */ /* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
"MSGS_FROM_TWO_PLUS_USERS" = "%@ nouveaux messages de %@, %@ et d'autres"; "MSGS_FROM_TWO_PLUS_USERS" = "%@ nouveaux messages de %@, %@ et dautres";
/* Multiple messages in two rooms */ /* Multiple messages in two rooms */
"MSGS_IN_TWO_ROOMS" = "%@ nouveaux messages dans %@ et %@"; "MSGS_IN_TWO_ROOMS" = "%@ nouveaux messages dans %@ et %@";
/* Look, stuff's happened, alright? Just open the app. */ /* Look, stuff's happened, alright? Just open the app. */
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ nouveaux messages dans %@, %@ et d'autres"; "MSGS_IN_TWO_PLUS_ROOMS" = "%@ nouveaux messages dans %@, %@ et dautres";
/* A user has invited you to a chat */ /* A user has invited you to a chat */
"USER_INVITE_TO_CHAT" = "%@ vous a invité dans une discussion"; "USER_INVITE_TO_CHAT" = "%@ vous a invité dans une discussion";
/* A user has invited you to an (unamed) group chat */ /* A user has invited you to an (unamed) group chat */
@ -43,17 +43,17 @@
/* Incoming one-to-one video call */ /* Incoming one-to-one video call */
"VIDEO_CALL_FROM_USER" = "Appel vidéo de %@"; "VIDEO_CALL_FROM_USER" = "Appel vidéo de %@";
/* Incoming unnamed voice conference invite from a specific person */ /* Incoming unnamed voice conference invite from a specific person */
"VOICE_CONF_FROM_USER" = "Téléconférence vocale de %@"; "VOICE_CONF_FROM_USER" = "Téléconférence audio de %@";
/* Incoming unnamed video conference invite from a specific person */ /* Incoming unnamed video conference invite from a specific person */
"VIDEO_CONF_FROM_USER" = "Téléconférence vidéo de %@"; "VIDEO_CONF_FROM_USER" = "Téléconférence vidéo de %@";
/* Incoming named voice conference invite from a specific person */ /* Incoming named voice conference invite from a specific person */
"VOICE_CONF_NAMED_FROM_USER" = "Téléconférence vocale de %@ : '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "Téléconférence audio de %@ : « %@ »";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Téléconférence vidéo de %@ : '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "Téléconférence vidéo de %@ : « %@ »";
/* Message title for a specific person in a named room */ /* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ dans %@"; "MSG_FROM_USER_IN_ROOM_TITLE" = "%@ dans %@";
/* Sticker from a specific person, not referencing a room. */ /* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ a envoyé un sticker"; "STICKER_FROM_USER" = "%@ a envoyé un autocollant";
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ veut vérifier"; "KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ veut vérifier";
/* New message indicator on unknown room */ /* New message indicator on unknown room */
"MESSAGE" = "Message"; "MESSAGE" = "Message";
@ -61,3 +61,4 @@
"MESSAGE_FROM_X" = "Message de %@"; "MESSAGE_FROM_X" = "Message de %@";
/* New message indicator on a room */ /* New message indicator on a room */
"MESSAGE_IN_X" = "Message dans %@"; "MESSAGE_IN_X" = "Message dans %@";
"MESSAGE_PROTECTED" = "Nouveau message";

View file

@ -195,8 +195,8 @@
"encrypted_room_message_placeholder" = "Envoyer un message chiffré…"; "encrypted_room_message_placeholder" = "Envoyer un message chiffré…";
"room_message_short_placeholder" = "Envoyer un message…"; "room_message_short_placeholder" = "Envoyer un message…";
"room_offline_notification" = "La connexion au serveur a été perdue."; "room_offline_notification" = "La connexion au serveur a été perdue.";
"room_unsent_messages_notification" = "Messages non envoyés. %@ ou %@ maintenant ?"; "room_unsent_messages_notification" = "Messages non envoyés.";
"room_unsent_messages_unknown_devices_notification" = "Message non envoyé car des sessions inconnues sont présentes. %@ ou %@ maintenant ?"; "room_unsent_messages_unknown_devices_notification" = "Message non envoyé car des sessions inconnues sont présentes.";
"room_ongoing_conference_call" = "Téléconférence en cours. Rejoindre en %@ ou %@."; "room_ongoing_conference_call" = "Téléconférence en cours. Rejoindre en %@ ou %@.";
"room_prompt_resend" = "Tout renvoyer"; "room_prompt_resend" = "Tout renvoyer";
"room_prompt_cancel" = "tout annuler"; "room_prompt_cancel" = "tout annuler";

View file

@ -210,8 +210,8 @@
"room_message_short_placeholder" = "Üzenet küldése…"; "room_message_short_placeholder" = "Üzenet küldése…";
"room_message_reply_to_short_placeholder" = "Válasz küldése…"; "room_message_reply_to_short_placeholder" = "Válasz küldése…";
"room_offline_notification" = "A szerverrel megszakadt a kapcsolat."; "room_offline_notification" = "A szerverrel megszakadt a kapcsolat.";
"room_unsent_messages_notification" = "Üzenet nincs elküldve. Most %@ vagy %@?"; "room_unsent_messages_notification" = "Üzenet nincs elküldve.";
"room_unsent_messages_unknown_devices_notification" = "Az üzenet nincs elküldve, mert ismeretlen munkamenet van jelen. Most %@ vagy %@?"; "room_unsent_messages_unknown_devices_notification" = "Az üzenet nincs elküldve, mert ismeretlen munkamenet van jelen.";
"room_ongoing_conference_call" = "Konferencia hívás van folyamatban. Csatlakozol mint %@ vagy %@."; "room_ongoing_conference_call" = "Konferencia hívás van folyamatban. Csatlakozol mint %@ vagy %@.";
"room_ongoing_conference_call_with_close" = "Konferencia hívás van folyamatban. Csatlakozol mint %@ vagy %@. %@."; "room_ongoing_conference_call_with_close" = "Konferencia hívás van folyamatban. Csatlakozol mint %@ vagy %@. %@.";
"room_ongoing_conference_call_close" = "Bezár"; "room_ongoing_conference_call_close" = "Bezár";

View file

@ -401,8 +401,8 @@
"room_participants_remove_prompt_msg" = "Ertu viss um að þú viljir fjarlægja %@ úr þessu spjalli?"; "room_participants_remove_prompt_msg" = "Ertu viss um að þú viljir fjarlægja %@ úr þessu spjalli?";
"room_participants_invite_prompt_msg" = "Ertu viss um að þú viljir bjóða %@ á þetta spjall?"; "room_participants_invite_prompt_msg" = "Ertu viss um að þú viljir bjóða %@ á þetta spjall?";
"room_participants_invite_malformed_id" = "Rangt formað auðkenni. Ætti að vera tölvupóstfang eða Matrix-auðkenni á borð við'@sérheiti:lén'"; "room_participants_invite_malformed_id" = "Rangt formað auðkenni. Ætti að vera tölvupóstfang eða Matrix-auðkenni á borð við'@sérheiti:lén'";
"room_unsent_messages_notification" = "Skilaboð ekki send. %@ eða %@ núna?"; "room_unsent_messages_notification" = "Skilaboð ekki send.";
"room_unsent_messages_unknown_devices_notification" = "Skilaboð ekki send vegna þess að vart var við óþekkt tæki. %@ eða %@ núna?"; "room_unsent_messages_unknown_devices_notification" = "Skilaboð ekki send vegna þess að vart var við óþekkt tæki.";
"room_ongoing_conference_call" = "Símafundur í gangi. Taka þátt með %@ eða %@."; "room_ongoing_conference_call" = "Símafundur í gangi. Taka þátt með %@ eða %@.";
"room_ongoing_conference_call_with_close" = "Símafundur í gangi. Taka þátt með %@ eða %@. %@ því."; "room_ongoing_conference_call_with_close" = "Símafundur í gangi. Taka þátt með %@ eða %@. %@ því.";
"room_conference_call_no_power" = "Þú þarft aðgangsheimildir til að sýsla með símafundi á þessari spjallrás"; "room_conference_call_no_power" = "Þú þarft aðgangsheimildir til að sýsla með símafundi á þessari spjallrás";

View file

@ -216,8 +216,8 @@
"room_message_short_placeholder" = "Invia un messaggio…"; "room_message_short_placeholder" = "Invia un messaggio…";
"room_message_reply_to_short_placeholder" = "Invia una risposta…"; "room_message_reply_to_short_placeholder" = "Invia una risposta…";
"room_offline_notification" = "La connessione al server è stata persa."; "room_offline_notification" = "La connessione al server è stata persa.";
"room_unsent_messages_notification" = "Messaggi non inviati. %1$s o %2$s ora?"; "room_unsent_messages_notification" = "Messaggi non inviati.";
"room_unsent_messages_unknown_devices_notification" = "Messaggi non inviati a causa della presenza di sessioni sconosciute. %1$s o %2$s ora?"; "room_unsent_messages_unknown_devices_notification" = "Messaggi non inviati a causa della presenza di sessioni sconosciute.";
"room_ongoing_conference_call" = "Avvio conferenza. Unisciti come %@ o %@."; "room_ongoing_conference_call" = "Avvio conferenza. Unisciti come %@ o %@.";
"room_ongoing_conference_call_with_close" = "Avvio conferenza. Unisciti come %@ o %@. %@."; "room_ongoing_conference_call_with_close" = "Avvio conferenza. Unisciti come %@ o %@. %@.";
"room_ongoing_conference_call_close" = "Chiudi"; "room_ongoing_conference_call_close" = "Chiudi";

View file

@ -200,8 +200,8 @@
"encrypted_room_message_placeholder" = "暗号文を送信…"; "encrypted_room_message_placeholder" = "暗号文を送信…";
"room_message_short_placeholder" = "ここに送信文を入力…"; "room_message_short_placeholder" = "ここに送信文を入力…";
"room_offline_notification" = "サーバとの接続が失われました."; "room_offline_notification" = "サーバとの接続が失われました.";
"room_unsent_messages_notification" = "文章が送信できませんでした。現在 %@ または %@ ?"; "room_unsent_messages_notification" = "文章が送信できませんでした.";
"room_unsent_messages_unknown_devices_notification" = "未知のセッションが存在するために文章が送信されませんでした。現在%@ or %@ "; "room_unsent_messages_unknown_devices_notification" = "未知のセッションが存在するために文章が送信されませんでした.";
"room_ongoing_conference_call" = "会議通話実施中。 %@ または %@で参加してください。"; "room_ongoing_conference_call" = "会議通話実施中。 %@ または %@で参加してください。";
"room_ongoing_conference_call_with_close" = "会議通話実施中。%@または%@で参加してください。 %@。"; "room_ongoing_conference_call_with_close" = "会議通話実施中。%@または%@で参加してください。 %@。";
"room_ongoing_conference_call_close" = "閉じる"; "room_ongoing_conference_call_close" = "閉じる";

View file

@ -18,5 +18,6 @@
"NSCameraUsageDescription" = "De camera wordt gebruikt om fotos en videos te maken, en voor videogesprekken."; "NSCameraUsageDescription" = "De camera wordt gebruikt om fotos en videos te maken, en voor videogesprekken.";
"NSPhotoLibraryUsageDescription" = "De fotogalerij wordt gebruikt om fotos en videos te versturen."; "NSPhotoLibraryUsageDescription" = "De fotogalerij wordt gebruikt om fotos en videos te versturen.";
"NSMicrophoneUsageDescription" = "De microfoon wordt gebruikt om videos te maken, en voor spraakoproepen."; "NSMicrophoneUsageDescription" = "De microfoon wordt gebruikt om videos te maken, en voor spraakoproepen.";
"NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Matrix gebruiken, kan Element de e-mailadressen en telefoonnummers in uw adresboek naar uw gekozen Matrix-identiteitsserver sturen. Waar mogelijk worden persoonlijke gegevens gehasht voor verzenden - bekijk het privacybeleid van uw identiteitsserver voor meer informatie."; "NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Matrix gebruiken, kan Element de e-mailadressen en telefoonnummers in uw adresboek naar uw gekozen Matrix-identiteitsserver sturen. Waar mogelijk worden persoonlijke gegevens gehasht voor verzending - bekijk het privacybeleid van uw identiteitsserver voor meer informatie.";
"NSCalendarsUsageDescription" = "Bekijk uw geplande afspraken in de app."; "NSCalendarsUsageDescription" = "Bekijk uw geplande afspraken in de app.";
"NSFaceIDUsageDescription" = "Face ID wordt gebruikt om toegang te krijgen tot uw app.";

View file

@ -19,7 +19,7 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "%@ heeft een bericht gestuurd"; "MSG_FROM_USER" = "%@ heeft een bericht gestuurd";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ geplaatst in %@"; "MSG_FROM_USER_IN_ROOM" = "%@ heeft een bericht in %@ geplaatst";
/** Single, unencrypted messages (where we can include the content */ /** Single, unencrypted messages (where we can include the content */
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -33,7 +33,7 @@
/** Image Messages **/ /** Image Messages **/
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ heeft een afbeelding %@ gestuurd"; "IMAGE_FROM_USER" = "%@ heeft een afbeelding gestuurd %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ heeft een afbeelding %@ in %@ geplaatst"; "IMAGE_FROM_USER_IN_ROOM" = "%@ heeft een afbeelding %@ in %@ geplaatst";
/** Coalesced messages **/ /** Coalesced messages **/
@ -83,3 +83,15 @@
/* Sticker from a specific person, not referencing a room. */ /* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ heeft een sticker gestuurd"; "STICKER_FROM_USER" = "%@ heeft een sticker gestuurd";
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ wil verifiëren"; "KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ wil verifiëren";
"MESSAGE_PROTECTED" = "Nieuw Bericht";
/* New message indicator on a room */
"MESSAGE_IN_X" = "Bericht in %@";
/* New message indicator from a DM */
"MESSAGE_FROM_X" = "Bericht van %@";
/** Notification messages **/
/* New message indicator on unknown room */
"MESSAGE" = "Bericht";

View file

@ -204,8 +204,8 @@
"encrypted_room_message_placeholder" = "Stuur een versleuteld bericht…"; "encrypted_room_message_placeholder" = "Stuur een versleuteld bericht…";
"room_message_short_placeholder" = "Stuur een bericht…"; "room_message_short_placeholder" = "Stuur een bericht…";
"room_offline_notification" = "De verbinding met de server is verbroken."; "room_offline_notification" = "De verbinding met de server is verbroken.";
"room_unsent_messages_notification" = "Berichten niet verstuurd. Nu %@ of %@?"; "room_unsent_messages_notification" = "Berichten niet verstuurd.";
"room_unsent_messages_unknown_devices_notification" = "Bericht is niet verstuurd doordat er onbekende apparaten aanwezig zijn. Nu %@ of %@?"; "room_unsent_messages_unknown_devices_notification" = "Bericht is niet verstuurd doordat er onbekende apparaten aanwezig zijn.";
"room_ongoing_conference_call" = "Er is een vergadergesprek gaande. Neem deel met %@ of %@."; "room_ongoing_conference_call" = "Er is een vergadergesprek gaande. Neem deel met %@ of %@.";
"room_prompt_resend" = "alles opnieuw versturen"; "room_prompt_resend" = "alles opnieuw versturen";
"room_prompt_cancel" = "alles annuleren"; "room_prompt_cancel" = "alles annuleren";

View file

@ -392,7 +392,7 @@
"contacts_address_book_no_contact" = "Brak lokalnych kontaktów"; "contacts_address_book_no_contact" = "Brak lokalnych kontaktów";
"auth_msisdn_validation_error" = "Nie można zweryfikować numeru telefonu."; "auth_msisdn_validation_error" = "Nie można zweryfikować numeru telefonu.";
"room_participants_invite_malformed_id" = "Uszkodzony ID. Powinien być adres e-mail lub Matrix ID podobny do '@localpart:domain'"; "room_participants_invite_malformed_id" = "Uszkodzony ID. Powinien być adres e-mail lub Matrix ID podobny do '@localpart:domain'";
"room_unsent_messages_notification" = "Wiadomość nie została wysłana. Czy %@ lub %@ teraz?"; "room_unsent_messages_notification" = "Wiadomość nie została wysłana.";
"room_ongoing_conference_call_with_close" = "Przychodzące połączenie grupowe. Dołącz z %@ lub z %@. %@ to."; "room_ongoing_conference_call_with_close" = "Przychodzące połączenie grupowe. Dołącz z %@ lub z %@. %@ to.";
"directory_search_results_title" = "Przeglądaj wyniki katalogów"; "directory_search_results_title" = "Przeglądaj wyniki katalogów";
"room_event_action_kick_prompt_reason" = "Powód wyrzucenia użytkownika"; "room_event_action_kick_prompt_reason" = "Powód wyrzucenia użytkownika";

View file

@ -185,8 +185,8 @@
"encrypted_room_message_placeholder" = "Отправить зашифрованное сообщение…"; "encrypted_room_message_placeholder" = "Отправить зашифрованное сообщение…";
"room_message_short_placeholder" = "Отправить сообщение…"; "room_message_short_placeholder" = "Отправить сообщение…";
"room_offline_notification" = "Связь с сервером потеряна."; "room_offline_notification" = "Связь с сервером потеряна.";
"room_unsent_messages_notification" = "Сообщения не отправлены. %@ или %@ сейчас?"; "room_unsent_messages_notification" = "Сообщения не отправлены.";
"room_unsent_messages_unknown_devices_notification" = "Сообщение не отправлено из-за присутствия неизвестных сеансов. %@ или %@ сейчас?"; "room_unsent_messages_unknown_devices_notification" = "Сообщение не отправлено из-за присутствия неизвестных сеансов.";
"room_ongoing_conference_call" = "Текущий групповой вызов. Войти как %@ или %@."; "room_ongoing_conference_call" = "Текущий групповой вызов. Войти как %@ или %@.";
"room_prompt_resend" = "Отправить все"; "room_prompt_resend" = "Отправить все";
"room_prompt_cancel" = "отменить все"; "room_prompt_cancel" = "отменить все";

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,19 @@
"MESSAGE_PROTECTED" = "නව පණිවිඩය";
/** Notification messages **/
/* New message indicator on unknown room */
"MESSAGE" = "පණිවිඩය";
/* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */
"ACTION_FROM_USER" = "* %@ %@";
/** Single, unencrypted messages (where we can include the content */
/* New message from a specific person, not referencing a room. Content included. */
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";

View file

@ -173,7 +173,7 @@
"encrypted_room_message_placeholder" = "Dërgoni një mesazhi të fshehtëzuar…"; "encrypted_room_message_placeholder" = "Dërgoni një mesazhi të fshehtëzuar…";
"room_message_short_placeholder" = "Dërgoni një mesazh…"; "room_message_short_placeholder" = "Dërgoni një mesazh…";
"room_offline_notification" = "Humbi lidhja me shërbyesin."; "room_offline_notification" = "Humbi lidhja me shërbyesin.";
"room_unsent_messages_notification" = "Mesazhet su dërguan. %@ apo %@ tani?"; "room_unsent_messages_notification" = "Mesazhet su dërguan.";
"room_ongoing_conference_call_close" = "Mbylle"; "room_ongoing_conference_call_close" = "Mbylle";
"room_prompt_resend" = "Ridërgoji krejt"; "room_prompt_resend" = "Ridërgoji krejt";
"room_prompt_cancel" = "anuloji krejt"; "room_prompt_cancel" = "anuloji krejt";

View file

@ -200,8 +200,8 @@
"encrypted_room_message_placeholder" = "Gửi tin nhắn đã mã hoá…"; "encrypted_room_message_placeholder" = "Gửi tin nhắn đã mã hoá…";
"room_message_short_placeholder" = "Gửi tin nhắn…"; "room_message_short_placeholder" = "Gửi tin nhắn…";
"room_offline_notification" = "Kết nối tới máy chủ thất bại."; "room_offline_notification" = "Kết nối tới máy chủ thất bại.";
"room_unsent_messages_notification" = "Các tin nhắn chưa được gửi. %@ hoặc %@ ngay bây giờ?"; "room_unsent_messages_notification" = "Các tin nhắn chưa được gửi.";
"room_unsent_messages_unknown_devices_notification" = "Các tin nhắn chưa được gửi tới các thiết bị không xác định hiện hành. %@ hoặc %@ ngay bây giờ?"; "room_unsent_messages_unknown_devices_notification" = "Các tin nhắn chưa được gửi tới các thiết bị không xác định hiện hành.";
"room_ongoing_conference_call" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@."; "room_ongoing_conference_call" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@.";
"room_ongoing_conference_call_with_close" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@. %@ nó."; "room_ongoing_conference_call_with_close" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@. %@ nó.";
"room_ongoing_conference_call_close" = "Đóng"; "room_ongoing_conference_call_close" = "Đóng";

View file

@ -189,8 +189,8 @@
"encrypted_room_message_placeholder" = "发送加密消息…"; "encrypted_room_message_placeholder" = "发送加密消息…";
"room_message_short_placeholder" = "发送消息…"; "room_message_short_placeholder" = "发送消息…";
"room_offline_notification" = "到服务器的连接已经丢失。"; "room_offline_notification" = "到服务器的连接已经丢失。";
"room_unsent_messages_notification" = "消息没有发送。现在 %@ 或 %@ "; "room_unsent_messages_notification" = "消息没有发送。";
"room_unsent_messages_unknown_devices_notification" = "由于未知会话在线所以消息没有发送。现在 %@ 或 %@"; "room_unsent_messages_unknown_devices_notification" = "由于未知会话在线所以消息没有发送。";
"room_ongoing_conference_call" = "收到会议通话。以 %@ 或 %@ 加入。"; "room_ongoing_conference_call" = "收到会议通话。以 %@ 或 %@ 加入。";
"room_prompt_resend" = "全部重新发送"; "room_prompt_resend" = "全部重新发送";
"room_prompt_cancel" = "全部取消"; "room_prompt_cancel" = "全部取消";

View file

@ -266,8 +266,8 @@
"room_two_users_are_typing" = "%@ 和 %@ 正在輸入…"; "room_two_users_are_typing" = "%@ 和 %@ 正在輸入…";
"room_many_users_are_typing" = "%@、%@ 和 %@ 正在輸入…"; "room_many_users_are_typing" = "%@、%@ 和 %@ 正在輸入…";
"room_message_short_placeholder" = "傳送訊息…"; "room_message_short_placeholder" = "傳送訊息…";
"room_unsent_messages_notification" = "訊息未被傳送。現在 %@ 或 %@ 嗎?"; "room_unsent_messages_notification" = "訊息未被傳送。";
"room_unsent_messages_unknown_devices_notification" = "由於存在未知的工作階段導致訊息未被傳送。現在 %@ 或 %@ 嗎?"; "room_unsent_messages_unknown_devices_notification" = "由於存在未知的工作階段導致訊息未被傳送。";
"room_conference_call_no_power" = "您需要管理此聊天室群組通話的權限"; "room_conference_call_no_power" = "您需要管理此聊天室群組通話的權限";
"room_prompt_resend" = "全部重新傳送"; "room_prompt_resend" = "全部重新傳送";
"room_prompt_cancel" = "全部取消"; "room_prompt_cancel" = "全部取消";

View file

@ -16,6 +16,8 @@
#import <MatrixKit/MatrixKit.h> #import <MatrixKit/MatrixKit.h>
@class CircleProgressView;
/** /**
Action identifier used when the user pressed edit button displayed in front of a selected event. Action identifier used when the user pressed edit button displayed in front of a selected event.
@ -148,6 +150,13 @@ extern NSString *const kMXKRoomBubbleCellCallBackButtonPressed;
*/ */
+ (CGFloat)attachmentBubbleCellHeightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth; + (CGFloat)attachmentBubbleCellHeightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth;
- (IBAction)onProgressLongPressGesture:(UILongPressGestureRecognizer*)recognizer;
/**
update tick view(s) according to the current sent state.
*/
- (void)updateTickViewWithFailedEventIds:(NSSet *)failedEventIds;
/** /**
Blur the view by adding a transparent overlay. Default is NO. Blur the view by adding a transparent overlay. Default is NO.
*/ */
@ -163,4 +172,9 @@ extern NSString *const kMXKRoomBubbleCellCallBackButtonPressed;
*/ */
@property (nonatomic) UIView *markerView; @property (nonatomic) UIView *markerView;
/**
Message tick views (sending, sent) displayed alongside the related component.
*/
@property (nonatomic) NSArray *messageStatusViews;
@end @end

View file

@ -452,6 +452,16 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa
return objc_getAssociatedObject(self, @selector(markerView)); return objc_getAssociatedObject(self, @selector(markerView));
} }
- (void)setMessageStatusViews:(NSArray *)arrayOfViews
{
objc_setAssociatedObject(self, @selector(messageStatusViews), arrayOfViews, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSArray *)messageStatusViews
{
return objc_getAssociatedObject(self, @selector(messageStatusViews));
}
- (void)updateUserNameColor - (void)updateUserNameColor
{ {
static UserNameColorGenerator *userNameColorGenerator; static UserNameColorGenerator *userNameColorGenerator;
@ -659,6 +669,82 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa
return rowHeight; return rowHeight;
} }
- (void)updateTickViewWithFailedEventIds:(NSSet *)failedEventIds
{
for (UIView *tickView in self.messageStatusViews)
{
[tickView removeFromSuperview];
}
self.messageStatusViews = nil;
NSMutableArray *statusViews = [NSMutableArray new];
UIView *tickView = nil;
if ([bubbleData isKindOfClass:RoomBubbleCellData.class]
&& ((RoomBubbleCellData*)bubbleData).componentIndexOfSentMessageTick >= 0)
{
UIImage *image = [UIImage imageNamed:@"sent_message_tick"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
tickView = [[UIImageView alloc] initWithImage:image];
tickView.tintColor = ThemeService.shared.theme.messageTickColor;
[statusViews addObject:tickView];
[self addTickView:tickView atIndex:((RoomBubbleCellData*)bubbleData).componentIndexOfSentMessageTick];
}
NSInteger index = bubbleData.bubbleComponents.count;
while (index--)
{
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[index];
NSArray<MXReceiptData*> *receipts = bubbleData.readReceipts[component.event.eventId];
if (receipts.count == 0) {
if (component.event.sentState == MXEventSentStateUploading
|| component.event.sentState == MXEventSentStateEncrypting
|| component.event.sentState == MXEventSentStatePreparing
|| component.event.sentState == MXEventSentStateSending)
{
if ([failedEventIds containsObject:component.event.eventId] || (bubbleData.attachment && component.event.sentState != MXEventSentStateSending))
{
UIView *progressContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
CircleProgressView *progressView = [[CircleProgressView alloc] initWithFrame:CGRectMake(24, 24, 16, 16)];
progressView.lineColor = ThemeService.shared.theme.messageTickColor;
[progressContentView addSubview:progressView];
self.progressChartView = progressView;
tickView = progressContentView;
[progressView startAnimating];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onProgressLongPressGesture:)];
[tickView addGestureRecognizer:longPress];
}
else
{
UIImage *image = [UIImage imageNamed:@"sending_message_tick"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
tickView = [[UIImageView alloc] initWithImage:image];
tickView.tintColor = ThemeService.shared.theme.messageTickColor;
}
[statusViews addObject:tickView];
[self addTickView:tickView atIndex:index];
}
}
if (component.event.sentState == MXEventSentStateFailed)
{
tickView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"error_message_tick"]];
[statusViews addObject:tickView];
[self addTickView:tickView atIndex:index];
}
}
if (statusViews.count)
{
self.messageStatusViews = statusViews;
}
}
#pragma mark - User actions #pragma mark - User actions
- (IBAction)onEditButtonPressed:(id)sender - (IBAction)onEditButtonPressed:(id)sender
@ -694,6 +780,15 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa
#pragma mark - Internals #pragma mark - Internals
- (void)addTickView:(UIView *)tickView atIndex:(NSInteger)index
{
CGRect componentFrame = [self componentFrameInContentViewForIndex: index];
tickView.frame = CGRectMake(self.contentView.bounds.size.width - tickView.frame.size.width - 2 * RoomBubbleCellLayout.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height);
[self.contentView addSubview:tickView];
}
- (void)addEditButtonForComponent:(NSUInteger)componentIndex completion:(void (^ __nullable)(BOOL finished))completion - (void)addEditButtonForComponent:(NSUInteger)componentIndex completion:(void (^ __nullable)(BOOL finished))completion
{ {
MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[componentIndex]; MXKRoomBubbleComponent *component = bubbleData.bubbleComponents[componentIndex];
@ -758,4 +853,12 @@ NSString *const kMXKRoomBubbleCellCallBackButtonPressed = @"kMXKRoomBubbleCellCa
self.editButton = editButton; self.editButton = editButton;
} }
- (IBAction)onProgressLongPressGesture:(UILongPressGestureRecognizer*)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan && self.delegate)
{
[self.delegate cell:self didRecognizeAction:kMXKRoomBubbleCellLongPressOnProgressView userInfo:nil];
}
}
@end @end

View file

@ -19,6 +19,13 @@
#import "UserEncryptionTrustLevel.h" #import "UserEncryptionTrustLevel.h"
typedef NS_ENUM(NSUInteger, RoomSentStatus)
{
RoomSentStatusOk,
RoomSentStatusSentFailed,
RoomSentStatusSentFailedDueToUnknownDevices
};
/** /**
Define a `MXRoom` category at Riot level. Define a `MXRoom` category at Riot level.
*/ */
@ -44,6 +51,9 @@
*/ */
@property (nonatomic) id notificationCenterDidUpdateObserver; @property (nonatomic) id notificationCenterDidUpdateObserver;
/// Check if all messages have been sent.
@property (nonatomic, readonly) RoomSentStatus sentStatus;
/** /**
Update the room tag. Update the room tag.

View file

@ -656,4 +656,30 @@
return objc_getAssociatedObject(self, @selector(notificationCenterDidUpdateObserver)); return objc_getAssociatedObject(self, @selector(notificationCenterDidUpdateObserver));
} }
#pragma mark - Unread messages
- (RoomSentStatus)sentStatus
{
RoomSentStatus status = RoomSentStatusOk;
NSArray<MXEvent*> *outgoingMsgs = self.outgoingMessages;
for (MXEvent *event in outgoingMsgs)
{
if (event.sentState == MXEventSentStateFailed)
{
status = RoomSentStatusSentFailed;
// Check if the error is due to unknown devices
if ([event.sentError.domain isEqualToString:MXEncryptingErrorDomain]
&& event.sentError.code == MXEncryptingErrorUnknownDeviceCode)
{
status = RoomSentStatusSentFailedDueToUnknownDevices;
break;
}
}
}
return status;
}
@end @end

View file

@ -50,6 +50,7 @@ internal enum Asset {
internal static let chevron = ImageAsset(name: "chevron") internal static let chevron = ImageAsset(name: "chevron")
internal static let closeButton = ImageAsset(name: "close_button") internal static let closeButton = ImageAsset(name: "close_button")
internal static let disclosureIcon = ImageAsset(name: "disclosure_icon") internal static let disclosureIcon = ImageAsset(name: "disclosure_icon")
internal static let errorIcon = ImageAsset(name: "error_icon")
internal static let faceidIcon = ImageAsset(name: "faceid_icon") internal static let faceidIcon = ImageAsset(name: "faceid_icon")
internal static let group = ImageAsset(name: "group") internal static let group = ImageAsset(name: "group")
internal static let monitor = ImageAsset(name: "monitor") internal static let monitor = ImageAsset(name: "monitor")
@ -98,12 +99,18 @@ internal enum Asset {
internal static let peopleEmptyScreenArtworkDark = ImageAsset(name: "people_empty_screen_artwork_dark") internal static let peopleEmptyScreenArtworkDark = ImageAsset(name: "people_empty_screen_artwork_dark")
internal static let peopleFloatingAction = ImageAsset(name: "people_floating_action") internal static let peopleFloatingAction = ImageAsset(name: "people_floating_action")
internal static let error = ImageAsset(name: "error") internal static let error = ImageAsset(name: "error")
internal static let errorMessageTick = ImageAsset(name: "error_message_tick")
internal static let roomActivitiesRetry = ImageAsset(name: "room_activities_retry")
internal static let scrolldown = ImageAsset(name: "scrolldown") internal static let scrolldown = ImageAsset(name: "scrolldown")
internal static let sendingMessageTick = ImageAsset(name: "sending_message_tick")
internal static let sentMessageTick = ImageAsset(name: "sent_message_tick")
internal static let typing = ImageAsset(name: "typing") internal static let typing = ImageAsset(name: "typing")
internal static let roomContextMenuCopy = ImageAsset(name: "room_context_menu_copy") internal static let roomContextMenuCopy = ImageAsset(name: "room_context_menu_copy")
internal static let roomContextMenuDelete = ImageAsset(name: "room_context_menu_delete")
internal static let roomContextMenuEdit = ImageAsset(name: "room_context_menu_edit") internal static let roomContextMenuEdit = ImageAsset(name: "room_context_menu_edit")
internal static let roomContextMenuMore = ImageAsset(name: "room_context_menu_more") internal static let roomContextMenuMore = ImageAsset(name: "room_context_menu_more")
internal static let roomContextMenuReply = ImageAsset(name: "room_context_menu_reply") internal static let roomContextMenuReply = ImageAsset(name: "room_context_menu_reply")
internal static let roomContextMenuRetry = ImageAsset(name: "room_context_menu_retry")
internal static let uploadIcon = ImageAsset(name: "upload_icon") internal static let uploadIcon = ImageAsset(name: "upload_icon")
internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon") internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon")
internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon") internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon")

View file

@ -2722,6 +2722,14 @@ internal enum VectorL10n {
internal static var roomEventActionDelete: String { internal static var roomEventActionDelete: String {
return VectorL10n.tr("Vector", "room_event_action_delete") return VectorL10n.tr("Vector", "room_event_action_delete")
} }
/// Are you sure you want to delete this unsent message?
internal static var roomEventActionDeleteConfirmationMessage: String {
return VectorL10n.tr("Vector", "room_event_action_delete_confirmation_message")
}
/// Delete unsent message
internal static var roomEventActionDeleteConfirmationTitle: String {
return VectorL10n.tr("Vector", "room_event_action_delete_confirmation_title")
}
/// Edit /// Edit
internal static var roomEventActionEdit: String { internal static var roomEventActionEdit: String {
return VectorL10n.tr("Vector", "room_event_action_edit") return VectorL10n.tr("Vector", "room_event_action_edit")
@ -2818,7 +2826,7 @@ internal enum VectorL10n {
internal static var roomIntroCellAddParticipantsAction: String { internal static var roomIntroCellAddParticipantsAction: String {
return VectorL10n.tr("Vector", "room_intro_cell_add_participants_action") return VectorL10n.tr("Vector", "room_intro_cell_add_participants_action")
} }
/// This is the begining of your direct message with /// This is the beginning of your direct message with
internal static var roomIntroCellInformationDmSentence1Part1: String { internal static var roomIntroCellInformationDmSentence1Part1: String {
return VectorL10n.tr("Vector", "room_intro_cell_information_dm_sentence1_part1") return VectorL10n.tr("Vector", "room_intro_cell_information_dm_sentence1_part1")
} }
@ -2834,7 +2842,7 @@ internal enum VectorL10n {
internal static var roomIntroCellInformationMultipleDmSentence2: String { internal static var roomIntroCellInformationMultipleDmSentence2: String {
return VectorL10n.tr("Vector", "room_intro_cell_information_multiple_dm_sentence2") return VectorL10n.tr("Vector", "room_intro_cell_information_multiple_dm_sentence2")
} }
/// This is the begining of /// This is the beginning of
internal static var roomIntroCellInformationRoomSentence1Part1: String { internal static var roomIntroCellInformationRoomSentence1Part1: String {
return VectorL10n.tr("Vector", "room_intro_cell_information_room_sentence1_part1") return VectorL10n.tr("Vector", "room_intro_cell_information_room_sentence1_part1")
} }
@ -3326,13 +3334,21 @@ internal enum VectorL10n {
internal static func roomTwoUsersAreTyping(_ p1: String, _ p2: String) -> String { internal static func roomTwoUsersAreTyping(_ p1: String, _ p2: String) -> String {
return VectorL10n.tr("Vector", "room_two_users_are_typing", p1, p2) return VectorL10n.tr("Vector", "room_two_users_are_typing", p1, p2)
} }
/// Messages not sent. %@ or %@ now? /// Are you sure you want to delete all unsent messages in this room?
internal static func roomUnsentMessagesNotification(_ p1: String, _ p2: String) -> String { internal static var roomUnsentMessagesCancelMessage: String {
return VectorL10n.tr("Vector", "room_unsent_messages_notification", p1, p2) return VectorL10n.tr("Vector", "room_unsent_messages_cancel_message")
} }
/// Message not sent due to unknown sessions being present. %@ or %@ now? /// Delete unsent messages
internal static func roomUnsentMessagesUnknownDevicesNotification(_ p1: String, _ p2: String) -> String { internal static var roomUnsentMessagesCancelTitle: String {
return VectorL10n.tr("Vector", "room_unsent_messages_unknown_devices_notification", p1, p2) return VectorL10n.tr("Vector", "room_unsent_messages_cancel_title")
}
/// Messages failed to send.
internal static var roomUnsentMessagesNotification: String {
return VectorL10n.tr("Vector", "room_unsent_messages_notification")
}
/// Message failed to send due to unknown sessions being present.
internal static var roomUnsentMessagesUnknownDevicesNotification: String {
return VectorL10n.tr("Vector", "room_unsent_messages_unknown_devices_notification")
} }
/// End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption. /// End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption.
internal static var roomWarningAboutEncryption: String { internal static var roomWarningAboutEncryption: String {

View file

@ -63,6 +63,8 @@ import UIKit
var selectedBackgroundColor: UIColor { get } var selectedBackgroundColor: UIColor { get }
var messageTickColor: UIColor { get }
// MARK: - Call Screen Specific Colors // MARK: - Call Screen Specific Colors
var callScreenButtonTintColor: UIColor { get } var callScreenButtonTintColor: UIColor { get }

View file

@ -84,6 +84,8 @@ class DarkTheme: NSObject, Theme {
var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E)
var secondaryCircleButtonBackgroundColor: UIColor = UIColor(rgb: 0xE3E8F0) var secondaryCircleButtonBackgroundColor: UIColor = UIColor(rgb: 0xE3E8F0)
var messageTickColor: UIColor = .white
func applyStyle(onTabBar tabBar: UITabBar) { func applyStyle(onTabBar tabBar: UITabBar) {
tabBar.unselectedItemTintColor = self.tabBarUnselectedItemTintColor tabBar.unselectedItemTintColor = self.tabBarUnselectedItemTintColor
tabBar.tintColor = self.tintColor tabBar.tintColor = self.tintColor

View file

@ -52,6 +52,8 @@ class DefaultTheme: NSObject, Theme {
var warningColor: UIColor = UIColor(rgb: 0xFF4B55) var warningColor: UIColor = UIColor(rgb: 0xFF4B55)
var messageTickColor: UIColor = UIColor(rgb: 0xC1C6CD)
var avatarColors: [UIColor] = [ var avatarColors: [UIColor] = [
UIColor(rgb: 0x03B381), UIColor(rgb: 0x03B381),
UIColor(rgb: 0x368BD6), UIColor(rgb: 0x368BD6),

View file

@ -0,0 +1,112 @@
//
// 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 BadgeLabel: UILabel {
// MARK: - Public properties
@IBInspectable var badgeColor: UIColor = .red {
didSet {
setNeedsDisplay()
}
}
@IBInspectable var borderWidth: CGFloat = 0 {
didSet {
invalidateIntrinsicContentSize()
}
}
@IBInspectable var borderColor: UIColor = .white {
didSet {
invalidateIntrinsicContentSize()
}
}
@IBInspectable var padding: CGSize = CGSize(width: 10, height: 2) {
didSet {
invalidateIntrinsicContentSize()
}
}
// MARK: - Lifecycle
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.size.height / 2
}
override var intrinsicContentSize: CGSize {
var intrinsicSize = super.intrinsicContentSize
intrinsicSize.height = max(intrinsicSize.height + padding.height, intrinsicSize.height) + borderWidth / 2
intrinsicSize.width = max(intrinsicSize.width + padding.width, intrinsicSize.height)
return intrinsicSize
}
override func draw(_ rect: CGRect) {
if let context = UIGraphicsGetCurrentContext() {
context.saveGState()
let rect = self.bounds.insetBy(dx: borderWidth / 2, dy: borderWidth / 2)
let cornerRadius = rect.height / 2
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
context.addPath(path.cgPath)
context.setLineWidth(borderWidth)
context.setStrokeColor(borderColor.cgColor)
context.setFillColor(badgeColor.cgColor)
if borderWidth > 0 {
context.drawPath(using: .fillStroke)
} else {
context.drawPath(using: .fill)
}
context.restoreGState()
}
super.draw(rect)
}
// MARK: - Interface Builder
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setupView()
}
// MARK: - Private methods
private func setupView() {
self.textAlignment = .center
self.textColor = .white
}
}

View file

@ -179,6 +179,11 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
*/ */
@property (nonatomic, readonly) NSUInteger missedHighlightDirectDiscussionsCount; @property (nonatomic, readonly) NSUInteger missedHighlightDirectDiscussionsCount;
/**
The current number of the direct chats with unsent messages.
*/
@property (nonatomic, readonly) NSUInteger unsentMessagesDirectDiscussionsCount;
/** /**
The current number of the group chats with missed notifications, including the invites. The current number of the group chats with missed notifications, including the invites.
*/ */
@ -189,4 +194,9 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
*/ */
@property (nonatomic, readonly) NSUInteger missedHighlightGroupDiscussionsCount; @property (nonatomic, readonly) NSUInteger missedHighlightGroupDiscussionsCount;
/**
The current number of the group chats with unsent messages.
*/
@property (nonatomic, readonly) NSUInteger unsentMessagesGroupDiscussionsCount;
@end @end

View file

@ -1146,6 +1146,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
_missedFavouriteDiscussionsCount = _missedHighlightFavouriteDiscussionsCount = 0; _missedFavouriteDiscussionsCount = _missedHighlightFavouriteDiscussionsCount = 0;
_missedDirectDiscussionsCount = _missedHighlightDirectDiscussionsCount = 0; _missedDirectDiscussionsCount = _missedHighlightDirectDiscussionsCount = 0;
_missedGroupDiscussionsCount = _missedHighlightGroupDiscussionsCount = 0; _missedGroupDiscussionsCount = _missedHighlightGroupDiscussionsCount = 0;
_unsentMessagesDirectDiscussionsCount = 0;
_unsentMessagesGroupDiscussionsCount = 0;
secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1; secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1;
@ -1282,6 +1284,18 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
} }
} }
if (room.sentStatus != RoomSentStatusOk)
{
if (room.isDirect)
{
_unsentMessagesDirectDiscussionsCount ++;
}
else
{
_unsentMessagesGroupDiscussionsCount ++;
}
}
} }
if (_recentsDataSourceMode == RecentsDataSourceModeHome) if (_recentsDataSourceMode == RecentsDataSourceModeHome)
@ -1295,6 +1309,18 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others. // Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others.
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) { comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedAscending;
}
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedDescending;
}
if (recentCellData1.highlightCount) if (recentCellData1.highlightCount)
{ {
if (recentCellData2.highlightCount) if (recentCellData2.highlightCount)
@ -1352,6 +1378,18 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Sort each rooms collection by considering first the rooms with some unread messages then the others. // Sort each rooms collection by considering first the rooms with some unread messages then the others.
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) { comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedAscending;
}
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedDescending;
}
if (recentCellData1.hasUnread) if (recentCellData1.hasUnread)
{ {
if (recentCellData2.hasUnread) if (recentCellData2.hasUnread)
@ -1391,6 +1429,25 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}]; }];
} }
else if (conversationCellDataArray.count > 0 && (_recentsDataSourceMode == RecentsDataSourceModeRooms || _recentsDataSourceMode == RecentsDataSourceModePeople))
{
[conversationCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedAscending;
}
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
{
return NSOrderedDescending;
}
return NSOrderedAscending;
}];
}
} }
NSLog(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000); NSLog(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);

View file

@ -30,4 +30,7 @@
@property (weak, nonatomic) IBOutlet UIView *missedNotifAndUnreadBadgeBgView; @property (weak, nonatomic) IBOutlet UIView *missedNotifAndUnreadBadgeBgView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedNotifAndUnreadBadgeBgViewWidthConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedNotifAndUnreadBadgeBgViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lastEventDecriptionLabelTrailingConstraint;
@property (weak, nonatomic) IBOutlet UIImageView *unsentImageView;
@end @end

View file

@ -20,6 +20,7 @@
#import "AvatarGenerator.h" #import "AvatarGenerator.h"
#import "MXEvent.h" #import "MXEvent.h"
#import "MXRoom+Riot.h"
#import "ThemeService.h" #import "ThemeService.h"
#import "Riot-Swift.h" #import "Riot-Swift.h"
@ -102,6 +103,9 @@ static const CGFloat kDirectRoomBorderWidth = 3.0;
self.lastEventDescription.text = roomCellData.lastEventTextMessage; self.lastEventDescription.text = roomCellData.lastEventTextMessage;
} }
self.unsentImageView.hidden = roomCellData.roomSummary.room.sentStatus == RoomSentStatusOk;
self.lastEventDecriptionLabelTrailingConstraint.constant = self.unsentImageView.hidden ? 10 : 30;
// Notify unreads and bing // Notify unreads and bing
if (roomCellData.hasUnread) if (roomCellData.hasUnread)
{ {

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -15,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/> <rect key="frame" x="0.0" y="0.0" width="600" height="74"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="L2L-l5-wPx" id="aXz-IR-jj5"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="L2L-l5-wPx" id="aXz-IR-jj5">
<rect key="frame" x="0.0" y="0.0" width="600" height="73.5"/> <rect key="frame" x="0.0" y="0.0" width="600" height="74"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e7r-zL-9bw" userLabel="Bing indicator"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e7r-zL-9bw" userLabel="Bing indicator">
@ -55,7 +53,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LastEventDescription" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQt-mN-T6b"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LastEventDescription" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQt-mN-T6b">
<rect key="frame" x="69" y="39" width="521" height="20"/> <rect key="frame" x="69" y="39" width="501" height="20"/>
<accessibility key="accessibilityConfiguration" identifier="LastEventDescription"/> <accessibility key="accessibilityConfiguration" identifier="LastEventDescription"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="20" id="e6p-DU-3ny"/> <constraint firstAttribute="height" constant="20" id="e6p-DU-3ny"/>
@ -101,8 +99,16 @@
<constraint firstAttribute="width" constant="16" id="i9u-Bs-pBy"/> <constraint firstAttribute="width" constant="16" id="i9u-Bs-pBy"/>
</constraints> </constraints>
</imageView> </imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="error_icon" translatesAutoresizingMaskIntoConstraints="NO" id="F6K-PV-15f">
<rect key="frame" x="574" y="41" width="16" height="16"/>
<constraints>
<constraint firstAttribute="width" constant="16" id="dkD-bq-4ND"/>
<constraint firstAttribute="height" constant="16" id="lNd-8B-gRr"/>
</constraints>
</imageView>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="F6K-PV-15f" firstAttribute="trailing" secondItem="360-Go-RcG" secondAttribute="trailing" id="3qB-Na-Eqs"/>
<constraint firstItem="8CY-Ku-0qh" firstAttribute="centerX" secondItem="RX5-eD-c3c" secondAttribute="centerX" id="FVh-1h-VkB"/> <constraint firstItem="8CY-Ku-0qh" firstAttribute="centerX" secondItem="RX5-eD-c3c" secondAttribute="centerX" id="FVh-1h-VkB"/>
<constraint firstItem="360-Go-RcG" firstAttribute="leading" secondItem="OeZ-wN-eil" secondAttribute="trailing" constant="8" id="KuE-8m-e9A"/> <constraint firstItem="360-Go-RcG" firstAttribute="leading" secondItem="OeZ-wN-eil" secondAttribute="trailing" constant="8" id="KuE-8m-e9A"/>
<constraint firstItem="e7r-zL-9bw" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" id="PUW-if-ewh"/> <constraint firstItem="e7r-zL-9bw" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" id="PUW-if-ewh"/>
@ -114,10 +120,11 @@
<constraint firstAttribute="trailing" secondItem="360-Go-RcG" secondAttribute="trailing" constant="10" id="YqC-WC-Wqe"/> <constraint firstAttribute="trailing" secondItem="360-Go-RcG" secondAttribute="trailing" constant="10" id="YqC-WC-Wqe"/>
<constraint firstItem="NAZ-zd-MHS" firstAttribute="centerY" secondItem="dQt-mN-T6b" secondAttribute="centerY" constant="2" id="c6L-cn-sJL"/> <constraint firstItem="NAZ-zd-MHS" firstAttribute="centerY" secondItem="dQt-mN-T6b" secondAttribute="centerY" constant="2" id="c6L-cn-sJL"/>
<constraint firstItem="OeZ-wN-eil" firstAttribute="centerY" secondItem="360-Go-RcG" secondAttribute="centerY" id="fYc-th-Nay"/> <constraint firstItem="OeZ-wN-eil" firstAttribute="centerY" secondItem="360-Go-RcG" secondAttribute="centerY" id="fYc-th-Nay"/>
<constraint firstItem="F6K-PV-15f" firstAttribute="centerY" secondItem="dQt-mN-T6b" secondAttribute="centerY" id="iMe-h4-M1a"/>
<constraint firstItem="dQt-mN-T6b" firstAttribute="top" secondItem="Lg1-xQ-AGn" secondAttribute="bottom" constant="4" id="iaT-57-GOs"/> <constraint firstItem="dQt-mN-T6b" firstAttribute="top" secondItem="Lg1-xQ-AGn" secondAttribute="bottom" constant="4" id="iaT-57-GOs"/>
<constraint firstItem="RX5-eD-c3c" firstAttribute="top" secondItem="aXz-IR-jj5" secondAttribute="top" constant="15" id="mga-fG-I0L"/> <constraint firstItem="RX5-eD-c3c" firstAttribute="top" secondItem="aXz-IR-jj5" secondAttribute="top" constant="15" id="mga-fG-I0L"/>
<constraint firstItem="NAZ-zd-MHS" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" constant="44" id="ofi-HP-uke"/> <constraint firstItem="NAZ-zd-MHS" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" constant="44" id="ofi-HP-uke"/>
<constraint firstAttribute="trailing" secondItem="dQt-mN-T6b" secondAttribute="trailing" constant="10" id="t2m-pb-5zd"/> <constraint firstAttribute="trailing" secondItem="dQt-mN-T6b" secondAttribute="trailing" constant="30" id="t2m-pb-5zd"/>
<constraint firstItem="Lg1-xQ-AGn" firstAttribute="top" secondItem="aXz-IR-jj5" secondAttribute="top" constant="14" id="tY3-6V-A3B"/> <constraint firstItem="Lg1-xQ-AGn" firstAttribute="top" secondItem="aXz-IR-jj5" secondAttribute="top" constant="14" id="tY3-6V-A3B"/>
<constraint firstItem="RX5-eD-c3c" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" constant="13" id="tgy-cX-Wxm"/> <constraint firstItem="RX5-eD-c3c" firstAttribute="leading" secondItem="aXz-IR-jj5" secondAttribute="leading" constant="13" id="tgy-cX-Wxm"/>
<constraint firstItem="8CY-Ku-0qh" firstAttribute="centerY" secondItem="RX5-eD-c3c" secondAttribute="centerY" id="ukJ-yz-Kit"/> <constraint firstItem="8CY-Ku-0qh" firstAttribute="centerY" secondItem="RX5-eD-c3c" secondAttribute="centerY" id="ukJ-yz-Kit"/>
@ -129,6 +136,7 @@
<outlet property="directRoomBorderView" destination="8CY-Ku-0qh" id="vKk-ZO-TQq"/> <outlet property="directRoomBorderView" destination="8CY-Ku-0qh" id="vKk-ZO-TQq"/>
<outlet property="encryptedRoomIcon" destination="NAZ-zd-MHS" id="ZsH-Zr-Q4K"/> <outlet property="encryptedRoomIcon" destination="NAZ-zd-MHS" id="ZsH-Zr-Q4K"/>
<outlet property="lastEventDate" destination="360-Go-RcG" id="Y0L-Dj-ZVn"/> <outlet property="lastEventDate" destination="360-Go-RcG" id="Y0L-Dj-ZVn"/>
<outlet property="lastEventDecriptionLabelTrailingConstraint" destination="t2m-pb-5zd" id="cxp-7Z-bEg"/>
<outlet property="lastEventDescription" destination="dQt-mN-T6b" id="MSz-h1-cAL"/> <outlet property="lastEventDescription" destination="dQt-mN-T6b" id="MSz-h1-cAL"/>
<outlet property="missedNotifAndUnreadBadgeBgView" destination="OeZ-wN-eil" id="tVo-8Z-hc2"/> <outlet property="missedNotifAndUnreadBadgeBgView" destination="OeZ-wN-eil" id="tVo-8Z-hc2"/>
<outlet property="missedNotifAndUnreadBadgeBgViewWidthConstraint" destination="86T-0d-rAI" id="KLF-Du-rHT"/> <outlet property="missedNotifAndUnreadBadgeBgViewWidthConstraint" destination="86T-0d-rAI" id="KLF-Du-rHT"/>
@ -136,10 +144,13 @@
<outlet property="missedNotifAndUnreadIndicator" destination="e7r-zL-9bw" id="jWE-0y-BMv"/> <outlet property="missedNotifAndUnreadIndicator" destination="e7r-zL-9bw" id="jWE-0y-BMv"/>
<outlet property="roomAvatar" destination="RX5-eD-c3c" id="dIC-8p-inL"/> <outlet property="roomAvatar" destination="RX5-eD-c3c" id="dIC-8p-inL"/>
<outlet property="roomTitle" destination="Lg1-xQ-AGn" id="q7Q-TM-5C8"/> <outlet property="roomTitle" destination="Lg1-xQ-AGn" id="q7Q-TM-5C8"/>
<outlet property="unsentImageView" destination="F6K-PV-15f" id="EnH-mb-j6s"/>
</connections> </connections>
<point key="canvasLocation" x="-131.19999999999999" y="81.859070464767626"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
<resources> <resources>
<image name="e2e_verified" width="10" height="12"/> <image name="e2e_verified" width="10" height="12"/>
<image name="error_icon" width="16" height="16"/>
</resources> </resources>
</document> </document>

View file

@ -16,6 +16,8 @@
#import <MatrixKit/MatrixKit.h> #import <MatrixKit/MatrixKit.h>
@class BadgeLabel;
/** /**
'RoomCollectionViewCell' class is used to display a room in a collection view. 'RoomCollectionViewCell' class is used to display a room in a collection view.
*/ */
@ -38,9 +40,7 @@
@property (weak, nonatomic) IBOutlet MXKImageView *roomAvatar; @property (weak, nonatomic) IBOutlet MXKImageView *roomAvatar;
@property (weak, nonatomic) IBOutlet UIImageView *encryptedRoomIcon; @property (weak, nonatomic) IBOutlet UIImageView *encryptedRoomIcon;
@property (weak, nonatomic) IBOutlet UILabel *missedNotifAndUnreadBadgeLabel; @property (weak, nonatomic) IBOutlet BadgeLabel *badgeLabel;
@property (weak, nonatomic) IBOutlet UIView *missedNotifAndUnreadBadgeBgView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedNotifAndUnreadBadgeBgViewWidthConstraint;
@property (nonatomic, readonly) NSString *roomId; @property (nonatomic, readonly) NSString *roomId;

View file

@ -22,6 +22,7 @@
#import "Riot-Swift.h" #import "Riot-Swift.h"
#import "MXRoomSummary+Riot.h" #import "MXRoomSummary+Riot.h"
#import "MXRoom+Riot.h"
#import "MXTools.h" #import "MXTools.h"
@ -42,10 +43,6 @@ static const CGFloat kDirectRoomBorderWidth = 3.0;
[_roomAvatar.layer setCornerRadius:_roomAvatar.frame.size.width / 2]; [_roomAvatar.layer setCornerRadius:_roomAvatar.frame.size.width / 2];
_roomAvatar.clipsToBounds = YES; _roomAvatar.clipsToBounds = YES;
// Initialize unread count badge
[_missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10];
_missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = 0;
// Disable the user interaction on the room avatar. // Disable the user interaction on the room avatar.
self.roomAvatar.userInteractionEnabled = NO; self.roomAvatar.userInteractionEnabled = NO;
@ -69,7 +66,6 @@ static const CGFloat kDirectRoomBorderWidth = 3.0;
self.roomTitle.textColor = ThemeService.shared.theme.textPrimaryColor; self.roomTitle.textColor = ThemeService.shared.theme.textPrimaryColor;
self.roomTitle1.textColor = ThemeService.shared.theme.textPrimaryColor; self.roomTitle1.textColor = ThemeService.shared.theme.textPrimaryColor;
self.roomTitle2.textColor = ThemeService.shared.theme.textPrimaryColor; self.roomTitle2.textColor = ThemeService.shared.theme.textPrimaryColor;
self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor;
// Prepare direct room border // Prepare direct room border
CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.shared.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.shared.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha);
@ -94,8 +90,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0;
- (void)render:(MXKCellData *)cellData - (void)render:(MXKCellData *)cellData
{ {
// Hide by default missed notifications and unread widgets // Hide by default missed notifications and unread widgets
self.missedNotifAndUnreadBadgeBgView.hidden = YES; self.badgeLabel.hidden = YES;
self.missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = 0;
roomCellData = (id<MXKRecentCellDataStoring>)cellData; roomCellData = (id<MXKRecentCellDataStoring>)cellData;
if (roomCellData) if (roomCellData)
@ -121,31 +116,24 @@ static const CGFloat kDirectRoomBorderWidth = 3.0;
} }
// Notify unreads and bing // Notify unreads and bing
if (roomCellData.hasUnread) if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite
|| roomCellData.roomSummary.room.sentStatus != RoomSentStatusOk)
{ {
if (0 < roomCellData.notificationCount) self.badgeLabel.hidden = NO;
{ self.badgeLabel.badgeColor = ThemeService.shared.theme.noticeColor;
self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.badgeLabel.text = @"!";
self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor;
self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue;
[self.missedNotifAndUnreadBadgeLabel sizeToFit];
self.missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = self.missedNotifAndUnreadBadgeLabel.frame.size.width + 18;
}
// Use bold font for the room title // Use bold font for the room title
self.roomTitle.font = self.roomTitle1.font = self.roomTitle2.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold]; self.roomTitle.font = self.roomTitle1.font = self.roomTitle2.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold];
} }
else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) else if (roomCellData.hasUnread)
{ {
self.missedNotifAndUnreadBadgeBgView.hidden = NO; if (0 < roomCellData.notificationCount)
self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.noticeColor; {
self.badgeLabel.hidden = NO;
self.missedNotifAndUnreadBadgeLabel.text = @"!"; self.badgeLabel.badgeColor = roomCellData.highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor;
[self.missedNotifAndUnreadBadgeLabel sizeToFit]; self.badgeLabel.text = roomCellData.notificationCountStringValue;
}
self.missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = self.missedNotifAndUnreadBadgeLabel.frame.size.width + 18;
// Use bold font for the room title // Use bold font for the room title
self.roomTitle.font = self.roomTitle1.font = self.roomTitle2.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold]; self.roomTitle.font = self.roomTitle1.font = self.roomTitle2.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold];

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -34,25 +32,12 @@
<constraint firstAttribute="width" secondItem="xws-BR-H47" secondAttribute="height" multiplier="1:1" id="bEP-hL-5lg"/> <constraint firstAttribute="width" secondItem="xws-BR-H47" secondAttribute="height" multiplier="1:1" id="bEP-hL-5lg"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Q6g-b0-3sZ"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="!" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="scs-Ov-Tjv" customClass="BadgeLabel" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="80" y="5" width="0.0" height="20"/> <rect key="frame" x="56" y="8" width="16.5" height="16.5"/>
<subviews> <fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZUZ-tv-dVV"> <nil key="textColor"/>
<rect key="frame" x="-4.5" y="1.5" width="9" height="17"/> <nil key="highlightedColor"/>
<accessibility key="accessibilityConfiguration" identifier="MissedNotifAndUnreadBadge"/> </label>
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.0" green="0.72547743060000003" blue="0.0041503219759999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="D9K-B0-riB"/>
<constraint firstItem="ZUZ-tv-dVV" firstAttribute="centerY" secondItem="Q6g-b0-3sZ" secondAttribute="centerY" id="XGQ-9J-nIX"/>
<constraint firstAttribute="width" id="jeX-st-swl"/>
<constraint firstItem="ZUZ-tv-dVV" firstAttribute="centerX" secondItem="Q6g-b0-3sZ" secondAttribute="centerX" id="km0-Wj-nJ0"/>
</constraints>
</view>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="encryption_normal" translatesAutoresizingMaskIntoConstraints="NO" id="5Yd-df-HbB"> <imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="encryption_normal" translatesAutoresizingMaskIntoConstraints="NO" id="5Yd-df-HbB">
<rect key="frame" x="51" y="52" width="21" height="20"/> <rect key="frame" x="51" y="52" width="21" height="20"/>
<constraints> <constraints>
@ -83,7 +68,7 @@
</label> </label>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jta-3V-4wL"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jta-3V-4wL">
<rect key="frame" x="30" y="105" width="20" height="10"/> <rect key="frame" x="30" y="105" width="20" height="10"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/> <color key="backgroundColor" systemColor="groupTableViewBackgroundColor"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="10" id="eU4-Qq-wum"/> <constraint firstAttribute="height" constant="10" id="eU4-Qq-wum"/>
<constraint firstAttribute="width" constant="20" id="sH5-UK-Q7A"/> <constraint firstAttribute="width" constant="20" id="sH5-UK-Q7A"/>
@ -96,9 +81,9 @@
<constraint firstItem="oxX-IL-dG4" firstAttribute="top" secondItem="T1Q-RS-8o6" secondAttribute="bottom" constant="4" id="2DB-H2-E2v"/> <constraint firstItem="oxX-IL-dG4" firstAttribute="top" secondItem="T1Q-RS-8o6" secondAttribute="bottom" constant="4" id="2DB-H2-E2v"/>
<constraint firstAttribute="bottom" secondItem="jta-3V-4wL" secondAttribute="bottom" id="3rt-Ig-1rG"/> <constraint firstAttribute="bottom" secondItem="jta-3V-4wL" secondAttribute="bottom" id="3rt-Ig-1rG"/>
<constraint firstItem="oxX-IL-dG4" firstAttribute="leading" secondItem="eCk-zY-LXq" secondAttribute="leading" constant="4" id="6gu-JD-Gb1"/> <constraint firstItem="oxX-IL-dG4" firstAttribute="leading" secondItem="eCk-zY-LXq" secondAttribute="leading" constant="4" id="6gu-JD-Gb1"/>
<constraint firstItem="scs-Ov-Tjv" firstAttribute="centerY" secondItem="xws-BR-H47" secondAttribute="top" constant="6" id="CRF-wK-Lcp"/>
<constraint firstItem="X8H-1U-wc3" firstAttribute="centerX" secondItem="oxX-IL-dG4" secondAttribute="centerX" id="K9T-eO-WNb"/> <constraint firstItem="X8H-1U-wc3" firstAttribute="centerX" secondItem="oxX-IL-dG4" secondAttribute="centerX" id="K9T-eO-WNb"/>
<constraint firstItem="xws-BR-H47" firstAttribute="centerX" secondItem="T1Q-RS-8o6" secondAttribute="centerX" id="Lo3-Ov-Bw8"/> <constraint firstItem="xws-BR-H47" firstAttribute="centerX" secondItem="T1Q-RS-8o6" secondAttribute="centerX" id="Lo3-Ov-Bw8"/>
<constraint firstAttribute="trailing" secondItem="Q6g-b0-3sZ" secondAttribute="trailing" id="Mf1-H6-oH4"/>
<constraint firstItem="Jkz-Zp-aaG" firstAttribute="centerX" secondItem="oxX-IL-dG4" secondAttribute="centerX" id="OQy-tF-e3Z"/> <constraint firstItem="Jkz-Zp-aaG" firstAttribute="centerX" secondItem="oxX-IL-dG4" secondAttribute="centerX" id="OQy-tF-e3Z"/>
<constraint firstItem="jta-3V-4wL" firstAttribute="centerX" secondItem="eCk-zY-LXq" secondAttribute="centerX" id="R87-mq-SlO"/> <constraint firstItem="jta-3V-4wL" firstAttribute="centerX" secondItem="eCk-zY-LXq" secondAttribute="centerX" id="R87-mq-SlO"/>
<constraint firstItem="5Yd-df-HbB" firstAttribute="bottom" secondItem="T1Q-RS-8o6" secondAttribute="bottom" constant="2" id="RQU-MS-Qfr"/> <constraint firstItem="5Yd-df-HbB" firstAttribute="bottom" secondItem="T1Q-RS-8o6" secondAttribute="bottom" constant="2" id="RQU-MS-Qfr"/>
@ -107,29 +92,37 @@
<constraint firstItem="T1Q-RS-8o6" firstAttribute="top" secondItem="eCk-zY-LXq" secondAttribute="top" constant="10" id="cc7-bg-15Z"/> <constraint firstItem="T1Q-RS-8o6" firstAttribute="top" secondItem="eCk-zY-LXq" secondAttribute="top" constant="10" id="cc7-bg-15Z"/>
<constraint firstItem="Jkz-Zp-aaG" firstAttribute="leading" secondItem="eCk-zY-LXq" secondAttribute="leading" constant="7" id="fPh-Lb-Bv9"/> <constraint firstItem="Jkz-Zp-aaG" firstAttribute="leading" secondItem="eCk-zY-LXq" secondAttribute="leading" constant="7" id="fPh-Lb-Bv9"/>
<constraint firstItem="xws-BR-H47" firstAttribute="centerY" secondItem="T1Q-RS-8o6" secondAttribute="centerY" id="faX-hg-WfP"/> <constraint firstItem="xws-BR-H47" firstAttribute="centerY" secondItem="T1Q-RS-8o6" secondAttribute="centerY" id="faX-hg-WfP"/>
<constraint firstItem="scs-Ov-Tjv" firstAttribute="centerX" secondItem="xws-BR-H47" secondAttribute="trailing" priority="750" constant="-6" id="fgA-Sf-Y4E"/>
<constraint firstAttribute="trailing" secondItem="oxX-IL-dG4" secondAttribute="trailing" constant="4" id="hDl-X9-M4n"/> <constraint firstAttribute="trailing" secondItem="oxX-IL-dG4" secondAttribute="trailing" constant="4" id="hDl-X9-M4n"/>
<constraint firstItem="T1Q-RS-8o6" firstAttribute="centerX" secondItem="eCk-zY-LXq" secondAttribute="centerX" id="hmB-fl-oN2"/> <constraint firstItem="T1Q-RS-8o6" firstAttribute="centerX" secondItem="eCk-zY-LXq" secondAttribute="centerX" id="hmB-fl-oN2"/>
<constraint firstItem="Q6g-b0-3sZ" firstAttribute="top" secondItem="eCk-zY-LXq" secondAttribute="top" constant="5" id="jST-Ic-lsn"/>
<constraint firstAttribute="trailing" secondItem="X8H-1U-wc3" secondAttribute="trailing" constant="7" id="o5i-7H-n0G"/> <constraint firstAttribute="trailing" secondItem="X8H-1U-wc3" secondAttribute="trailing" constant="7" id="o5i-7H-n0G"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="scs-Ov-Tjv" secondAttribute="trailing" id="qGg-o0-u1H"/>
<constraint firstAttribute="trailing" secondItem="Jkz-Zp-aaG" secondAttribute="trailing" constant="7" id="uQe-FG-3lb"/> <constraint firstAttribute="trailing" secondItem="Jkz-Zp-aaG" secondAttribute="trailing" constant="7" id="uQe-FG-3lb"/>
<constraint firstItem="X8H-1U-wc3" firstAttribute="top" secondItem="oxX-IL-dG4" secondAttribute="top" id="uTm-3W-QoM"/> <constraint firstItem="X8H-1U-wc3" firstAttribute="top" secondItem="oxX-IL-dG4" secondAttribute="top" id="uTm-3W-QoM"/>
<constraint firstItem="5Yd-df-HbB" firstAttribute="trailing" secondItem="T1Q-RS-8o6" secondAttribute="trailing" constant="2" id="wqP-uJ-EaY"/> <constraint firstItem="5Yd-df-HbB" firstAttribute="trailing" secondItem="T1Q-RS-8o6" secondAttribute="trailing" constant="2" id="wqP-uJ-EaY"/>
</constraints> </constraints>
<connections> <connections>
<outlet property="badgeLabel" destination="scs-Ov-Tjv" id="KPV-Qb-cnT"/>
<outlet property="directRoomBorderView" destination="xws-BR-H47" id="34A-hu-DXq"/> <outlet property="directRoomBorderView" destination="xws-BR-H47" id="34A-hu-DXq"/>
<outlet property="editionArrowView" destination="jta-3V-4wL" id="XLj-Cx-3bn"/> <outlet property="editionArrowView" destination="jta-3V-4wL" id="XLj-Cx-3bn"/>
<outlet property="encryptedRoomIcon" destination="5Yd-df-HbB" id="5pc-Vi-wMZ"/> <outlet property="encryptedRoomIcon" destination="5Yd-df-HbB" id="5pc-Vi-wMZ"/>
<outlet property="missedNotifAndUnreadBadgeBgView" destination="Q6g-b0-3sZ" id="jNG-dA-dfP"/>
<outlet property="missedNotifAndUnreadBadgeBgViewWidthConstraint" destination="jeX-st-swl" id="4sa-wn-bgT"/>
<outlet property="missedNotifAndUnreadBadgeLabel" destination="ZUZ-tv-dVV" id="6IV-rz-s4I"/>
<outlet property="roomAvatar" destination="T1Q-RS-8o6" id="4sR-Wm-jwz"/> <outlet property="roomAvatar" destination="T1Q-RS-8o6" id="4sR-Wm-jwz"/>
<outlet property="roomTitle" destination="oxX-IL-dG4" id="vff-Fw-AOf"/> <outlet property="roomTitle" destination="oxX-IL-dG4" id="vff-Fw-AOf"/>
<outlet property="roomTitle1" destination="X8H-1U-wc3" id="nnS-Hp-1qV"/> <outlet property="roomTitle1" destination="X8H-1U-wc3" id="nnS-Hp-1qV"/>
<outlet property="roomTitle2" destination="Jkz-Zp-aaG" id="xO1-Av-NID"/> <outlet property="roomTitle2" destination="Jkz-Zp-aaG" id="xO1-Av-NID"/>
</connections> </connections>
<point key="canvasLocation" x="22" y="81"/>
</collectionViewCell> </collectionViewCell>
</objects> </objects>
<designables>
<designable name="scs-Ov-Tjv">
<size key="intrinsicContentSize" width="16.5" height="16.5"/>
</designable>
</designables>
<resources> <resources>
<image name="encryption_normal" width="16" height="16"/> <image name="encryption_normal" width="16" height="16"/>
<systemColor name="groupTableViewBackgroundColor">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources> </resources>
</document> </document>

View file

@ -87,6 +87,11 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
*/ */
@property(nonatomic) BOOL isKeyVerificationOperationPending; @property(nonatomic) BOOL isKeyVerificationOperationPending;
/**
Index of the component which needs a sent tick displayed. -1 if none.
*/
@property(nonatomic) NSInteger componentIndexOfSentMessageTick;
/** /**
Indicate to update additional content height. Indicate to update additional content height.
*/ */

View file

@ -53,6 +53,7 @@ static NSAttributedString *timestampVerticalWhitespace = nil;
if (self) if (self)
{ {
_eventsToShowAllReactions = [NSMutableSet set]; _eventsToShowAllReactions = [NSMutableSet set];
_componentIndexOfSentMessageTick = -1;
} }
return self; return self;
} }

View file

@ -21,6 +21,8 @@ import Foundation
case reply case reply
case edit case edit
case more case more
case resend
case delete
// MARK: - Properties // MARK: - Properties
@ -36,6 +38,10 @@ import Foundation
title = VectorL10n.roomEventActionEdit title = VectorL10n.roomEventActionEdit
case .more: case .more:
title = VectorL10n.roomEventActionMore title = VectorL10n.roomEventActionMore
case .resend:
title = VectorL10n.retry
case .delete:
title = VectorL10n.roomEventActionDelete
} }
return title return title
@ -53,6 +59,10 @@ import Foundation
image = Asset.Images.roomContextMenuEdit.image image = Asset.Images.roomContextMenuEdit.image
case .more: case .more:
image = Asset.Images.roomContextMenuMore.image image = Asset.Images.roomContextMenuMore.image
case .resend:
image = Asset.Images.roomContextMenuRetry.image
case .delete:
image = Asset.Images.roomContextMenuDelete.image
default: default:
image = nil image = nil
} }

View file

@ -99,4 +99,7 @@
- (void)roomDataSource:(RoomDataSource*)roomDataSource didUpdateEncryptionTrustLevel:(RoomEncryptionTrustLevel)roomEncryptionTrustLevel; - (void)roomDataSource:(RoomDataSource*)roomDataSource didUpdateEncryptionTrustLevel:(RoomEncryptionTrustLevel)roomEncryptionTrustLevel;
- (void)roomDataSource:(RoomDataSource*)roomDataSource didCancel:(MXEvent *)event;
@end @end

View file

@ -28,7 +28,6 @@
#import "MXRoom+Riot.h" #import "MXRoom+Riot.h"
@interface RoomDataSource() <BubbleReactionsViewModelDelegate> @interface RoomDataSource() <BubbleReactionsViewModelDelegate>
{ {
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
@ -48,6 +47,8 @@
@property(nonatomic, readwrite) RoomEncryptionTrustLevel encryptionTrustLevel; @property(nonatomic, readwrite) RoomEncryptionTrustLevel encryptionTrustLevel;
@property (nonatomic, strong) NSMutableSet *failedEventIds;
@property (nonatomic) RoomBubbleCellData *roomCreationCellData; @property (nonatomic) RoomBubbleCellData *roomCreationCellData;
@property (nonatomic) BOOL showRoomCreationCell; @property (nonatomic) BOOL showRoomCreationCell;
@ -240,6 +241,7 @@
for (RoomBubbleCellData *cellData in bubbles) for (RoomBubbleCellData *cellData in bubbles)
{ {
cellData.containsLastMessage = NO; cellData.containsLastMessage = NO;
cellData.componentIndexOfSentMessageTick = -1;
} }
// The cell containing the last message is the last one with an actual display. // The cell containing the last message is the last one with an actual display.
@ -253,6 +255,8 @@
break; break;
} }
} }
[self updateStatusInfo];
} }
} }
@ -609,8 +613,16 @@
// Auto animate the sticker in case of animated gif // Auto animate the sticker in case of animated gif
bubbleCell.isAutoAnimatedGif = (cellData.attachment && cellData.attachment.type == MXKAttachmentTypeSticker); bubbleCell.isAutoAnimatedGif = (cellData.attachment && cellData.attachment.type == MXKAttachmentTypeSticker);
[self applyMaskToAttachmentViewOfBubbleCell: bubbleCell];
[self setupAccessibilityForCell:bubbleCell withCellData:cellData]; [self setupAccessibilityForCell:bubbleCell withCellData:cellData];
// We are interested only by outgoing messages
if ([cellData.senderId isEqualToString: self.mxSession.credentials.userId])
{
[bubbleCell updateTickViewWithFailedEventIds:self.failedEventIds];
}
} }
return cell; return cell;
@ -974,6 +986,57 @@
[self.delegate dataSource:self didRecognizeAction:kMXKRoomBubbleCellLongPressOnReactionView inCell:nil userInfo:@{ kMXKRoomBubbleCellEventIdKey: eventId }]; [self.delegate dataSource:self didRecognizeAction:kMXKRoomBubbleCellLongPressOnReactionView inCell:nil userInfo:@{ kMXKRoomBubbleCellEventIdKey: eventId }];
} }
- (void)applyMaskToAttachmentViewOfBubbleCell:(MXKRoomBubbleTableViewCell *)cell
{
if (cell.attachmentView && !cell.attachmentView.layer.mask)
{
UIBezierPath *myClippingPath = [UIBezierPath bezierPathWithRoundedRect:cell.attachmentView.bounds cornerRadius:6];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = myClippingPath.CGPath;
cell.attachmentView.layer.mask = mask;
}
}
#pragma mark - Message status management
- (void)updateStatusInfo
{
if (!self.failedEventIds)
{
self.failedEventIds = [NSMutableSet new];
}
NSInteger bubbleIndex = bubbles.count;
while (bubbleIndex--)
{
RoomBubbleCellData *cellData = bubbles[bubbleIndex];
NSInteger componentIndex = cellData.bubbleComponents.count;
while (componentIndex--) {
MXKRoomBubbleComponent *component = cellData.bubbleComponents[componentIndex];
MXEventSentState eventState = component.event.sentState;
if (eventState == MXEventSentStateFailed)
{
[self.failedEventIds addObject:component.event.eventId];
continue;
}
NSArray<MXReceiptData*> *receipts = cellData.readReceipts[component.event.eventId];
if (receipts.count)
{
return;
}
if (eventState == MXEventSentStateSent)
{
cellData.componentIndexOfSentMessageTick = componentIndex;
return;
}
}
}
}
#pragma mark - Room creation intro cell #pragma mark - Room creation intro cell
- (BOOL)canShowRoomCreationIntroCell - (BOOL)canShowRoomCreationIntroCell

View file

@ -2433,7 +2433,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
// Add actions for a failed event // Add actions for a failed event
if (selectedEvent.sentState == MXEventSentStateFailed) if (selectedEvent.sentState == MXEventSentStateFailed)
{ {
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_resend", @"Vector", nil) [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"retry", @"Vector", nil)
style:UIAlertActionStyleDefault style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) { handler:^(UIAlertAction * action) {
@ -4618,32 +4618,14 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
-(BOOL)checkUnsentMessages -(BOOL)checkUnsentMessages
{ {
BOOL hasUnsent = NO; RoomSentStatus sentStatus = RoomSentStatusOk;
BOOL hasUnsentDueToUnknownDevices = NO;
if ([self.activitiesView isKindOfClass:RoomActivitiesView.class]) if ([self.activitiesView isKindOfClass:RoomActivitiesView.class])
{ {
NSArray<MXEvent*> *outgoingMsgs = self.roomDataSource.room.outgoingMessages; sentStatus = self.roomDataSource.room.sentStatus;
for (MXEvent *event in outgoingMsgs) if (sentStatus != RoomSentStatusOk)
{ {
if (event.sentState == MXEventSentStateFailed) NSString *notification = sentStatus == RoomSentStatusSentFailedDueToUnknownDevices ?
{
hasUnsent = YES;
// Check if the error is due to unknown devices
if ([event.sentError.domain isEqualToString:MXEncryptingErrorDomain]
&& event.sentError.code == MXEncryptingErrorUnknownDeviceCode)
{
hasUnsentDueToUnknownDevices = YES;
break;
}
}
}
if (hasUnsent)
{
NSString *notification = hasUnsentDueToUnknownDevices ?
NSLocalizedStringFromTable(@"room_unsent_messages_unknown_devices_notification", @"Vector", nil) : NSLocalizedStringFromTable(@"room_unsent_messages_unknown_devices_notification", @"Vector", nil) :
NSLocalizedStringFromTable(@"room_unsent_messages_notification", @"Vector", nil); NSLocalizedStringFromTable(@"room_unsent_messages_notification", @"Vector", nil);
@ -4713,7 +4695,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
} }
} }
return hasUnsent; return sentStatus != RoomSentStatusOk;
} }
- (void)eventDidChangeSentState:(NSNotification *)notif - (void)eventDidChangeSentState:(NSNotification *)notif
@ -4851,19 +4833,32 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
- (void)cancelAllUnsentMessages - (void)cancelAllUnsentMessages
{ {
// Remove unsent event ids currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_unsent_messages_cancel_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"room_unsent_messages_cancel_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert];
for (NSUInteger index = 0; index < self.roomDataSource.room.outgoingMessages.count;)
{ MXWeakify(self);
MXEvent *event = self.roomDataSource.room.outgoingMessages[index]; [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
if (event.sentState == MXEventSentStateFailed) MXStrongifyAndReturnIfNil(self);
self->currentAlert = nil;
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"delete"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
MXStrongifyAndReturnIfNil(self);
// Remove unsent event ids
for (NSUInteger index = 0; index < self.roomDataSource.room.outgoingMessages.count;)
{ {
[self.roomDataSource removeEventWithEventId:event.eventId]; MXEvent *event = self.roomDataSource.room.outgoingMessages[index];
if (event.sentState == MXEventSentStateFailed)
{
[self.roomDataSource removeEventWithEventId:event.eventId];
}
else
{
index ++;
}
} }
else }]];
{
index ++; [self presentViewController:currentAlert animated:YES completion:nil];
}
}
} }
# pragma mark - Encryption Information view # pragma mark - Encryption Information view
@ -5336,147 +5331,22 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
- (NSArray<RoomContextualMenuItem*>*)contextualMenuItemsForEvent:(MXEvent*)event andCell:(id<MXKCellRendering>)cell - (NSArray<RoomContextualMenuItem*>*)contextualMenuItemsForEvent:(MXEvent*)event andCell:(id<MXKCellRendering>)cell
{ {
NSString *eventId = event.eventId; if (event.sentState == MXEventSentStateFailed)
MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell *)cell;
MXKAttachment *attachment = roomBubbleTableViewCell.bubbleData.attachment;
MXWeakify(self);
// Copy action
BOOL isCopyActionEnabled = !attachment || attachment.type != MXKAttachmentTypeSticker;
if (attachment && !BuildSettings.messageDetailsAllowCopyMedia)
{ {
isCopyActionEnabled = NO; return @[
[self resendMenuItemWithEvent:event],
[self deleteMenuItemWithEvent:event],
[self editMenuItemWithEvent:event],
[self copyMenuItemWithEvent:event andCell:cell]
];
} }
if (isCopyActionEnabled) return @[
{ [self copyMenuItemWithEvent:event andCell:cell],
switch (event.eventType) { [self replyMenuItemWithEvent:event],
case MXEventTypeRoomMessage: [self editMenuItemWithEvent:event],
{ [self moreMenuItemWithEvent:event andCell:cell]
NSString *messageType = event.content[@"msgtype"]; ];
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
isCopyActionEnabled = NO;
}
break;
}
case MXEventTypeKeyVerificationStart:
case MXEventTypeKeyVerificationAccept:
case MXEventTypeKeyVerificationKey:
case MXEventTypeKeyVerificationMac:
case MXEventTypeKeyVerificationDone:
case MXEventTypeKeyVerificationCancel:
isCopyActionEnabled = NO;
break;
default:
break;
}
}
RoomContextualMenuItem *copyMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionCopy];
copyMenuItem.isEnabled = isCopyActionEnabled;
copyMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
if (!attachment)
{
NSArray *components = roomBubbleTableViewCell.bubbleData.bubbleComponents;
MXKRoomBubbleComponent *selectedComponent;
for (selectedComponent in components)
{
if ([selectedComponent.event.eventId isEqualToString:event.eventId])
{
break;
}
selectedComponent = nil;
}
NSString *textMessage = selectedComponent.textMessage;
if (textMessage)
{
MXKPasteboardManager.shared.pasteboard.string = textMessage;
}
else
{
NSLog(@"[RoomViewController] Contextual menu copy failed. Text is nil for room id/event id: %@/%@", selectedComponent.event.roomId, selectedComponent.event.eventId);
}
[self hideContextualMenuAnimated:YES];
}
else if (attachment.type != MXKAttachmentTypeSticker)
{
[self hideContextualMenuAnimated:YES completion:^{
[self startActivityIndicator];
[attachment copy:^{
[self stopActivityIndicator];
} failure:^(NSError *error) {
[self stopActivityIndicator];
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
// Start animation in case of download during attachment preparing
[roomBubbleTableViewCell startProgressUI];
}];
}
};
// Reply action
RoomContextualMenuItem *replyMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionReply];
replyMenuItem.isEnabled = [self.roomDataSource canReplyToEventWithId:eventId];
replyMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self selectEventWithId:eventId inputToolBarSendMode:RoomInputToolbarViewSendModeReply showTimestamp:NO];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
};
// Edit action
RoomContextualMenuItem *editMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionEdit];
editMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self editEventContentWithId:eventId];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
};
editMenuItem.isEnabled = [self.roomDataSource canEditEventWithId:eventId];
// More action
RoomContextualMenuItem *moreMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionMore];
moreMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES completion:nil];
[self showAdditionalActionsMenuForEvent:event inCell:cell animated:YES];
};
// Actions list
NSArray<RoomContextualMenuItem*> *actionItems = @[
copyMenuItem,
replyMenuItem,
editMenuItem,
moreMenuItem
];
return actionItems;
} }
- (void)showContextualMenuForEvent:(MXEvent*)event fromSingleTapGesture:(BOOL)usedSingleTapGesture cell:(id<MXKCellRendering>)cell animated:(BOOL)animated - (void)showContextualMenuForEvent:(MXEvent*)event fromSingleTapGesture:(BOOL)usedSingleTapGesture cell:(id<MXKCellRendering>)cell animated:(BOOL)animated
@ -5585,6 +5455,197 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
self.overlayContainerView.userInteractionEnabled = enableOverlayContainerUserInteractions; self.overlayContainerView.userInteractionEnabled = enableOverlayContainerUserInteractions;
} }
- (RoomContextualMenuItem *)resendMenuItemWithEvent:(MXEvent*)event
{
MXWeakify(self);
RoomContextualMenuItem *resendMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionResend];
resendMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self cancelEventSelection];
[self.roomDataSource resendEventWithEventId:event.eventId success:nil failure:nil];
};
return resendMenuItem;
}
- (RoomContextualMenuItem *)deleteMenuItemWithEvent:(MXEvent*)event
{
MXWeakify(self);
RoomContextualMenuItem *deleteMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionDelete];
deleteMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
MXWeakify(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:YES completion:^{
MXStrongifyAndReturnIfNil(self);
self->currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_event_action_delete_confirmation_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"room_event_action_delete_confirmation_message", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
}]];
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"delete"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) {
[self.roomDataSource removeEventWithEventId:event.eventId];
}]];
[self presentViewController:self->currentAlert animated:YES completion:nil];
}];
};
return deleteMenuItem;
}
- (RoomContextualMenuItem *)editMenuItemWithEvent:(MXEvent*)event
{
MXWeakify(self);
RoomContextualMenuItem *editMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionEdit];
editMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self editEventContentWithId:event.eventId];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
};
editMenuItem.isEnabled = [self.roomDataSource canEditEventWithId:event.eventId];
return editMenuItem;
}
- (RoomContextualMenuItem *)copyMenuItemWithEvent:(MXEvent*)event andCell:(id<MXKCellRendering>)cell
{
MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell *)cell;
MXKAttachment *attachment = roomBubbleTableViewCell.bubbleData.attachment;
MXWeakify(self);
BOOL isCopyActionEnabled = !attachment || attachment.type != MXKAttachmentTypeSticker;
if (attachment && !BuildSettings.messageDetailsAllowCopyMedia)
{
isCopyActionEnabled = NO;
}
if (isCopyActionEnabled)
{
switch (event.eventType) {
case MXEventTypeRoomMessage:
{
NSString *messageType = event.content[@"msgtype"];
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
{
isCopyActionEnabled = NO;
}
break;
}
case MXEventTypeKeyVerificationStart:
case MXEventTypeKeyVerificationAccept:
case MXEventTypeKeyVerificationKey:
case MXEventTypeKeyVerificationMac:
case MXEventTypeKeyVerificationDone:
case MXEventTypeKeyVerificationCancel:
isCopyActionEnabled = NO;
break;
default:
break;
}
}
RoomContextualMenuItem *copyMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionCopy];
copyMenuItem.isEnabled = isCopyActionEnabled;
copyMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
if (!attachment)
{
NSArray *components = roomBubbleTableViewCell.bubbleData.bubbleComponents;
MXKRoomBubbleComponent *selectedComponent;
for (selectedComponent in components)
{
if ([selectedComponent.event.eventId isEqualToString:event.eventId])
{
break;
}
selectedComponent = nil;
}
NSString *textMessage = selectedComponent.textMessage;
if (textMessage)
{
MXKPasteboardManager.shared.pasteboard.string = textMessage;
}
else
{
NSLog(@"[RoomViewController] Contextual menu copy failed. Text is nil for room id/event id: %@/%@", selectedComponent.event.roomId, selectedComponent.event.eventId);
}
[self hideContextualMenuAnimated:YES];
}
else if (attachment.type != MXKAttachmentTypeSticker)
{
[self hideContextualMenuAnimated:YES completion:^{
[self startActivityIndicator];
[attachment copy:^{
[self stopActivityIndicator];
} failure:^(NSError *error) {
[self stopActivityIndicator];
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
// Start animation in case of download during attachment preparing
[roomBubbleTableViewCell startProgressUI];
}];
}
};
return copyMenuItem;
}
- (RoomContextualMenuItem *)replyMenuItemWithEvent:(MXEvent*)event
{
MXWeakify(self);
RoomContextualMenuItem *replyMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionReply];
replyMenuItem.isEnabled = [self.roomDataSource canReplyToEventWithId:event.eventId];
replyMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self selectEventWithId:event.eventId inputToolBarSendMode:RoomInputToolbarViewSendModeReply showTimestamp:NO];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
};
return replyMenuItem;
}
- (RoomContextualMenuItem *)moreMenuItemWithEvent:(MXEvent*)event andCell:(id<MXKCellRendering>)cell
{
MXWeakify(self);
RoomContextualMenuItem *moreMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionMore];
moreMenuItem.action = ^{
MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES completion:nil];
[self showAdditionalActionsMenuForEvent:event inCell:cell animated:YES];
};
return moreMenuItem;
}
#pragma mark - RoomContextualMenuViewControllerDelegate #pragma mark - RoomContextualMenuViewControllerDelegate
- (void)roomContextualMenuViewControllerDidTapBackgroundOverlay:(RoomContextualMenuViewController *)viewController - (void)roomContextualMenuViewControllerDidTapBackgroundOverlay:(RoomContextualMenuViewController *)viewController

View file

@ -30,6 +30,11 @@
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mainHeightConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *mainHeightConstraint;
@property (weak, nonatomic) IBOutlet UIView *unsentMessagesContentView;
@property (weak, nonatomic) IBOutlet UIButton *resendButton;
@property (weak, nonatomic) IBOutlet UIButton *deleteButton;
@property (weak, nonatomic) IBOutlet UILabel *unsentMessageLabel;
/** /**
Notify that some messages are not sent. Notify that some messages are not sent.
Replace the current notification if any. Replace the current notification if any.

View file

@ -118,64 +118,51 @@
{ {
self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
} }
[self.resendButton.layer setCornerRadius:5];
self.resendButton.clipsToBounds = YES;
[self.resendButton setTitle:NSLocalizedStringFromTable(@"retry", @"Vector", nil) forState:UIControlStateNormal];
self.resendButton.backgroundColor = ThemeService.shared.theme.tintColor;
UIImage *image = [[UIImage imageNamed:@"room_context_menu_delete"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[self.deleteButton setImage:image forState:UIControlStateNormal];
self.deleteButton.tintColor = ThemeService.shared.theme.warningColor;
self.unsentMessageLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
self.unsentMessagesContentView.backgroundColor = ThemeService.shared.theme.backgroundColor;
} }
#pragma mark - #pragma mark -
- (IBAction)onCancelSendingPressed:(id)sender
{
void (^onCancelLinkPressed)(void) = objc_getAssociatedObject(self.deleteButton, "onCancelLinkPressed");
if (onCancelLinkPressed)
{
onCancelLinkPressed ();
}
}
- (IBAction)onResendMessagesPressed:(id)sender
{
void (^onResendLinkPressed)(void) = objc_getAssociatedObject(self.resendButton, "onResendLinkPressed");
if (onResendLinkPressed)
{
onResendLinkPressed();
}
}
- (void)displayUnsentMessagesNotification:(NSString*)notification withResendLink:(void (^)(void))onResendLinkPressed andCancelLink:(void (^)(void))onCancelLinkPressed andIconTapGesture:(void (^)(void))onIconTapGesture - (void)displayUnsentMessagesNotification:(NSString*)notification withResendLink:(void (^)(void))onResendLinkPressed andCancelLink:(void (^)(void))onCancelLinkPressed andIconTapGesture:(void (^)(void))onIconTapGesture
{ {
[self reset]; [self reset];
if (onResendLinkPressed && onCancelLinkPressed) if (onResendLinkPressed && onCancelLinkPressed)
{ {
NSString *resendLink = NSLocalizedStringFromTable(@"room_prompt_resend", @"Vector", nil); self.unsentMessagesContentView.hidden = NO;
NSString *cancelLink = NSLocalizedStringFromTable(@"room_prompt_cancel", @"Vector", nil); self.unsentMessageLabel.text = notification;
NSString *notif = [NSString stringWithFormat:notification, resendLink, cancelLink];
NSMutableAttributedString *tappableNotif = [[NSMutableAttributedString alloc] initWithString:notif];
objc_setAssociatedObject(self.messageTextView, "onResendLinkPressed", [onResendLinkPressed copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(self.resendButton, "onResendLinkPressed", [onResendLinkPressed copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self.messageTextView, "onCancelLinkPressed", [onCancelLinkPressed copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(self.deleteButton, "onCancelLinkPressed", [onCancelLinkPressed copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
NSRange range = [notif rangeOfString:resendLink];
[tappableNotif addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
[tappableNotif addAttribute:NSLinkAttributeName value:@"onResendLink" range:range];
range = [notif rangeOfString:cancelLink];
[tappableNotif addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
[tappableNotif addAttribute:NSLinkAttributeName value:@"onCancelLink" range:range];
NSRange wholeString = NSMakeRange(0, tappableNotif.length);
[tappableNotif addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.warningColor range:wholeString];
[tappableNotif addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString];
self.messageTextView.attributedText = tappableNotif;
self.messageTextView.tintColor = ThemeService.shared.theme.warningColor;
self.messageTextView.hidden = NO;
self.messageTextView.backgroundColor = [UIColor clearColor];
}
else
{
self.messageLabel.text = notification;
self.messageLabel.textColor = ThemeService.shared.theme.warningColor;
self.messageLabel.hidden = NO;
}
self.iconImageView.image = [UIImage imageNamed:@"error"];
self.iconImageView.tintColor = ThemeService.shared.theme.tintColor;
self.iconImageView.hidden = NO;
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]; [self checkHeight:YES];
@ -517,6 +504,7 @@
- (void)reset - (void)reset
{ {
self.separatorView.hidden = NO; self.separatorView.hidden = NO;
self.unsentMessagesContentView.hidden = YES;
self.backgroundColor = UIColor.clearColor; self.backgroundColor = UIColor.clearColor;

View file

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -56,16 +55,71 @@
<outlet property="delegate" destination="iN0-l3-epB" id="ZAk-sC-QpQ"/> <outlet property="delegate" destination="iN0-l3-epB" id="ZAk-sC-QpQ"/>
</connections> </connections>
</textView> </textView>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="l7B-JK-ZKf">
<rect key="frame" x="0.0" y="1" width="600" height="52"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="error_icon" translatesAutoresizingMaskIntoConstraints="NO" id="f50-cK-AVb">
<rect key="frame" x="13" y="18" width="16" height="16"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Messages failed to send" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZD8-X6-qAB" userLabel="Message Label">
<rect key="frame" x="41" y="17" width="166" height="18"/>
<accessibility key="accessibilityConfiguration" identifier="RoomActivitiesViewMessageLabel"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UwY-F8-8nJ">
<rect key="frame" x="477" y="14" width="24" height="24"/>
<state key="normal" image="room_context_menu_delete"/>
<connections>
<action selector="onCancelSendingPressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="nCu-h1-Hek"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="d0g-ev-lDj">
<rect key="frame" x="513" y="12" width="75" height="28"/>
<color key="backgroundColor" red="0.028153735480000001" green="0.82494870580000002" blue="0.051896891280000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="LeftButton"/>
<constraints>
<constraint firstAttribute="height" constant="28" id="LhJ-4D-OZI"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<inset key="contentEdgeInsets" minX="12" minY="0.0" maxX="8" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="0.0" maxY="0.0"/>
<state key="normal" title="Retry" image="room_activities_retry">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="onResendMessagesPressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="Aj1-oT-c0C"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="d0g-ev-lDj" firstAttribute="leading" secondItem="UwY-F8-8nJ" secondAttribute="trailing" constant="12" id="IZZ-du-a29"/>
<constraint firstItem="d0g-ev-lDj" firstAttribute="centerY" secondItem="l7B-JK-ZKf" secondAttribute="centerY" id="Uos-j3-ARf"/>
<constraint firstItem="ZD8-X6-qAB" firstAttribute="centerY" secondItem="l7B-JK-ZKf" secondAttribute="centerY" id="YCs-5T-5kQ"/>
<constraint firstItem="UwY-F8-8nJ" firstAttribute="centerY" secondItem="l7B-JK-ZKf" secondAttribute="centerY" id="YRY-fg-2qs"/>
<constraint firstItem="f50-cK-AVb" firstAttribute="leading" secondItem="l7B-JK-ZKf" secondAttribute="leading" constant="13" id="da5-bp-l7B"/>
<constraint firstAttribute="trailing" secondItem="d0g-ev-lDj" secondAttribute="trailing" constant="12" id="foj-YD-tjx"/>
<constraint firstItem="UwY-F8-8nJ" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="ZD8-X6-qAB" secondAttribute="trailing" constant="12" id="mPP-0E-MHa"/>
<constraint firstItem="ZD8-X6-qAB" firstAttribute="leading" secondItem="f50-cK-AVb" secondAttribute="trailing" constant="12" id="tWy-Tu-kM5"/>
<constraint firstItem="f50-cK-AVb" firstAttribute="centerY" secondItem="l7B-JK-ZKf" secondAttribute="centerY" id="zea-t6-SnQ"/>
</constraints>
</view>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="1Mq-77-vvo" firstAttribute="leading" secondItem="qhJ-5H-64e" secondAttribute="leading" constant="13" id="2S8-TD-jHO"/> <constraint firstItem="1Mq-77-vvo" firstAttribute="leading" secondItem="qhJ-5H-64e" secondAttribute="leading" constant="13" id="2S8-TD-jHO"/>
<constraint firstItem="7bS-1u-GUX" firstAttribute="leading" secondItem="d6j-oN-9uA" secondAttribute="trailing" constant="13" id="6Js-Lq-pKz"/> <constraint firstItem="7bS-1u-GUX" firstAttribute="leading" secondItem="d6j-oN-9uA" secondAttribute="trailing" constant="13" id="6Js-Lq-pKz"/>
<constraint firstAttribute="trailing" secondItem="l7B-JK-ZKf" secondAttribute="trailing" id="6ub-bL-RIw"/>
<constraint firstItem="7bS-1u-GUX" firstAttribute="centerY" secondItem="d6j-oN-9uA" secondAttribute="centerY" id="BIB-uG-AY7"/> <constraint firstItem="7bS-1u-GUX" firstAttribute="centerY" secondItem="d6j-oN-9uA" secondAttribute="centerY" id="BIB-uG-AY7"/>
<constraint firstAttribute="bottom" secondItem="l7B-JK-ZKf" secondAttribute="bottom" id="G9G-RU-ftj"/>
<constraint firstAttribute="trailing" secondItem="1Mq-77-vvo" secondAttribute="trailing" constant="10" id="YBp-az-maq"/> <constraint firstAttribute="trailing" secondItem="1Mq-77-vvo" secondAttribute="trailing" constant="10" id="YBp-az-maq"/>
<constraint firstItem="d6j-oN-9uA" firstAttribute="leading" secondItem="qhJ-5H-64e" secondAttribute="leading" constant="13" id="YYC-Q1-IoC"/> <constraint firstItem="d6j-oN-9uA" firstAttribute="leading" secondItem="qhJ-5H-64e" secondAttribute="leading" constant="13" id="YYC-Q1-IoC"/>
<constraint firstItem="6ND-Cq-ABj" firstAttribute="leading" secondItem="d6j-oN-9uA" secondAttribute="trailing" constant="13" id="ZdK-4Z-Yfz"/> <constraint firstItem="6ND-Cq-ABj" firstAttribute="leading" secondItem="d6j-oN-9uA" secondAttribute="trailing" constant="13" id="ZdK-4Z-Yfz"/>
<constraint firstItem="6ND-Cq-ABj" firstAttribute="top" secondItem="qhJ-5H-64e" secondAttribute="top" constant="10" id="j7I-pC-7fV"/> <constraint firstItem="6ND-Cq-ABj" firstAttribute="top" secondItem="qhJ-5H-64e" secondAttribute="top" constant="10" id="j7I-pC-7fV"/>
<constraint firstItem="l7B-JK-ZKf" firstAttribute="leading" secondItem="qhJ-5H-64e" secondAttribute="leading" id="k98-cf-ItU"/>
<constraint firstAttribute="bottom" secondItem="6ND-Cq-ABj" secondAttribute="bottom" constant="10" id="m0j-16-mJw"/> <constraint firstAttribute="bottom" secondItem="6ND-Cq-ABj" secondAttribute="bottom" constant="10" id="m0j-16-mJw"/>
<constraint firstItem="l7B-JK-ZKf" firstAttribute="top" secondItem="1Mq-77-vvo" secondAttribute="bottom" id="qLJ-nv-QD0"/>
<constraint firstItem="d6j-oN-9uA" firstAttribute="centerY" secondItem="qhJ-5H-64e" secondAttribute="centerY" id="rEU-px-J59"/> <constraint firstItem="d6j-oN-9uA" firstAttribute="centerY" secondItem="qhJ-5H-64e" secondAttribute="centerY" id="rEU-px-J59"/>
<constraint firstItem="1Mq-77-vvo" firstAttribute="top" secondItem="qhJ-5H-64e" secondAttribute="top" id="stG-o2-SK4"/> <constraint firstItem="1Mq-77-vvo" firstAttribute="top" secondItem="qhJ-5H-64e" secondAttribute="top" id="stG-o2-SK4"/>
<constraint firstAttribute="trailing" secondItem="7bS-1u-GUX" secondAttribute="trailing" constant="30" id="tCW-EI-6Yt"/> <constraint firstAttribute="trailing" secondItem="7bS-1u-GUX" secondAttribute="trailing" constant="30" id="tCW-EI-6Yt"/>
@ -87,15 +141,26 @@
<nil key="simulatedBottomBarMetrics"/> <nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections> <connections>
<outlet property="deleteButton" destination="UwY-F8-8nJ" id="aV5-96-x5E"/>
<outlet property="iconImageView" destination="d6j-oN-9uA" id="Qhw-fw-uGc"/> <outlet property="iconImageView" destination="d6j-oN-9uA" id="Qhw-fw-uGc"/>
<outlet property="mainHeightConstraint" destination="xPK-Yw-hQ9" id="dJ5-pI-KyT"/> <outlet property="mainHeightConstraint" destination="xPK-Yw-hQ9" id="dJ5-pI-KyT"/>
<outlet property="messageLabel" destination="7bS-1u-GUX" id="5c1-hT-y49"/> <outlet property="messageLabel" destination="7bS-1u-GUX" id="5c1-hT-y49"/>
<outlet property="messageTextView" destination="6ND-Cq-ABj" id="xWk-ga-9xS"/> <outlet property="messageTextView" destination="6ND-Cq-ABj" id="xWk-ga-9xS"/>
<outlet property="resendButton" destination="d0g-ev-lDj" id="iQ1-LZ-cZh"/>
<outlet property="separatorView" destination="1Mq-77-vvo" id="8fc-AO-8hF"/> <outlet property="separatorView" destination="1Mq-77-vvo" id="8fc-AO-8hF"/>
<outlet property="unsentMessageLabel" destination="ZD8-X6-qAB" id="0FN-Nu-lfo"/>
<outlet property="unsentMessagesContentView" destination="l7B-JK-ZKf" id="6aW-n4-Bc5"/>
</connections> </connections>
<point key="canvasLocation" x="-390.39999999999998" y="80.50974512743629"/>
</view> </view>
</objects> </objects>
<resources> <resources>
<image name="typing" width="31" height="30"/> <image name="error_icon" width="16" height="16"/>
<image name="room_activities_retry" width="16" height="16"/>
<image name="room_context_menu_delete" width="24" height="24"/>
<image name="typing" width="30" height="30"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources> </resources>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="75"/> <rect key="frame" x="0.0" y="0.0" width="600" height="75"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/> <rect key="frame" x="0.0" y="0.0" width="600" height="75"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView"> <view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
@ -40,7 +37,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="31" width="192" height="33"/> <rect key="frame" x="56" y="31" width="192" height="34"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -65,7 +62,7 @@
</constraints> </constraints>
</imageView> </imageView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="10" width="70" height="64"/> <rect key="frame" x="515" y="10" width="70" height="65"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -73,38 +70,26 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="13" width="100" height="70"/> <rect key="frame" x="487" y="31" width="100" height="34"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats"> <view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="CircleProgressView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="60" width="100" height="10"/> <rect key="frame" x="84" y="18" width="16" height="16"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/> <accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/> <constraint firstAttribute="width" constant="16" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/> <constraint firstAttribute="height" constant="16" id="Jb4-9E-tG0"/>
</constraints> </constraints>
</view> </view>
</subviews> </subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="bottom" secondItem="hJj-TC-pxK" secondAttribute="bottom" id="C8V-iB-bXf"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/> <constraint firstAttribute="trailing" secondItem="hJj-TC-pxK" secondAttribute="trailing" id="bku-C1-qxN"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UyS-dv-e6D"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UyS-dv-e6D">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/> <rect key="frame" x="8" y="3" width="584" height="69"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="r5X-QJ-laa"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="r5X-QJ-laa">
@ -119,11 +104,13 @@
<constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="2Ih-ga-N9s"/> <constraint firstItem="hgp-Z5-rAj" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="2Ih-ga-N9s"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="31" id="96U-67-5TP"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="31" id="96U-67-5TP"/>
<constraint firstItem="fdx-qs-8en" firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" id="9XN-k2-Ep8"/>
<constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="85" id="Bkh-h2-JOQ"/> <constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="85" id="Bkh-h2-JOQ"/>
<constraint firstItem="UyS-dv-e6D" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="Fs4-RT-yIy"/> <constraint firstItem="UyS-dv-e6D" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="Fs4-RT-yIy"/>
<constraint firstItem="r5X-QJ-laa" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-6" id="GPC-Kc-JrE"/> <constraint firstItem="r5X-QJ-laa" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-6" id="GPC-Kc-JrE"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
<constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="Ixr-7h-f8j"/> <constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="Ixr-7h-f8j"/>
<constraint firstItem="fdx-qs-8en" firstAttribute="top" secondItem="5IE-JS-uf3" secondAttribute="top" id="Kyb-Ci-eFL"/>
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/> <constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/>
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/> <constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="XSL-TG-m62"/> <constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="XSL-TG-m62"/>
@ -135,7 +122,6 @@
<constraint firstItem="r5X-QJ-laa" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" id="puT-Ah-us5"/> <constraint firstItem="r5X-QJ-laa" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" id="puT-Ah-us5"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/> <constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
<constraint firstAttribute="trailingMargin" secondItem="UyS-dv-e6D" secondAttribute="trailing" constant="-8" id="v9l-9W-ReX"/> <constraint firstAttribute="trailingMargin" secondItem="UyS-dv-e6D" secondAttribute="trailing" constant="-8" id="v9l-9W-ReX"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/> <constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
@ -157,10 +143,10 @@
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/> <outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/> <outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
<outlet property="userNameTapGestureMaskView" destination="r5X-QJ-laa" id="m58-qZ-LfT"/> <outlet property="userNameTapGestureMaskView" destination="r5X-QJ-laa" id="m58-qZ-LfT"/>
</connections> </connections>
<point key="canvasLocation" x="-235" y="114"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/> <rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="119.5"/> <rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View">
@ -70,7 +67,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="75" width="192" height="34"/> <rect key="frame" x="56" y="75" width="192" height="35"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -87,7 +84,7 @@
</constraints> </constraints>
</imageView> </imageView>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View"> <imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
<rect key="frame" x="136" y="76" width="32" height="32"/> <rect key="frame" x="136" y="76.5" width="32" height="32"/>
<accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/> <accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/> <constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
@ -95,7 +92,7 @@
</constraints> </constraints>
</imageView> </imageView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="54" width="70" height="65"/> <rect key="frame" x="515" y="54" width="70" height="66"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -103,38 +100,26 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="57" width="100" height="70"/> <rect key="frame" x="487" y="75" width="100" height="35"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats"> <view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="CircleProgressView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="60" width="100" height="10"/> <rect key="frame" x="84" y="19" width="16" height="16"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/> <accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/> <constraint firstAttribute="width" constant="16" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/> <constraint firstAttribute="height" constant="16" id="Jb4-9E-tG0"/>
</constraints> </constraints>
</view> </view>
</subviews> </subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="trailing" secondItem="hJj-TC-pxK" secondAttribute="trailing" id="8X2-ow-q9k"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/> <constraint firstAttribute="bottom" secondItem="hJj-TC-pxK" secondAttribute="bottom" id="kz8-Ey-P6M"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0">
<rect key="frame" x="0.0" y="0.0" width="600" height="119"/> <rect key="frame" x="8" y="3" width="584" height="114"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4ru-pn-Aka"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4ru-pn-Aka">
@ -155,6 +140,7 @@
<constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/> <constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/>
<constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="Ixr-7h-f8j"/> <constraint firstItem="q9c-0p-QyP" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="Ixr-7h-f8j"/>
<constraint firstItem="4ru-pn-Aka" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-6" id="K0X-dz-PvH"/> <constraint firstItem="4ru-pn-Aka" firstAttribute="top" secondItem="q9c-0p-QyP" secondAttribute="top" constant="-6" id="K0X-dz-PvH"/>
<constraint firstItem="fdx-qs-8en" firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" id="RVF-EL-9zx"/>
<constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/> <constraint firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" constant="10" id="SHN-tC-zsJ"/>
<constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/> <constraint firstAttribute="bottom" secondItem="IOg-Kt-8vW" secondAttribute="bottom" id="TPw-iE-nii"/>
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="XSL-TG-m62"/> <constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="54" id="XSL-TG-m62"/>
@ -164,10 +150,10 @@
<constraint firstItem="4ru-pn-Aka" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-10" id="djP-gt-Mas"/> <constraint firstItem="4ru-pn-Aka" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-10" id="djP-gt-Mas"/>
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/> <constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/>
<constraint firstAttribute="trailing" secondItem="SFg-55-RF4" secondAttribute="trailing" constant="10" id="jvR-oT-EQF"/> <constraint firstAttribute="trailing" secondItem="SFg-55-RF4" secondAttribute="trailing" constant="10" id="jvR-oT-EQF"/>
<constraint firstItem="fdx-qs-8en" firstAttribute="top" secondItem="5IE-JS-uf3" secondAttribute="top" id="nUn-a5-c09"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/> <constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
<constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/> <constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
<constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/> <constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/>
@ -193,10 +179,10 @@
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/> <outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/> <outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
<outlet property="userNameTapGestureMaskView" destination="4ru-pn-Aka" id="28k-f4-1LY"/> <outlet property="userNameTapGestureMaskView" destination="4ru-pn-Aka" id="28k-f4-1LY"/>
</connections> </connections>
<point key="canvasLocation" x="34" y="113"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,11 +13,11 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="40"/> <rect key="frame" x="0.0" y="0.0" width="600" height="40"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="39"/> <rect key="frame" x="0.0" y="0.0" width="600" height="40"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="3" width="192" height="33"/> <rect key="frame" x="56" y="3" width="192" height="34"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -45,7 +42,7 @@
</constraints> </constraints>
</imageView> </imageView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="3" width="70" height="36"/> <rect key="frame" x="515" y="3" width="70" height="37"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -53,44 +50,33 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="-15.5" width="100" height="70"/> <rect key="frame" x="487" y="3" width="100" height="34"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats"> <view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="CircleProgressView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="60" width="100" height="10"/> <rect key="frame" x="84" y="18" width="16" height="16"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/> <accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/> <constraint firstAttribute="width" constant="16" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/> <constraint firstAttribute="height" constant="16" id="Jb4-9E-tG0"/>
</constraints> </constraints>
</view> </view>
</subviews> </subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="trailing" secondItem="hJj-TC-pxK" secondAttribute="trailing" id="9Ig-QL-eeA"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/> <constraint firstAttribute="bottom" secondItem="hJj-TC-pxK" secondAttribute="bottom" id="bfS-zB-FMB"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WiZ-KM-lSH"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WiZ-KM-lSH">
<rect key="frame" x="0.0" y="0.0" width="600" height="39"/> <rect key="frame" x="8" y="3" width="584" height="34"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
</subviews> </subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="96U-67-5TP"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="96U-67-5TP"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" id="AF6-HL-Xfw"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
<constraint firstItem="WiZ-KM-lSH" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="ICD-ch-XIt"/> <constraint firstItem="WiZ-KM-lSH" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="topMargin" constant="-8" id="ICD-ch-XIt"/>
<constraint firstAttribute="trailingMargin" secondItem="WiZ-KM-lSH" secondAttribute="trailing" constant="-8" id="QZK-47-doo"/> <constraint firstAttribute="trailingMargin" secondItem="WiZ-KM-lSH" secondAttribute="trailing" constant="-8" id="QZK-47-doo"/>
@ -99,11 +85,11 @@
<constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="XSL-TG-m62"/> <constraint firstItem="IOg-Kt-8vW" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="XSL-TG-m62"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="bSL-lG-ued"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="bSL-lG-ued"/>
<constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/> <constraint firstAttribute="trailing" secondItem="IOg-Kt-8vW" secondAttribute="trailing" constant="15" id="hQV-lO-7aQ"/>
<constraint firstItem="fdx-qs-8en" firstAttribute="top" secondItem="5IE-JS-uf3" secondAttribute="top" id="lNc-m9-BWs"/>
<constraint firstAttribute="bottomMargin" secondItem="WiZ-KM-lSH" secondAttribute="bottom" constant="-8" id="ofs-BR-F97"/> <constraint firstAttribute="bottomMargin" secondItem="WiZ-KM-lSH" secondAttribute="bottom" constant="-8" id="ofs-BR-F97"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="K9X-gn-noF" secondAttribute="leading" id="p93-5h-lvW"/>
<constraint firstItem="WiZ-KM-lSH" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="qKa-jp-T43"/> <constraint firstItem="WiZ-KM-lSH" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="qKa-jp-T43"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/> <constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
</constraints> </constraints>
@ -123,8 +109,8 @@
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/> <outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
</connections> </connections>
<point key="canvasLocation" x="34" y="113"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="75"/> <rect key="frame" x="0.0" y="0.0" width="600" height="75"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/> <rect key="frame" x="0.0" y="0.0" width="600" height="75"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView"> <view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="hgp-Z5-rAj" userLabel="Picture View" customClass="MXKImageView">
@ -40,7 +37,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="31" width="192" height="33"/> <rect key="frame" x="56" y="31" width="192" height="34"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -71,7 +68,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</activityIndicatorView> </activityIndicatorView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="10" width="70" height="64"/> <rect key="frame" x="515" y="10" width="70" height="65"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -80,37 +77,14 @@
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="13" width="100" height="70"/> <rect key="frame" x="487" y="13" width="100" height="70"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats">
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/>
</constraints>
</view>
</subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UyS-dv-e6D"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UyS-dv-e6D">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/> <rect key="frame" x="8" y="3" width="584" height="69"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sbr-Th-TTb"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sbr-Th-TTb">
@ -164,12 +138,11 @@
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/> <outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/> <outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/> <outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
<outlet property="userNameTapGestureMaskView" destination="sbr-Th-TTb" id="jz6-Gf-FqU"/> <outlet property="userNameTapGestureMaskView" destination="sbr-Th-TTb" id="jz6-Gf-FqU"/>
</connections> </connections>
<point key="canvasLocation" x="34" y="114"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,7 +13,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="120"/> <rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="119.5"/> <rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SFg-55-RF4" userLabel="Pagination Title View">
@ -70,7 +67,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="75" width="192" height="34"/> <rect key="frame" x="56" y="75" width="192" height="35"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -87,7 +84,7 @@
</constraints> </constraints>
</imageView> </imageView>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View"> <imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Cot-3X-2cU" userLabel="Play Icon Image View">
<rect key="frame" x="136" y="76" width="32" height="32"/> <rect key="frame" x="136" y="76.5" width="32" height="32"/>
<accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/> <accessibility key="accessibilityConfiguration" identifier="PlayIconImageView"/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/> <constraint firstAttribute="height" constant="32" id="8io-Wk-GzF"/>
@ -95,13 +92,13 @@
</constraints> </constraints>
</imageView> </imageView>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="jmK-pe-WZd"> <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="jmK-pe-WZd">
<rect key="frame" x="142" y="82" width="20" height="20"/> <rect key="frame" x="142" y="82.5" width="20" height="20"/>
<userDefinedRuntimeAttributes> <userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="ActivityIndicator"/> <userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="ActivityIndicator"/>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</activityIndicatorView> </activityIndicatorView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="54" width="70" height="65"/> <rect key="frame" x="515" y="54" width="70" height="66"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -109,38 +106,15 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="57" width="100" height="70"/> <rect key="frame" x="487" y="50" width="100" height="70"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats">
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/>
</constraints>
</view>
</subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3b7-4a-YL0">
<rect key="frame" x="0.0" y="0.0" width="600" height="119"/> <rect key="frame" x="8" y="3" width="584" height="114"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="y8m-dS-1Df"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="y8m-dS-1Df">
@ -155,6 +129,7 @@
<constraint firstItem="y8m-dS-1Df" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" id="6XL-SF-Mbj"/> <constraint firstItem="y8m-dS-1Df" firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" id="6XL-SF-Mbj"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="leading" secondItem="hgp-Z5-rAj" secondAttribute="trailing" constant="13" id="6mM-Ag-m0K"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="75" id="96U-67-5TP"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="75" id="96U-67-5TP"/>
<constraint firstAttribute="bottom" secondItem="fdx-qs-8en" secondAttribute="bottom" id="AeT-4F-mKp"/>
<constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="85" id="Bkh-h2-JOQ"/> <constraint firstAttribute="trailing" secondItem="q9c-0p-QyP" secondAttribute="trailing" constant="85" id="Bkh-h2-JOQ"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
<constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/> <constraint firstItem="SFg-55-RF4" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="56" id="I4N-5Q-LFe"/>
@ -175,7 +150,6 @@
<constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/> <constraint firstItem="hgp-Z5-rAj" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leading" constant="13" id="tuw-aU-ncu"/>
<constraint firstItem="y8m-dS-1Df" firstAttribute="bottom" secondItem="q9c-0p-QyP" secondAttribute="bottom" constant="6" id="tvi-jE-y62"/> <constraint firstItem="y8m-dS-1Df" firstAttribute="bottom" secondItem="q9c-0p-QyP" secondAttribute="bottom" constant="6" id="tvi-jE-y62"/>
<constraint firstItem="y8m-dS-1Df" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-10" id="ucU-Df-AZJ"/> <constraint firstItem="y8m-dS-1Df" firstAttribute="leading" secondItem="q9c-0p-QyP" secondAttribute="leading" constant="-10" id="ucU-Df-AZJ"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
<constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/> <constraint firstItem="SFg-55-RF4" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="10" id="wJX-7V-bJB"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
<constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/> <constraint firstAttribute="bottomMargin" secondItem="3b7-4a-YL0" secondAttribute="bottom" constant="-8" id="wpa-8Z-Gy3"/>
@ -200,12 +174,11 @@
<outlet property="paginationTitleView" destination="SFg-55-RF4" id="mbP-6I-gOn"/> <outlet property="paginationTitleView" destination="SFg-55-RF4" id="mbP-6I-gOn"/>
<outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/> <outlet property="pictureView" destination="hgp-Z5-rAj" id="rKM-QG-RJN"/>
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
<outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/> <outlet property="userNameLabel" destination="q9c-0p-QyP" id="JId-R7-LoM"/>
<outlet property="userNameTapGestureMaskView" destination="y8m-dS-1Df" id="0Nv-To-W4c"/> <outlet property="userNameTapGestureMaskView" destination="y8m-dS-1Df" id="0Nv-To-W4c"/>
</connections> </connections>
<point key="canvasLocation" x="-26" y="113"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait"> <device id="retina4_7" orientation="portrait" appearance="light"/>
<adaptation id="fullscreen"/>
</device>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@ -16,11 +13,11 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="40"/> <rect key="frame" x="0.0" y="0.0" width="600" height="40"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WmY-Jw-mqv" id="ef1-Tq-U3Z">
<rect key="frame" x="0.0" y="0.0" width="600" height="39"/> <rect key="frame" x="0.0" y="0.0" width="600" height="40"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView"> <view contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="5IE-JS-uf3" userLabel="Attachment View" customClass="MXKImageView">
<rect key="frame" x="56" y="3" width="192" height="33"/> <rect key="frame" x="56" y="3" width="192" height="34"/>
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AttachmentView"/> <accessibility key="accessibilityConfiguration" identifier="AttachmentView"/>
<constraints> <constraints>
@ -51,7 +48,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</activityIndicatorView> </activityIndicatorView>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW"> <view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOg-Kt-8vW">
<rect key="frame" x="515" y="3" width="70" height="36"/> <rect key="frame" x="515" y="3" width="70" height="37"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/> <accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints> <constraints>
@ -59,43 +56,21 @@
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdx-qs-8en" userLabel="ProgressView">
<rect key="frame" x="487" y="-15.5" width="100" height="70"/> <rect key="frame" x="487" y="-33" width="100" height="70"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="rate" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumFontSize="4" preferredMaxLayoutWidth="100" translatesAutoresizingMaskIntoConstraints="NO" id="eU5-iK-u8i" userLabel="Progress stats">
<rect key="frame" x="0.0" y="60" width="100" height="10"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressStats"/>
<fontDescription key="fontDescription" type="system" pointSize="8"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hJj-TC-pxK" customClass="MXKPieChartView">
<rect key="frame" x="30" y="0.0" width="40" height="40"/>
<accessibility key="accessibilityConfiguration" identifier="ProgressChartView"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="Cpt-s4-tlK"/>
<constraint firstAttribute="height" constant="40" id="Jb4-9E-tG0"/>
</constraints>
</view>
</subviews>
<gestureRecognizers/> <gestureRecognizers/>
<constraints> <constraints>
<constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/> <constraint firstAttribute="height" constant="70" id="5w2-Hm-hZx"/>
<constraint firstAttribute="centerX" secondItem="eU5-iK-u8i" secondAttribute="centerX" id="APi-aE-mLc"/>
<constraint firstItem="eU5-iK-u8i" firstAttribute="leading" secondItem="fdx-qs-8en" secondAttribute="leading" id="Njw-3a-E9Y"/>
<constraint firstAttribute="bottom" secondItem="eU5-iK-u8i" secondAttribute="bottom" id="QMO-g9-QVE"/>
<constraint firstAttribute="centerX" secondItem="hJj-TC-pxK" secondAttribute="centerX" id="laR-Vg-ol3"/>
<constraint firstItem="hJj-TC-pxK" firstAttribute="top" secondItem="fdx-qs-8en" secondAttribute="top" id="ovD-8p-4dP"/>
<constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/> <constraint firstAttribute="width" constant="100" id="ryE-fW-SgG"/>
<constraint firstAttribute="trailing" secondItem="eU5-iK-u8i" secondAttribute="trailing" id="teG-8q-BOX"/>
</constraints> </constraints>
</view> </view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WiZ-KM-lSH"> <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WiZ-KM-lSH">
<rect key="frame" x="0.0" y="0.0" width="600" height="39"/> <rect key="frame" x="8" y="3" width="584" height="34"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
</subviews> </subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="fdx-qs-8en" firstAttribute="bottom" secondItem="5IE-JS-uf3" secondAttribute="bottom" id="5k7-pL-bQ4"/>
<constraint firstItem="8Bq-Mk-bN8" firstAttribute="centerY" secondItem="5IE-JS-uf3" secondAttribute="centerY" id="5xu-oS-Iyd"/> <constraint firstItem="8Bq-Mk-bN8" firstAttribute="centerY" secondItem="5IE-JS-uf3" secondAttribute="centerY" id="5xu-oS-Iyd"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="96U-67-5TP"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="ef1-Tq-U3Z" secondAttribute="top" constant="3" id="96U-67-5TP"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="Cot-3X-2cU" secondAttribute="centerY" id="H5t-l6-fL1"/>
@ -111,7 +86,6 @@
<constraint firstItem="WiZ-KM-lSH" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="qKa-jp-T43"/> <constraint firstItem="WiZ-KM-lSH" firstAttribute="leading" secondItem="ef1-Tq-U3Z" secondAttribute="leadingMargin" constant="-8" id="qKa-jp-T43"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="centerX" secondItem="Cot-3X-2cU" secondAttribute="centerX" id="sF7-QL-vdj"/>
<constraint firstItem="8Bq-Mk-bN8" firstAttribute="centerX" secondItem="5IE-JS-uf3" secondAttribute="centerX" id="tYB-P5-rWe"/> <constraint firstItem="8Bq-Mk-bN8" firstAttribute="centerX" secondItem="5IE-JS-uf3" secondAttribute="centerX" id="tYB-P5-rWe"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="centerY" secondItem="fdx-qs-8en" secondAttribute="centerY" id="v0F-Ts-14P"/>
<constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/> <constraint firstItem="5IE-JS-uf3" firstAttribute="top" secondItem="K9X-gn-noF" secondAttribute="top" id="wkX-zQ-iQS"/>
<constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/> <constraint firstAttribute="trailing" secondItem="fdx-qs-8en" secondAttribute="trailing" constant="13" id="xKk-Gz-moE"/>
</constraints> </constraints>
@ -130,10 +104,9 @@
<outlet property="bubbleOverlayContainer" destination="WiZ-KM-lSH" id="07W-1f-K5G"/> <outlet property="bubbleOverlayContainer" destination="WiZ-KM-lSH" id="07W-1f-K5G"/>
<outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/> <outlet property="fileTypeIconView" destination="K9X-gn-noF" id="4Pj-bc-3gk"/>
<outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/> <outlet property="playIconView" destination="Cot-3X-2cU" id="KEF-KK-Og1"/>
<outlet property="progressChartView" destination="hJj-TC-pxK" id="Zz3-s5-Qqr"/>
<outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/> <outlet property="progressView" destination="fdx-qs-8en" id="V7E-pn-Xze"/>
<outlet property="statsLabel" destination="eU5-iK-u8i" id="MSm-kU-RSY"/>
</connections> </connections>
<point key="canvasLocation" x="-26" y="113"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View file

@ -0,0 +1,147 @@
//
// 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 CircleProgressView: MXKPieChartView {
// MARK: - Constants
private static let minStrokeEnd: CGFloat = 0.000000000001
private static let maxStrokeEnd: CGFloat = 1
// MARK: - Public properties
@IBInspectable var lineColor: UIColor = .lightGray {
didSet {
shapeLayer?.strokeColor = lineColor.cgColor
}
}
@IBInspectable var lineWidth: CGFloat = 2 {
didSet {
shapeLayer?.lineWidth = lineWidth
}
}
var value: CGFloat = 0 {
didSet {
stopAnimating()
strokeEnd = max(min(value, CircleProgressView.maxStrokeEnd), CircleProgressView.minStrokeEnd)
}
}
override var progress: CGFloat {
get {
return value
}
set {
value = newValue
}
}
// MARK: - Private members
private weak var shapeLayer: CAShapeLayer?
private var strokeEnd: CGFloat = minStrokeEnd {
didSet {
shapeLayer?.strokeEnd = strokeEnd
}
}
private var startAngle: CGFloat = -.pi/2
private(set) var isAnimating = false
// MARK: - Lifecycle
required init?(coder: NSCoder) {
super.init(coder: coder)
initLayer()
initPath()
}
override init(frame: CGRect) {
super.init(frame: frame)
initLayer()
initPath()
}
override func layoutSubviews() {
super.layoutSubviews()
shapeLayer?.frame = self.layer.bounds
initPath()
}
// MARK: - Interface Builder
override func prepareForInterfaceBuilder() {
value = 0.8
}
// MARK: - Animation management
func startAnimating() {
guard !isAnimating else {
return
}
isAnimating = true
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotationAnimation.fromValue = CGFloat.pi / 2
rotationAnimation.toValue = CGFloat.pi * 2.5
rotationAnimation.repeatCount = .infinity
rotationAnimation.duration = 2
shapeLayer?.add(rotationAnimation, forKey: "rotationAnimation")
let strokeAnimation = CABasicAnimation(keyPath: "strokeEnd")
strokeAnimation.fromValue = 0
strokeAnimation.toValue = 0.9
strokeAnimation.repeatCount = .infinity
strokeAnimation.duration = 0.9
strokeAnimation.autoreverses = true
strokeAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
shapeLayer?.add(strokeAnimation, forKey: "path")
}
func stopAnimating() {
guard isAnimating else {
return
}
shapeLayer?.removeAllAnimations()
isAnimating = false
}
// MARK: - Private methods
private func initLayer() {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = lineColor.cgColor
layer.lineCap = .round
layer.lineWidth = lineWidth
layer.allowsEdgeAntialiasing = true
layer.strokeEnd = strokeEnd
self.layer.insertSublayer(layer, at: 0)
shapeLayer = layer
}
private func initPath() {
let endAngle: CGFloat = startAngle + .pi * 2
let path = UIBezierPath(arcCenter: CGPoint(x: self.bounds.midX, y: self.bounds.midY), radius: (self.bounds.width - lineWidth) / 2, startAngle: startAngle, endAngle: endAngle, clockwise: true)
shapeLayer?.path = path.cgPath
}
}

View file

@ -888,21 +888,43 @@
withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)];
// Update the badge on People and Rooms tabs // Update the badge on People and Rooms tabs
[self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount if (recentsDataSource.unsentMessagesDirectDiscussionsCount)
onTabBarItem:TABBAR_PEOPLE_INDEX {
withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; [self setBadgeValue:@"!"
[self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX
onTabBarItem:TABBAR_ROOMS_INDEX withBadgeColor:ThemeService.shared.theme.noticeColor];
withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; }
else
{
[self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount
onTabBarItem:TABBAR_PEOPLE_INDEX
withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)];
}
if (recentsDataSource.unsentMessagesGroupDiscussionsCount)
{
[self setMissedDiscussionsCount:recentsDataSource.unsentMessagesGroupDiscussionsCount
onTabBarItem:TABBAR_ROOMS_INDEX
withBadgeColor:ThemeService.shared.theme.noticeColor];
}
else
{
[self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount
onTabBarItem:TABBAR_ROOMS_INDEX
withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)];
}
} }
- (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor
{ {
if (count) [self setBadgeValue:count ? [self tabBarBadgeStringValue:count] : nil onTabBarItem:index withBadgeColor:badgeColor];
}
- (void)setBadgeValue:(NSString *)value onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor
{
if (value)
{ {
NSString *badgeValue = [self tabBarBadgeStringValue:count]; self.tabBar.items[index].badgeValue = value;
self.tabBar.items[index].badgeValue = badgeValue;
self.tabBar.items[index].badgeColor = badgeColor; self.tabBar.items[index].badgeColor = badgeColor;

View file

@ -360,9 +360,9 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.subTitleTextColor = ThemeService.shared.theme.textSecondaryColor; self.subTitleTextColor = ThemeService.shared.theme.textSecondaryColor;
self.prefixTextColor = ThemeService.shared.theme.textSecondaryColor; self.prefixTextColor = ThemeService.shared.theme.textSecondaryColor;
self.bingTextColor = ThemeService.shared.theme.noticeColor; self.bingTextColor = ThemeService.shared.theme.noticeColor;
self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.encryptingTextColor = ThemeService.shared.theme.textPrimaryColor;
self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; self.sendingTextColor = ThemeService.shared.theme.textPrimaryColor;
self.errorTextColor = ThemeService.shared.theme.warningColor; self.errorTextColor = ThemeService.shared.theme.textPrimaryColor;
self.showEditionMention = YES; self.showEditionMention = YES;
self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor; self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor;