Skip to content

Commit 0d3cb9a

Browse files
committed
Add ping my watch support
1 parent 538bed2 commit 0d3cb9a

67 files changed

Lines changed: 542 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
.theos/
22
packages/
33
.DS_Store
4+
doc/
5+
memory/
6+
AGENTS.md
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.findmylocaldevice-playsounds</key>
6+
<true/>
7+
<key>com.apple.security.exception.mach-lookup.global-name</key>
8+
<array>
9+
<string>com.apple.findmylocaldevice</string>
10+
</array>
11+
</dict>
12+
</plist>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#import <Foundation/Foundation.h>
2+
#import <dispatch/dispatch.h>
3+
4+
#include "utils.h"
5+
6+
@interface NFMWhereIsMyCompanionConnection : NSObject
7+
+ (instancetype)sharedDeviceConnection;
8+
- (void)playSoundAndLightsOnCompanionWithCompletion:(void (^)(BOOL success))completion;
9+
- (void)playSoundOnCompanionWithCompletion:(void (^)(BOOL success))completion;
10+
@end
11+
12+
static const NSTimeInterval kWFPMWHelperPrimaryTimeoutSeconds = 4.0;
13+
static const NSTimeInterval kWFPMWHelperFallbackTimeoutSeconds = 4.0;
14+
static const NSTimeInterval kWFPMWHelperRunLoopSliceSeconds = 0.05;
15+
16+
static BOOL WFPMWHelperWaitForCompletion(BOOL *completed,
17+
const char *selectorName,
18+
NSTimeInterval timeoutSeconds) {
19+
NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:timeoutSeconds];
20+
21+
while (!*completed && [deadline timeIntervalSinceNow] > 0) {
22+
@autoreleasepool {
23+
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
24+
beforeDate:[NSDate dateWithTimeIntervalSinceNow:kWFPMWHelperRunLoopSliceSeconds]];
25+
}
26+
}
27+
28+
if (!*completed) {
29+
Log("helper timed out waiting for %s", selectorName);
30+
return NO;
31+
}
32+
33+
return YES;
34+
}
35+
36+
static BOOL WFPMWHelperInvokePingSelector(NFMWhereIsMyCompanionConnection *connection,
37+
SEL selector,
38+
NSTimeInterval timeoutSeconds) {
39+
if (!connection || !selector || ![connection respondsToSelector:selector]) {
40+
return NO;
41+
}
42+
43+
__block BOOL completed = NO;
44+
__block BOOL reportedSuccess = NO;
45+
const char *selectorName = sel_getName(selector);
46+
47+
Log("helper using selector %s", selectorName);
48+
void (^completion)(BOOL) = ^(BOOL played) {
49+
completed = YES;
50+
reportedSuccess = played;
51+
Log("helper completion for %s: %s", selectorName, played ? "YES" : "NO");
52+
};
53+
54+
if (selector == @selector(playSoundAndLightsOnCompanionWithCompletion:)) {
55+
[connection playSoundAndLightsOnCompanionWithCompletion:completion];
56+
} else if (selector == @selector(playSoundOnCompanionWithCompletion:)) {
57+
[connection playSoundOnCompanionWithCompletion:completion];
58+
} else {
59+
Log("helper received unsupported selector %s", selectorName);
60+
return NO;
61+
}
62+
63+
if (!WFPMWHelperWaitForCompletion(&completed, selectorName, timeoutSeconds)) {
64+
return NO;
65+
}
66+
67+
if (!reportedSuccess) {
68+
Log("helper received completion for %s with reported result NO", selectorName);
69+
}
70+
71+
return YES;
72+
}
73+
74+
int main(__unused int argc, __unused char *argv[]) {
75+
@autoreleasepool {
76+
NFMWhereIsMyCompanionConnection *connection = [NFMWhereIsMyCompanionConnection sharedDeviceConnection];
77+
if (!connection) {
78+
Log("helper could not access sharedDeviceConnection");
79+
return 1;
80+
}
81+
82+
BOOL didPlay = NO;
83+
if ([connection respondsToSelector:@selector(playSoundAndLightsOnCompanionWithCompletion:)]) {
84+
didPlay = WFPMWHelperInvokePingSelector(connection,
85+
@selector(playSoundAndLightsOnCompanionWithCompletion:),
86+
kWFPMWHelperPrimaryTimeoutSeconds);
87+
}
88+
89+
if (!didPlay && [connection respondsToSelector:@selector(playSoundOnCompanionWithCompletion:)]) {
90+
didPlay = WFPMWHelperInvokePingSelector(connection,
91+
@selector(playSoundOnCompanionWithCompletion:),
92+
kWFPMWHelperFallbackTimeoutSeconds);
93+
}
94+
95+
Log("helper finished ping request with result: %s", didPlay ? "YES" : "NO");
96+
return didPlay ? 0 : 1;
97+
}
98+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
include $(THEOS)/makefiles/common.mk
2+
3+
BUNDLE_NAME = PingMyWatchControlCenter
4+
TOOL_NAME = WatchFixPingMyWatchHelper
5+
6+
$(BUNDLE_NAME)_FILES = PingMyWatchControlCenter.xm $(WATCHFIX_UTILS_FILES)
7+
$(BUNDLE_NAME)_CFLAGS = -fobjc-arc $(WATCHFIX_UTILS_CFLAGS)
8+
$(BUNDLE_NAME)_BUNDLE_EXTENSION = bundle
9+
$(BUNDLE_NAME)_INSTALL_PATH = /Library/ControlCenter/Bundles/
10+
$(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = ControlCenterUIKit NanoRegistry
11+
$(BUNDLE_NAME)_RESOURCE_DIRS = Resources
12+
13+
$(TOOL_NAME)_FILES = Helper/main.xm $(WATCHFIX_UTILS_FILES)
14+
$(TOOL_NAME)_CFLAGS = -fobjc-arc $(WATCHFIX_UTILS_CFLAGS)
15+
$(TOOL_NAME)_PRIVATE_FRAMEWORKS = NanoLeash
16+
$(TOOL_NAME)_INSTALL_PATH = /Library/ControlCenter/Bundles/$(BUNDLE_NAME).bundle
17+
$(TOOL_NAME)_CODESIGN_FLAGS = -S$(CURDIR)/Helper/Entitlements.plist
18+
19+
include $(THEOS_MAKE_PATH)/bundle.mk
20+
include $(THEOS_MAKE_PATH)/tool.mk
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#import <ControlCenterUIKit/CCUIToggleModule.h>
2+
3+
@interface WFPingMyWatchControlCenterModule : CCUIToggleModule
4+
5+
@property(nonatomic, assign, getter=isPingInProgress) BOOL pingInProgress;
6+
7+
@end

0 commit comments

Comments
 (0)