mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-22 17:42:45 +02:00
Modular integrations UI: File renaming
This commit is contained in:
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
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 "IntegrationManagerViewController.h"
|
||||
|
||||
#import "WidgetManager.h"
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
NSString *kJavascriptSendResponseToModular = @"riotIOS.sendResponse('%@', %@);";
|
||||
|
||||
|
||||
@interface IntegrationManagerViewController ()
|
||||
{
|
||||
MXSession *mxSession;
|
||||
NSString *roomId;
|
||||
NSString *screen;
|
||||
NSString *widgetId;
|
||||
NSString *scalarToken;
|
||||
|
||||
MXHTTPOperation *operation;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IntegrationManagerViewController
|
||||
|
||||
- (instancetype)initForMXSession:(MXSession *)theMXSession inRoom:(NSString *)theRoomId screen:(NSString *)theScreen widgetId:(NSString *)theWidgetId
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
mxSession = theMXSession;
|
||||
roomId = theRoomId;
|
||||
screen = theScreen;
|
||||
widgetId = theWidgetId;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
[super destroy];
|
||||
|
||||
[operation cancel];
|
||||
operation = nil;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
webView.scalesPageToFit = NO;
|
||||
|
||||
webView.delegate = self;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if (!self.URL && !operation)
|
||||
{
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
|
||||
[self startActivityIndicator];
|
||||
|
||||
// Make sure we a scalar token
|
||||
operation = [[WidgetManager sharedManager] getScalarTokenForMXSession:mxSession success:^(NSString *theScalarToken) {
|
||||
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
if (self)
|
||||
{
|
||||
self->operation = nil;
|
||||
[self stopActivityIndicator];
|
||||
|
||||
scalarToken = theScalarToken;
|
||||
|
||||
// Launch the webview on the right modular webapp page
|
||||
self.URL = [self interfaceUrl];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
if (self)
|
||||
{
|
||||
self->operation = nil;
|
||||
[self stopActivityIndicator];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
/**
|
||||
Build the URL to use in the Modular interface webapp.
|
||||
*/
|
||||
- (NSString *)interfaceUrl
|
||||
{
|
||||
NSMutableString *url;
|
||||
|
||||
if (scalarToken)
|
||||
{
|
||||
url = [NSMutableString stringWithFormat:@"%@?scalar_token=%@&room_id=%@",
|
||||
[[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsUiUrl"],
|
||||
[scalarToken stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
[roomId stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
|
||||
];
|
||||
|
||||
if (screen)
|
||||
{
|
||||
[url appendString:@"&screen="];
|
||||
[url appendString:[screen stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
|
||||
if (widgetId)
|
||||
{
|
||||
[url appendString:@"&integ_id="];
|
||||
[url appendString:[widgetId stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
- (void)enableDebug
|
||||
{
|
||||
// Setup console.log() -> NSLog() route
|
||||
JSContext *ctx = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
|
||||
ctx[@"console"][@"log"] = ^(JSValue * msg) {
|
||||
NSLog(@"-- JavaScript: %@", msg);
|
||||
};
|
||||
|
||||
// Redirect all console.* logging methods to console.log
|
||||
[webView stringByEvaluatingJavaScriptFromString:@"console.debug = console.log; console.info = console.log; console.warn = console.log; console.error = console.log;"];
|
||||
}
|
||||
|
||||
#pragma mark - UIWebViewDelegate
|
||||
|
||||
-(void)webViewDidFinishLoad:(UIWebView *)theWebView
|
||||
{
|
||||
[self enableDebug];
|
||||
|
||||
// Setup js code
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"IntegrationManager" ofType:@"js"];
|
||||
NSString *js = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
|
||||
[webView stringByEvaluatingJavaScriptFromString:js];
|
||||
}
|
||||
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
|
||||
{
|
||||
NSString *urlString = [[request URL] absoluteString];
|
||||
|
||||
if ([urlString hasPrefix:@"js:"])
|
||||
{
|
||||
// Listen only to scheme of the JS-UIWebView bridge
|
||||
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
|
||||
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
NSError *error;
|
||||
NSDictionary *parameters = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers
|
||||
error:&error];
|
||||
if (!error)
|
||||
{
|
||||
[self onMessage:parameters];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Modular postMessage API
|
||||
|
||||
- (void)onMessage:(NSDictionary*)JSData
|
||||
{
|
||||
NSDictionary *eventData;
|
||||
MXJSONModelSetDictionary(eventData, JSData[@"event.data"]);
|
||||
|
||||
NSString *roomIdInEvent, *userId, *action;
|
||||
|
||||
MXJSONModelSetString(roomIdInEvent, eventData[@"room_id"]);
|
||||
MXJSONModelSetString(userId, eventData[@"user_id"]);
|
||||
MXJSONModelSetString(action, eventData[@"action"]);
|
||||
|
||||
if (!roomIdInEvent)
|
||||
{
|
||||
[self sendLocalisedError:@"widget_integration_missing_room_id" toEvent:eventData];
|
||||
return;
|
||||
}
|
||||
|
||||
if (![roomIdInEvent isEqualToString:roomId])
|
||||
{
|
||||
[self sendError:[NSString stringWithFormat:NSLocalizedStringFromTable(@"widget_integration_room_not_visible", @"Vector", nil), roomIdInEvent] toEvent:eventData];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// These APIs don't require userId
|
||||
if ([@"join_rules_state" isEqualToString:action])
|
||||
{
|
||||
//getJoinRules(event, roomId);
|
||||
return;
|
||||
}
|
||||
else if ([@"set_plumbing_state" isEqualToString:action])
|
||||
{
|
||||
//setPlumbingState(event, roomId, event.data.status);
|
||||
return;
|
||||
}
|
||||
else if ([@"get_membership_count" isEqualToString:action])
|
||||
{
|
||||
//getMembershipCount(event, roomId);
|
||||
return;
|
||||
}
|
||||
else if ([@"set_widget" isEqualToString:action])
|
||||
{
|
||||
//setWidget(event, roomId);
|
||||
return;
|
||||
}
|
||||
else if ([@"get_widgets" isEqualToString:action])
|
||||
{
|
||||
[self getWidgets:eventData];
|
||||
return;
|
||||
}
|
||||
else if ([@"can_send_event" isEqualToString:action])
|
||||
{
|
||||
[self canSendEvent:eventData];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!userId)
|
||||
{
|
||||
[self sendLocalisedError:@"widget_integration_missing_user_id" toEvent:eventData];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([@"membership_state" isEqualToString:action])
|
||||
{
|
||||
[self getMembershipState:userId eventData:eventData];
|
||||
}
|
||||
else if ([@"invite" isEqualToString:action])
|
||||
{
|
||||
//inviteUser(event, roomId, userId);
|
||||
}
|
||||
else if ([@"bot_options" isEqualToString:action])
|
||||
{
|
||||
//botOptions(event, roomId, userId);
|
||||
}
|
||||
else if ([@"set_bot_options" isEqualToString:action])
|
||||
{
|
||||
//setBotOptions(event, roomId, userId);
|
||||
}
|
||||
else if ([@"set_bot_power" isEqualToString:action])
|
||||
{
|
||||
//setBotPower(event, roomId, userId, event.data.level);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[IntegrationManagerViewControllerVC] Unhandled postMessage event with action %@: %@", action, JSData);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendBoolResponse:(BOOL)response toEvent:(NSDictionary*)eventData
|
||||
{
|
||||
// Convert BOOL to "true" or "false"
|
||||
NSString *js = [NSString stringWithFormat:kJavascriptSendResponseToModular,
|
||||
eventData[@"_id"],
|
||||
response ? @"true" : @"false"];
|
||||
|
||||
[webView stringByEvaluatingJavaScriptFromString:js];
|
||||
}
|
||||
|
||||
- (void)sendNSObjectResponse:(NSObject*)response toEvent:(NSDictionary*)eventData
|
||||
{
|
||||
NSString *jsString;
|
||||
|
||||
if (response)
|
||||
{
|
||||
// Convert response into a JS object through a JSON string
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:response
|
||||
options:0
|
||||
error:0];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
|
||||
jsString = [NSString stringWithFormat:@"JSON.parse('%@')", jsonString];
|
||||
}
|
||||
else
|
||||
{
|
||||
jsString = @"null";
|
||||
}
|
||||
|
||||
NSString *js = [NSString stringWithFormat:kJavascriptSendResponseToModular,
|
||||
eventData[@"_id"],
|
||||
jsString];
|
||||
|
||||
[webView stringByEvaluatingJavaScriptFromString:js];
|
||||
}
|
||||
|
||||
- (void)sendError:(NSString*)message toEvent:(NSDictionary*)eventData
|
||||
{
|
||||
// TODO: JS has an additional optional parameter: nestedError
|
||||
[self sendNSObjectResponse:@{
|
||||
@"error": @{
|
||||
@"message": message
|
||||
}
|
||||
}
|
||||
toEvent:eventData];
|
||||
}
|
||||
|
||||
- (void)sendLocalisedError:(NSString*)errorKey toEvent:(NSDictionary*)eventData
|
||||
{
|
||||
[self sendError:NSLocalizedStringFromTable(errorKey, @"Vector", nil) toEvent:eventData];
|
||||
}
|
||||
|
||||
#pragma mark - Modular postMessage Implementation
|
||||
|
||||
- (MXRoom *)roomCheckWithEvent:(NSDictionary*)eventData
|
||||
{
|
||||
MXRoom *room = [mxSession roomWithRoomId:roomId];
|
||||
if (!room)
|
||||
{
|
||||
[self sendLocalisedError:@"widget_integration_room_not_recognised" toEvent:eventData];
|
||||
}
|
||||
|
||||
return room;
|
||||
}
|
||||
|
||||
- (void)getWidgets:(NSDictionary*)eventData
|
||||
{
|
||||
MXRoom *room = [self roomCheckWithEvent:eventData];
|
||||
|
||||
if (room)
|
||||
{
|
||||
NSArray<Widget*> *widgets = [[WidgetManager sharedManager] widgetsInRoom:room];
|
||||
|
||||
NSMutableArray<NSDictionary*> *widgetStateEvents = [NSMutableArray arrayWithCapacity:widgets.count];
|
||||
|
||||
for (Widget *widget in widgets)
|
||||
{
|
||||
[widgetStateEvents addObject:widget.widgetEvent.JSONDictionary];
|
||||
}
|
||||
|
||||
[self sendNSObjectResponse:widgetStateEvents toEvent:eventData];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)canSendEvent:(NSDictionary*)eventData
|
||||
{
|
||||
NSString *eventType;
|
||||
BOOL isState = NO;
|
||||
|
||||
MXRoom *room = [self roomCheckWithEvent:eventData];
|
||||
|
||||
if (room)
|
||||
{
|
||||
if (room.state.membership != MXMembershipJoin)
|
||||
{
|
||||
[self sendLocalisedError:@"widget_integration_must_be_in_room" toEvent:eventData];
|
||||
return;
|
||||
}
|
||||
|
||||
MXJSONModelSetString(eventType, eventData[@"event_type"]);
|
||||
MXJSONModelSetBoolean(isState, eventData[@"is_state"]);
|
||||
|
||||
MXRoomPowerLevels *powerLevels = room.state.powerLevels;
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:mxSession.myUser.userId];
|
||||
|
||||
BOOL canSend = NO;
|
||||
|
||||
if (isState)
|
||||
{
|
||||
canSend = (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:eventType]);
|
||||
}
|
||||
else
|
||||
{
|
||||
canSend = (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsMessage:eventType]);
|
||||
}
|
||||
|
||||
if (canSend)
|
||||
{
|
||||
[self sendBoolResponse:YES toEvent:eventData];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self sendLocalisedError:@"widget_integration_no_permission_in_room" toEvent:eventData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)getMembershipState:(NSString*)userId eventData:(NSDictionary*)eventData
|
||||
{
|
||||
MXRoom *room = [self roomCheckWithEvent:eventData];
|
||||
|
||||
if (room)
|
||||
{
|
||||
MXRoomMember *member = [room.state memberWithUserId:userId];
|
||||
[self sendNSObjectResponse:member.originalEvent.JSONDictionary toEvent:eventData];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user