├── README.md
├── .gitignore
├── DingTalkAssistant.plist
├── XcodeProject
└── DingTalkAssistant.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── buginux.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ ├── xcuserdata
│ └── buginux.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── DingTalkAssistant.xcscheme
│ └── project.pbxproj
├── control
├── GPS
├── WBGPSPickerViewController.h
└── WBGPSPickerViewController.m
├── WIFI
├── WBWifiListViewController.h
├── WBWifiStore.h
├── WBWifiModel.h
├── WBWifiModel.m
├── WBWifiStore.m
└── WBWifiListViewController.m
├── MenuWindow
├── WBMenuView.h
├── WBAssistantManager.h
├── WBWindow.h
├── WBMenuViewController.h
├── WBGlobalSettingViewController.h
├── WBWindow.m
├── WBMenuView.m
├── WBAssistantManager.m
├── WBGlobalSettingViewController.m
└── WBMenuViewController.m
├── Makefile
└── Tweak.xm
/README.md:
--------------------------------------------------------------------------------
1 | # 钉钉打卡助手
2 |
3 | 开发中...
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 | obj
3 | *.deb
4 | .theos/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/DingTalkAssistant.plist:
--------------------------------------------------------------------------------
1 | { Filter = { Bundles = ( "com.laiwang.DingTalk" ); }; }
2 |
--------------------------------------------------------------------------------
/XcodeProject/DingTalkAssistant.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/control:
--------------------------------------------------------------------------------
1 | Package: com.swiftyper.dingtalkassistant
2 | Name: DingTalkAssistant
3 | Depends: mobilesubstrate
4 | Version: 0.0.1
5 | Architecture: iphoneos-arm
6 | Description: An awesome MobileSubstrate tweak!
7 | Maintainer: buginux
8 | Author: buginux
9 | Section: Tweaks
10 |
--------------------------------------------------------------------------------
/XcodeProject/DingTalkAssistant.xcodeproj/project.xcworkspace/xcuserdata/buginux.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/buginux/DingTalkAssistant/HEAD/XcodeProject/DingTalkAssistant.xcodeproj/project.xcworkspace/xcuserdata/buginux.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/GPS/WBGPSPickerViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBGPSPickerViewController.h
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WBGPSPickerViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/WIFI/WBWifiListViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiListViewController.h
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WBWifiListViewController : UITableViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/MenuWindow/WBMenuView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBMenuView.h
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WBMenuView : UIView
12 |
13 | @property (nonatomic, strong) UIButton *menuButton;
14 | @property (nonatomic, strong) UIButton *closeButton;
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/MenuWindow/WBAssistantManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBAssistantManager.h
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WBAssistantManager : NSObject
12 |
13 | + (instancetype)sharedManager;
14 |
15 | - (void)showMenu;
16 | - (void)hideMenu;
17 | - (void)toggleMenu;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | THEOS_DEVICE_IP = localhost
2 | THEOS_DEVICE_PORT = 2222
3 |
4 | include $(THEOS)/makefiles/common.mk
5 |
6 | TWEAK_NAME = DingTalkAssistant
7 | DingTalkAssistant_FILES = $(wildcard MenuWindow/*.m) $(wildcard WIFI/*.m) $(wildcard GPS/*.m) Tweak.xm
8 | DingTalkAssistant_FRAMEWORKS = SystemConfiguration
9 |
10 | include $(THEOS_MAKE_PATH)/tweak.mk
11 |
12 | after-install::
13 | install.exec "killall -9 DingTalk"
14 |
--------------------------------------------------------------------------------
/GPS/WBGPSPickerViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBGPSPickerViewController.m
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBGPSPickerViewController.h"
10 |
11 | @interface WBGPSPickerViewController ()
12 |
13 | @end
14 |
15 | @implementation WBGPSPickerViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 |
20 | self.title = @"GPS 设置";
21 |
22 | self.view.backgroundColor = [UIColor whiteColor];
23 | }
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/MenuWindow/WBWindow.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBWindow.h
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol WBWindowEventDelegate;
12 |
13 | @interface WBWindow : UIWindow
14 |
15 | @property (nonatomic, unsafe_unretained) id eventDelegate;
16 |
17 | @end
18 |
19 | @protocol WBWindowEventDelegate
20 |
21 | - (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow;
22 | - (BOOL)canBecomeKeyWindow;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/XcodeProject/DingTalkAssistant.xcodeproj/xcuserdata/buginux.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | DingTalkAssistant.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | A21AED291F2A2AFD0004944A
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/WIFI/WBWifiStore.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiStore.h
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/29.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class WBWifiModel;
12 | @interface WBWifiStore : NSObject
13 |
14 | + (instancetype)sharedStore;
15 |
16 | @property (nonatomic, strong) NSMutableArray *currentWifiList;
17 | @property (nonatomic, strong) NSMutableArray *historyWifiList;
18 |
19 | - (void)fetchCurrentWifi;
20 | - (void)fetchHistoryWifi;
21 | - (void)appendHistoryWifi:(WBWifiModel *)wifi;
22 | - (void)saveHistoryWifi;
23 |
24 | - (void)hookWifi:(WBWifiModel *)wifi;
25 | - (WBWifiModel *)wifiHooked;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/MenuWindow/WBMenuViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBMenuViewController.h
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol WBMenuViewControllerDelegate;
12 |
13 | @interface WBMenuViewController : UIViewController
14 |
15 | @property (nonatomic, unsafe_unretained) id delegate;
16 |
17 | - (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates;
18 | - (BOOL)wantsWindowToBecomeKey;
19 |
20 | @end
21 |
22 | @protocol WBMenuViewControllerDelegate
23 |
24 | - (void)menuViewControllerDidFinish:(WBMenuViewController *)menuViewController;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/WIFI/WBWifiModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiModel.h
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/29.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface WBWifiModel : NSObject
13 |
14 | @property (nonatomic, strong) NSString *interfaceName;
15 | @property (nonatomic, copy) NSString *BSSID;
16 | @property (nonatomic, copy) NSData *SSIDData;
17 | @property (nonatomic, copy) NSString *SSID;
18 | @property (nonatomic, assign) SCNetworkReachabilityFlags flags;
19 |
20 | @property (nonatomic, assign) BOOL selected;
21 | @property (nonatomic, strong, readonly) NSString *wifiName;
22 |
23 | - (instancetype)initWithInterfaceName:(NSString *)ifname dictionary:(NSDictionary *)dictionary;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/MenuWindow/WBGlobalSettingViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // WBGlobalSettingViewController.h
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol WBGlobalSettingViewControllerDelegate;
12 |
13 | @interface WBGlobalSettingViewController : UITableViewController
14 |
15 | @property (nonatomic, unsafe_unretained) id delegate;
16 |
17 | /// We pretend that one of the app's windows is still the key window, even though the explorer window may have become key.
18 | /// We want to display debug state about the application, not about this tool.
19 | + (void)setApplicationWindow:(UIWindow *)applicationWindow;
20 |
21 | @end
22 |
23 | @protocol WBGlobalSettingViewControllerDelegate
24 |
25 | - (void)globalSettingViewControllerDidFinish:(WBGlobalSettingViewController *)viewController;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/MenuWindow/WBWindow.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBWindow.m
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBWindow.h"
10 |
11 | @implementation WBWindow
12 |
13 | - (instancetype)initWithFrame:(CGRect)frame {
14 | if (self = [super initWithFrame:frame]) {
15 | self.backgroundColor = [UIColor clearColor];
16 | // Some apps have windows at UIWindowLevelStatusBar + n.
17 | // If we make the window level too high, we block out UIAlertViews.
18 | // There's a balance between staying above the app's windows and staying below alerts.
19 | // UIWindowLevelStatusBar + 100 seems to hit that balance.
20 | self.windowLevel = UIWindowLevelStatusBar + 100.0;
21 | }
22 | return self;
23 | }
24 |
25 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
26 | BOOL pointInside = NO;
27 |
28 | if ([self.eventDelegate shouldHandleTouchAtPoint:point]) {
29 | pointInside = [super pointInside:point withEvent:event];
30 | }
31 |
32 | return pointInside;
33 | }
34 |
35 | - (BOOL)shouldAffectStatusBarAppearance {
36 | return [self isKeyWindow];
37 | }
38 |
39 |
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/MenuWindow/WBMenuView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBMenuView.m
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBMenuView.h"
10 |
11 | @implementation WBMenuView
12 |
13 | - (instancetype)initWithFrame:(CGRect)frame {
14 | if (self = [super initWithFrame:frame]) {
15 | [self commonInit];
16 | }
17 | return self;
18 | }
19 |
20 | - (void)commonInit {
21 | self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.2];
22 |
23 | UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
24 | [menuButton setTitle:@"菜单" forState:UIControlStateNormal];
25 | [menuButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
26 | menuButton.titleLabel.font = [UIFont systemFontOfSize:14.0];
27 | [menuButton sizeToFit];
28 | [self addSubview:menuButton];
29 | self.menuButton = menuButton;
30 |
31 | UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
32 | [closeButton setTitle:@"关闭" forState:UIControlStateNormal];
33 | closeButton.titleLabel.font = [UIFont systemFontOfSize:14.0];
34 | [closeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
35 | [closeButton sizeToFit];
36 | [self addSubview:closeButton];
37 | self.closeButton = closeButton;
38 |
39 | CGSize menuButtonSize = menuButton.frame.size;
40 | CGSize closeButtonSize = closeButton.frame.size;
41 | menuButton.frame = CGRectMake(8.0, 0.0, menuButtonSize.width, menuButtonSize.height);
42 | closeButton.frame = CGRectMake(CGRectGetMaxX(menuButton.frame) + 8.0, CGRectGetMinY(menuButton.frame), closeButtonSize.width, closeButtonSize.height);
43 | }
44 |
45 | - (CGSize)sizeThatFits:(CGSize)size {
46 | CGFloat width = CGRectGetMaxX(self.closeButton.frame) + 8.0;
47 | CGFloat height = CGRectGetHeight(self.menuButton.frame);
48 | return CGSizeMake(width, height);
49 | }
50 |
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/Tweak.xm:
--------------------------------------------------------------------------------
1 | #import "MenuWindow/WBAssistantManager.h"
2 | #import "WIFI/WBWifiStore.h"
3 | #import "WIFI/WBWifiModel.h"
4 | #import
5 |
6 | %hook DTAppDelegate
7 |
8 | - (void)applicationDidBecomeActive:(id)arg1 {
9 | %orig;
10 |
11 | [[WBAssistantManager sharedManager] showMenu];
12 | }
13 |
14 | %end
15 |
16 | CFArrayRef (*oldCNCopySupportedInterfaces)();
17 | CFDictionaryRef (*oldCNCopyCurrentNetworkInfo)(CFStringRef interfaceName);
18 | Boolean (*oldSCNetworkReachabilityGetFlags)(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags *flags);
19 |
20 | CFArrayRef newCNCopySupportedInterfaces() {
21 | CFArrayRef result = NULL;
22 |
23 | WBWifiModel *wifi = [[WBWifiStore sharedStore] wifiHooked];
24 |
25 | if(wifi && wifi.interfaceName) {
26 | NSArray *array = [NSArray arrayWithObject:wifi.interfaceName];
27 | result = (CFArrayRef)CFRetain((__bridge CFArrayRef)(array));
28 | }
29 |
30 | if(!result) {
31 | result = oldCNCopySupportedInterfaces();
32 | }
33 |
34 | return result;
35 | }
36 |
37 | CFDictionaryRef newCNCopyCurrentNetworkInfo(CFStringRef interfaceName) {
38 | CFDictionaryRef result = NULL;
39 |
40 | WBWifiModel *wifi = [[WBWifiStore sharedStore] wifiHooked];
41 | if(wifi) {
42 | NSDictionary *dictionary = @{
43 | @"BSSID": (wifi.BSSID ? wifi.BSSID : @""),
44 | @"SSID": (wifi.SSID ? wifi.SSID : @""),
45 | @"SSIDDATA": (wifi.SSIDData ? wifi.SSIDData : @"")
46 | };
47 | result = (CFDictionaryRef)CFRetain((__bridge CFDictionaryRef)(dictionary));
48 | }
49 |
50 | if(!result) {
51 | result = oldCNCopyCurrentNetworkInfo(interfaceName);
52 | }
53 |
54 | return result;
55 | }
56 |
57 | Boolean newSCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags *flags) {
58 | Boolean result = false;
59 |
60 | WBWifiModel *wifi = [[WBWifiStore sharedStore] wifiHooked];
61 | if(wifi && wifi.flags > 0) {
62 | result = true;
63 | *flags = wifi.flags;
64 | }
65 |
66 | if(!result) {
67 | result = oldSCNetworkReachabilityGetFlags(target, flags);
68 | }
69 |
70 | return result;
71 | }
72 |
73 | %ctor {
74 | %init;
75 |
76 | MSHookFunction(&CNCopySupportedInterfaces, &newCNCopySupportedInterfaces, &oldCNCopySupportedInterfaces);
77 | MSHookFunction(&CNCopyCurrentNetworkInfo, &newCNCopyCurrentNetworkInfo, &oldCNCopyCurrentNetworkInfo);
78 | MSHookFunction(&SCNetworkReachabilityGetFlags, &newSCNetworkReachabilityGetFlags, &oldSCNetworkReachabilityGetFlags);
79 | }
80 |
--------------------------------------------------------------------------------
/MenuWindow/WBAssistantManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBAssistantManager.m
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBAssistantManager.h"
10 | #import "WBWindow.h"
11 | #import "WBMenuViewController.h"
12 |
13 | @interface WBAssistantManager ()
14 |
15 | @property (nonatomic, strong) WBWindow *menuWindow;
16 | @property (nonatomic, strong) WBMenuViewController *menuViewController;
17 |
18 | @end
19 |
20 | @implementation WBAssistantManager
21 |
22 | + (instancetype)sharedManager {
23 | static WBAssistantManager *sharedManager = nil;
24 | static dispatch_once_t onceToken;
25 | dispatch_once(&onceToken, ^{
26 | sharedManager = [[[self class] alloc] init];
27 | });
28 | return sharedManager;
29 | }
30 |
31 | - (instancetype)init {
32 | if (self = [super init]) {
33 |
34 | }
35 | return self;
36 | }
37 |
38 | - (WBWindow *)menuWindow {
39 | NSAssert([NSThread isMainThread], @"You must use %@ from the main thread only.", NSStringFromClass([self class]));
40 | if (!_menuWindow) {
41 | _menuWindow = [[WBWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
42 | _menuWindow.eventDelegate = self;
43 | _menuWindow.rootViewController = self.menuViewController;
44 | }
45 | return _menuWindow;
46 | }
47 |
48 | - (WBMenuViewController *)menuViewController {
49 | if (!_menuViewController) {
50 | _menuViewController = [[WBMenuViewController alloc] init];
51 | _menuViewController.delegate = self;
52 | }
53 | return _menuViewController;
54 | }
55 |
56 | - (void)showMenu {
57 | self.menuWindow.hidden = NO;
58 | }
59 |
60 | - (void)hideMenu {
61 | self.menuWindow.hidden = YES;
62 | }
63 |
64 | - (void)toggleMenu {
65 | if (self.menuWindow.isHidden) {
66 | [self showMenu];
67 | } else {
68 | [self hideMenu];
69 | }
70 | }
71 |
72 | #pragma mark - WBWindowEventDelegate
73 |
74 | - (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow {
75 | return [self.menuViewController shouldReceiveTouchAtWindowPoint:pointInWindow];
76 | }
77 |
78 | - (BOOL)canBecomeKeyWindow {
79 | return [self.menuViewController wantsWindowToBecomeKey];
80 | }
81 |
82 | #pragma mark - WBMenuViewControllerDelegate
83 |
84 | - (void)menuViewControllerDidFinish:(WBMenuViewController *)menuViewController {
85 | [self hideMenu];
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/MenuWindow/WBGlobalSettingViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBGlobalSettingViewController.m
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBGlobalSettingViewController.h"
10 | #import "../GPS/WBGPSPickerViewController.h"
11 | #import "../WIFI/WBWifiListViewController.h"
12 |
13 | static UIWindow *s_applicationWindow = nil;
14 |
15 | @implementation WBGlobalSettingViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 |
20 | [self setupUI];
21 | }
22 |
23 | - (void)setupUI {
24 | self.title = @"设置";
25 |
26 | self.tableView.tableFooterView = [UIView new];
27 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonTapped:)];
28 | }
29 |
30 | + (void)setApplicationWindow:(UIWindow *)applicationWindow {
31 | s_applicationWindow = applicationWindow;
32 | }
33 |
34 | - (void)doneButtonTapped:(UIButton *)sender {
35 | [self.delegate globalSettingViewControllerDidFinish:self];
36 | }
37 |
38 | - (NSString *)titleForRowAtIndexPath:(NSIndexPath *)indexPath {
39 | if (indexPath.row == 0) {
40 | return @"GPS 设置";
41 | } else {
42 | return @"WIFI 设置";
43 | }
44 | }
45 |
46 | - (UIViewController *)viewControllerToPushForRowAtIndexPath:(NSIndexPath *)indexPath {
47 | if (indexPath.row == 0) {
48 | return [WBGPSPickerViewController new];
49 | } else {
50 | return [WBWifiListViewController new];
51 | }
52 | }
53 |
54 | #pragma mark - Table view data source
55 |
56 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
57 | return 2;
58 | }
59 |
60 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
61 | static NSString *CellIdentifier = @"Cell";
62 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
63 | if (!cell) {
64 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
65 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
66 | cell.textLabel.font = [UIFont systemFontOfSize:14.0];
67 | }
68 |
69 | cell.textLabel.text = [self titleForRowAtIndexPath:indexPath];
70 |
71 | return cell;
72 | }
73 |
74 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
75 | UIViewController *viewControllerToPush = [self viewControllerToPushForRowAtIndexPath:indexPath];
76 | [self.navigationController pushViewController:viewControllerToPush animated:YES];
77 | }
78 |
79 | @end
80 |
--------------------------------------------------------------------------------
/WIFI/WBWifiModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiModel.m
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/29.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBWifiModel.h"
10 |
11 | @interface WBWifiModel ()
12 |
13 | @end
14 |
15 | @implementation WBWifiModel
16 |
17 | - (void)encodeWithCoder:(NSCoder *)aCoder {
18 | [aCoder encodeObject:self.interfaceName forKey:@"ifnam"];
19 | [aCoder encodeInt32:self.flags forKey:@"flags"];
20 | [aCoder encodeObject:self.SSID forKey:@"SSID"];
21 | [aCoder encodeObject:self.BSSID forKey:@"BSSID"];
22 | [aCoder encodeObject:self.SSIDData forKey:@"SSIDDATA"];
23 | [aCoder encodeBool:self.selected forKey:@"selected"];
24 | }
25 |
26 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
27 | if (self = [super init]) {
28 | _interfaceName = [[aDecoder decodeObjectForKey:@"ifnam"] copy];
29 | _flags = [aDecoder decodeInt32ForKey:@"flags"];
30 | _SSID = [[aDecoder decodeObjectForKey:@"SSID"] copy];
31 | _BSSID = [[aDecoder decodeObjectForKey:@"BSSID"] copy];
32 | _SSIDData = [[aDecoder decodeObjectForKey:@"SSIDDATA"] copy];
33 | _selected = [aDecoder decodeBoolForKey:@"selected"];
34 | }
35 | return self;
36 | }
37 |
38 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary {
39 | if (self = [super init]) {
40 | _SSID = [[dictionary valueForKey:@"SSID"] copy];
41 | _BSSID = [[dictionary valueForKey:@"BSSID"] copy];
42 | _SSIDData = [[dictionary valueForKey:@"SSIDDATA"] copy];
43 | }
44 | return self;
45 | }
46 |
47 | - (instancetype)initWithInterfaceName:(NSString *)ifname dictionary:(NSDictionary *)dictionary {
48 | if (self = [self initWithDictionary:dictionary]) {
49 | _interfaceName = ifname;
50 | }
51 | return self;
52 | }
53 |
54 | - (NSString *)wifiName {
55 | if ([self.SSID length] > 0) {
56 | return self.SSID;
57 | }
58 |
59 | if ([self.BSSID length] > 0) {
60 | return self.BSSID;
61 | }
62 |
63 | return @"未知 WIFI";
64 | }
65 |
66 | - (BOOL)isEqualToWifi:(WBWifiModel *)wifi {
67 | if (!wifi) {
68 | return NO;
69 | }
70 |
71 | BOOL haveEqualSSID = (!self.SSID && !wifi.SSID) || [self.SSID isEqualToString:wifi.SSID];
72 | BOOL haveEqualBSSID = (!self.BSSID && !wifi.BSSID) || [self.BSSID isEqualToString:wifi.BSSID];
73 |
74 | return haveEqualSSID && haveEqualBSSID;
75 | }
76 |
77 | - (BOOL)isEqual:(id)object {
78 | if (self == object) {
79 | return YES;
80 | }
81 |
82 | if (![object isKindOfClass:[WBWifiModel class]]) {
83 | return NO;
84 | }
85 |
86 | return [self isEqualToWifi:object];
87 | }
88 |
89 | - (NSUInteger)hash {
90 | return [self.SSID hash] ^ [self.BSSID hash];
91 | }
92 |
93 | @end
94 |
--------------------------------------------------------------------------------
/XcodeProject/DingTalkAssistant.xcodeproj/xcuserdata/buginux.xcuserdatad/xcschemes/DingTalkAssistant.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/WIFI/WBWifiStore.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiStore.m
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/29.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBWifiStore.h"
10 | #import "WBWifiModel.h"
11 | #import
12 | #import
13 |
14 | static NSString * const kWifiHookedKey = @"WifiHookedKey";
15 | static NSString * const kHistoryWifiKey = @"HistoryWifiKey";
16 |
17 | @implementation WBWifiStore
18 |
19 | + (instancetype)sharedStore {
20 | static WBWifiStore *store = nil;
21 | static dispatch_once_t onceToken;
22 | dispatch_once(&onceToken, ^{
23 | store = [[[self class] alloc] init];
24 | });
25 | return store;
26 | }
27 |
28 | - (instancetype)init {
29 | if (self = [super init]) {
30 | _currentWifiList = [[NSMutableArray alloc] init];
31 | _historyWifiList = [[NSMutableArray alloc] init];
32 | }
33 | return self;
34 | }
35 |
36 | - (void)fetchCurrentWifi {
37 | [self.currentWifiList removeAllObjects];
38 |
39 | CFArrayRef arrayRef = CNCopySupportedInterfaces();
40 | NSArray *interfaces = (__bridge NSArray *)(arrayRef);
41 |
42 | if ([interfaces count] > 0) {
43 | NSString *interfaceName = [interfaces firstObject];
44 |
45 | CFDictionaryRef info = CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName);
46 | NSDictionary *dictionary = (__bridge NSDictionary *)(info);
47 |
48 | if (dictionary) {
49 | WBWifiModel *wifi = [[WBWifiModel alloc] initWithInterfaceName:interfaceName dictionary:dictionary];
50 | wifi.flags = [self fetchCurrentNetworkStatus];
51 | [self.currentWifiList addObject:wifi];
52 | }
53 | }
54 | }
55 |
56 | - (void)fetchHistoryWifi {
57 | NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kHistoryWifiKey];
58 |
59 | if ([data length] > 0) {
60 | NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
61 |
62 | if ([array count] > 0) {
63 | NSMutableArray *copyArray = [[NSMutableArray alloc] initWithArray:array];
64 | self.historyWifiList = copyArray;
65 | }
66 | }
67 | }
68 |
69 | - (void)appendHistoryWifi:(WBWifiModel *)wifi {
70 | if (![self.historyWifiList containsObject:wifi]) {
71 | [self.historyWifiList addObject:wifi];
72 | }
73 | }
74 |
75 | - (void)saveHistoryWifi {
76 | NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.historyWifiList];
77 |
78 | if (data) {
79 | [[NSUserDefaults standardUserDefaults] setObject:data forKey:kHistoryWifiKey];
80 | [[NSUserDefaults standardUserDefaults] synchronize];
81 | }
82 | }
83 |
84 | - (SCNetworkReachabilityFlags)fetchCurrentNetworkStatus {
85 | struct sockaddr_in zeroAddress;
86 | bzero(&zeroAddress, sizeof(zeroAddress));
87 | zeroAddress.sin_len = sizeof(zeroAddress);
88 | zeroAddress.sin_family = AF_INET;
89 |
90 | SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
91 | SCNetworkReachabilityFlags flags;
92 |
93 | BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
94 | CFRelease(defaultRouteReachability);
95 |
96 | if (!didRetrieveFlags) {
97 | NSLog(@"Error. Could not receover network reachability flags.");
98 | return 0;
99 | }
100 |
101 | return flags;
102 | }
103 |
104 | - (void)hookWifi:(WBWifiModel *)wifi {
105 | if (!wifi) {
106 | return;
107 | }
108 |
109 | NSData *data = [NSKeyedArchiver archivedDataWithRootObject:wifi];
110 |
111 | if ([data length] > 0) {
112 | [[NSUserDefaults standardUserDefaults] setObject:data forKey:kWifiHookedKey];
113 | [[NSUserDefaults standardUserDefaults] synchronize];
114 | [self fetchCurrentWifi];
115 | }
116 | }
117 |
118 | - (WBWifiModel *)wifiHooked {
119 | WBWifiModel *wifi = nil;
120 |
121 | NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kWifiHookedKey];
122 | if ([data length] > 0) {
123 | wifi = [NSKeyedUnarchiver unarchiveObjectWithData:data];
124 | }
125 |
126 | return wifi;
127 | }
128 |
129 | @end
130 |
--------------------------------------------------------------------------------
/WIFI/WBWifiListViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBWifiListViewController.m
3 | // DingTalkAssistant
4 | //
5 | // Created by buginux on 2017/7/28.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBWifiListViewController.h"
10 | #import "WBWifiStore.h"
11 | #import "WBWifiModel.h"
12 |
13 | @interface WBWifiListViewController ()
14 |
15 | @property (nonatomic, strong) WBWifiStore *store;
16 | @property (nonatomic, strong) WBWifiModel *selectedWifi;
17 |
18 | @end
19 |
20 | @implementation WBWifiListViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 | self.title = @"WIFI 设置";
25 |
26 | self.store = [WBWifiStore sharedStore];
27 | [self.store fetchCurrentWifi];
28 | [self.store fetchHistoryWifi];
29 | for (WBWifiModel *wifi in self.store.historyWifiList) {
30 | if (wifi.selected) {
31 | self.selectedWifi = wifi;
32 | }
33 | }
34 | [self.tableView reloadData];
35 | }
36 |
37 |
38 | - (NSString *)titleForSection:(NSInteger)section {
39 | if (section == 0) {
40 | return @"当前 Wifi";
41 | } else {
42 | return @"历史 Wifi";
43 | }
44 | }
45 |
46 | - (WBWifiModel *)wifiForRowAtIndexPath:(NSIndexPath *)indexPath {
47 | if (indexPath.section == 0) {
48 | return self.store.currentWifiList[indexPath.row];
49 | } else if (indexPath.section == 1) {
50 | return self.store.historyWifiList[indexPath.row];
51 | }
52 | return nil;
53 | }
54 |
55 | - (void)selectWifi:(WBWifiModel *)currentWifi {
56 | for (WBWifiModel *wifi in self.store.currentWifiList) {
57 | wifi.selected = (wifi == currentWifi);
58 | }
59 | for (WBWifiModel *wifi in self.store.historyWifiList) {
60 | wifi.selected = (wifi == currentWifi);
61 | }
62 |
63 | if (![self.store wifiHooked]) {
64 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"初次设置需重启后才会生效" message:nil preferredStyle:UIAlertControllerStyleAlert];
65 | [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
66 | [alert addAction:[UIAlertAction actionWithTitle:@"重启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
67 | exit(0);
68 | }]];
69 |
70 | [self presentViewController:alert animated:YES completion:nil];
71 | }
72 |
73 | self.selectedWifi = currentWifi;
74 | [self.store hookWifi:currentWifi];
75 | [self.store appendHistoryWifi:currentWifi];
76 | [self.store saveHistoryWifi];
77 | [self.tableView reloadData];
78 | }
79 |
80 | #pragma mark - UITableViewDataSource
81 |
82 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
83 | NSInteger numberOfSection = 0;
84 |
85 | if ([self.store.currentWifiList count] > 0) {
86 | numberOfSection += 1;
87 | }
88 |
89 | if ([self.store.historyWifiList count] > 0) {
90 | numberOfSection += 1;
91 | }
92 |
93 | return numberOfSection;
94 | }
95 |
96 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
97 | if (section == 0) {
98 | return [self.store.currentWifiList count];
99 | } else if (section == 1) {
100 | return [self.store.historyWifiList count];
101 | }
102 |
103 | return 0;
104 | }
105 |
106 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
107 | static NSString *CellIdentifier = @"Cell";
108 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
109 |
110 | if (!cell) {
111 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
112 | cell.textLabel.font = [UIFont systemFontOfSize:14.0];
113 | cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0];
114 | }
115 |
116 | WBWifiModel *wifi = [self wifiForRowAtIndexPath:indexPath];
117 | cell.textLabel.text = wifi.wifiName;
118 | cell.accessoryType = wifi.selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
119 |
120 | return cell;
121 | }
122 |
123 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
124 | return [self titleForSection:section];
125 | }
126 |
127 | #pragma mark - UITableViewDelegate
128 |
129 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
130 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
131 |
132 | WBWifiModel *selectedWifi = [self wifiForRowAtIndexPath:indexPath];
133 | if ([self.selectedWifi isEqual:selectedWifi]) {
134 | return;
135 | }
136 |
137 | NSString *message = [NSString stringWithFormat:@"确定将钉钉的 WIFI 切换为 %@ 吗?", selectedWifi.wifiName];
138 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
139 |
140 | __unsafe_unretained __typeof(self)weakSelf = self;
141 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
142 | UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
143 | [weakSelf selectWifi:selectedWifi];
144 | }];
145 | [alert addAction:cancelAction];
146 | [alert addAction:okAction];
147 |
148 | [self presentViewController:alert animated:YES completion:nil];
149 | }
150 |
151 | @end
152 |
--------------------------------------------------------------------------------
/MenuWindow/WBMenuViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WBMenuViewController.m
3 | // FlowWindow
4 | //
5 | // Created by buginux on 2017/7/27.
6 | // Copyright © 2017年 buginux. All rights reserved.
7 | //
8 |
9 | #import "WBMenuViewController.h"
10 | #import "WBGlobalSettingViewController.h"
11 | #import "WBMenuView.h"
12 |
13 | @interface WBMenuViewController ()
14 |
15 | @property (nonatomic, strong) WBMenuView *menu;
16 |
17 | /// Gesture recognizer for dragging a view in move mode
18 | @property (nonatomic, strong) UIPanGestureRecognizer *movePanGR;
19 |
20 | /// Only valid while a move pan gesture is in progress.
21 | @property (nonatomic, assign) CGRect menuFrameBeforeDragging;
22 |
23 | /// Tracked so we can restore the key window after dismissing a modal.
24 | /// We need to become key after modal presentation so we can correctly capture intput.
25 | /// If we're just showing the toolbar, we want the main app's window to remain key so that we don't interfere with input, status bar, etc.
26 | @property (nonatomic, strong) UIWindow *previousKeyWindow;
27 |
28 | /// Similar to the previousKeyWindow property above, we need to track status bar styling if
29 | /// the app doesn't use view controller based status bar management. When we present a modal,
30 | /// we want to change the status bar style to UIStausBarStyleDefault. Before changing, we stash
31 | /// the current style. On dismissal, we return the staus bar to the style that the app was using previously.
32 | @property (nonatomic, assign) UIStatusBarStyle previousStatusBarStyle;
33 |
34 | @end
35 |
36 | @implementation WBMenuViewController
37 |
38 | - (void)viewDidLoad {
39 | [super viewDidLoad];
40 |
41 | [self setupMenu];
42 | [self setupMenuActions];
43 |
44 | // View moving
45 | self.movePanGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMovePan:)];
46 | [self.view addGestureRecognizer:self.movePanGR];
47 | }
48 |
49 | - (void)viewWillAppear:(BOOL)animated {
50 | [super viewWillAppear:animated];
51 |
52 | }
53 |
54 | - (void)setupMenu {
55 | self.menu = [[WBMenuView alloc] init];
56 | [self.menu sizeToFit];
57 |
58 | CGRect frame = self.menu.frame;
59 | frame.origin.x = CGRectGetWidth([UIScreen mainScreen].bounds) - CGRectGetWidth(self.menu.frame);
60 | frame.origin.y = 100;
61 | self.menu.frame = frame;
62 |
63 | self.menu.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
64 |
65 | [self.view addSubview:self.menu];
66 | }
67 |
68 | - (void)setupMenuActions {
69 | [self.menu.menuButton addTarget:self action:@selector(menuButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
70 | [self.menu.closeButton addTarget:self action:@selector(closeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
71 | }
72 |
73 | - (void)menuButtonTapped:(UIButton *)sender {
74 | [self toggleSettingViewController];
75 | }
76 |
77 | - (void)closeButtonTapped:(UIButton *)sender {
78 | [self.delegate menuViewControllerDidFinish:self];
79 | }
80 |
81 | - (void)handleMovePan:(UIPanGestureRecognizer *)movePanGR {
82 | switch (movePanGR.state) {
83 | case UIGestureRecognizerStateBegan:
84 | self.menuFrameBeforeDragging = self.menu.frame;
85 | [self updateMenuPositionWithDragGesture:movePanGR];
86 | break;
87 |
88 | case UIGestureRecognizerStateChanged:
89 | case UIGestureRecognizerStateEnded:
90 | [self updateMenuPositionWithDragGesture:movePanGR];
91 | break;
92 |
93 | default:
94 | break;
95 | }
96 | }
97 |
98 | - (UIWindow *)statusWindow {
99 | NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"];
100 | return [[UIApplication sharedApplication] valueForKey:statusBarString];
101 | }
102 |
103 | - (void)updateMenuPositionWithDragGesture:(UIPanGestureRecognizer *)movePanGR {
104 | CGPoint translation = [movePanGR translationInView:self.menu.superview];
105 | CGRect newSelectedViewFrame = self.menuFrameBeforeDragging;
106 | newSelectedViewFrame.origin.x = newSelectedViewFrame.origin.x + translation.x;
107 | newSelectedViewFrame.origin.y = newSelectedViewFrame.origin.y + translation.y;
108 | self.menu.frame = newSelectedViewFrame;
109 | }
110 |
111 | - (void)toggleSettingViewController {
112 | BOOL menuModalShown = [[self presentedViewController] isKindOfClass:[UINavigationController class]];
113 | menuModalShown = menuModalShown && [[[(UINavigationController *)[self presentedViewController] viewControllers] firstObject] isKindOfClass:[WBGlobalSettingViewController class]];
114 | if (menuModalShown) {
115 | [self resignKeyAndDismissViewControllerAnimated:YES completion:nil];
116 | } else {
117 | void (^presentBlock)() = ^{
118 | WBGlobalSettingViewController *settingViewController = [[WBGlobalSettingViewController alloc] init];
119 | settingViewController.delegate = self;
120 | [WBGlobalSettingViewController setApplicationWindow:[[UIApplication sharedApplication] keyWindow]];
121 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:settingViewController];
122 | [self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];
123 | };
124 |
125 | if (self.presentedViewController) {
126 | [self resignKeyAndDismissViewControllerAnimated:NO completion:presentBlock];
127 | } else {
128 | presentBlock();
129 | }
130 | }
131 | }
132 |
133 | #pragma mark - Touch Handling
134 |
135 | - (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates {
136 | BOOL shouldReceiveTouch = NO;
137 |
138 | CGPoint pointInLocalCoordinates = [self.view convertPoint:pointInWindowCoordinates fromView:nil];
139 |
140 | // Always if it's on the menu
141 | if (CGRectContainsPoint(self.menu.frame, pointInLocalCoordinates)) {
142 | shouldReceiveTouch = YES;
143 | }
144 |
145 | // Always if we have a modal presented
146 | if (!shouldReceiveTouch && self.presentedViewController) {
147 | shouldReceiveTouch = YES;
148 | }
149 |
150 | return shouldReceiveTouch;
151 | }
152 |
153 | #pragma mark - WBGlobalSettingViewControllerDelegate
154 |
155 | - (void)globalSettingViewControllerDidFinish:(WBGlobalSettingViewController *)controller {
156 | [self resignKeyAndDismissViewControllerAnimated:YES completion:nil];
157 | }
158 |
159 |
160 | #pragma mark - Modal Presentation and Window Management
161 |
162 | - (void)makeKeyAndPresentViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion {
163 | // Save the current key window so we can restore it following dismissal.
164 | self.previousKeyWindow = [[UIApplication sharedApplication] keyWindow];
165 |
166 | // Make our window key to correctly handle input.
167 | [self.view.window makeKeyWindow];
168 |
169 | // Move the status bar on top of FLEX so we can get scroll to top behavior for taps.
170 | [[self statusWindow] setWindowLevel:self.view.window.windowLevel + 1.0];
171 |
172 | // If this app doesn't use view controller based status bar management and we're on iOS 7+,
173 | // make sure the status bar style is UIStatusBarStyleDefault. We don't actully have to check
174 | // for view controller based management because the global methods no-op if that is turned on.
175 | self.previousStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle];
176 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
177 |
178 | // Show the view controller.
179 | [self presentViewController:viewController animated:animated completion:completion];
180 | }
181 |
182 | - (void)resignKeyAndDismissViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion {
183 | UIWindow *previousKeyWindow = self.previousKeyWindow;
184 | self.previousKeyWindow = nil;
185 | [previousKeyWindow makeKeyWindow];
186 | [[previousKeyWindow rootViewController] setNeedsStatusBarAppearanceUpdate];
187 |
188 | // Restore the status bar window's normal window level.
189 | // We want it above FLEX while a modal is presented for scroll to top, but below FLEX otherwise for exploration.
190 | [[self statusWindow] setWindowLevel:UIWindowLevelStatusBar];
191 |
192 | // Restore the stauts bar style if the app is using global status bar management.
193 | [[UIApplication sharedApplication] setStatusBarStyle:self.previousStatusBarStyle];
194 |
195 | [self dismissViewControllerAnimated:animated completion:completion];
196 | }
197 |
198 | - (BOOL)wantsWindowToBecomeKey {
199 | return self.previousKeyWindow != nil;
200 | }
201 |
202 | @end
203 |
--------------------------------------------------------------------------------
/XcodeProject/DingTalkAssistant.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A29D798F1F2B6E8700595835 /* WBWifiListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A29D798E1F2B6E8700595835 /* WBWifiListViewController.m */; };
11 | A29D79961F2B757000595835 /* WBGPSPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A29D79951F2B757000595835 /* WBGPSPickerViewController.m */; };
12 | A29D79B11F2C5DBD00595835 /* WBWifiStore.m in Sources */ = {isa = PBXBuildFile; fileRef = A29D79B01F2C5DBD00595835 /* WBWifiStore.m */; };
13 | A29D79B41F2C5DCF00595835 /* WBWifiModel.m in Sources */ = {isa = PBXBuildFile; fileRef = A29D79B31F2C5DCF00595835 /* WBWifiModel.m */; };
14 | /* End PBXBuildFile section */
15 |
16 | /* Begin PBXCopyFilesBuildPhase section */
17 | A21AED281F2A2AFD0004944A /* CopyFiles */ = {
18 | isa = PBXCopyFilesBuildPhase;
19 | buildActionMask = 2147483647;
20 | dstPath = "include/$(PRODUCT_NAME)";
21 | dstSubfolderSpec = 16;
22 | files = (
23 | );
24 | runOnlyForDeploymentPostprocessing = 0;
25 | };
26 | /* End PBXCopyFilesBuildPhase section */
27 |
28 | /* Begin PBXFileReference section */
29 | A21AED2A1F2A2AFD0004944A /* libDingTalkAssistant.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDingTalkAssistant.a; sourceTree = BUILT_PRODUCTS_DIR; };
30 | A29D798D1F2B6E8700595835 /* WBWifiListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WBWifiListViewController.h; path = ../../WIFI/WBWifiListViewController.h; sourceTree = ""; };
31 | A29D798E1F2B6E8700595835 /* WBWifiListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WBWifiListViewController.m; path = ../../WIFI/WBWifiListViewController.m; sourceTree = ""; };
32 | A29D79941F2B757000595835 /* WBGPSPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WBGPSPickerViewController.h; path = ../../GPS/WBGPSPickerViewController.h; sourceTree = ""; };
33 | A29D79951F2B757000595835 /* WBGPSPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WBGPSPickerViewController.m; path = ../../GPS/WBGPSPickerViewController.m; sourceTree = ""; };
34 | A29D79AF1F2C5DBD00595835 /* WBWifiStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WBWifiStore.h; path = ../../WIFI/WBWifiStore.h; sourceTree = ""; };
35 | A29D79B01F2C5DBD00595835 /* WBWifiStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WBWifiStore.m; path = ../../WIFI/WBWifiStore.m; sourceTree = ""; };
36 | A29D79B21F2C5DCF00595835 /* WBWifiModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WBWifiModel.h; path = ../../WIFI/WBWifiModel.h; sourceTree = ""; };
37 | A29D79B31F2C5DCF00595835 /* WBWifiModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WBWifiModel.m; path = ../../WIFI/WBWifiModel.m; sourceTree = ""; };
38 | /* End PBXFileReference section */
39 |
40 | /* Begin PBXFrameworksBuildPhase section */
41 | A21AED271F2A2AFD0004944A /* Frameworks */ = {
42 | isa = PBXFrameworksBuildPhase;
43 | buildActionMask = 2147483647;
44 | files = (
45 | );
46 | runOnlyForDeploymentPostprocessing = 0;
47 | };
48 | /* End PBXFrameworksBuildPhase section */
49 |
50 | /* Begin PBXGroup section */
51 | A21AED211F2A2AFD0004944A = {
52 | isa = PBXGroup;
53 | children = (
54 | A21AED2C1F2A2AFD0004944A /* DingTalkAssistant */,
55 | A21AED2B1F2A2AFD0004944A /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | A21AED2B1F2A2AFD0004944A /* Products */ = {
60 | isa = PBXGroup;
61 | children = (
62 | A21AED2A1F2A2AFD0004944A /* libDingTalkAssistant.a */,
63 | );
64 | name = Products;
65 | sourceTree = "";
66 | };
67 | A21AED2C1F2A2AFD0004944A /* DingTalkAssistant */ = {
68 | isa = PBXGroup;
69 | children = (
70 | A29D79901F2B750C00595835 /* GPS */,
71 | A29D798C1F2B6E5A00595835 /* WIFI */,
72 | A2753E1C1F2A33C800C2293B /* MenuWindow */,
73 | );
74 | path = DingTalkAssistant;
75 | sourceTree = "";
76 | };
77 | A2753E1C1F2A33C800C2293B /* MenuWindow */ = {
78 | isa = PBXGroup;
79 | children = (
80 | );
81 | path = MenuWindow;
82 | sourceTree = "";
83 | };
84 | A29D798C1F2B6E5A00595835 /* WIFI */ = {
85 | isa = PBXGroup;
86 | children = (
87 | A29D798D1F2B6E8700595835 /* WBWifiListViewController.h */,
88 | A29D798E1F2B6E8700595835 /* WBWifiListViewController.m */,
89 | A29D79AF1F2C5DBD00595835 /* WBWifiStore.h */,
90 | A29D79B01F2C5DBD00595835 /* WBWifiStore.m */,
91 | A29D79B21F2C5DCF00595835 /* WBWifiModel.h */,
92 | A29D79B31F2C5DCF00595835 /* WBWifiModel.m */,
93 | );
94 | name = WIFI;
95 | sourceTree = "";
96 | };
97 | A29D79901F2B750C00595835 /* GPS */ = {
98 | isa = PBXGroup;
99 | children = (
100 | A29D79941F2B757000595835 /* WBGPSPickerViewController.h */,
101 | A29D79951F2B757000595835 /* WBGPSPickerViewController.m */,
102 | );
103 | name = GPS;
104 | sourceTree = "";
105 | };
106 | /* End PBXGroup section */
107 |
108 | /* Begin PBXNativeTarget section */
109 | A21AED291F2A2AFD0004944A /* DingTalkAssistant */ = {
110 | isa = PBXNativeTarget;
111 | buildConfigurationList = A21AED331F2A2AFD0004944A /* Build configuration list for PBXNativeTarget "DingTalkAssistant" */;
112 | buildPhases = (
113 | A21AED261F2A2AFD0004944A /* Sources */,
114 | A21AED271F2A2AFD0004944A /* Frameworks */,
115 | A21AED281F2A2AFD0004944A /* CopyFiles */,
116 | );
117 | buildRules = (
118 | );
119 | dependencies = (
120 | );
121 | name = DingTalkAssistant;
122 | productName = DingTalkAssistant;
123 | productReference = A21AED2A1F2A2AFD0004944A /* libDingTalkAssistant.a */;
124 | productType = "com.apple.product-type.library.static";
125 | };
126 | /* End PBXNativeTarget section */
127 |
128 | /* Begin PBXProject section */
129 | A21AED221F2A2AFD0004944A /* Project object */ = {
130 | isa = PBXProject;
131 | attributes = {
132 | LastUpgradeCheck = 0830;
133 | ORGANIZATIONNAME = buginux;
134 | TargetAttributes = {
135 | A21AED291F2A2AFD0004944A = {
136 | CreatedOnToolsVersion = 8.3.3;
137 | DevelopmentTeam = AMCXGTYG4X;
138 | ProvisioningStyle = Automatic;
139 | };
140 | };
141 | };
142 | buildConfigurationList = A21AED251F2A2AFD0004944A /* Build configuration list for PBXProject "DingTalkAssistant" */;
143 | compatibilityVersion = "Xcode 3.2";
144 | developmentRegion = English;
145 | hasScannedForEncodings = 0;
146 | knownRegions = (
147 | en,
148 | );
149 | mainGroup = A21AED211F2A2AFD0004944A;
150 | productRefGroup = A21AED2B1F2A2AFD0004944A /* Products */;
151 | projectDirPath = "";
152 | projectRoot = "";
153 | targets = (
154 | A21AED291F2A2AFD0004944A /* DingTalkAssistant */,
155 | );
156 | };
157 | /* End PBXProject section */
158 |
159 | /* Begin PBXSourcesBuildPhase section */
160 | A21AED261F2A2AFD0004944A /* Sources */ = {
161 | isa = PBXSourcesBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | A29D79961F2B757000595835 /* WBGPSPickerViewController.m in Sources */,
165 | A29D79B11F2C5DBD00595835 /* WBWifiStore.m in Sources */,
166 | A29D79B41F2C5DCF00595835 /* WBWifiModel.m in Sources */,
167 | A29D798F1F2B6E8700595835 /* WBWifiListViewController.m in Sources */,
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | };
171 | /* End PBXSourcesBuildPhase section */
172 |
173 | /* Begin XCBuildConfiguration section */
174 | A21AED311F2A2AFD0004944A /* Debug */ = {
175 | isa = XCBuildConfiguration;
176 | buildSettings = {
177 | ALWAYS_SEARCH_USER_PATHS = NO;
178 | CLANG_ANALYZER_NONNULL = YES;
179 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
181 | CLANG_CXX_LIBRARY = "libc++";
182 | CLANG_ENABLE_MODULES = YES;
183 | CLANG_ENABLE_OBJC_ARC = YES;
184 | CLANG_WARN_BOOL_CONVERSION = YES;
185 | CLANG_WARN_CONSTANT_CONVERSION = YES;
186 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
187 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
188 | CLANG_WARN_EMPTY_BODY = YES;
189 | CLANG_WARN_ENUM_CONVERSION = YES;
190 | CLANG_WARN_INFINITE_RECURSION = YES;
191 | CLANG_WARN_INT_CONVERSION = YES;
192 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
193 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
194 | CLANG_WARN_UNREACHABLE_CODE = YES;
195 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
196 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
197 | COPY_PHASE_STRIP = NO;
198 | DEBUG_INFORMATION_FORMAT = dwarf;
199 | ENABLE_STRICT_OBJC_MSGSEND = YES;
200 | ENABLE_TESTABILITY = YES;
201 | GCC_C_LANGUAGE_STANDARD = gnu99;
202 | GCC_DYNAMIC_NO_PIC = NO;
203 | GCC_NO_COMMON_BLOCKS = YES;
204 | GCC_OPTIMIZATION_LEVEL = 0;
205 | GCC_PREPROCESSOR_DEFINITIONS = (
206 | "DEBUG=1",
207 | "$(inherited)",
208 | );
209 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
210 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
211 | GCC_WARN_UNDECLARED_SELECTOR = YES;
212 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
213 | GCC_WARN_UNUSED_FUNCTION = YES;
214 | GCC_WARN_UNUSED_VARIABLE = YES;
215 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
216 | MTL_ENABLE_DEBUG_INFO = YES;
217 | ONLY_ACTIVE_ARCH = YES;
218 | SDKROOT = iphoneos;
219 | };
220 | name = Debug;
221 | };
222 | A21AED321F2A2AFD0004944A /* Release */ = {
223 | isa = XCBuildConfiguration;
224 | buildSettings = {
225 | ALWAYS_SEARCH_USER_PATHS = NO;
226 | CLANG_ANALYZER_NONNULL = YES;
227 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
229 | CLANG_CXX_LIBRARY = "libc++";
230 | CLANG_ENABLE_MODULES = YES;
231 | CLANG_ENABLE_OBJC_ARC = YES;
232 | CLANG_WARN_BOOL_CONVERSION = YES;
233 | CLANG_WARN_CONSTANT_CONVERSION = YES;
234 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
235 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
236 | CLANG_WARN_EMPTY_BODY = YES;
237 | CLANG_WARN_ENUM_CONVERSION = YES;
238 | CLANG_WARN_INFINITE_RECURSION = YES;
239 | CLANG_WARN_INT_CONVERSION = YES;
240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
241 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
242 | CLANG_WARN_UNREACHABLE_CODE = YES;
243 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
244 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
245 | COPY_PHASE_STRIP = NO;
246 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
247 | ENABLE_NS_ASSERTIONS = NO;
248 | ENABLE_STRICT_OBJC_MSGSEND = YES;
249 | GCC_C_LANGUAGE_STANDARD = gnu99;
250 | GCC_NO_COMMON_BLOCKS = YES;
251 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
252 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
253 | GCC_WARN_UNDECLARED_SELECTOR = YES;
254 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
255 | GCC_WARN_UNUSED_FUNCTION = YES;
256 | GCC_WARN_UNUSED_VARIABLE = YES;
257 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
258 | MTL_ENABLE_DEBUG_INFO = NO;
259 | SDKROOT = iphoneos;
260 | VALIDATE_PRODUCT = YES;
261 | };
262 | name = Release;
263 | };
264 | A21AED341F2A2AFD0004944A /* Debug */ = {
265 | isa = XCBuildConfiguration;
266 | buildSettings = {
267 | DEVELOPMENT_TEAM = AMCXGTYG4X;
268 | OTHER_LDFLAGS = "-ObjC";
269 | PRODUCT_NAME = "$(TARGET_NAME)";
270 | SKIP_INSTALL = YES;
271 | };
272 | name = Debug;
273 | };
274 | A21AED351F2A2AFD0004944A /* Release */ = {
275 | isa = XCBuildConfiguration;
276 | buildSettings = {
277 | DEVELOPMENT_TEAM = AMCXGTYG4X;
278 | OTHER_LDFLAGS = "-ObjC";
279 | PRODUCT_NAME = "$(TARGET_NAME)";
280 | SKIP_INSTALL = YES;
281 | };
282 | name = Release;
283 | };
284 | /* End XCBuildConfiguration section */
285 |
286 | /* Begin XCConfigurationList section */
287 | A21AED251F2A2AFD0004944A /* Build configuration list for PBXProject "DingTalkAssistant" */ = {
288 | isa = XCConfigurationList;
289 | buildConfigurations = (
290 | A21AED311F2A2AFD0004944A /* Debug */,
291 | A21AED321F2A2AFD0004944A /* Release */,
292 | );
293 | defaultConfigurationIsVisible = 0;
294 | defaultConfigurationName = Release;
295 | };
296 | A21AED331F2A2AFD0004944A /* Build configuration list for PBXNativeTarget "DingTalkAssistant" */ = {
297 | isa = XCConfigurationList;
298 | buildConfigurations = (
299 | A21AED341F2A2AFD0004944A /* Debug */,
300 | A21AED351F2A2AFD0004944A /* Release */,
301 | );
302 | defaultConfigurationIsVisible = 0;
303 | defaultConfigurationName = Release;
304 | };
305 | /* End XCConfigurationList section */
306 | };
307 | rootObject = A21AED221F2A2AFD0004944A /* Project object */;
308 | }
309 |
--------------------------------------------------------------------------------