This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
6.9 KiB
202 lines
6.9 KiB
/** |
|
* Copyright (c) 2015-present, Facebook, Inc. |
|
* |
|
* This source code is licensed under the MIT license found in the |
|
* LICENSE file in the root directory of this source tree. |
|
*/ |
|
|
|
#import "RCTActionSheetManager.h" |
|
|
|
#import <React/RCTBridge.h> |
|
#import <React/RCTConvert.h> |
|
#import <React/RCTLog.h> |
|
#import <React/RCTUIManager.h> |
|
#import <React/RCTUtils.h> |
|
|
|
@interface RCTActionSheetManager () <UIActionSheetDelegate> |
|
@end |
|
|
|
@implementation RCTActionSheetManager |
|
{ |
|
// Use NSMapTable, as UIAlertViews do not implement <NSCopying> |
|
// which is required for NSDictionary keys |
|
NSMapTable *_callbacks; |
|
} |
|
|
|
RCT_EXPORT_MODULE() |
|
|
|
@synthesize bridge = _bridge; |
|
|
|
- (dispatch_queue_t)methodQueue |
|
{ |
|
return dispatch_get_main_queue(); |
|
} |
|
|
|
/* |
|
* The `anchor` option takes a view to set as the anchor for the share |
|
* popup to point to, on iPads running iOS 8. If it is not passed, it |
|
* defaults to centering the share popup on screen without any arrows. |
|
*/ |
|
- (CGRect)sourceRectInView:(UIView *)sourceView |
|
anchorViewTag:(NSNumber *)anchorViewTag |
|
{ |
|
if (anchorViewTag) { |
|
UIView *anchorView = [self.bridge.uiManager viewForReactTag:anchorViewTag]; |
|
return [anchorView convertRect:anchorView.bounds toView:sourceView]; |
|
} else { |
|
return (CGRect){sourceView.center, {1, 1}}; |
|
} |
|
} |
|
|
|
RCT_EXPORT_METHOD(showActionSheetWithOptions:(NSDictionary *)options |
|
callback:(RCTResponseSenderBlock)callback) |
|
{ |
|
if (RCTRunningInAppExtension()) { |
|
RCTLogError(@"Unable to show action sheet from app extension"); |
|
return; |
|
} |
|
|
|
if (!_callbacks) { |
|
_callbacks = [NSMapTable strongToStrongObjectsMapTable]; |
|
} |
|
|
|
NSString *title = [RCTConvert NSString:options[@"title"]]; |
|
NSString *message = [RCTConvert NSString:options[@"message"]]; |
|
NSArray<NSString *> *buttons = [RCTConvert NSStringArray:options[@"options"]]; |
|
NSInteger destructiveButtonIndex = options[@"destructiveButtonIndex"] ? [RCTConvert NSInteger:options[@"destructiveButtonIndex"]] : -1; |
|
NSInteger cancelButtonIndex = options[@"cancelButtonIndex"] ? [RCTConvert NSInteger:options[@"cancelButtonIndex"]] : -1; |
|
|
|
UIViewController *controller = RCTPresentedViewController(); |
|
|
|
if (controller == nil) { |
|
RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", options); |
|
return; |
|
} |
|
|
|
/* |
|
* The `anchor` option takes a view to set as the anchor for the share |
|
* popup to point to, on iPads running iOS 8. If it is not passed, it |
|
* defaults to centering the share popup on screen without any arrows. |
|
*/ |
|
NSNumber *anchorViewTag = [RCTConvert NSNumber:options[@"anchor"]]; |
|
UIView *sourceView = controller.view; |
|
CGRect sourceRect = [self sourceRectInView:sourceView anchorViewTag:anchorViewTag]; |
|
|
|
UIAlertController *alertController = |
|
[UIAlertController alertControllerWithTitle:title |
|
message:message |
|
preferredStyle:UIAlertControllerStyleActionSheet]; |
|
|
|
NSInteger index = 0; |
|
for (NSString *option in buttons) { |
|
UIAlertActionStyle style = UIAlertActionStyleDefault; |
|
if (index == destructiveButtonIndex) { |
|
style = UIAlertActionStyleDestructive; |
|
} else if (index == cancelButtonIndex) { |
|
style = UIAlertActionStyleCancel; |
|
} |
|
|
|
NSInteger localIndex = index; |
|
[alertController addAction:[UIAlertAction actionWithTitle:option |
|
style:style |
|
handler:^(__unused UIAlertAction *action){ |
|
callback(@[@(localIndex)]); |
|
}]]; |
|
|
|
index++; |
|
} |
|
|
|
alertController.modalPresentationStyle = UIModalPresentationPopover; |
|
alertController.popoverPresentationController.sourceView = sourceView; |
|
alertController.popoverPresentationController.sourceRect = sourceRect; |
|
if (!anchorViewTag) { |
|
alertController.popoverPresentationController.permittedArrowDirections = 0; |
|
} |
|
[controller presentViewController:alertController animated:YES completion:nil]; |
|
|
|
alertController.view.tintColor = [RCTConvert UIColor:options[@"tintColor"]]; |
|
} |
|
|
|
RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options |
|
failureCallback:(RCTResponseErrorBlock)failureCallback |
|
successCallback:(RCTResponseSenderBlock)successCallback) |
|
{ |
|
if (RCTRunningInAppExtension()) { |
|
RCTLogError(@"Unable to show action sheet from app extension"); |
|
return; |
|
} |
|
|
|
NSMutableArray<id> *items = [NSMutableArray array]; |
|
NSString *message = [RCTConvert NSString:options[@"message"]]; |
|
if (message) { |
|
[items addObject:message]; |
|
} |
|
NSURL *URL = [RCTConvert NSURL:options[@"url"]]; |
|
if (URL) { |
|
if ([URL.scheme.lowercaseString isEqualToString:@"data"]) { |
|
NSError *error; |
|
NSData *data = [NSData dataWithContentsOfURL:URL |
|
options:(NSDataReadingOptions)0 |
|
error:&error]; |
|
if (!data) { |
|
failureCallback(error); |
|
return; |
|
} |
|
[items addObject:data]; |
|
} else { |
|
[items addObject:URL]; |
|
} |
|
} |
|
if (items.count == 0) { |
|
RCTLogError(@"No `url` or `message` to share"); |
|
return; |
|
} |
|
|
|
UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; |
|
|
|
NSString *subject = [RCTConvert NSString:options[@"subject"]]; |
|
if (subject) { |
|
[shareController setValue:subject forKey:@"subject"]; |
|
} |
|
|
|
NSArray *excludedActivityTypes = [RCTConvert NSStringArray:options[@"excludedActivityTypes"]]; |
|
if (excludedActivityTypes) { |
|
shareController.excludedActivityTypes = excludedActivityTypes; |
|
} |
|
|
|
UIViewController *controller = RCTPresentedViewController(); |
|
shareController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, __unused NSArray *returnedItems, NSError *activityError) { |
|
if (activityError) { |
|
failureCallback(activityError); |
|
} else { |
|
successCallback(@[@(completed), RCTNullIfNil(activityType)]); |
|
} |
|
}; |
|
|
|
shareController.modalPresentationStyle = UIModalPresentationPopover; |
|
NSNumber *anchorViewTag = [RCTConvert NSNumber:options[@"anchor"]]; |
|
if (!anchorViewTag) { |
|
shareController.popoverPresentationController.permittedArrowDirections = 0; |
|
} |
|
shareController.popoverPresentationController.sourceView = controller.view; |
|
shareController.popoverPresentationController.sourceRect = [self sourceRectInView:controller.view anchorViewTag:anchorViewTag]; |
|
|
|
[controller presentViewController:shareController animated:YES completion:nil]; |
|
|
|
shareController.view.tintColor = [RCTConvert UIColor:options[@"tintColor"]]; |
|
} |
|
|
|
#pragma mark UIActionSheetDelegate Methods |
|
|
|
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex |
|
{ |
|
RCTResponseSenderBlock callback = [_callbacks objectForKey:actionSheet]; |
|
if (callback) { |
|
callback(@[@(buttonIndex)]); |
|
[_callbacks removeObjectForKey:actionSheet]; |
|
} else { |
|
RCTLogWarn(@"No callback registered for action sheet: %@", actionSheet.title); |
|
} |
|
} |
|
|
|
@end
|
|
|