Merge pull request #28 from vector-im/room_photo_selection

Room photo selection

Improve the room settings page
-> add the room photo management 
-> display if a room is public or private
-> enable / disable the room notification

Else
Improve the room naming.
This commit is contained in:
Yannick LE COLLEN 2015-12-17 12:05:20 +01:00
commit 27690a4333
20 changed files with 1125 additions and 70 deletions

View file

@ -25,9 +25,15 @@
717928481C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 717928411C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.xib */; };
717928491C03852C00407D96 /* TableViewCellWithLabelAndTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 717928431C03852C00407D96 /* TableViewCellWithLabelAndTextField.m */; };
7179284A1C03852C00407D96 /* TableViewCellWithLabelAndTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = 717928441C03852C00407D96 /* TableViewCellWithLabelAndTextField.xib */; };
71B2A3BB1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2A3B91C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.m */; };
71B2A3BC1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 71B2A3BA1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.xib */; };
71B2A3C01C203C7100472061 /* TableViewCellWithLabelAndSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2A3BE1C203C7100472061 /* TableViewCellWithLabelAndSwitch.m */; };
71B2A3C11C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib in Resources */ = {isa = PBXBuildFile; fileRef = 71B2A3BF1C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib */; };
71C5F2951C074ACC004C094B /* RoomSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71C5F2941C074ACC004C094B /* RoomSettingsViewController.m */; };
71EBE66D1C04C4D300E7D953 /* RoomActivitiesView.m in Sources */ = {isa = PBXBuildFile; fileRef = 71EBE66B1C04C4D300E7D953 /* RoomActivitiesView.m */; };
71EBE66E1C04C4D300E7D953 /* RoomActivitiesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 71EBE66C1C04C4D300E7D953 /* RoomActivitiesView.xib */; };
71F7F5151C218D8900E7ED8F /* RecentCellData.m in Sources */ = {isa = PBXBuildFile; fileRef = 71F7F5141C218D8900E7ED8F /* RecentCellData.m */; };
71F7F5181C22CC7500E7ED8F /* MXRoom+Vector.m in Sources */ = {isa = PBXBuildFile; fileRef = 71F7F5171C22CC7500E7ED8F /* MXRoom+Vector.m */; };
F001D7621B8207C000A162C3 /* RoomInputToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = F001D75C1B8207C000A162C3 /* RoomInputToolbarView.m */; };
F001D7631B8207C000A162C3 /* RoomInputToolbarView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F001D75D1B8207C000A162C3 /* RoomInputToolbarView.xib */; };
F001D76C1B821E4F00A162C3 /* MediaPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F001D76B1B821E4F00A162C3 /* MediaPickerViewController.m */; };
@ -188,12 +194,22 @@
717928421C03852C00407D96 /* TableViewCellWithLabelAndTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableViewCellWithLabelAndTextField.h; path = TableViewCell/TableViewCellWithLabelAndTextField.h; sourceTree = "<group>"; };
717928431C03852C00407D96 /* TableViewCellWithLabelAndTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableViewCellWithLabelAndTextField.m; path = TableViewCell/TableViewCellWithLabelAndTextField.m; sourceTree = "<group>"; };
717928441C03852C00407D96 /* TableViewCellWithLabelAndTextField.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TableViewCellWithLabelAndTextField.xib; path = TableViewCell/TableViewCellWithLabelAndTextField.xib; sourceTree = "<group>"; };
71B2A3B81C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableViewCellWithLabelAndMXKImageView.h; path = TableViewCell/TableViewCellWithLabelAndMXKImageView.h; sourceTree = "<group>"; };
71B2A3B91C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableViewCellWithLabelAndMXKImageView.m; path = TableViewCell/TableViewCellWithLabelAndMXKImageView.m; sourceTree = "<group>"; };
71B2A3BA1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TableViewCellWithLabelAndMXKImageView.xib; path = TableViewCell/TableViewCellWithLabelAndMXKImageView.xib; sourceTree = "<group>"; };
71B2A3BD1C203C7100472061 /* TableViewCellWithLabelAndSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableViewCellWithLabelAndSwitch.h; path = TableViewCell/TableViewCellWithLabelAndSwitch.h; sourceTree = "<group>"; };
71B2A3BE1C203C7100472061 /* TableViewCellWithLabelAndSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableViewCellWithLabelAndSwitch.m; path = TableViewCell/TableViewCellWithLabelAndSwitch.m; sourceTree = "<group>"; };
71B2A3BF1C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TableViewCellWithLabelAndSwitch.xib; path = TableViewCell/TableViewCellWithLabelAndSwitch.xib; sourceTree = "<group>"; };
71C5F2931C074ACC004C094B /* RoomSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomSettingsViewController.h; sourceTree = "<group>"; };
71C5F2941C074ACC004C094B /* RoomSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomSettingsViewController.m; sourceTree = "<group>"; };
71C5F2991C077007004C094B /* VectorDesignValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VectorDesignValues.h; sourceTree = "<group>"; };
71EBE66A1C04C4D300E7D953 /* RoomActivitiesView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RoomActivitiesView.h; path = RoomActivitiesView/RoomActivitiesView.h; sourceTree = "<group>"; };
71EBE66B1C04C4D300E7D953 /* RoomActivitiesView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RoomActivitiesView.m; path = RoomActivitiesView/RoomActivitiesView.m; sourceTree = "<group>"; };
71EBE66C1C04C4D300E7D953 /* RoomActivitiesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RoomActivitiesView.xib; path = RoomActivitiesView/RoomActivitiesView.xib; sourceTree = "<group>"; };
71F7F5131C218D8900E7ED8F /* RecentCellData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentCellData.h; sourceTree = "<group>"; };
71F7F5141C218D8900E7ED8F /* RecentCellData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCellData.m; sourceTree = "<group>"; };
71F7F5161C22CC7500E7ED8F /* MXRoom+Vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MXRoom+Vector.h"; sourceTree = "<group>"; };
71F7F5171C22CC7500E7ED8F /* MXRoom+Vector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MXRoom+Vector.m"; sourceTree = "<group>"; };
9B179239B79688A61A3F465F /* libPods-Vector.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Vector.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F001D75B1B8207C000A162C3 /* RoomInputToolbarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomInputToolbarView.h; sourceTree = "<group>"; };
F001D75C1B8207C000A162C3 /* RoomInputToolbarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomInputToolbarView.m; sourceTree = "<group>"; };
@ -402,9 +418,15 @@
7179283C1C03852C00407D96 /* TableViewCellSeparator.h */,
7179283D1C03852C00407D96 /* TableViewCellSeparator.m */,
7179283E1C03852C00407D96 /* TableViewCellSeparator.xib */,
71B2A3BD1C203C7100472061 /* TableViewCellWithLabelAndSwitch.h */,
71B2A3BE1C203C7100472061 /* TableViewCellWithLabelAndSwitch.m */,
71B2A3BF1C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib */,
7179283F1C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.h */,
717928401C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.m */,
717928411C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.xib */,
71B2A3B81C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.h */,
71B2A3B91C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.m */,
71B2A3BA1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.xib */,
717928421C03852C00407D96 /* TableViewCellWithLabelAndTextField.h */,
717928431C03852C00407D96 /* TableViewCellWithLabelAndTextField.m */,
717928441C03852C00407D96 /* TableViewCellWithLabelAndTextField.xib */,
@ -514,6 +536,8 @@
F00C47881BFF854400DBABC9 /* RoomList */ = {
isa = PBXGroup;
children = (
71F7F5131C218D8900E7ED8F /* RecentCellData.h */,
71F7F5141C218D8900E7ED8F /* RecentCellData.m */,
F00C47891BFF854400DBABC9 /* RecentsDataSource.h */,
F00C478A1BFF854400DBABC9 /* RecentsDataSource.m */,
);
@ -697,6 +721,8 @@
F0C34CB51C17145F00C36F09 /* Categories */ = {
isa = PBXGroup;
children = (
71F7F5161C22CC7500E7ED8F /* MXRoom+Vector.h */,
71F7F5171C22CC7500E7ED8F /* MXRoom+Vector.m */,
F0C34CB61C17145F00C36F09 /* MXKRoomBubbleTableViewCell+Vector.h */,
F0C34CB71C17145F00C36F09 /* MXKRoomBubbleTableViewCell+Vector.m */,
);
@ -858,6 +884,7 @@
F02528D91C11B6FC00E1FE1B /* camera_play.png in Resources */,
F0D2D9881C197DCB007B8C96 /* RoomIncomingTextMsgBubbleCell.xib in Resources */,
F02529001C11B6FC00E1FE1B /* settings_icon.png in Resources */,
71B2A3BC1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.xib in Resources */,
F02528D81C11B6FC00E1FE1B /* camera_picture.png in Resources */,
F02528E01C11B6FC00E1FE1B /* create_room.png in Resources */,
F02528DF1C11B6FC00E1FE1B /* camera_video.png in Resources */,
@ -890,6 +917,7 @@
F0C34B641C15C28300C36F09 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib in Resources */,
F02528D61C11B6FC00E1FE1B /* camera_capture@2x.png in Resources */,
71046D601C0C86C600DCA984 /* RoomTitleViewWithTopic.xib in Resources */,
71B2A3C11C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib in Resources */,
F02528D51C11B6FC00E1FE1B /* camera_capture.png in Resources */,
F02528EA1C11B6FC00E1FE1B /* low_priority_icon@2x.png in Resources */,
F02528EE1C11B6FC00E1FE1B /* mute_icon@3x.png in Resources */,
@ -1022,6 +1050,7 @@
F094AA051B78E3D400B1FBBF /* empty.mm in Sources */,
F0A1CD221B9F4BBA00F9C15C /* RoomParticipantsViewController.m in Sources */,
F001D76C1B821E4F00A162C3 /* MediaPickerViewController.m in Sources */,
71F7F5151C218D8900E7ED8F /* RecentCellData.m in Sources */,
F084DAAE1BB57BD100B4C530 /* AuthInputsEmailIdentityBasedView.m in Sources */,
71352D591C10569F001D50B0 /* AvatarGenerator.m in Sources */,
717928471C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.m in Sources */,
@ -1030,6 +1059,7 @@
7165A25B1C05CD42003635D7 /* SegmentedViewController.m in Sources */,
F094AA321B78E42600B1FBBF /* GlobalNotificationSettingsViewController.m in Sources */,
F094A9A81B78D8F000B1FBBF /* main.m in Sources */,
71B2A3C01C203C7100472061 /* TableViewCellWithLabelAndSwitch.m in Sources */,
F00C47861BFF77C800DBABC9 /* RecentTableViewCell.m in Sources */,
F0DD7D881B7B507100C4BE02 /* RoomCreationStep2ViewController.m in Sources */,
71352D651C10A265001D50B0 /* Contact.m in Sources */,
@ -1039,6 +1069,7 @@
F094AA351B78E42600B1FBBF /* RecentsViewController.m in Sources */,
F08BE09E1B87025B00C480FB /* EventFormatter.m in Sources */,
F05895001B8B7E6600B73E85 /* RoomBubbleCellData.m in Sources */,
71F7F5181C22CC7500E7ED8F /* MXRoom+Vector.m in Sources */,
F0D2D9831C197DCB007B8C96 /* RoomIncomingAttachmentBubbleCell.m in Sources */,
F0C34B611C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.m in Sources */,
71C5F2951C074ACC004C094B /* RoomSettingsViewController.m in Sources */,
@ -1048,6 +1079,7 @@
F08BE0A21B87064000C480FB /* RoomDataSource.m in Sources */,
716FDC8A1C186A3A001034CB /* InviteRecentTableViewCell.m in Sources */,
F0C34CB31C16269D00C36F09 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */,
71B2A3BB1C2013DC00472061 /* TableViewCellWithLabelAndMXKImageView.m in Sources */,
F0D2D9851C197DCB007B8C96 /* RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
71046D5E1C0C639300DCA984 /* RoomTitleViewWithTopic.m in Sources */,
F0C34B631C15C28300C36F09 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */,

View file

@ -132,12 +132,17 @@
// Room Details
"room_details_title" = "Room Details";
"room_details_mute_notifs" = "Mute notifications";
"room_details_photo" = "Photo";
"room_details_room_name" = "Room Name";
"room_details_topic" = "Topic";
"room_details_people" = "People";
"room_details_settings" = "Settings";
"room_details_fail_to_update_topic" = "Fail to update the topic";
"room_details_fail_to_update_room_name" = "Fail to update the room name";
"room_details_with_updates" = "The updates will be lost : are you sure to leave ?";
"room_details_room_is_public" = "This room is public";
"room_details_room_is_private" = "This room is private";
"notification_settings_global_notification_settings" = "Global Notification Settings";
@ -157,4 +162,11 @@
"public_room_section_title" = "Public Rooms (at %@):";
"bug_report_prompt" = "The application has crashed last time. Would you like to submit a crash report?";
"rage_shake_prompt" = "You seem to be shaking the phone in frustration. Would you like to submit a bug report?";
"camera_access_not_granted" = "Vector doesn't have permission to use Camera, please change privacy settings";
"camera_access_not_granted" = "Vector doesn't have permission to use Camera, please change privacy settings";
// room display name
"room_displayname_invite_from" = "Invite from %@";
"room_displayname_room_invite" = "Room Invite";
"room_displayname_two_members" = "%@ and %@";
"room_displayname_more_than_two_members" = "%@ and %u others";

View file

@ -0,0 +1,58 @@
/*
Copyright 2015 OpenMarket 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 <MatrixKit/MatrixKit.h>
/**
Define a `MXRoom` category at Vector level.
*/
@interface MXRoom (Vector)
/**
Returns YES if there is an push rule to disable the notifications for this room.
*/
@property(nonatomic, readonly) BOOL areRoomNotificationsMuted;
/**
Returns YES if the oneself user is a moderator i.e. he is allowed to update the room name or the avatar..
*/
@property(nonatomic, readonly) BOOL isModerator;
/**
Returns the vector displayname.
*/
@property(nonatomic, readonly) NSString* vectorDisplayname;
/**
Toggle a room rule notifications.
@param mute YES to disable room notification
@return the dedicated push rule
*/
- (void)toggleRoomNotifications:(BOOL)mute;
/**
Set the room avatar in the dedicated MXKImageView.
The vector style implies to use in order :
1 - the default avatar if there is one
2 - the member avatar for < 3 members rooms
3 - the first later of the room name.
@param mxkImageView the destinated MXKImageView.
*/
- (void)setRoomAvatarImageIn:(MXKImageView*)mxkImageView;
@end

View file

@ -0,0 +1,373 @@
/*
Copyright 2015 OpenMarket 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 "MXRoom+Vector.h"
#import "AvatarGenerator.h"
@interface MXRoom ()
// create property for the extensions
// rule events observer
@property id notificationCenterDidFailObserver;
@property id notificationCenterDidUpdateObserver;
@end
@implementation MXRoom (Vector)
/**
Returns the room rule notifition.
@return the dedicated push rule
*/
- (MXPushRule*)getRoomPushRule
{
NSArray* rules = self.mxSession.notificationCenter.rules.global.room;
// sanity checks
if (rules)
{
for(MXPushRule* rule in rules)
{
// the rule id is the room Id
// it is the server trick to avoid duplicated rule on the same room.
if ([rule.ruleId isEqualToString:self.state.roomId])
{
return rule;
}
}
}
return nil;
}
- (BOOL)areRoomNotificationsMuted
{
MXPushRule* rule = [self getRoomPushRule];
if (rule)
{
for (MXPushRuleAction *ruleAction in rule.actions)
{
if (ruleAction.actionType == MXPushRuleActionTypeDontNotify)
{
return rule.enabled;
}
}
}
return NO;
}
- (BOOL)isModerator
{
// Check whether the user has enough power to rename the room or update the avatar
MXRoomPowerLevels *powerLevels = [self.state powerLevels];
NSUInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxSession.myUser.userId];
return (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName]);
}
- (void)toggleRoomNotifications:(BOOL)mute
{
BOOL isNotified = ![self areRoomNotificationsMuted];
// check if the state is already in the right state
if (isNotified == !mute)
{
return;
}
MXNotificationCenter* notificationCenter = self.mxSession.notificationCenter;
MXPushRule* rule = [self getRoomPushRule];
if (!mute)
{
// let the other notification rules manage the pushes.
[notificationCenter removeRule:rule];
}
else
{
// user does not want to have push
// if there is no rule
if (!rule)
{
// add one
[notificationCenter addRoomRule:self.state.roomId
notify:NO
sound:NO
highlight:NO];
}
else
{
// check if the user did not define one
BOOL hasDontNotifyRule = NO;
for (MXPushRuleAction *ruleAction in rule.actions)
{
if (ruleAction.actionType == MXPushRuleActionTypeDontNotify)
{
hasDontNotifyRule = YES;
break;
}
}
// if the user defined one, use it
if (hasDontNotifyRule)
{
[notificationCenter enableRule:rule isEnabled:YES];
}
else
{
__weak typeof(self) weakSelf = self;
// if the user defined a room rule
// the rule is deleted before adding new one
id localNotificationCenterDidUpdateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterDidUpdateRules object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
MXPushRule* rule = [self getRoomPushRule];
// check if the rule has been deleted
// there is no way to know if the notif is really for this rule..
if (!rule)
{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf.notificationCenterDidUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:strongSelf.notificationCenterDidUpdateObserver];
strongSelf.notificationCenterDidUpdateObserver = nil;
}
if (strongSelf.notificationCenterDidFailObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:strongSelf.notificationCenterDidUpdateObserver];
strongSelf.notificationCenterDidUpdateObserver = nil;
}
// add one dedicated rule
[notificationCenter addRoomRule:self.state.roomId
notify:NO
sound:NO
highlight:NO];
}
}];
id localNotificationCenterDidFailObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXNotificationCenterDidFailRulesUpdate object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf.notificationCenterDidUpdateObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:strongSelf.notificationCenterDidUpdateObserver];
strongSelf.notificationCenterDidUpdateObserver = nil;
}
if (strongSelf.notificationCenterDidFailObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:strongSelf.notificationCenterDidUpdateObserver];
strongSelf.notificationCenterDidUpdateObserver = nil;
}
}];
self.notificationCenterDidUpdateObserver = localNotificationCenterDidUpdateObserver;
self.notificationCenterDidFailObserver = localNotificationCenterDidFailObserver;
// remove the rule notification
// the notifications are used to tell
[notificationCenter removeRule:rule];
}
}
}
}
- (void)setRoomAvatarImageIn:(MXKImageView*)mxkImageView
{
NSString* roomAvatarUrl = self.state.avatar;
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
if (!roomAvatarUrl)
{
NSString* myUserId = self.mxSession.myUser.userId;
NSArray* members = self.state.members;
if (members.count < 3)
{
// use the member avatar only it is an active member
for (MXRoomMember *roomMember in members)
{
if ((MXMembershipJoin == roomMember.membership) && ((members.count == 1) || ![roomMember.userId isEqualToString:myUserId]))
{
roomAvatarUrl = roomMember.avatarUrl;
break;
}
}
}
}
UIImage* avatarImage = [AvatarGenerator generateRoomAvatar:self];
if (roomAvatarUrl)
{
mxkImageView.enableInMemoryCache = YES;
[mxkImageView setImageURL:[self.mxSession.matrixRestClient urlOfContentThumbnail:roomAvatarUrl toFitViewSize:mxkImageView.frame.size withMethod:MXThumbnailingMethodCrop] withType:nil andImageOrientation:UIImageOrientationUp previewImage:avatarImage];
}
else
{
mxkImageView.image = avatarImage;
}
mxkImageView.contentMode = UIViewContentModeScaleAspectFill;
}
- (NSString *)vectorDisplayname
{
// this algo is the one defined in
// https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617
// calculateRoomName(room, userId)
MXRoomState* roomState = self.state;
if (roomState.name.length > 0)
{
return roomState.name;
}
NSString *alias = roomState.canonicalAlias;
if (!alias)
{
// For rooms where canonical alias is not defined, we use the 1st alias as a workaround
NSArray *aliases = roomState.aliases;
if (aliases.count)
{
alias = [aliases[0] copy];
}
}
if (alias)
{
return alias;
}
NSString* myUserId = self.mxSession.myUser.userId;
NSArray* members = roomState.members;
NSMutableArray* othersActiveMembers = [[NSMutableArray alloc] init];
NSMutableArray* activeMembers = [[NSMutableArray alloc] init];
for(MXRoomMember* member in members)
{
if (member.membership != MXMembershipLeave)
{
if (![member.userId isEqualToString:myUserId])
{
[othersActiveMembers addObject:member];
}
[activeMembers addObject:member];
}
}
// sort the members by their creation (oldest first)
othersActiveMembers = [[othersActiveMembers sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
uint64_t originServerTs1 = 0;
uint64_t originServerTs2 = 0;
MXRoomMember* member1 = (MXRoomMember*)obj1;
MXRoomMember* member2 = (MXRoomMember*)obj2;
if (member1.originalEvent)
{
originServerTs1 = member1.originalEvent.originServerTs;
}
if (member2.originalEvent)
{
originServerTs2 = member2.originalEvent.originServerTs;
}
if (originServerTs1 == originServerTs2)
{
return NSOrderedSame;
}
else
{
return originServerTs1 > originServerTs2 ? NSOrderedDescending : NSOrderedAscending;
}
}] mutableCopy];
NSString* displayName = @"";
// TODO: Localisation
if (othersActiveMembers.count == 0)
{
if (activeMembers.count == 1)
{
MXRoomMember* member = [activeMembers objectAtIndex:0];
if (member.membership == MXMembershipInvite)
{
if (member.originalEvent.sender)
{
// extract who invited us to the room
displayName = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_displayname_invite_from", @"Vector", nil), [roomState memberName:member.originalEvent.sender]];
}
else
{
displayName = NSLocalizedStringFromTable(@"room_displayname_room_invite", @"Vector", nil);
}
}
else
{
displayName = myUserId;
}
}
}
else if (othersActiveMembers.count == 1)
{
MXRoomMember* member = [othersActiveMembers objectAtIndex:0];
displayName = [roomState memberName:member.userId];
}
else if (othersActiveMembers.count == 2)
{
MXRoomMember* member1 = [othersActiveMembers objectAtIndex:0];
MXRoomMember* member2 = [othersActiveMembers objectAtIndex:1];
displayName = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_displayname_two_members", @"Vector", nil), [roomState memberName:member1.userId], [roomState memberName:member2.userId]];
}
else
{
MXRoomMember* member = [othersActiveMembers objectAtIndex:0];
displayName = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_displayname_more_than_two_members", @"Vector", nil), [roomState memberName:member.userId], othersActiveMembers.count - 1];
}
return displayName;
}
@end

View file

@ -0,0 +1,26 @@
/*
Copyright 2015 OpenMarket 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 <Foundation/Foundation.h>
#import <MatrixSDK/MatrixSDK.h>
#import "MXKRecentCellData.h"
/**
`RecentCellData` is Vector cuustomized MXKRecentCellData` cell.
*/
@interface RecentCellData : MXKRecentCellData
@end

View file

@ -0,0 +1,32 @@
/*
Copyright 2015 OpenMarket 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 "RecentCellData.h"
#import "MXRoom+Vector.h"
@implementation RecentCellData
// trick to hide the mother class property as it is readonly one.
// self.roomDisplayname returns this value instead of the mother class.
@synthesize roomDisplayname;
- (void)update
{
[super update];
roomDisplayname = self.roomDataSource.room.vectorDisplayname;
}
@end

View file

@ -22,6 +22,10 @@
#import "InviteRecentTableViewCell.h"
#import "MXRoom+Vector.h"
#import "RecentCellData.h"
@interface RecentsDataSource()
{
NSMutableArray* invitesCellDataArray;
@ -62,10 +66,15 @@
sectionsCount = 0;
roomTagsListenerByUserId = [[NSMutableDictionary alloc] init];
// Set default data and view classes
[self registerCellDataClass:RecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier];
}
return self;
}
- (void)removeMatrixSession:(MXSession*)matrixSession
{
[super removeMatrixSession:matrixSession];
@ -109,6 +118,28 @@
}
}
- (BOOL)isRoomNotifiedAtIndexPath:(NSIndexPath *)indexPath
{
MXRoom* room = [self getRoomAtIndexPath:indexPath];
if (room)
{
return !room.areRoomNotificationsMuted;
}
return YES;
}
- (void)muteRoomNotifications:(BOOL)mute atIndexPath:(NSIndexPath *)indexPath
{
MXRoom* room = [self getRoomAtIndexPath:indexPath];
// sanity check
if (room)
{
[room toggleRoomNotifications:mute];
}
}
- (void)refreshRoomsSectionsAndReload
{

View file

@ -16,6 +16,8 @@
#import "AvatarGenerator.h"
#import "MXRoom+Vector.h"
@implementation AvatarGenerator
static NSMutableDictionary *imageByKeyDict = nil;
@ -156,7 +158,7 @@ static UILabel* backgroundLabel = nil;
// if the displayname is the userID
// skip the @
if (!displayname && [text hasPrefix:@"@"])
if (!displayname && ([text hasPrefix:@"@"] || [text hasPrefix:@"#"]))
{
text = [text substringFromIndex:1];
}
@ -176,7 +178,7 @@ static UILabel* backgroundLabel = nil;
*/
+ (UIImage*)generateRoomAvatar:(MXRoom*)room
{
NSString* displayName = room.state.displayname;
NSString* displayName = room.vectorDisplayname;
NSString* roomId = room.state.roomId;
// the selected color is based on the roomId
@ -184,7 +186,7 @@ static UILabel* backgroundLabel = nil;
NSString* text = displayName;
// ignore the first #
if ([text hasPrefix:@"#"])
if ([text hasPrefix:@"#"] || [text hasPrefix:@"@"])
{
text = [text substringFromIndex:1];
}

View file

@ -325,11 +325,18 @@ static NSMutableDictionary* backgroundByImageNameDict;
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray* actions = [[NSMutableArray alloc] init];
MXRoom* room = [self.dataSource getRoomAtIndexPath:indexPath];
if (room)
{
NSArray* invitedRooms = room.mxSession.invitedRooms;
// display no action for the invited room
if (invitedRooms && ([invitedRooms indexOfObject:room] != NSNotFound))
{
return actions;
}
NSString* title = @" ";
// pushes settings

View file

@ -16,7 +16,9 @@
#import <MatrixKit/MatrixKit.h>
@interface RoomSettingsViewController : MXKRoomSettingsViewController<UITextViewDelegate>
#import "MediaPickerViewController.h"
@interface RoomSettingsViewController : MXKRoomSettingsViewController<UITextViewDelegate, MediaPickerViewControllerDelegate>
@end

View file

@ -16,19 +16,32 @@
#import "RoomSettingsViewController.h"
#import <Photos/Photos.h>
#import <MediaPlayer/MediaPlayer.h>
#import "TableViewCellWithLabelAndTextField.h"
#import "TableViewCellWithLabelAndLargeTextView.h"
#import "TableViewCellWithLabelAndMXKImageView.h"
#import "TableViewCellWithLabelAndSwitch.h"
#import "TableViewCellSeparator.h"
#import "RageShakeManager.h"
#import "VectorDesignValues.h"
#import "AvatarGenerator.h"
#import "MXRoom+Vector.h"
#define ROOM_SECTION 0
#define ROOM_SECTION_NAME 0
#define ROOM_SECTION_TOPIC 1
#define ROOM_SECTION_COUNT 2
#define ROOM_SECTION_PHOTO 0
#define ROOM_SECTION_NAME 1
#define ROOM_SECTION_TOPIC 2
#define ROOM_SECTION_PRIV_PUB 3
#define ROOM_SECTION_MUTE_NOTIFICATIONS 4
#define ROOM_SECTION_COUNT 5
#define ROOM_TOPIC_CELL_HEIGHT 99
@ -48,6 +61,15 @@
UIActivityIndicatorView* updatingSpinner;
MXKAlert *currentAlert;
// listen to more events than the mother class
id extraEventsListener;
// picker
MediaPickerViewController* mediaPicker;
// switches
UISwitch *roomNotifSwitch;
}
@end
@ -93,6 +115,8 @@
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didMXSessionStateChange:) name:kMXSessionStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateRules:) name:kMXNotificationCenterDidUpdateRules object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didAccountUserInfoDidChange:) name:kMXKAccountUserInfoDidChangeNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
@ -101,6 +125,8 @@
[self dismissFirstResponder];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXNotificationCenterDidUpdateRules object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXKAccountUserInfoDidChangeNotification object:nil];
}
// this method is called when the viewcontroller is displayed inside another one.
@ -150,16 +176,19 @@
- (void)showUpdatingSpinner
{
self.tableView.userInteractionEnabled = NO;
// Add a spinner
updatingSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
updatingSpinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
updatingSpinner.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
updatingSpinner.hidesWhenStopped = NO;
[updatingSpinner startAnimating];
updatingSpinner.center = self.view.center;
[self.view addSubview:updatingSpinner];
if (!updatingSpinner)
{
self.tableView.userInteractionEnabled = NO;
// Add a spinner
updatingSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
updatingSpinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
updatingSpinner.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
updatingSpinner.hidesWhenStopped = NO;
[updatingSpinner startAnimating];
updatingSpinner.center = self.view.center;
[self.view addSubview:updatingSpinner];
}
}
- (void)hideUpdatingSpinner
@ -232,10 +261,38 @@
}
}
- (void)didUpdateRules:(NSNotification *)notif
{
[self.tableView reloadData];
}
- (void)didAccountUserInfoDidChange:(NSNotification *)notif
{
[self.tableView reloadData];
}
- (IBAction)onCancel:(id)sender
{
// warn if there is a pending update ?
[self.navigationController popViewControllerAnimated:YES];
// if there are some updated fields
if (updatedItemsDict && (updatedItemsDict.count > 0))
{
// ensure that the user understands that the updates will be lost if
MXKAlert* alert = [[MXKAlert alloc] initWithTitle:nil message:NSLocalizedStringFromTable(@"room_details_with_updates", @"Vector", nil) style:MXKAlertStyleAlert];
[alert addActionWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:MXKAlertActionStyleCancel handler:^(MXKAlert *alert) {
[self.navigationController popViewControllerAnimated:YES];
}];
[alert addActionWithTitle:NSLocalizedStringFromTable(@"save", @"Vector", nil) style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
[self onSave:nil];
}];
[alert showInViewController:self];
}
else
{
[self.navigationController popViewControllerAnimated:YES];
}
}
- (void)onSaveFailed:(NSString*)message withKey:(NSString*)key
@ -274,9 +331,60 @@
- (IBAction)onSave:(id)sender
{
[self showUpdatingSpinner];
// check if there is some update
if (mxRoomState && updatedItemsDict && (updatedItemsDict.count > 0))
{
if ([updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO"])
{
// Retrieve the current picture and make sure its orientation is up
UIImage *updatedPicture = [MXKTools forceImageOrientationUp:[updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO"]];
// Upload picture
MXKMediaLoader *uploader = [MXKMediaManager prepareUploaderWithMatrixSession:mxRoom.mxSession initialRange:0 andRange:1.0];
[uploader uploadData:UIImageJPEGRepresentation(updatedPicture, 0.5) filename:nil mimeType:@"image/jpeg" success:^(NSString *url)
{
[updatedItemsDict removeObjectForKey:@"ROOM_SECTION_PHOTO"];
[updatedItemsDict setObject:url forKey:@"ROOM_SECTION_PHOTO_URL"];
[self onSave:nil];
} failure:^(NSError *error)
{
NSLog(@"[Vector RoomSettingsViewController] Failed to upload image: %@", error);
[updatedItemsDict removeObjectForKey:@"ROOM_SECTION_PHOTO"];
[self onSave:nil];
}];
return;
}
if ([updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO_URL"])
{
__weak typeof(self) weakSelf = self;
NSString* photoUrl = [updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO_URL"];
[mxRoom setAvatar:photoUrl success:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf->updatedItemsDict removeObjectForKey:@"ROOM_SECTION_PHOTO_URL"];
[strongSelf onSave:nil];
} failure:^(NSError *error) {
NSLog(@"[Vector RoomSettingsViewController] Failed to update the room avatar %@", error);
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf->updatedItemsDict removeObjectForKey:@"ROOM_SECTION_PHOTO_URL"];
[strongSelf onSave:nil];
}];
return;
}
// has a new room name
if ([updatedItemsDict objectForKey:@"ROOM_SECTION_NAME"])
{
@ -284,7 +392,6 @@
if (![newName isEqualToString:mxRoomState.name])
{
[self showUpdatingSpinner];
__weak typeof(self) weakSelf = self;
pendingOperation = [mxRoom setName:newName success:^{
@ -319,7 +426,6 @@
if (![newTopic isEqualToString:mxRoomState.topic])
{
[self showUpdatingSpinner];
__weak typeof(self) weakSelf = self;
pendingOperation = [mxRoom setTopic:newTopic success:^{
@ -348,6 +454,15 @@
}
}
if ([updatedItemsDict objectForKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"])
{
[mxRoom toggleRoomNotifications:roomNotifSwitch.on];
[updatedItemsDict removeObjectForKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"];
[self onSave:nil];
}
[self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0);
[self hideUpdatingSpinner];
[self.navigationController popViewControllerAnimated:YES];
@ -430,7 +545,63 @@
// retrieve row as a ROOM_SECTION_XX index
row = (row - 1) / 2;
if (row == ROOM_SECTION_TOPIC)
if (row == ROOM_SECTION_MUTE_NOTIFICATIONS)
{
TableViewCellWithLabelAndSwitch *roomNotifCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithLabelAndSwitch defaultReuseIdentifier]];
if (!roomNotifCell)
{
roomNotifCell = [[TableViewCellWithLabelAndSwitch alloc] init];
[roomNotifCell.mxkSwitch addTarget:self action:@selector(onSwitchUpdate:) forControlEvents:UIControlEventValueChanged];
roomNotifCell.mxkSwitch.onTintColor = VECTOR_GREEN_COLOR;
}
roomNotifCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_mute_notifs", @"Vector", nil);
roomNotifSwitch = roomNotifCell.mxkSwitch;
if (updatedItemsDict && [updatedItemsDict objectForKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"])
{
roomNotifSwitch.on = ((NSNumber*)[updatedItemsDict objectForKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"]).boolValue;
}
else
{
roomNotifSwitch.on = mxRoom.areRoomNotificationsMuted;
}
cell = roomNotifCell;
}
else if (row == ROOM_SECTION_PHOTO)
{
TableViewCellWithLabelAndMXKImageView *roomPhotoCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithLabelAndMXKImageView defaultReuseIdentifier]];
if (!roomPhotoCell)
{
roomPhotoCell = [[TableViewCellWithLabelAndMXKImageView alloc] init];
// tap on avatar to update it
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onRoomAvatarTap:)];
[roomPhotoCell.mxkImageView addGestureRecognizer:tap];
}
roomPhotoCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_photo", @"Vector", nil);
if (updatedItemsDict && [updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO"])
{
roomPhotoCell.mxkImageView.image = (UIImage*)[updatedItemsDict objectForKey:@"ROOM_SECTION_PHOTO"];
}
else
{
[mxRoom setRoomAvatarImageIn:roomPhotoCell.mxkImageView];
roomPhotoCell.mxkImageView.alpha = mxRoom.isModerator ? 1.0f : 0.5f;
}
[roomPhotoCell.mxkImageView.layer setCornerRadius:roomPhotoCell.mxkImageView.frame.size.width / 2];
roomPhotoCell.mxkImageView.clipsToBounds = YES;
roomPhotoCell.userInteractionEnabled = mxRoom.isModerator;
cell = roomPhotoCell;
}
else if (row == ROOM_SECTION_TOPIC)
{
TableViewCellWithLabelAndLargeTextView *roomTopicCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithLabelAndLargeTextView defaultReuseIdentifier]];
@ -460,8 +631,8 @@
roomTopicCell.mxkTextView.delegate = self;
// disable the edition if the user cannoy update it
roomTopicCell.mxkTextView.editable = isSuperUser;
roomTopicCell.mxkTextView.textColor = isSuperUser ? [UIColor blackColor] : [UIColor lightGrayColor];
roomTopicCell.mxkTextView.editable = mxRoom.isModerator;
roomTopicCell.mxkTextView.textColor = mxRoom.isModerator ? [UIColor blackColor] : [UIColor lightGrayColor];
cell = roomTopicCell;
}
@ -492,13 +663,28 @@
nameTextField = roomNameCell.mxkTextField;
// disable the edition if the user cannoy update it
roomNameCell.editable = isSuperUser;
roomNameCell.mxkTextField.textColor = isSuperUser ? [UIColor blackColor] : [UIColor lightGrayColor];
roomNameCell.editable = mxRoom.isModerator;
roomNameCell.mxkTextField.textColor = mxRoom.isModerator ? [UIColor blackColor] : [UIColor lightGrayColor];
// Add a "textFieldDidChange" notification method to the text field control.
[roomNameCell.mxkTextField addTarget:self action:@selector(onTextFieldUpdate:) forControlEvents:UIControlEventEditingChanged];
}
else if (row == ROOM_SECTION_PRIV_PUB)
{
TableViewCellWithLabelAndTextField *privPublicCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithLabelAndTextField defaultReuseIdentifier]];
if (!privPublicCell)
{
privPublicCell = [[TableViewCellWithLabelAndTextField alloc] init];
}
privPublicCell.mxkTextField.userInteractionEnabled = NO;
privPublicCell.mxkTextField.text = @"";
privPublicCell.mxkLabel.text = mxRoom.state.isPublic ? NSLocalizedStringFromTable(@"room_details_room_is_public", @"Vector", nil) : NSLocalizedStringFromTable(@"room_details_room_is_private", @"Vector", nil);
cell = privPublicCell;
}
}
return cell;
@ -509,14 +695,124 @@
if (self.tableView == aTableView)
{
[self dismissFirstResponder];
if (indexPath.section == ROOM_SECTION)
{
NSUInteger row = indexPath.row;
// the even views are the line separator
if ((row % 2) == 0)
{
return;
}
// retrieve row as a ROOM_SECTION_XX index
row = (row - 1) / 2;
if (row == ROOM_SECTION_PHOTO)
{
[self onRoomAvatarTap:nil];
}
}
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
#pragma mark - MediaPickerViewController Delegate
- (void)dismissMediaPicker
{
if (scrollView == self.tableView)
if (mediaPicker)
{
[self dismissFirstResponder];
[mediaPicker withdrawViewControllerAnimated:YES completion:nil];
mediaPicker = nil;
}
}
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectImage:(UIImage*)image withURL:(NSURL *)imageURL
{
[self dismissMediaPicker];
if (image)
{
[self getNavigationItem].rightBarButtonItem.enabled = YES;
NSMutableDictionary* dict = [self getUpdatedItemsDict];
[dict setObject:image forKey:@"ROOM_SECTION_PHOTO"];
[self.tableView reloadData];
}
}
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(NSURL*)videoURL isCameraRecording:(BOOL)isCameraRecording
{
// this method should not be called
[self dismissMediaPicker];
}
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectAssets:(NSArray *)assets
{
if (assets.count > 0)
{
PHAsset* asset = [assets objectAtIndex:0];
PHContentEditingInputRequestOptions *editOptions = [[PHContentEditingInputRequestOptions alloc] init];
[asset requestContentEditingInputWithOptions:editOptions
completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
if (contentEditingInput.mediaType == PHAssetMediaTypeImage)
{
// Here the fullSizeImageURL is related to a local file path
NSData *data = [NSData dataWithContentsOfURL:contentEditingInput.fullSizeImageURL];
UIImage *image = [UIImage imageWithData:data];
if (image)
{
[self getNavigationItem].rightBarButtonItem.enabled = YES;
NSMutableDictionary* dict = [self getUpdatedItemsDict];
[dict setObject:image forKey:@"ROOM_SECTION_PHOTO"];
[self.tableView reloadData];
}
}
}];
}
[self dismissMediaPicker];
}
#pragma mark - actions
- (void)onRoomAvatarTap:(UITapGestureRecognizer *)recognizer
{
mediaPicker = [MediaPickerViewController mediaPickerViewController];
mediaPicker.mediaTypes = @[(NSString *)kUTTypeImage];
mediaPicker.multipleSelections = NO;
mediaPicker.selectionButtonCustomLabel = NSLocalizedStringFromTable(@"media_picker_attach", @"Vector", nil);
mediaPicker.delegate = self;
UINavigationController *navigationController = [UINavigationController new];
[navigationController pushViewController:mediaPicker animated:NO];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)onSwitchUpdate:(UISwitch*)uiSwitch
{
if (uiSwitch == roomNotifSwitch)
{
NSMutableDictionary* dict = [self getUpdatedItemsDict];
if (roomNotifSwitch.on == mxRoom.areRoomNotificationsMuted)
{
[dict removeObjectForKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"];
}
else
{
[dict setObject:[NSNumber numberWithBool:roomNotifSwitch.on] forKey:@"ROOM_SECTION_MUTE_NOTIFICATIONS"];
}
[self getNavigationItem].rightBarButtonItem.enabled = (dict.count != 0);
[self.tableView reloadData];
}
}

View file

@ -24,6 +24,9 @@
#import "AvatarGenerator.h"
#import <Photos/Photos.h>
#import <MediaPlayer/MediaPlayer.h>
#define SETTINGS_SECTION_SIGN_OUT_INDEX 0
#define SETTINGS_SECTION_USER_SETTINGS_INDEX 1
#define SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX 2
@ -1001,7 +1004,26 @@
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectAssets:(NSArray *)assets
{
// this method should not be called
if (assets.count > 0)
{
PHAsset* asset = [assets objectAtIndex:0];
PHContentEditingInputRequestOptions *editOptions = [[PHContentEditingInputRequestOptions alloc] init];
[asset requestContentEditingInputWithOptions:editOptions
completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
if (contentEditingInput.mediaType == PHAssetMediaTypeImage)
{
// Here the fullSizeImageURL is related to a local file path
NSData *data = [NSData dataWithContentsOfURL:contentEditingInput.fullSizeImageURL];
UIImage *image = [UIImage imageWithData:data];
newAvatarImage = image;
[self.tableView reloadData];
}
}];
}
[self dismissMediaPicker];
}

View file

@ -22,6 +22,8 @@
#import "VectorDesignValues.h"
#import "MXRoom+Vector.h"
@implementation RecentTableViewCell
#pragma mark - Class methods
@ -78,44 +80,8 @@
}
self.roomAvatar.backgroundColor = [UIColor clearColor];
MXRoom* room = roomCellData.roomDataSource.room;
NSString* roomAvatarUrl = room.state.avatar;
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
if (!roomAvatarUrl)
{
NSString* myUserId = room.mxSession.myUser.userId;
NSArray* members = room.state.members;
if (members.count < 3)
{
// use the member avatar only it is an active member
for (MXRoomMember *roomMember in members)
{
if ((MXMembershipJoin == roomMember.membership) && ((members.count == 1) || ![roomMember.userId isEqualToString:myUserId]))
{
roomAvatarUrl = roomMember.avatarUrl;
break;
}
}
}
}
UIImage* avatarImage = [AvatarGenerator generateRoomAvatar:room];
if (roomAvatarUrl)
{
self.roomAvatar.enableInMemoryCache = YES;
[self.roomAvatar setImageURL:[roomCellData.roomDataSource.mxSession.matrixRestClient urlOfContentThumbnail:roomAvatarUrl toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop] withType:nil andImageOrientation:UIImageOrientationUp previewImage:avatarImage];
}
else
{
self.roomAvatar.image = avatarImage;
}
[roomCellData.roomDataSource.room setRoomAvatarImageIn:self.roomAvatar];
}
else
{

View file

@ -18,6 +18,8 @@
#import "VectorDesignValues.h"
#import "MXRoom+Vector.h"
@implementation RoomTitleViewWithTopic
- (void)refreshDisplay
@ -26,7 +28,7 @@
if (self.mxRoom)
{
NSString* roomName = self.displayNameTextField.text;
NSString* roomName = self.mxRoom.vectorDisplayname;
if (roomName)
{

View file

@ -0,0 +1,27 @@
/*
Copyright 2015 OpenMarket 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 <MatrixSDK/MatrixSDK.h>
#import "MXKTableViewCell.h"
#import "MXKImageView.h"
@interface TableViewCellWithLabelAndMXKImageView : MXKTableViewCell
@property (strong, nonatomic) IBOutlet UILabel *mxkLabel;
@property (strong, nonatomic) IBOutlet MXKImageView *mxkImageView;
@end

View file

@ -0,0 +1,22 @@
/*
Copyright 2015 OpenMarket 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 "TableViewCellWithLabelAndMXKImageView.h"
@implementation TableViewCellWithLabelAndMXKImageView
@end

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="aCf-VI-ocb" customClass="TableViewCellWithLabelAndMXKImageView">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="aCf-VI-ocb" id="Eg5-vl-rni">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xx4-AP-OQs">
<rect key="frame" x="10" y="11" width="544" height="21"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Ts-eR-MZV" userLabel="Mxk ImageView" customClass="MXKImageView">
<rect key="frame" x="560" y="5" width="34" height="34"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" constant="34" id="Ejk-bJ-0MB"/>
<constraint firstAttribute="height" constant="34" id="m9S-XK-OTa"/>
</constraints>
</view>
</subviews>
<animations/>
<constraints>
<constraint firstItem="Xx4-AP-OQs" firstAttribute="leading" secondItem="Eg5-vl-rni" secondAttribute="leading" constant="10" id="Wih-ke-1dd"/>
<constraint firstItem="7Ts-eR-MZV" firstAttribute="leading" secondItem="Xx4-AP-OQs" secondAttribute="trailing" constant="6" id="fSB-ec-jkJ"/>
<constraint firstAttribute="centerY" secondItem="Xx4-AP-OQs" secondAttribute="centerY" id="v6O-QC-moW"/>
</constraints>
</tableViewCellContentView>
<animations/>
<constraints>
<constraint firstAttribute="trailing" secondItem="7Ts-eR-MZV" secondAttribute="trailing" constant="6" id="JNP-da-JzI"/>
<constraint firstItem="7Ts-eR-MZV" firstAttribute="centerY" secondItem="aCf-VI-ocb" secondAttribute="centerY" id="lgB-TU-fX3"/>
</constraints>
<connections>
<outlet property="mxkImageView" destination="7Ts-eR-MZV" id="fP1-hq-oEh"/>
<outlet property="mxkLabel" destination="Xx4-AP-OQs" id="Va7-zb-8uX"/>
</connections>
</tableViewCell>
</objects>
</document>

View file

@ -0,0 +1,24 @@
/*
Copyright 2015 OpenMarket 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 "MXKTableViewCell.h"
@interface TableViewCellWithLabelAndSwitch : MXKTableViewCell
@property (strong, nonatomic) IBOutlet UILabel *mxkLabel;
@property (strong, nonatomic) IBOutlet UISwitch *mxkSwitch;
@end

View file

@ -0,0 +1,22 @@
/*
Copyright 2015 OpenMarket 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 "TableViewCellWithLabelAndSwitch.h"
@implementation TableViewCellWithLabelAndSwitch
@end

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="aCf-VI-ocb" customClass="TableViewCellWithLabelAndSwitch">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="aCf-VI-ocb" id="Eg5-vl-rni">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9dA-E8-w3v">
<rect key="frame" x="543" y="6" width="51" height="31"/>
<animations/>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xx4-AP-OQs">
<rect key="frame" x="8" y="11" width="527" height="21"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Xx4-AP-OQs" secondAttribute="bottom" constant="11" id="2wi-Xu-jlr"/>
<constraint firstItem="9dA-E8-w3v" firstAttribute="top" secondItem="Eg5-vl-rni" secondAttribute="top" constant="6" id="7fZ-Vc-PCU"/>
<constraint firstItem="Xx4-AP-OQs" firstAttribute="top" secondItem="Eg5-vl-rni" secondAttribute="top" constant="11" id="WhC-iv-1UK"/>
<constraint firstItem="Xx4-AP-OQs" firstAttribute="leading" secondItem="Eg5-vl-rni" secondAttribute="leading" constant="8" id="Wih-ke-1dd"/>
<constraint firstAttribute="bottom" secondItem="9dA-E8-w3v" secondAttribute="bottom" constant="6" id="efV-Gs-ip0"/>
<constraint firstItem="9dA-E8-w3v" firstAttribute="leading" secondItem="Xx4-AP-OQs" secondAttribute="trailing" constant="8" id="hms-8a-BYd"/>
<constraint firstAttribute="trailing" secondItem="9dA-E8-w3v" secondAttribute="trailing" constant="8" id="oN3-Ph-hS5"/>
</constraints>
</tableViewCellContentView>
<animations/>
<connections>
<outlet property="mxkLabel" destination="Xx4-AP-OQs" id="jTM-zE-gtP"/>
<outlet property="mxkSwitch" destination="9dA-E8-w3v" id="sko-Dh-EsF"/>
</connections>
</tableViewCell>
</objects>
</document>