Merge pull request #1535 from vector-im/list_widgets

Widgets: list active widgets in a room
This commit is contained in:
manuroe 2017-09-28 10:01:43 +02:00 committed by GitHub
commit 3ab1863a49
6 changed files with 233 additions and 25 deletions

View file

@ -73,6 +73,7 @@
32AE61F21F0D2183007255F4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32AE61EC1F0D2183007255F4 /* InfoPlist.strings */; };
32AE61F31F0D2183007255F4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32AE61EE1F0D2183007255F4 /* Localizable.strings */; };
32AE61F41F0D2183007255F4 /* Vector.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32AE61F01F0D2183007255F4 /* Vector.strings */; };
32C2356F1F7B871800E38FC5 /* WidgetPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */; };
32D392181EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D392161EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m */; };
32D392191EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32D392171EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib */; };
32E84FA11F6BD32700CA0B89 /* apps-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 32E84F9E1F6BD32700CA0B89 /* apps-icon.png */; };
@ -81,8 +82,8 @@
32F3AE1A1F6FF4E600F0F004 /* WidgetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F3AE191F6FF4E600F0F004 /* WidgetViewController.m */; };
32FD0A3D1EB0CD9B0072B066 /* BugReportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FD0A3B1EB0CD9B0072B066 /* BugReportViewController.m */; };
32FD0A3E1EB0CD9B0072B066 /* BugReportViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32FD0A3C1EB0CD9B0072B066 /* BugReportViewController.xib */; };
92324BE31F4F66D3009DE194 /* IncomingCallView.m in Sources */ = {isa = PBXBuildFile; fileRef = 92324BE21F4F66D3009DE194 /* IncomingCallView.m */; };
83711A7C1F6F8E7D008F0D4D /* KeyboardGrowingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83711A7B1F6F8E7D008F0D4D /* KeyboardGrowingTextView.m */; };
92324BE31F4F66D3009DE194 /* IncomingCallView.m in Sources */ = {isa = PBXBuildFile; fileRef = 92324BE21F4F66D3009DE194 /* IncomingCallView.m */; };
92324BE61F4F6A60009DE194 /* CircleButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 92324BE51F4F6A60009DE194 /* CircleButton.m */; };
A27ECCE3FC4971745D2CB78D /* libPods-RiotShareExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7246451C668D6782166E22EC /* libPods-RiotShareExtension.a */; };
F0131DE51F2200D600CBF707 /* RiotSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F0131DE41F2200D600CBF707 /* RiotSplitViewController.m */; };
@ -650,6 +651,8 @@
32AE61ED1F0D2183007255F4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = InfoPlist.strings; sourceTree = "<group>"; };
32AE61EF1F0D2183007255F4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = Localizable.strings; sourceTree = "<group>"; };
32AE61F11F0D2183007255F4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = Vector.strings; sourceTree = "<group>"; };
32C2356D1F7B871800E38FC5 /* WidgetPickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WidgetPickerViewController.h; sourceTree = "<group>"; };
32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WidgetPickerViewController.m; sourceTree = "<group>"; };
32D392151EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryServerDetailTableViewCell.h; sourceTree = "<group>"; };
32D392161EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryServerDetailTableViewCell.m; sourceTree = "<group>"; };
32D392171EB9B7AB009A2BAF /* DirectoryServerDetailTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DirectoryServerDetailTableViewCell.xib; sourceTree = "<group>"; };
@ -1351,6 +1354,8 @@
3233F72E1F31F4BF006ACA81 /* JitsiViewController.h */,
3233F72F1F31F4BF006ACA81 /* JitsiViewController.m */,
3233F7301F31F4BF006ACA81 /* JitsiViewController.xib */,
32C2356D1F7B871800E38FC5 /* WidgetPickerViewController.h */,
32C2356E1F7B871800E38FC5 /* WidgetPickerViewController.m */,
);
path = Widgets;
sourceTree = "<group>";
@ -2972,7 +2977,7 @@
"${PODS_ROOT}/MatrixKit/MatrixKit/Views/RoomTitle/MXKRoomTitleView.xib",
"${PODS_ROOT}/MatrixKit/MatrixKit/Views/RoomTitle/MXKRoomTitleViewWithTopic.xib",
"${PODS_ROOT}/MatrixKit/MatrixKit/Views/Search/MXKSearchTableViewCell.xib",
"$PODS_CONFIGURATION_BUILD_DIR/MatrixKit/MatrixKit.bundle",
$PODS_CONFIGURATION_BUILD_DIR/MatrixKit/MatrixKit.bundle,
"${PODS_ROOT}/MatrixSDK/MatrixSDK/Data/Store/MXCoreDataStore/MXCoreDataStore.xcdatamodeld",
);
name = "[CP] Copy Pods Resources";
@ -3078,6 +3083,7 @@
32471CDC1F1373A100BDF50A /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */,
F083BE2B1E7009ED00A9B29C /* AuthInputsView.m in Sources */,
321082B21F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.m in Sources */,
32C2356F1F7B871800E38FC5 /* WidgetPickerViewController.m in Sources */,
F083BE661E7009ED00A9B29C /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */,
F083BE141E7009ED00A9B29C /* HomeViewController.m in Sources */,
F083BDFB1E7009ED00A9B29C /* RoomSearchDataSource.m in Sources */,

View file

@ -72,12 +72,20 @@ WidgetManagerErrorCode;
/**
List all active widgets of a given type in a room.
@param widgetType the types of widget to search.
@param widgetTypes the types of widget to search. Nil means all types.
@param room the room to check.
@return a list of widgets.
*/
- (NSArray<Widget*> *)widgetsOfTypes:(NSArray<NSString*>*)widgetTypes inRoom:(MXRoom*)room;
/**
List all active widgets of a given type in a room, excluding some types.
@param notWidgetTypes the types of widget to not consider. Nil means all types.
@param room the room to check.
@return a list of widgets.
*/
- (NSArray<Widget*> *)widgetsNotOfTypes:(NSArray<NSString*>*)notWidgetTypes inRoom:(MXRoom*)room;
/**
Add a modular widget to a room.

View file

@ -87,7 +87,17 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
return [self widgetsOfTypes:nil inRoom:room];
}
- (NSArray<Widget *> *)widgetsOfTypes:(NSArray<NSString *> *)widgetTypes inRoom:(MXRoom *)room
- (NSArray<Widget*> *)widgetsOfTypes:(NSArray<NSString*>*)widgetTypes inRoom:(MXRoom*)room;
{
return [self widgetsOfTypes:widgetTypes butNotTypesOf:nil inRoom:room];
}
- (NSArray<Widget*> *)widgetsNotOfTypes:(NSArray<NSString*>*)notWidgetTypes inRoom:(MXRoom*)room
{
return [self widgetsOfTypes:nil butNotTypesOf:notWidgetTypes inRoom:room];
}
- (NSArray<Widget*> *)widgetsOfTypes:(NSArray<NSString*>*)widgetTypes butNotTypesOf:(NSArray<NSString*>*)notWidgetTypes inRoom:(MXRoom*)room;
{
// Widget id -> widget
NSMutableDictionary <NSString*, Widget *> *widgets = [NSMutableDictionary dictionary];
@ -118,14 +128,21 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
for (MXEvent *widgetEvent in widgetEvents)
{
// Filter widget types if required
if (widgetTypes)
if (widgetTypes || notWidgetTypes)
{
NSString *widgetType;
MXJSONModelSetString(widgetType, widgetEvent.content[@"type"]);
if (widgetType && NSNotFound == [widgetTypes indexOfObject:widgetType])
if (widgetType)
{
continue;
if (widgetTypes && NSNotFound == [widgetTypes indexOfObject:widgetType])
{
continue;
}
if (notWidgetTypes && NSNotFound != [notWidgetTypes indexOfObject:widgetType])
{
continue;
}
}
}

View file

@ -110,7 +110,7 @@
#import "MXRoom+Riot.h"
#import "IntegrationManagerViewController.h"
#import "WidgetViewController.h"
#import "WidgetPickerViewController.h"
@interface RoomViewController ()
{
@ -1197,13 +1197,31 @@
barButtonItem.enabled = YES;
}
BOOL matrixAppsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"matrixApps"];
if (!matrixAppsEnabled && self.navigationItem.rightBarButtonItems.count == 2)
if (self.navigationItem.rightBarButtonItems.count == 2)
{
// If the setting is disabled, do not show the icon
self.navigationItem.rightBarButtonItems = @[self.navigationItem.rightBarButtonItem];
BOOL matrixAppsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"matrixApps"];
if (!matrixAppsEnabled)
{
// If the setting is disabled, do not show the icon
self.navigationItem.rightBarButtonItems = @[self.navigationItem.rightBarButtonItem];
}
else if (self.widgetsCount)
{
// Show there are widgets by changing the "apps" icon color
// TODO: Design must be reviewed
UIImage *icon = self.navigationItem.rightBarButtonItems[1].image;
icon = [MXKTools paintImage:icon withColor:kRiotColorPinkRed];
icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.navigationItem.rightBarButtonItems[1].image = icon;
}
else
{
// Reset original icon
self.navigationItem.rightBarButtonItems[1].image = [UIImage imageNamed:@"apps-icon"];
}
}
// Do not change title view class here if the expanded header is visible.
if (self.expandedHeaderContainer.hidden)
{
@ -2889,19 +2907,16 @@
// Matrix Apps button
else if (self.navigationItem.rightBarButtonItems.count == 2 && sender == self.navigationItem.rightBarButtonItems[1])
{
// Temporary code to test `WidgetViewController`
// TODO: remove it
// NSArray<Widget *> *widgets = [[WidgetManager sharedManager] widgetsInRoom:self.roomDataSource.room];
// if (widgets.count)
// {
// // Hide back button title
// self.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
//
// WidgetViewController *widgetVC = [[WidgetViewController alloc] initForWidget:widgets[0]];
// [self.navigationController pushViewController:widgetVC animated:YES];
// }
// else
if (self.widgetsCount)
{
WidgetPickerViewController *widgetPicker = [[WidgetPickerViewController alloc] initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId];
[widgetPicker showInViewController:self];
}
else
{
// No widgets -> Directly show the integration manager
IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] initForMXSession:self.roomDataSource.mxSession
inRoom:self.roomDataSource.roomId
screen:kIntegrationManagerMainScreen
@ -3453,6 +3468,7 @@
// Update the bar
[self refreshActivitiesViewDisplay];
[self refreshRoomInputToolbar];
[self refreshRoomTitle];
}
}];
}
@ -3473,6 +3489,12 @@
[[AppDelegate theDelegate] showErrorAsAlert:error];
}
- (NSUInteger)widgetsCount
{
return [[WidgetManager sharedManager] widgetsNotOfTypes:@[kWidgetTypeJitsi]
inRoom:self.roomDataSource.room].count;
}
#pragma mark - Unreachable Network Handling
- (void)refreshActivitiesViewDisplay

View file

@ -0,0 +1,56 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <UIKit/UIKit.h>
#import <MatrixSDK/MatrixSDK.h>
#import <MatrixKit/MatrixKit.h>
/**
`WidgetPickerViewController` displays the list of widgets within a room plus a
way to open the integration manager for this room.
TODO: The feature is still in dev. WidgetPickerViewController` is not yet a pure
UIViewController.
As there is no specified design, the list is displayed in a simple UIAlertController.
It would be nice if this picker could directly:
- Remove a widget
- Launch the integration manager to edit a widget
- Automatically updates on widgets change
*/
@interface WidgetPickerViewController : NSObject
/**
The UIAlertController instance which handles the dialog.
*/
@property (nonatomic, readonly) UIAlertController *alertController;
/**
Create the `WidgetPickerViewController` instance.
@param mxSession the session to use.
@param roomId the room where to list available widgets.
*/
- (instancetype)initForMXSession:(MXSession*)mxSession inRoom:(NSString*)roomId;
/**
Show the dialog in a given view controller.
@param mxkViewController the mxkViewController where to show the dialog.
*/
- (void)showInViewController:(MXKViewController*)mxkViewController;
@end

View file

@ -0,0 +1,99 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "WidgetPickerViewController.h"
#import "AppDelegate.h"
#import "WidgetManager.h"
#import "WidgetViewController.h"
#import "IntegrationManagerViewController.h"
@interface WidgetPickerViewController ()
{
MXSession *mxSession;
NSString *roomId;
}
@end
@implementation WidgetPickerViewController
- (instancetype)initForMXSession:(MXSession*)theMXSession inRoom:(NSString*)theRoomId
{
self = [super init];
if (self)
{
mxSession = theMXSession;
roomId = theRoomId;
_alertController = [UIAlertController alertControllerWithTitle:@"Matrix Apps"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
}
return self;
}
- (void)showInViewController:(MXKViewController *)mxkViewController
{
UIAlertAction *alertAction;
MXRoom *room = [mxSession roomWithRoomId:roomId];
NSArray<Widget*> *widgets = [[WidgetManager sharedManager] widgetsNotOfTypes:@[kWidgetTypeJitsi]
inRoom:room];
// List widgets
for (Widget *widget in widgets)
{
alertAction = [UIAlertAction actionWithTitle:widget.name
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action)
{
// Hide back button title
mxkViewController.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
// Display the widget
WidgetViewController *widgetVC = [[WidgetViewController alloc] initForWidget:widget];
[mxkViewController.navigationController pushViewController:widgetVC animated:YES];
}];
[_alertController addAction:alertAction];
}
// Link to the integration manager
alertAction = [UIAlertAction actionWithTitle:@"Manage integrations..."
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action)
{
IntegrationManagerViewController *modularVC = [[IntegrationManagerViewController alloc] initForMXSession:self->mxSession
inRoom:self->roomId
screen:kIntegrationManagerMainScreen
widgetId:nil];
[mxkViewController presentViewController:modularVC animated:NO completion:nil];
}];
[_alertController addAction:alertAction];
// Cancel
alertAction = [UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:nil];
[_alertController addAction:alertAction];
// And show it
[mxkViewController presentViewController:_alertController animated:YES completion:nil];
}
@end