diff --git a/Vector.xcodeproj/project.pbxproj b/Vector.xcodeproj/project.pbxproj index cb5251a39..cc2e007a1 100644 --- a/Vector.xcodeproj/project.pbxproj +++ b/Vector.xcodeproj/project.pbxproj @@ -128,6 +128,14 @@ F047DBB51C576F2200952DA2 /* AuthenticationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F047DBB41C576F2200952DA2 /* AuthenticationViewController.xib */; }; F047DBB91C576F6600952DA2 /* AuthInputsPasswordBasedView.m in Sources */ = {isa = PBXBuildFile; fileRef = F047DBB71C576F6600952DA2 /* AuthInputsPasswordBasedView.m */; }; F047DBBA1C576F6600952DA2 /* AuthInputsPasswordBasedView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F047DBB81C576F6600952DA2 /* AuthInputsPasswordBasedView.xib */; }; + F056417B1C7C9FD7002276ED /* TableViewCellWithButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F05641791C7C9FD7002276ED /* TableViewCellWithButton.m */; }; + F056417C1C7C9FD7002276ED /* TableViewCellWithButton.xib in Resources */ = {isa = PBXBuildFile; fileRef = F056417A1C7C9FD7002276ED /* TableViewCellWithButton.xib */; }; + F05641831C7CBB58002276ED /* bubbles_bg_landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = F056417D1C7CBB58002276ED /* bubbles_bg_landscape.png */; }; + F05641841C7CBB58002276ED /* bubbles_bg_landscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F056417E1C7CBB58002276ED /* bubbles_bg_landscape@2x.png */; }; + F05641851C7CBB58002276ED /* bubbles_bg_landscape@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F056417F1C7CBB58002276ED /* bubbles_bg_landscape@3x.png */; }; + F056418C1C7CBEBD002276ED /* group.png in Resources */ = {isa = PBXBuildFile; fileRef = F05641891C7CBEBD002276ED /* group.png */; }; + F056418D1C7CBEBD002276ED /* group@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F056418A1C7CBEBD002276ED /* group@2x.png */; }; + F056418E1C7CBEBD002276ED /* group@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F056418B1C7CBEBD002276ED /* group@3x.png */; }; F05895001B8B7E6600B73E85 /* RoomBubbleCellData.m in Sources */ = {isa = PBXBuildFile; fileRef = F05894FF1B8B7E6600B73E85 /* RoomBubbleCellData.m */; }; F08BE09E1B87025B00C480FB /* EventFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F08BE09D1B87025B00C480FB /* EventFormatter.m */; }; F08BE0A21B87064000C480FB /* RoomDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F08BE0A11B87064000C480FB /* RoomDataSource.m */; }; @@ -149,6 +157,8 @@ F094AA351B78E42600B1FBBF /* RecentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F094AA231B78E42600B1FBBF /* RecentsViewController.m */; }; F094AA371B78E42600B1FBBF /* RoomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F094AA271B78E42600B1FBBF /* RoomViewController.m */; }; F094AA381B78E42600B1FBBF /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F094AA291B78E42600B1FBBF /* SettingsViewController.m */; }; + F09E24ED1C6DE24900D39503 /* RoomMemberTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = F09E24EB1C6DE24900D39503 /* RoomMemberTitleView.m */; }; + F09E24EE1C6DE24900D39503 /* RoomMemberTitleView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F09E24EC1C6DE24900D39503 /* RoomMemberTitleView.xib */; }; F09EE0021C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F09EDFF71C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.m */; }; F09EE0031C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F09EDFF81C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib */; }; F09EE0041C5134BE0078712F /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F09EDFFA1C5134BE0078712F /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m */; }; @@ -158,6 +168,8 @@ F09EE0081C5134BE0078712F /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F09EE0001C5134BE0078712F /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m */; }; F09EE0091C5134BE0078712F /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F09EE0011C5134BE0078712F /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib */; }; F0A1CD221B9F4BBA00F9C15C /* RoomParticipantsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F0A1CD211B9F4BBA00F9C15C /* RoomParticipantsViewController.m */; }; + F0BE3DF01C6CE17200AC3111 /* RoomMemberDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F0BE3DEF1C6CE17200AC3111 /* RoomMemberDetailsViewController.m */; }; + F0BE3DF21C6CE28300AC3111 /* RoomMemberDetailsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0BE3DF11C6CE28300AC3111 /* RoomMemberDetailsViewController.xib */; }; F0C34B611C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0C34B561C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.m */; }; F0C34B621C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0C34B571C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.xib */; }; F0C34B631C15C28300C36F09 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0C34B591C15C28300C36F09 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m */; }; @@ -365,6 +377,15 @@ F047DBB61C576F6600952DA2 /* AuthInputsPasswordBasedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthInputsPasswordBasedView.h; sourceTree = ""; }; F047DBB71C576F6600952DA2 /* AuthInputsPasswordBasedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthInputsPasswordBasedView.m; sourceTree = ""; }; F047DBB81C576F6600952DA2 /* AuthInputsPasswordBasedView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AuthInputsPasswordBasedView.xib; sourceTree = ""; }; + F05641781C7C9FD7002276ED /* TableViewCellWithButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableViewCellWithButton.h; path = TableViewCell/TableViewCellWithButton.h; sourceTree = ""; }; + F05641791C7C9FD7002276ED /* TableViewCellWithButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableViewCellWithButton.m; path = TableViewCell/TableViewCellWithButton.m; sourceTree = ""; }; + F056417A1C7C9FD7002276ED /* TableViewCellWithButton.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TableViewCellWithButton.xib; path = TableViewCell/TableViewCellWithButton.xib; sourceTree = ""; }; + F056417D1C7CBB58002276ED /* bubbles_bg_landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bubbles_bg_landscape.png; sourceTree = ""; }; + F056417E1C7CBB58002276ED /* bubbles_bg_landscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bubbles_bg_landscape@2x.png"; sourceTree = ""; }; + F056417F1C7CBB58002276ED /* bubbles_bg_landscape@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bubbles_bg_landscape@3x.png"; sourceTree = ""; }; + F05641891C7CBEBD002276ED /* group.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = group.png; sourceTree = ""; }; + F056418A1C7CBEBD002276ED /* group@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "group@2x.png"; sourceTree = ""; }; + F056418B1C7CBEBD002276ED /* group@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "group@3x.png"; sourceTree = ""; }; F05894FE1B8B7E6600B73E85 /* RoomBubbleCellData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomBubbleCellData.h; sourceTree = ""; }; F05894FF1B8B7E6600B73E85 /* RoomBubbleCellData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomBubbleCellData.m; sourceTree = ""; }; F08BE09C1B87025B00C480FB /* EventFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventFormatter.h; sourceTree = ""; }; @@ -401,6 +422,9 @@ F094AA271B78E42600B1FBBF /* RoomViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomViewController.m; sourceTree = ""; }; F094AA281B78E42600B1FBBF /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = ""; }; F094AA291B78E42600B1FBBF /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = ""; }; + F09E24EA1C6DE24900D39503 /* RoomMemberTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMemberTitleView.h; sourceTree = ""; }; + F09E24EB1C6DE24900D39503 /* RoomMemberTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMemberTitleView.m; sourceTree = ""; }; + F09E24EC1C6DE24900D39503 /* RoomMemberTitleView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomMemberTitleView.xib; sourceTree = ""; }; F09EDFF61C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomIncomingTextMsgWithoutSenderNameBubbleCell.h; sourceTree = ""; }; F09EDFF71C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomIncomingTextMsgWithoutSenderNameBubbleCell.m; sourceTree = ""; }; F09EDFF81C5134BE0078712F /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib; sourceTree = ""; }; @@ -415,6 +439,9 @@ F09EE0011C5134BE0078712F /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib; sourceTree = ""; }; F0A1CD201B9F4BBA00F9C15C /* RoomParticipantsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomParticipantsViewController.h; sourceTree = ""; }; F0A1CD211B9F4BBA00F9C15C /* RoomParticipantsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomParticipantsViewController.m; sourceTree = ""; }; + F0BE3DEE1C6CE17200AC3111 /* RoomMemberDetailsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMemberDetailsViewController.h; sourceTree = ""; }; + F0BE3DEF1C6CE17200AC3111 /* RoomMemberDetailsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMemberDetailsViewController.m; sourceTree = ""; }; + F0BE3DF11C6CE28300AC3111 /* RoomMemberDetailsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomMemberDetailsViewController.xib; sourceTree = ""; }; F0C34B551C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomOutgoingAttachmentBubbleCell.h; sourceTree = ""; }; F0C34B561C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomOutgoingAttachmentBubbleCell.m; sourceTree = ""; }; F0C34B571C15C28300C36F09 /* RoomOutgoingAttachmentBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomOutgoingAttachmentBubbleCell.xib; sourceTree = ""; }; @@ -526,6 +553,9 @@ 7179283B1C0384DE00407D96 /* TableViewCell */ = { isa = PBXGroup; children = ( + F05641781C7C9FD7002276ED /* TableViewCellWithButton.h */, + F05641791C7C9FD7002276ED /* TableViewCellWithButton.m */, + F056417A1C7C9FD7002276ED /* TableViewCellWithButton.xib */, 7179283C1C03852C00407D96 /* TableViewCellSeparator.h */, 7179283D1C03852C00407D96 /* TableViewCellSeparator.m */, 7179283E1C03852C00407D96 /* TableViewCellSeparator.xib */, @@ -579,6 +609,7 @@ children = ( F0CC4DBC1C4E26FA003BBE45 /* MediaAlbum */, 71F7F5191C23079100E7ED8F /* Contact */, + F09E24E91C6DE24900D39503 /* RoomMember */, 71046D581C0C631100DCA984 /* RoomTitle */, 71EBE6691C04C4BE00E7D953 /* RoomActivitiesView */, 7179283B1C0384DE00407D96 /* TableViewCell */, @@ -837,6 +868,9 @@ F094AA151B78E42600B1FBBF /* ViewController */ = { isa = PBXGroup; children = ( + F0BE3DEE1C6CE17200AC3111 /* RoomMemberDetailsViewController.h */, + F0BE3DEF1C6CE17200AC3111 /* RoomMemberDetailsViewController.m */, + F0BE3DF11C6CE28300AC3111 /* RoomMemberDetailsViewController.xib */, F094AA161B78E42600B1FBBF /* AccountDetailsViewController.h */, F094AA171B78E42600B1FBBF /* AccountDetailsViewController.m */, F094AA181B78E42600B1FBBF /* AuthenticationViewController.h */, @@ -880,6 +914,16 @@ path = ViewController; sourceTree = ""; }; + F09E24E91C6DE24900D39503 /* RoomMember */ = { + isa = PBXGroup; + children = ( + F09E24EA1C6DE24900D39503 /* RoomMemberTitleView.h */, + F09E24EB1C6DE24900D39503 /* RoomMemberTitleView.m */, + F09E24EC1C6DE24900D39503 /* RoomMemberTitleView.xib */, + ); + path = RoomMember; + sourceTree = ""; + }; F0C34CB51C17145F00C36F09 /* Categories */ = { isa = PBXGroup; children = ( @@ -906,6 +950,12 @@ F0DD7D1B1B7AA8C900C4BE02 /* Images */ = { isa = PBXGroup; children = ( + F05641891C7CBEBD002276ED /* group.png */, + F056418A1C7CBEBD002276ED /* group@2x.png */, + F056418B1C7CBEBD002276ED /* group@3x.png */, + F056417D1C7CBB58002276ED /* bubbles_bg_landscape.png */, + F056417E1C7CBB58002276ED /* bubbles_bg_landscape@2x.png */, + F056417F1C7CBB58002276ED /* bubbles_bg_landscape@3x.png */, F0DDDBB41C5A5F55000C6C46 /* Icon-170.png */, F0DDDBB51C5A5F55000C6C46 /* Icon-170@2x.png */, F0DDDBB61C5A5F55000C6C46 /* Icon-170@3x.png */, @@ -1073,6 +1123,7 @@ F02528D81C11B6FC00E1FE1B /* camera_picture.png in Resources */, F02528E01C11B6FC00E1FE1B /* create_room.png in Resources */, F02528DF1C11B6FC00E1FE1B /* camera_video.png in Resources */, + F056418C1C7CBEBD002276ED /* group.png in Resources */, F02528E31C11B6FC00E1FE1B /* favorite_icon.png in Resources */, F0C34B681C15C28300C36F09 /* RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib in Resources */, F0DDDBB81C5A5F55000C6C46 /* Icon-170@2x.png in Resources */, @@ -1104,16 +1155,20 @@ F02529041C11B6FC00E1FE1B /* typing@2x.png in Resources */, F0C34B641C15C28300C36F09 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib in Resources */, F0DA3FC81C4691CD0055438B /* details_icon.png in Resources */, + F05641831C7CBB58002276ED /* bubbles_bg_landscape.png in Resources */, F02528D61C11B6FC00E1FE1B /* camera_capture@2x.png in Resources */, 71046D601C0C86C600DCA984 /* RoomTitleView.xib in Resources */, 71B2A3C11C203C7100472061 /* TableViewCellWithLabelAndSwitch.xib in Resources */, F02528D51C11B6FC00E1FE1B /* camera_capture.png in Resources */, F02528EA1C11B6FC00E1FE1B /* low_priority_icon@2x.png in Resources */, + F05641851C7CBB58002276ED /* bubbles_bg_landscape@3x.png in Resources */, F02528EE1C11B6FC00E1FE1B /* mute_icon@3x.png in Resources */, + F056418E1C7CBEBD002276ED /* group@3x.png in Resources */, F003AA811C690628008B430C /* RoomAvatarTitleView.xib in Resources */, F02529071C11B6FC00E1FE1B /* unmute_icon@2x.png in Resources */, F0C34B701C15CA2E00C36F09 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib in Resources */, F025290D1C11B6FC00E1FE1B /* voice_call_icon@2x.png in Resources */, + F0BE3DF21C6CE28300AC3111 /* RoomMemberDetailsViewController.xib in Resources */, F0C34CB21C16269D00C36F09 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib in Resources */, F02528DC1C11B6FC00E1FE1B /* camera_switch.png in Resources */, F0DA3FC91C4691CD0055438B /* details_icon@2x.png in Resources */, @@ -1134,6 +1189,8 @@ F02528F41C11B6FC00E1FE1B /* remove_icon@3x.png in Resources */, F02528F71C11B6FC00E1FE1B /* search_icon.png in Resources */, 3235CD8A1C3426D10084EA40 /* HomeSearchTableViewCell.xib in Resources */, + F056417C1C7C9FD7002276ED /* TableViewCellWithButton.xib in Resources */, + F05641841C7CBB58002276ED /* bubbles_bg_landscape@2x.png in Resources */, F02528F81C11B6FC00E1FE1B /* search_icon@2x.png in Resources */, F02528EB1C11B6FC00E1FE1B /* low_priority_icon@3x.png in Resources */, 325F6A481C21D4C100C12F51 /* chevron@2x.png in Resources */, @@ -1146,6 +1203,7 @@ F001D76E1B83156000A162C3 /* MediaPickerViewController.xib in Resources */, F02529031C11B6FC00E1FE1B /* typing.png in Resources */, 32D200851C15C56A00A4E396 /* search_bg@3x.png in Resources */, + F056418D1C7CBEBD002276ED /* group@2x.png in Resources */, 71EBE66E1C04C4D300E7D953 /* RoomActivitiesView.xib in Resources */, 717928461C03852C00407D96 /* TableViewCellSeparator.xib in Resources */, F02528ED1C11B6FC00E1FE1B /* mute_icon@2x.png in Resources */, @@ -1168,6 +1226,7 @@ 716FDC8B1C186A3A001034CB /* InviteRecentTableViewCell.xib in Resources */, F02528E51C11B6FC00E1FE1B /* favorite_icon@3x.png in Resources */, F02529051C11B6FC00E1FE1B /* typing@3x.png in Resources */, + F09E24EE1C6DE24900D39503 /* RoomMemberTitleView.xib in Resources */, F0CC4DCB1C4E594C003BBE45 /* MediaAlbumContentViewController.xib in Resources */, F02528E71C11B6FC00E1FE1B /* logo.png in Resources */, 32D200841C15C56A00A4E396 /* search_bg@2x.png in Resources */, @@ -1253,6 +1312,7 @@ 323A520B1C3183CC00010773 /* UIViewController+VectorSearch.m in Sources */, 717928491C03852C00407D96 /* TableViewCellWithLabelAndTextField.m in Sources */, F094AA2F1B78E42600B1FBBF /* AccountDetailsViewController.m in Sources */, + F056417B1C7C9FD7002276ED /* TableViewCellWithButton.m in Sources */, F0CC4DC01C4E26FA003BBE45 /* MediaAlbumTableCell.m in Sources */, F022285B1C64D529000AF23C /* ExpandedRoomTitleView.m in Sources */, F0C34B671C15C28300C36F09 /* RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m in Sources */, @@ -1270,8 +1330,10 @@ 71F7F51D1C23079F00E7ED8F /* ContactTableViewCell.m in Sources */, 717928471C03852C00407D96 /* TableViewCellWithLabelAndLargeTextView.m in Sources */, F0D2D9871C197DCB007B8C96 /* RoomIncomingTextMsgBubbleCell.m in Sources */, + F0BE3DF01C6CE17200AC3111 /* RoomMemberDetailsViewController.m in Sources */, F0C34B6F1C15CA2E00C36F09 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m in Sources */, 7165A25B1C05CD42003635D7 /* SegmentedViewController.m in Sources */, + F09E24ED1C6DE24900D39503 /* RoomMemberTitleView.m in Sources */, 325F6A391C21810E00C12F51 /* DirectoryViewController.m in Sources */, 3235CD8D1C34309E0084EA40 /* HomeSearchCellData.m in Sources */, F094AA321B78E42600B1FBBF /* GlobalNotificationSettingsViewController.m in Sources */, diff --git a/Vector/Assets/Images/bubbles_bg_landscape.png b/Vector/Assets/Images/bubbles_bg_landscape.png new file mode 100644 index 000000000..c5b9e1922 Binary files /dev/null and b/Vector/Assets/Images/bubbles_bg_landscape.png differ diff --git a/Vector/Assets/Images/bubbles_bg_landscape@2x.png b/Vector/Assets/Images/bubbles_bg_landscape@2x.png new file mode 100644 index 000000000..5a22d5242 Binary files /dev/null and b/Vector/Assets/Images/bubbles_bg_landscape@2x.png differ diff --git a/Vector/Assets/Images/bubbles_bg_landscape@3x.png b/Vector/Assets/Images/bubbles_bg_landscape@3x.png new file mode 100644 index 000000000..c4cadaeb6 Binary files /dev/null and b/Vector/Assets/Images/bubbles_bg_landscape@3x.png differ diff --git a/Vector/Assets/Images/group.png b/Vector/Assets/Images/group.png new file mode 100644 index 000000000..61638ff93 Binary files /dev/null and b/Vector/Assets/Images/group.png differ diff --git a/Vector/Assets/Images/group@2x.png b/Vector/Assets/Images/group@2x.png new file mode 100644 index 000000000..e0cb02af8 Binary files /dev/null and b/Vector/Assets/Images/group@2x.png differ diff --git a/Vector/Assets/Images/group@3x.png b/Vector/Assets/Images/group@3x.png new file mode 100644 index 000000000..7597b1cff Binary files /dev/null and b/Vector/Assets/Images/group@3x.png differ diff --git a/Vector/Assets/en.lproj/Vector.strings b/Vector/Assets/en.lproj/Vector.strings index 8a2deb7df..f4197aa0c 100644 --- a/Vector/Assets/en.lproj/Vector.strings +++ b/Vector/Assets/en.lproj/Vector.strings @@ -92,13 +92,26 @@ "room_participants_invite_malformed_id_title" = "Invite Error"; "room_participants_invite_malformed_id" = "Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain'"; -"room_participants_active" = "Active"; +"room_participants_active" = "Online"; "room_participants_invite" = "Invite"; "room_participants_leave" = "Left"; "room_participants_ban" = "Banned"; -"room_participants_active_less_1_hour" = "Active less 1 hour ago"; -"room_participants_active_less_x_hours" = "Active less %lu hours ago"; -"room_participants_active_less_x_days" = "Active less %lu days ago"; +"room_participants_active_less_1_hour" = "Offline"; +"room_participants_active_less_x_hours" = "Offline %luh ago"; +"room_participants_active_less_x_days" = "Offline %lu days ago"; + +"room_participants_action_invite" = "Invite"; +"room_participants_action_leave" = "Leave from this room"; +"room_participants_action_remove" = "Remove from this room"; +"room_participants_action_ban" = "Block"; +"room_participants_action_unban" = "Unblock"; +"room_participants_action_set_default_power_level" = "Reset power level"; +"room_participants_action_set_moderator" = "Make moderator"; +"room_participants_action_set_admin" = "Make admin"; +"room_participants_action_set_custom_power_level" = "Set custom power level"; +"room_participants_action_start_chat" = "Start chat"; +"room_participants_action_start_voice_call" = "Start voice call"; +"room_participants_action_start_video_call" = "Start video call"; // Chat "room_one_user_is_typing" = "%@ is typing..."; diff --git a/Vector/Utils/VectorDesignValues.h b/Vector/Utils/VectorDesignValues.h index cc3c36482..3f7417a7c 100644 --- a/Vector/Utils/VectorDesignValues.h +++ b/Vector/Utils/VectorDesignValues.h @@ -34,12 +34,17 @@ extern UIColor *kVectorColorOrange; #pragma mark - Vector Text Colors extern UIColor *kVectorTextColorBlack; +extern UIColor *kVectorTextColorRed; extern UIColor *kVectorTextColorDarkGray; extern UIColor *kVectorTextColorGray; #pragma mark - Vector Navigation Bar Tint Color extern UIColor *kVectorNavBarTintColor; +#pragma mark - Vector Standard Room Member Power Level +extern NSUInteger const kVectorRoomModeratorLevel; +extern NSUInteger const kVectorRoomAdminLevel; + /** `VectorDesignValues` class manages the Vector design parameters */ diff --git a/Vector/Utils/VectorDesignValues.m b/Vector/Utils/VectorDesignValues.m index 8ce549587..d8478e317 100644 --- a/Vector/Utils/VectorDesignValues.m +++ b/Vector/Utils/VectorDesignValues.m @@ -23,11 +23,15 @@ UIColor *kVectorColorSiver; UIColor *kVectorColorOrange; UIColor *kVectorTextColorBlack; +UIColor *kVectorTextColorRed; UIColor *kVectorTextColorDarkGray; UIColor *kVectorTextColorGray; UIColor *kVectorNavBarTintColor; +NSUInteger const kVectorRoomModeratorLevel = 50; +NSUInteger const kVectorRoomAdminLevel = 100; + @implementation VectorDesignValues + (void)load @@ -42,6 +46,7 @@ UIColor *kVectorNavBarTintColor; kVectorColorSiver = [UIColor colorWithRed:(199.0 / 255.0) green:(199.0 / 255.0) blue:(204.0 / 255.0) alpha:1.0]; kVectorTextColorBlack = [UIColor colorWithRed:(60.0 / 255.0) green:(60.0 / 255.0) blue:(60.0 / 255.0) alpha:1.0]; + kVectorTextColorRed = [UIColor colorWithRed:(255.0 / 255.0) green:(0.0 / 255.0) blue:(100.0 / 255.0) alpha:1.0]; kVectorTextColorDarkGray = [UIColor colorWithRed:(74.0 / 255.0) green:(74.0 / 255.0) blue:(74.0 / 255.0) alpha:1.0]; kVectorTextColorGray = [UIColor colorWithRed:(157.0 / 255.0) green:(157.0 / 255.0) blue:(157.0 / 255.0) alpha:1.0]; diff --git a/Vector/ViewController/RoomMemberDetailsViewController.h b/Vector/ViewController/RoomMemberDetailsViewController.h new file mode 100644 index 000000000..b803824ed --- /dev/null +++ b/Vector/ViewController/RoomMemberDetailsViewController.h @@ -0,0 +1,30 @@ +/* + Copyright 2016 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 + +@interface RoomMemberDetailsViewController : MXKRoomMemberDetailsViewController + +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *actionTableViewTopConstraint; + +@property (weak, nonatomic) IBOutlet UIView *memberHeaderView; +@property (weak, nonatomic) IBOutlet UILabel *roomMemberNameLabel; + +@property (weak, nonatomic) IBOutlet UILabel *roomMemberStatusLabel; + +@property (weak, nonatomic) IBOutlet UIImageView *bottomImageView; +@end + diff --git a/Vector/ViewController/RoomMemberDetailsViewController.m b/Vector/ViewController/RoomMemberDetailsViewController.m new file mode 100644 index 000000000..1ad32cb95 --- /dev/null +++ b/Vector/ViewController/RoomMemberDetailsViewController.m @@ -0,0 +1,518 @@ +/* + Copyright 2016 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 "RoomMemberDetailsViewController.h" + +#import "AppDelegate.h" + +#import "RoomMemberTitleView.h" + +#import "VectorDesignValues.h" + +#import "RageShakeManager.h" + +#import "AvatarGenerator.h" + +#import "TableViewCellWithButton.h" + +@interface RoomMemberDetailsViewController () +{ + RoomMemberTitleView* memberTitleView; + + /** + Observe UIApplicationWillChangeStatusBarOrientationNotification to hide/show bubbles bg. + */ + id UIApplicationWillChangeStatusBarOrientationNotificationObserver; +} +@end + +@implementation RoomMemberDetailsViewController + +#pragma mark - Class methods + ++ (UINib *)nib +{ + return [UINib nibWithNibName:NSStringFromClass(self.class) + bundle:[NSBundle bundleForClass:self.class]]; +} + ++ (instancetype)roomMemberDetailsViewController +{ + return [[[self class] alloc] initWithNibName:NSStringFromClass(self.class) + bundle:[NSBundle bundleForClass:self.class]]; +} + +#pragma mark - + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. + + // Setup `MXKViewControllerHandling` properties + self.defaultBarTintColor = kVectorNavBarTintColor; + self.enableBarTintColorStatusChange = NO; + self.rageShakeManager = [RageShakeManager sharedManager]; + + // Set delegate to handle start chat option + self.delegate = [AppDelegate theDelegate]; + + self.memberHeaderView.backgroundColor = kVectorColorLightGrey; + self.roomMemberNameLabel.textColor = kVectorTextColorBlack; + self.roomMemberStatusLabel.textColor = kVectorColorGreen; + + self.navigationItem.titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 40)]; + + memberTitleView = [RoomMemberTitleView roomMemberTitleView]; + self.memberThumbnail = memberTitleView.memberAvatar; + + // Add the title view and define edge constraints + memberTitleView.translatesAutoresizingMaskIntoConstraints = NO; + [self.navigationItem.titleView addSubview:memberTitleView]; + + NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.navigationItem.titleView + attribute:NSLayoutAttributeTop + multiplier:1.0f + constant:0.0f]; + NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.navigationItem.titleView + attribute:NSLayoutAttributeBottom + multiplier:1.0f + constant:0.0f]; + NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self.navigationItem.titleView + attribute:NSLayoutAttributeLeading + multiplier:1.0f + constant:0.0f]; + NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:memberTitleView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self.navigationItem.titleView + attribute:NSLayoutAttributeTrailing + multiplier:1.0f + constant:0.0f]; + [NSLayoutConstraint activateConstraints:@[topConstraint, bottomConstraint, leadingConstraint, trailingConstraint]]; + + // Hide line separators of empty cells + self.tableView.tableFooterView = [[UIView alloc] init]; + + // Observe UIApplicationWillChangeStatusBarOrientationNotification to hide/show bubbles bg. + UIApplicationWillChangeStatusBarOrientationNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillChangeStatusBarOrientationNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + + NSNumber *orientation = (NSNumber*)(notif.userInfo[UIApplicationStatusBarOrientationUserInfoKey]); + self.bottomImageView.hidden = (orientation.integerValue == UIInterfaceOrientationLandscapeLeft || orientation.integerValue == UIInterfaceOrientationLandscapeRight); + }]; + + UIInterfaceOrientation screenOrientation = [[UIApplication sharedApplication] statusBarOrientation]; + self.bottomImageView.hidden = (screenOrientation == UIInterfaceOrientationLandscapeLeft || screenOrientation == UIInterfaceOrientationLandscapeRight); +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + // Hide the bottom border of the navigation bar to display the expander header + [self hideNavigationBarBorder:YES]; +} + +- (void)viewWillDisappear:(BOOL)animated +{ + [super viewWillDisappear:animated]; + + // Restore navigation bar display + [self hideNavigationBarBorder:NO]; +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinator +{ + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + + // Restore navigation bar display + [self hideNavigationBarBorder:NO]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(coordinator.transitionDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + // Hide the bottom border of the navigation bar + [self hideNavigationBarBorder:YES]; + + }); +} + +- (void)destroy +{ + [super destroy]; + + if (UIApplicationWillChangeStatusBarOrientationNotificationObserver) + { + [[NSNotificationCenter defaultCenter] removeObserver:UIApplicationWillChangeStatusBarOrientationNotificationObserver]; + UIApplicationWillChangeStatusBarOrientationNotificationObserver = nil; + } + + [memberTitleView removeFromSuperview]; + memberTitleView = nil; +} + +- (UIImage*)picturePlaceholder +{ + if (self.mxRoomMember) + { + // Use the vector style placeholder + return [AvatarGenerator generateRoomMemberAvatar:self.mxRoomMember.userId displayName:self.mxRoomMember.displayname]; + } + + return [UIImage imageNamed:@"placeholder"]; +} + +- (void)updateMemberInfo +{ + [super updateMemberInfo]; + + if (self.mxRoomMember) + { + self.roomMemberNameLabel.text = self.mxRoomMember.displayname ? self.mxRoomMember.displayname : self.mxRoomMember.userId; + + NSString* presenceText = nil; + + if (self.mxRoomMember.membership != MXMembershipJoin) + { + if (self.mxRoomMember.membership == MXMembershipInvite) + { + presenceText = NSLocalizedStringFromTable(@"room_participants_invite", @"Vector", nil); + } + else if (self.mxRoomMember.membership == MXMembershipLeave) + { + presenceText = NSLocalizedStringFromTable(@"room_participants_leave", @"Vector", nil); + } + else if (self.mxRoomMember.membership == MXMembershipBan) + { + presenceText = NSLocalizedStringFromTable(@"room_participants_ban", @"Vector", nil); + } + } + else if (self.mxRoomMember.userId) + { + MXUser *user = [self.mxRoom.mxSession userWithUserId:self.mxRoomMember.userId]; + if (user) + { + if (user.presence == MXPresenceOnline) + { + presenceText = NSLocalizedStringFromTable(@"room_participants_active", @"Vector", nil); + } + else + { + NSUInteger lastActiveMs = user.lastActiveAgo; + + if (-1 != lastActiveMs) + { + NSUInteger lastActivehour = lastActiveMs / 1000 / 60 / 60; + NSUInteger lastActiveDays = lastActivehour / 24; + + if (lastActivehour < 1) + { + presenceText = NSLocalizedStringFromTable(@"room_participants_active_less_1_hour", @"Vector", nil); + } + else if (lastActivehour < 24) + { + presenceText = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_participants_active_less_x_hours", @"Vector", nil), lastActivehour]; + } + else + { + presenceText = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_participants_active_less_x_days", @"Vector", nil), lastActiveDays]; + } + } + } + } + } + + self.roomMemberStatusLabel.text = presenceText; + } +} + +#pragma mark - Hide/Show navigation bar border + +- (void)hideNavigationBarBorder:(BOOL)isHidden +{ + // Consider the main navigation controller if the current view controller is embedded inside a split view controller. + UINavigationController *mainNavigationController = self.navigationController; + if (self.splitViewController && self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) + { + mainNavigationController = self.splitViewController.viewControllers.firstObject; + } + + if (isHidden) + { + // The default shadow image is nil. When non-nil, this property represents a custom shadow image to show instead + // of the default. For a custom shadow image to be shown, a custom background image must also be set with the + // setBackgroundImage:forBarMetrics: method. If the default background image is used, then the default shadow + // image will be used regardless of the value of this property. + [mainNavigationController.navigationBar setShadowImage:[[UIImage alloc] init]]; + [mainNavigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault]; + } + else + { + // Restore default navigationbar settings + [mainNavigationController.navigationBar setShadowImage:nil]; + [mainNavigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; + } +} + +#pragma mark - TableView data source + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + // Check user's power level before allowing an action (kick, ban, ...) + MXRoomPowerLevels *powerLevels = [self.mxRoom.state powerLevels]; + NSUInteger memberPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoomMember.userId]; + NSUInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId]; + + [actionsArray removeAllObjects]; + + // Consider the case of the user himself + if ([self.mxRoomMember.userId isEqualToString:self.mainSession.myUser.userId]) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionLeave)]; + + if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels]) + { + // Check whether the user may reduce his power level to become moderator + float normalizedOneSelfPowerLevel = [self.mxRoom.state memberNormalizedPowerLevel:self.mainSession.myUser.userId]; + if (normalizedOneSelfPowerLevel > 0.5) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetModerator)]; + } + + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetDefaultPowerLevel)]; + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetCustomPowerLevel)]; + } + } + else if (self.mxRoomMember) + { + // offer to start a new chat only if the room is not a 1:1 room with this user + // it does not make sense : it would open the same room + MXRoom* room = [self.mainSession privateOneToOneRoomWithUserId:self.mxRoomMember.userId]; + if (!room || (![room.state.roomId isEqualToString:self.mxRoom.state.roomId])) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionStartChat)]; + } + + if (self.enableVoipCall) + { + // Offer voip call options + [actionsArray addObject:@(MXKRoomMemberDetailsActionStartVoiceCall)]; + [actionsArray addObject:@(MXKRoomMemberDetailsActionStartVideoCall)]; + } + + // Consider membership of the selected member + switch (self.mxRoomMember.membership) + { + case MXMembershipInvite: + case MXMembershipJoin: + { + // update power level + if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels] && oneSelfPowerLevel > memberPowerLevel) + { + // Check whether user is admin + float normalizedOneSelfPowerLevel = [self.mxRoom.state memberNormalizedPowerLevel:self.mainSession.myUser.userId]; + if (normalizedOneSelfPowerLevel == 1) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetAdmin)]; + } + + // Check whether the member may become moderator + float normalizedMemberPowerLevel = [self.mxRoom.state memberNormalizedPowerLevel:self.mxRoomMember.userId]; + if (normalizedOneSelfPowerLevel >= 0.5 && normalizedMemberPowerLevel < 0.5) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetModerator)]; + } + + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetDefaultPowerLevel)]; + [actionsArray addObject:@(MXKRoomMemberDetailsActionSetCustomPowerLevel)]; + } + + // Check conditions to be able to kick someone + if (oneSelfPowerLevel >= [powerLevels kick] && oneSelfPowerLevel > memberPowerLevel) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionKick)]; + } + // Check conditions to be able to ban someone + if (oneSelfPowerLevel >= [powerLevels ban] && oneSelfPowerLevel > memberPowerLevel) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionBan)]; + } + break; + } + case MXMembershipLeave: + { + // Check conditions to be able to invite someone + if (oneSelfPowerLevel >= [powerLevels invite]) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionInvite)]; + } + // Check conditions to be able to ban someone + if (oneSelfPowerLevel >= [powerLevels ban] && oneSelfPowerLevel > memberPowerLevel) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionBan)]; + } + break; + } + case MXMembershipBan: + { + // Check conditions to be able to unban someone + if (oneSelfPowerLevel >= [powerLevels ban] && oneSelfPowerLevel > memberPowerLevel) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionUnban)]; + } + break; + } + default: + { + break; + } + } + } + + return actionsArray.count; +} + +- (NSString*)actionButtonTitle:(MXKRoomMemberDetailsAction)action +{ + NSString *title; + + switch (action) + { + case MXKRoomMemberDetailsActionInvite: + title = NSLocalizedStringFromTable(@"room_participants_action_invite", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionLeave: + title = NSLocalizedStringFromTable(@"room_participants_action_leave", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionKick: + title = NSLocalizedStringFromTable(@"room_participants_action_remove", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionBan: + title = NSLocalizedStringFromTable(@"room_participants_action_ban", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionUnban: + title = NSLocalizedStringFromTable(@"room_participants_action_unban", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionSetDefaultPowerLevel: + title = NSLocalizedStringFromTable(@"room_participants_action_set_default_power_level", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionSetModerator: + title = NSLocalizedStringFromTable(@"room_participants_action_set_moderator", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionSetAdmin: + title = NSLocalizedStringFromTable(@"room_participants_action_set_admin", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionSetCustomPowerLevel: + title = NSLocalizedStringFromTable(@"room_participants_action_set_custom_power_level", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionStartChat: + title = NSLocalizedStringFromTable(@"room_participants_action_start_chat", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionStartVoiceCall: + title = NSLocalizedStringFromTable(@"room_participants_action_start_voice_call", @"Vector", nil); + break; + case MXKRoomMemberDetailsActionStartVideoCall: + title = NSLocalizedStringFromTable(@"room_participants_action_start_video_call", @"Vector", nil); + break; + default: + break; + } + + return title; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInteger row = indexPath.row; + + TableViewCellWithButton *cell = [[TableViewCellWithButton alloc] init]; + + if (row < actionsArray.count) + { + NSNumber *actionNumber = [actionsArray objectAtIndex:row]; + + NSString *title = [self actionButtonTitle:actionNumber.unsignedIntegerValue]; + + [cell.mxkButton setTitle:title forState:UIControlStateNormal]; + [cell.mxkButton setTitle:title forState:UIControlStateHighlighted]; + + if (actionNumber.unsignedIntegerValue == MXKRoomMemberDetailsActionKick) + { + [cell.mxkButton setTitleColor:kVectorTextColorRed forState:UIControlStateNormal]; + [cell.mxkButton setTitleColor:kVectorTextColorRed forState:UIControlStateHighlighted]; + } + else + { + [cell.mxkButton setTitleColor:kVectorTextColorBlack forState:UIControlStateNormal]; + [cell.mxkButton setTitleColor:kVectorTextColorBlack forState:UIControlStateHighlighted]; + } + + [cell.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; + + cell.mxkButton.tag = actionNumber.unsignedIntegerValue; + } + + return cell; +} + +#pragma mark - + +- (void)onActionButtonPressed:(id)sender +{ + if ([sender isKindOfClass:[UIButton class]]) + { + // already a pending action + if ([self hasPendingAction]) + { + return; + } + + UIButton *button = (UIButton*)sender; + + switch (button.tag) + { + case MXKRoomMemberDetailsActionSetDefaultPowerLevel: + { + [self setPowerLevel:self.mxRoom.state.powerLevels.usersDefault]; + break; + } + case MXKRoomMemberDetailsActionSetModerator: + { + [self setPowerLevel:kVectorRoomModeratorLevel]; + break; + } + case MXKRoomMemberDetailsActionSetAdmin: + { + [self setPowerLevel:kVectorRoomAdminLevel]; + break; + } + default: + { + [super onActionButtonPressed:sender]; + } + } + } +} + +@end diff --git a/Vector/ViewController/RoomMemberDetailsViewController.xib b/Vector/ViewController/RoomMemberDetailsViewController.xib new file mode 100644 index 000000000..bbe76ba79 --- /dev/null +++ b/Vector/ViewController/RoomMemberDetailsViewController.xib @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vector/ViewController/RoomParticipantsViewController.h b/Vector/ViewController/RoomParticipantsViewController.h index 796d210c7..74c9d3759 100644 --- a/Vector/ViewController/RoomParticipantsViewController.h +++ b/Vector/ViewController/RoomParticipantsViewController.h @@ -18,6 +18,8 @@ #import "ContactTableViewCell.h" +#import "SegmentedViewController.h" + /** 'RoomParticipantsViewController' instance is used to edit members of the room defined by the property 'mxRoom'. @@ -58,6 +60,11 @@ */ @property (nonatomic) BOOL isAddParticipantSearchBarEditing; +/** + The potential segmented view controller in which the view controller is displayed. + */ +@property (nonatomic) SegmentedViewController *segmentedViewController; + /** Customize the UITableViewCell before rendering it. diff --git a/Vector/ViewController/RoomParticipantsViewController.m b/Vector/ViewController/RoomParticipantsViewController.m index 1a20a32f9..1a68d33ad 100644 --- a/Vector/ViewController/RoomParticipantsViewController.m +++ b/Vector/ViewController/RoomParticipantsViewController.m @@ -16,6 +16,8 @@ #import "RoomParticipantsViewController.h" +#import "RoomMemberDetailsViewController.h" + #import "VectorDesignValues.h" #import "RageShakeManager.h" @@ -47,6 +49,8 @@ // Observe kMXSessionWillLeaveRoomNotification to be notified if the user leaves the current room. id leaveRoomNotificationObserver; + + RoomMemberDetailsViewController *detailsViewController; } @end @@ -161,6 +165,12 @@ { [super viewWillAppear:animated]; + if (detailsViewController) + { + [detailsViewController destroy]; + detailsViewController = nil; + } + // Refresh display [self.tableView reloadData]; } @@ -795,6 +805,53 @@ } } } + else if (indexPath.section == participantsSection) + { + Contact *contact; + + // oneself dedicated cell + if (userMatrixId && indexPath.row == 0) + { + contact = [mxkContactsById objectForKey:userMatrixId]; + } + else + { + NSInteger index = indexPath.row; + + if (userMatrixId) + { + index --; + } + + if (index < mutableParticipants.count) + { + NSString *userId = mutableParticipants[index]; + contact = [mxkContactsById objectForKey:userId]; + } + } + + if (contact) + { + detailsViewController = [RoomMemberDetailsViewController roomMemberDetailsViewController]; + [detailsViewController displayRoomMember:contact.mxMember withMatrixRoom:self.mxRoom]; + + // Check whether the view controller is displayed inside a segmented one. + if (self.segmentedViewController) + { + // Hide back button title + self.segmentedViewController.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; + + [self.segmentedViewController.navigationController pushViewController:detailsViewController animated:YES]; + } + else + { + // Hide back button title + self.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; + + [self.navigationController pushViewController:detailsViewController animated:YES]; + } + } + } [tableView deselectRowAtIndexPath:indexPath animated:YES]; } diff --git a/Vector/ViewController/RoomViewController.m b/Vector/ViewController/RoomViewController.m index 8d3f5a587..c85616554 100644 --- a/Vector/ViewController/RoomViewController.m +++ b/Vector/ViewController/RoomViewController.m @@ -937,6 +937,7 @@ RoomParticipantsViewController* participantsViewController = [[RoomParticipantsViewController alloc] init]; participantsViewController.mxRoom = [session roomWithRoomId:roomid]; + participantsViewController.segmentedViewController = segmentedViewController; [viewControllers addObject:participantsViewController]; [titles addObject: NSLocalizedStringFromTable(@"room_details_settings", @"Vector", nil)]; diff --git a/Vector/Views/RoomMember/RoomMemberTitleView.h b/Vector/Views/RoomMember/RoomMemberTitleView.h new file mode 100644 index 000000000..ade3dfb53 --- /dev/null +++ b/Vector/Views/RoomMember/RoomMemberTitleView.h @@ -0,0 +1,40 @@ +/* + Copyright 2016 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 + +@interface RoomMemberTitleView : UIView + +/** + * Returns the `UINib` object initialized for the room member title view. + * + * @return The initialized `UINib` object or `nil` if there were errors during + * initialization or the nib file could not be located. + */ ++ (UINib *)nib; + +/** + Creates and returns a new `RoomMemberTitleView-inherited` object. + + @discussion This is the designated initializer for programmatic instantiation. + @return An initialized `RoomMemberTitleView-inherited` object if successful, `nil` otherwise. + */ ++ (instancetype)roomMemberTitleView; + +@property (weak, nonatomic) IBOutlet MXKImageView *memberAvatar; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *memberAvatarCenterXConstraint; + +@end \ No newline at end of file diff --git a/Vector/Views/RoomMember/RoomMemberTitleView.m b/Vector/Views/RoomMember/RoomMemberTitleView.m new file mode 100644 index 000000000..b8ae02f05 --- /dev/null +++ b/Vector/Views/RoomMember/RoomMemberTitleView.m @@ -0,0 +1,69 @@ +/* + Copyright 2016 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 "RoomMemberTitleView.h" + +@implementation RoomMemberTitleView + ++ (UINib *)nib +{ + return [UINib nibWithNibName:NSStringFromClass([self class]) + bundle:[NSBundle bundleForClass:[self class]]]; +} + ++ (instancetype)roomMemberTitleView +{ + return [[[self class] nib] instantiateWithOwner:nil options:nil].firstObject; +} + +- (void)awakeFromNib +{ + [super awakeFromNib]; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + if (self.superview) + { + + // Center horizontally the avatar into the navigation bar + CGRect frame = self.superview.frame; + UINavigationBar *navigationBar; + UIView *superView = self; + while (superView.superview) + { + if ([superView.superview isKindOfClass:[UINavigationBar class]]) + { + navigationBar = (UINavigationBar*)superView.superview; + break; + } + + superView = superView.superview; + } + + if (navigationBar) + { + CGSize navBarSize = navigationBar.frame.size; + CGFloat superviewCenterX = frame.origin.x + (frame.size.width / 2); + + self.memberAvatarCenterXConstraint.constant = (navBarSize.width / 2) - superviewCenterX; + } + } +} + +@end diff --git a/Vector/Views/RoomMember/RoomMemberTitleView.xib b/Vector/Views/RoomMember/RoomMemberTitleView.xib new file mode 100644 index 000000000..5b09bc177 --- /dev/null +++ b/Vector/Views/RoomMember/RoomMemberTitleView.xib @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vector/Views/TableViewCell/TableViewCellWithButton.h b/Vector/Views/TableViewCell/TableViewCellWithButton.h new file mode 100644 index 000000000..74bae2970 --- /dev/null +++ b/Vector/Views/TableViewCell/TableViewCellWithButton.h @@ -0,0 +1,21 @@ +/* + 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 "MXKTableViewCellWithButton.h" + +@interface TableViewCellWithButton : MXKTableViewCellWithButton + +@end \ No newline at end of file diff --git a/Vector/Views/TableViewCell/TableViewCellWithButton.m b/Vector/Views/TableViewCell/TableViewCellWithButton.m new file mode 100644 index 000000000..cc2b65d5b --- /dev/null +++ b/Vector/Views/TableViewCell/TableViewCellWithButton.m @@ -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 "TableViewCellWithButton.h" + +@implementation TableViewCellWithButton + +@end + diff --git a/Vector/Views/TableViewCell/TableViewCellWithButton.xib b/Vector/Views/TableViewCell/TableViewCellWithButton.xib new file mode 100644 index 000000000..53efde0be --- /dev/null +++ b/Vector/Views/TableViewCell/TableViewCellWithButton.xib @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +