Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2017-07-28 14:52:12 +00:00
commit 54828c4ab0
14 changed files with 192 additions and 41 deletions

View file

@ -114,7 +114,6 @@
"contacts_address_book_matrix_users_toggle" = "Nur Matrix-Nutzer";
"contacts_address_book_no_contact" = "Keine lokalen Kontakte";
"contacts_address_book_permission_required" = "Berechtigungen benötigt um auf lokale Kontakte zuzugreifen";
"contacts_matrix_users_section" = "BEKANNTE KONTAKTE";
// Chat participants
"room_participants_title" = "Teilnehmer";
"room_participants_add_participant" = "Teilnehmer hinzufügen";

View file

@ -167,7 +167,8 @@
"contacts_address_book_no_contact" = "No local contacts";
"contacts_address_book_permission_required" = "Permission required to access local contacts";
"contacts_address_book_permission_denied" = "You didn't allow Riot to access your local contacts";
"contacts_matrix_users_section" = "KNOWN CONTACTS";
"contacts_user_directory_section" = "USER DIRECTORY";
"contacts_user_directory_offline_section" = "USER DIRECTORY (offline)";
// Chat participants
"room_participants_title" = "Participants";

View file

@ -110,7 +110,7 @@
// Rooms tab
"room_directory_no_public_room" = "Aucun salon public disponible";
// Search
"search_rooms" = "SALONS";
"search_rooms" = "Salons";
"search_messages" = "Messages";
"search_people" = "Personnes";
"search_files" = "Fichiers";
@ -131,7 +131,6 @@
"contacts_address_book_no_contact" = "Aucun contact local";
"contacts_address_book_permission_required" = "Permissions requises pour accéder aux contacts locaux";
"contacts_address_book_permission_denied" = "Vous n'avez pas autorisé Riot à accéder à vos contacts locaux";
"contacts_matrix_users_section" = "CONTACTS CONNUS";
// Chat participants
"room_participants_title" = "Membres";
"room_participants_add_participant" = "Ajouter un membre";

View file

@ -161,7 +161,6 @@
"contacts_address_book_no_contact" = "Geen lokale contacten";
"contacts_address_book_permission_required" = "Permissie vereist voor toegang tot de lokale contacten";
"contacts_address_book_permission_denied" = "Je hebt Riot geen toegang tot je lokale contacten toegestaan";
"contacts_matrix_users_section" = "BEKENDE CONTACTEN";
// Chat participants
"room_participants_title" = "Deelnemers";

View file

@ -0,0 +1,48 @@
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Сообщение от %@";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ написал в %@";
/* New message from a specific person, not referencing a room. Content included. */
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";
/* New message from a specific person in a named room. Content included. */
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@ в %@: %@";
/* New action message from a specific person, not referencing a room. */
"ACTION_FROM_USER" = "%@ %@";
/* 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. */
"IMAGE_FROM_USER" = "%@ отправил Вам фото";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ отправил фото в %@";
/* Multiple unread messages in a room */
"UNREAD_IN_ROOM" = "%@ новых сообщений в %@";
/* Multiple unread messages from a specific person, not referencing a room */
"MSGS_FROM_USER" = "%@ сообщений от %@";
/* Multiple unread messages from two people */
"MSGS_FROM_TWO_USERS" = "%@ новых сообщений от %@ и %@";
/* Multiple unread messages from three people */
"MSGS_FROM_THREE_USERS" = "%@ новых сообщений от %@, %@ и %@";
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
"MSGS_FROM_TWO_PLUS_USERS" = "%@ новых сообщений %@, %@ и других";
/* Multiple messages in two rooms */
"MSGS_IN_TWO_ROOMS" = "%@ новых сообщений в %@ и %@";
/* Look, stuff's happened, alright? Just open the app. */
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ новых сообщений в %@, %@ и других";
/* A user has invited you to a chat */
"USER_INVITE_TO_CHAT" = "%@ пригласил Вас в чат";
/* A user has invited you to an (unamed) group chat */
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ пригласил Вас в групповой чат";
/* A user has invited you to a named room */
"USER_INVITE_TO_NAMED_ROOM" = "%@ пригласил Вас в %@";
/* Incoming one-to-one voice call */
"VOICE_CALL_FROM_USER" = "Звонок от %@";
/* Incoming one-to-one video call */
"VIDEO_CALL_FROM_USER" = "Видеозвонок от %@";
/* Incoming unnamed voice conference invite from a specific person */
"VOICE_CONF_FROM_USER" = "Групповой звонок от %@";
/* Incoming unnamed video conference invite from a specific person */
"VIDEO_CONF_FROM_USER" = "Видеоконференция %@";
/* Incoming named voice conference invite from a specific person */
"VOICE_CONF_NAMED_FROM_USER" = "Групповой звонок от %@: '%@'";
/* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Групповой видео звонок от %@: '%@'";

View file

@ -16,6 +16,20 @@
#import <MatrixKit/MatrixKit.h>
/**
The state of the users search from the homeserver user directory.
*/
typedef enum : NSUInteger
{
ContactsDataSourceUserDirectoryStateLoading,
ContactsDataSourceUserDirectoryStateLoadedButLimited,
ContactsDataSourceUserDirectoryStateLoaded,
// The search is based on local known matrix contacts
ContactsDataSourceUserDirectoryStateOfflineLoading,
ContactsDataSourceUserDirectoryStateOfflineLoaded
} ContactsDataSourceUserDirectoryState;
/**
'ContactsDataSource' is a base class to handle contacts in Riot.
*/
@ -145,4 +159,9 @@
*/
@property (nonatomic, readonly) MXKContact *searchInputContact;
/**
The state of the users search from the homeserver user directory.
*/
@property (nonatomic, readonly) ContactsDataSourceUserDirectoryState userDirectoryState;
@end

View file

@ -20,7 +20,7 @@
#import "RiotDesignValues.h"
#define CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE 0x01
#define CONTACTSDATASOURCE_KNOWNCONTACTS_BITWISE 0x02
#define CONTACTSDATASOURCE_USERDIRECTORY_BITWISE 0x02
#define CONTACTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT 30.0
#define CONTACTSDATASOURCE_LOCALCONTACTS_SECTION_HEADER_HEIGHT 65.0
@ -33,6 +33,9 @@
NSString *searchProcessingText;
NSMutableArray<MXKContact*> *searchProcessingLocalContacts;
NSMutableArray<MXKContact*> *searchProcessingMatrixContacts;
// The current request to the homeserver user directory
MXHTTPOperation *hsUserDirectoryOperation;
BOOL forceSearchResultRefresh;
@ -115,6 +118,9 @@
localContactsCheckboxContainer = nil;
localContactsCheckbox = nil;
[hsUserDirectoryOperation cancel];
hsUserDirectoryOperation = nil;
[super destroy];
}
@ -145,6 +151,13 @@
}
- (void)searchWithPattern:(NSString *)searchText forceReset:(BOOL)forceRefresh
{
// If possible, always start a new search by asking the homeserver user directory
BOOL hsUserDirectory = (self.mxSession.state != MXSessionStateHomeserverNotReachable);
[self searchWithPattern:searchText forceReset:forceRefresh hsUserDirectory:hsUserDirectory];
}
- (void)searchWithPattern:(NSString *)searchText forceReset:(BOOL)forceRefresh hsUserDirectory:(BOOL)hsUserDirectory
{
// Update search results.
searchText = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
@ -161,11 +174,59 @@
shrinkedSectionsBitMask = 0;
}
}
else if (forceRefresh || !searchProcessingText.length || [searchText hasPrefix:searchProcessingText] == NO)
else if (forceRefresh || ![searchText isEqualToString:searchProcessingText])
{
// Prepare on the main thread the arrays used to initialize the search on the processing queue.
unfilteredLocalContacts = [self unfilteredLocalContactsArray];
unfilteredMatrixContacts = [self unfilteredMatrixContactsArray];
if (!hsUserDirectory)
{
_userDirectoryState = ContactsDataSourceUserDirectoryStateOfflineLoading;
unfilteredMatrixContacts = [self unfilteredMatrixContactsArray];
}
else if (![searchText isEqualToString:searchProcessingText])
{
_userDirectoryState = ContactsDataSourceUserDirectoryStateLoading;
// Make a search on the homeserver user directory
[filteredMatrixContacts removeAllObjects];
filteredMatrixContacts = nil;
// Cancel previous operation
if (hsUserDirectoryOperation)
{
[hsUserDirectoryOperation cancel];
hsUserDirectoryOperation = nil;
}
hsUserDirectoryOperation = [self.mxSession.matrixRestClient searchUsers:searchText limit:50 success:^(MXUserSearchResponse *userSearchResponse) {
filteredMatrixContacts = [NSMutableArray arrayWithCapacity:userSearchResponse.results.count];
// Keep the response order as the hs ordered users by relevance
for (MXUser *mxUser in userSearchResponse.results)
{
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:mxUser.displayname andMatrixID:mxUser.userId];
[filteredMatrixContacts addObject:contact];
}
hsUserDirectoryOperation = nil;
_userDirectoryState = userSearchResponse.limited ? ContactsDataSourceUserDirectoryStateLoadedButLimited : ContactsDataSourceUserDirectoryStateLoaded;
// And inform the delegate about the update
[self.delegate dataSource:self didCellChange:nil];
} failure:^(NSError *error) {
// Ignore connection cancellation error
if ((![error.domain isEqualToString:NSURLErrorDomain] || error.code != NSURLErrorCancelled))
{
// But for other errors, launch a local search
NSLog(@"[ContactsDataSource] [MXRestClient searchUsers] returns an error. Do a search on local known contacts");
[self searchWithPattern:searchText forceReset:forceRefresh hsUserDirectory:NO];
}
}];
}
// Disclose the sections
shrinkedSectionsBitMask = 0;
@ -239,7 +300,12 @@
// Update the filtered contacts.
currentSearchText = searchProcessingText;
filteredLocalContacts = searchProcessingLocalContacts;
filteredMatrixContacts = searchProcessingMatrixContacts;
if (!hsUserDirectory)
{
filteredMatrixContacts = searchProcessingMatrixContacts;
_userDirectoryState = ContactsDataSourceUserDirectoryStateOfflineLoaded;
}
if (!self.forceMatrixIdInDisplayName)
{
@ -435,7 +501,7 @@
// Display a default cell when no local contacts is available.
count = filteredLocalContacts.count ? filteredLocalContacts.count : 1;
}
else if (section == filteredMatrixContactsSection && !(shrinkedSectionsBitMask & CONTACTSDATASOURCE_KNOWNCONTACTS_BITWISE))
else if (section == filteredMatrixContactsSection && !(shrinkedSectionsBitMask & CONTACTSDATASOURCE_USERDIRECTORY_BITWISE))
{
// Display a default cell when no contacts is available.
count = filteredMatrixContacts.count ? filteredMatrixContacts.count : 1;
@ -534,7 +600,15 @@
// Check whether a search session is in progress
if (currentSearchText.length)
{
tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"search_no_result", @"Vector", nil);
if (indexPath.section == filteredMatrixContactsSection &&
(_userDirectoryState == ContactsDataSourceUserDirectoryStateLoading || _userDirectoryState == ContactsDataSourceUserDirectoryStateOfflineLoading))
{
tableViewCell.textLabel.text = [NSBundle mxk_localizedStringForKey:@"search_searching"];
}
else
{
tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"search_no_result", @"Vector", nil);
}
}
else if (indexPath.section == filteredLocalContactsSection)
{
@ -643,7 +717,17 @@
}
else //if (section == filteredMatrixContactsSection)
{
title = NSLocalizedStringFromTable(@"contacts_matrix_users_section", @"Vector", nil);
switch (_userDirectoryState)
{
case ContactsDataSourceUserDirectoryStateOfflineLoading:
case ContactsDataSourceUserDirectoryStateOfflineLoaded:
title = NSLocalizedStringFromTable(@"contacts_user_directory_offline_section", @"Vector", nil);
break;
default:
title = NSLocalizedStringFromTable(@"contacts_user_directory_section", @"Vector", nil);
break;
}
if (currentSearchText.length)
{
@ -653,7 +737,8 @@
if (count)
{
NSString *roomCount = [NSString stringWithFormat:@" %tu", count];
NSString *roomCountFormat = (_userDirectoryState == ContactsDataSourceUserDirectoryStateLoadedButLimited) ? @" > %tu" : @" %tu";
NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count];
NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title
attributes:@{NSForegroundColorAttributeName : kRiotTextColorBlack,
@ -705,7 +790,7 @@
// This section is collapsable only if it is not empty
if (filteredMatrixContacts.count)
{
sectionBitwise = CONTACTSDATASOURCE_KNOWNCONTACTS_BITWISE;
sectionBitwise = CONTACTSDATASOURCE_USERDIRECTORY_BITWISE;
}
}
}
@ -928,7 +1013,7 @@
{
// Return the section header used when the section is shrinked
NSInteger savedShrinkedSectionsBitMask = shrinkedSectionsBitMask;
shrinkedSectionsBitMask = CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE | CONTACTSDATASOURCE_KNOWNCONTACTS_BITWISE;
shrinkedSectionsBitMask = CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE | CONTACTSDATASOURCE_USERDIRECTORY_BITWISE;
UIView *stickyHeader = [self viewForHeaderInSection:section withFrame:frame];

View file

@ -22,7 +22,7 @@
#import "AppDelegate.h"
#define CONTACTS_TABLEVC_LOCALCONTACTS_BITWISE 0x01
#define CONTACTS_TABLEVC_KNOWNCONTACTS_BITWISE 0x02
#define CONTACTS_TABLEVC_USERDIRECTORY_BITWISE 0x02
#define CONTACTS_TABLEVC_DEFAULT_SECTION_HEADER_HEIGHT 30.0
#define CONTACTS_TABLEVC_LOCALCONTACTS_SECTION_HEADER_HEIGHT 65.0

View file

@ -50,11 +50,6 @@
contactsSectionNumber = 0;
self.screenName = @"People";
// Prepare its contacts data source
contactsDataSource = [[ContactsDataSource alloc] init];
contactsDataSource.contactCellAccessoryType = UITableViewCellAccessoryDisclosureIndicator;
contactsDataSource.delegate = self;
}
- (void)viewDidLoad
@ -151,6 +146,13 @@
recentsDataSource = (RecentsDataSource*)listDataSource;
}
if (!contactsDataSource)
{
// Prepare its contacts data source
contactsDataSource = [[ContactsDataSource alloc] initWithMatrixSession:listDataSource.mxSession];
contactsDataSource.contactCellAccessoryType = UITableViewCellAccessoryDisclosureIndicator;
contactsDataSource.delegate = self;
}
}
#pragma mark - MXKDataSourceDelegate

View file

@ -615,7 +615,7 @@
contactsPickerViewController.contactsTableViewControllerDelegate = self;
// Prepare its data source
ContactsDataSource *contactsDataSource = [[ContactsDataSource alloc] init];
ContactsDataSource *contactsDataSource = [[ContactsDataSource alloc] initWithMatrixSession:self.mxRoom.mxSession];
contactsDataSource.areSectionsShrinkable = YES;
contactsDataSource.displaySearchInputInContactsList = YES;
contactsDataSource.forceMatrixIdInDisplayName = YES;

View file

@ -2576,7 +2576,7 @@
contactsPickerViewController.contactsTableViewControllerDelegate = self;
// Prepare its data source
ContactsDataSource *contactsDataSource = [[ContactsDataSource alloc] init];
ContactsDataSource *contactsDataSource = [[ContactsDataSource alloc] initWithMatrixSession:self.roomDataSource.mxSession];
contactsDataSource.areSectionsShrinkable = YES;
contactsDataSource.displaySearchInputInContactsList = YES;
contactsDataSource.forceMatrixIdInDisplayName = YES;

View file

@ -74,17 +74,6 @@
// Assign itself as delegate
self.contactsTableViewControllerDelegate = self;
// Prepare its data source
ContactsDataSource *dataSource = [[ContactsDataSource alloc] init];
dataSource.areSectionsShrinkable = YES;
dataSource.displaySearchInputInContactsList = YES;
dataSource.forceMatrixIdInDisplayName = YES;
// Add a plus icon to the contact cell when a search session is in progress,
// in order to make it more understandable for the end user.
dataSource.contactCellAccessoryImage = [UIImage imageNamed:@"plus_icon"];
[self displayList:dataSource];
}
- (void)viewDidLoad
@ -121,7 +110,18 @@
{
[self addMatrixSession:mxSession];
}
// Prepare its data source
ContactsDataSource *dataSource = [[ContactsDataSource alloc] initWithMatrixSession:self.mainSession]; // TO TEST
dataSource.areSectionsShrinkable = YES;
dataSource.displaySearchInputInContactsList = YES;
dataSource.forceMatrixIdInDisplayName = YES;
// Add a plus icon to the contact cell when a search session is in progress,
// in order to make it more understandable for the end user.
dataSource.contactCellAccessoryImage = [UIImage imageNamed:@"plus_icon"];
[self displayList:dataSource];
cancelBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(onButtonPressed:)];
self.navigationItem.leftBarButtonItem = cancelBarButtonItem;

View file

@ -211,7 +211,7 @@
[filesSearchViewController displaySearch:filesSearchDataSource];
// Init the search for people
peopleSearchDataSource = [[ContactsDataSource alloc] init];
peopleSearchDataSource = [[ContactsDataSource alloc] initWithMatrixSession:mainSession];
peopleSearchDataSource.areSectionsShrinkable = YES;
peopleSearchDataSource.displaySearchInputInContactsList = YES;
peopleSearchDataSource.contactCellAccessoryType = UITableViewCellAccessoryDisclosureIndicator;

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<?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">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -64,8 +64,7 @@
<rect key="frame" x="550" y="0.0" width="46" height="46"/>
<accessibility key="accessibilityConfiguration" identifier="SendButton"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="44" id="KnT-92-5v2"/>
<constraint firstAttribute="width" constant="46" id="Moy-iD-5A4"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="46" id="KnT-92-5v2"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
<state key="normal" title="Send"/>