mirror of
https://github.com/Sunnyyoung/WeChatTweak-macOS.git
synced 2025-07-07 16:16:07 +08:00
Refactor into standalone modules
This commit is contained in:
parent
4de5ca9fec
commit
3f3ec79543
|
@ -7,18 +7,20 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
7D14E5A41F6447DB00D75132 /* AlfredManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D14E5A21F6447DB00D75132 /* AlfredManager.h */; };
|
7D14E5A41F6447DB00D75132 /* Alfred.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D14E5A21F6447DB00D75132 /* Alfred.h */; };
|
||||||
7D14E5A51F6447DB00D75132 /* AlfredManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D14E5A31F6447DB00D75132 /* AlfredManager.m */; };
|
7D14E5A51F6447DB00D75132 /* Alfred.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D14E5A31F6447DB00D75132 /* Alfred.m */; };
|
||||||
7D2194CB264701950068F4CC /* AntiRevoke.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D2194C9264701950068F4CC /* AntiRevoke.h */; };
|
|
||||||
7D2194CC264701950068F4CC /* AntiRevoke.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D2194CA264701950068F4CC /* AntiRevoke.m */; };
|
7D2194CC264701950068F4CC /* AntiRevoke.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D2194CA264701950068F4CC /* AntiRevoke.m */; };
|
||||||
7D54A05C20E74D9400CB5306 /* TweakPreferencesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A05E20E74D9400CB5306 /* TweakPreferencesController.xib */; };
|
7D54A05C20E74D9400CB5306 /* TweakPreferencesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A05E20E74D9400CB5306 /* TweakPreferencesController.xib */; };
|
||||||
7D54A06A20E74FE500CB5306 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A06C20E74FE500CB5306 /* Localizable.strings */; };
|
7D54A06A20E74FE500CB5306 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D54A06C20E74FE500CB5306 /* Localizable.strings */; };
|
||||||
|
7D64150827A9469900A8A398 /* ContextMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D64150627A9469900A8A398 /* ContextMenu.m */; };
|
||||||
|
7D64150A27A9481C00A8A398 /* ContactData.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D64150927A9481C00A8A398 /* ContactData.m */; };
|
||||||
|
7D64150C27A94B9600A8A398 /* Directory.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D64150B27A94B9600A8A398 /* Directory.m */; };
|
||||||
|
7D64150E27A94BEA00A8A398 /* MultipleInstances.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D64150D27A94BEA00A8A398 /* MultipleInstances.m */; };
|
||||||
|
7D64151027A94DE200A8A398 /* PreferencesWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D64150F27A94DE200A8A398 /* PreferencesWindow.m */; };
|
||||||
7D9049F51F82A41A004E6370 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F31F82A415004E6370 /* fishhook.c */; };
|
7D9049F51F82A41A004E6370 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F31F82A415004E6370 /* fishhook.c */; };
|
||||||
7D9049F61F82A41A004E6370 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F41F82A415004E6370 /* fishhook.h */; };
|
7D9049F61F82A41A004E6370 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F41F82A415004E6370 /* fishhook.h */; };
|
||||||
7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */; };
|
7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */; };
|
||||||
7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */; };
|
7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */; };
|
||||||
7DB8AFBE206211D900E683AE /* WTConfigManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DB8AFBC206211D900E683AE /* WTConfigManager.h */; };
|
|
||||||
7DB8AFBF206211D900E683AE /* WTConfigManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB8AFBD206211D900E683AE /* WTConfigManager.m */; };
|
|
||||||
7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8422A1F40583F00D42D79 /* WeChatTweak.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8422A1F40583F00D42D79 /* WeChatTweak.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF842331F4058AB00D42D79 /* WeChatTweak.m */; };
|
7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF842331F4058AB00D42D79 /* WeChatTweak.m */; };
|
||||||
7DF842521F4058C600D42D79 /* TweakPreferencesController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8424F1F4058C600D42D79 /* TweakPreferencesController.h */; };
|
7DF842521F4058C600D42D79 /* TweakPreferencesController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DF8424F1F4058C600D42D79 /* TweakPreferencesController.h */; };
|
||||||
|
@ -32,14 +34,18 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
153504EC5C9196C0D85213CF /* libPods-WeChatTweak.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-WeChatTweak.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
153504EC5C9196C0D85213CF /* libPods-WeChatTweak.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-WeChatTweak.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7D14E5A21F6447DB00D75132 /* AlfredManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlfredManager.h; sourceTree = "<group>"; };
|
7D14E5A21F6447DB00D75132 /* Alfred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alfred.h; sourceTree = "<group>"; };
|
||||||
7D14E5A31F6447DB00D75132 /* AlfredManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlfredManager.m; sourceTree = "<group>"; };
|
7D14E5A31F6447DB00D75132 /* Alfred.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Alfred.m; sourceTree = "<group>"; };
|
||||||
7D2194C9264701950068F4CC /* AntiRevoke.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AntiRevoke.h; sourceTree = "<group>"; };
|
|
||||||
7D2194CA264701950068F4CC /* AntiRevoke.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AntiRevoke.m; sourceTree = "<group>"; };
|
7D2194CA264701950068F4CC /* AntiRevoke.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AntiRevoke.m; sourceTree = "<group>"; };
|
||||||
7D54A05F20E74E4600CB5306 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TweakPreferencesController.xib; sourceTree = "<group>"; };
|
7D54A05F20E74E4600CB5306 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/TweakPreferencesController.xib; sourceTree = "<group>"; };
|
||||||
7D54A07020E74FFD00CB5306 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
7D54A07020E74FFD00CB5306 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
7D54A07120E7535F00CB5306 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
7D54A07120E7535F00CB5306 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
7D54A07220E7536300CB5306 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
7D54A07220E7536300CB5306 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
|
7D64150627A9469900A8A398 /* ContextMenu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContextMenu.m; sourceTree = "<group>"; };
|
||||||
|
7D64150927A9481C00A8A398 /* ContactData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContactData.m; sourceTree = "<group>"; };
|
||||||
|
7D64150B27A94B9600A8A398 /* Directory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Directory.m; sourceTree = "<group>"; };
|
||||||
|
7D64150D27A94BEA00A8A398 /* MultipleInstances.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultipleInstances.m; sourceTree = "<group>"; };
|
||||||
|
7D64150F27A94DE200A8A398 /* PreferencesWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PreferencesWindow.m; sourceTree = "<group>"; };
|
||||||
7D64B96727853C2100A07164 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TweakPreferencesController.strings; sourceTree = "<group>"; };
|
7D64B96727853C2100A07164 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TweakPreferencesController.strings; sourceTree = "<group>"; };
|
||||||
7D64B96827853C2800A07164 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/TweakPreferencesController.strings"; sourceTree = "<group>"; };
|
7D64B96827853C2800A07164 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/TweakPreferencesController.strings"; sourceTree = "<group>"; };
|
||||||
7D64B96927853C2B00A07164 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/TweakPreferencesController.strings"; sourceTree = "<group>"; };
|
7D64B96927853C2B00A07164 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/TweakPreferencesController.strings"; sourceTree = "<group>"; };
|
||||||
|
@ -47,8 +53,6 @@
|
||||||
7D9049F41F82A415004E6370 /* fishhook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = "<group>"; };
|
7D9049F41F82A415004E6370 /* fishhook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = "<group>"; };
|
||||||
7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+WeChatTweak.h"; sourceTree = "<group>"; };
|
7D9049F71F82B6FB004E6370 /* NSString+WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+WeChatTweak.h"; sourceTree = "<group>"; };
|
||||||
7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+WeChatTweak.m"; sourceTree = "<group>"; };
|
7D9049F81F82B6FB004E6370 /* NSString+WeChatTweak.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+WeChatTweak.m"; sourceTree = "<group>"; };
|
||||||
7DB8AFBC206211D900E683AE /* WTConfigManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WTConfigManager.h; sourceTree = "<group>"; };
|
|
||||||
7DB8AFBD206211D900E683AE /* WTConfigManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WTConfigManager.m; sourceTree = "<group>"; };
|
|
||||||
7DF842271F40583F00D42D79 /* WeChatTweak.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WeChatTweak.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
7DF842271F40583F00D42D79 /* WeChatTweak.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WeChatTweak.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7DF8422A1F40583F00D42D79 /* WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeChatTweak.h; sourceTree = "<group>"; };
|
7DF8422A1F40583F00D42D79 /* WeChatTweak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeChatTweak.h; sourceTree = "<group>"; };
|
||||||
7DF8422B1F40583F00D42D79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
7DF8422B1F40583F00D42D79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
@ -83,17 +87,6 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7D5AAF3320DF4B7B00860EEE /* Manager */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
7D14E5A21F6447DB00D75132 /* AlfredManager.h */,
|
|
||||||
7D14E5A31F6447DB00D75132 /* AlfredManager.m */,
|
|
||||||
7DB8AFBC206211D900E683AE /* WTConfigManager.h */,
|
|
||||||
7DB8AFBD206211D900E683AE /* WTConfigManager.m */,
|
|
||||||
);
|
|
||||||
path = Manager;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
7D5AAF3520DF4B9700860EEE /* Controller */ = {
|
7D5AAF3520DF4B9700860EEE /* Controller */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -157,12 +150,17 @@
|
||||||
children = (
|
children = (
|
||||||
7DF8422A1F40583F00D42D79 /* WeChatTweak.h */,
|
7DF8422A1F40583F00D42D79 /* WeChatTweak.h */,
|
||||||
7DF842331F4058AB00D42D79 /* WeChatTweak.m */,
|
7DF842331F4058AB00D42D79 /* WeChatTweak.m */,
|
||||||
7D2194C9264701950068F4CC /* AntiRevoke.h */,
|
|
||||||
7D2194CA264701950068F4CC /* AntiRevoke.m */,
|
7D2194CA264701950068F4CC /* AntiRevoke.m */,
|
||||||
|
7D64150B27A94B9600A8A398 /* Directory.m */,
|
||||||
|
7D64150D27A94BEA00A8A398 /* MultipleInstances.m */,
|
||||||
|
7D64150F27A94DE200A8A398 /* PreferencesWindow.m */,
|
||||||
|
7D64150627A9469900A8A398 /* ContextMenu.m */,
|
||||||
|
7D64150927A9481C00A8A398 /* ContactData.m */,
|
||||||
|
7D14E5A21F6447DB00D75132 /* Alfred.h */,
|
||||||
|
7D14E5A31F6447DB00D75132 /* Alfred.m */,
|
||||||
7D5AAF3720DF4BB300860EEE /* Vendor */,
|
7D5AAF3720DF4BB300860EEE /* Vendor */,
|
||||||
7D5AAF3620DF4BA400860EEE /* Category */,
|
7D5AAF3620DF4BA400860EEE /* Category */,
|
||||||
7D5AAF3520DF4B9700860EEE /* Controller */,
|
7D5AAF3520DF4B9700860EEE /* Controller */,
|
||||||
7D5AAF3320DF4B7B00860EEE /* Manager */,
|
|
||||||
7DF842631F40594400D42D79 /* Resources */,
|
7DF842631F40594400D42D79 /* Resources */,
|
||||||
7D5AAF3820DF4BC400860EEE /* Supporting Files */,
|
7D5AAF3820DF4BC400860EEE /* Supporting Files */,
|
||||||
);
|
);
|
||||||
|
@ -196,10 +194,8 @@
|
||||||
7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */,
|
7D9049FA1F82B708004E6370 /* NSString+WeChatTweak.h in Headers */,
|
||||||
7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */,
|
7DF8422C1F40583F00D42D79 /* WeChatTweak.h in Headers */,
|
||||||
7DF8425B1F4058DD00D42D79 /* NSBundle+WeChatTweak.h in Headers */,
|
7DF8425B1F4058DD00D42D79 /* NSBundle+WeChatTweak.h in Headers */,
|
||||||
7DB8AFBE206211D900E683AE /* WTConfigManager.h in Headers */,
|
|
||||||
7D9049F61F82A41A004E6370 /* fishhook.h in Headers */,
|
7D9049F61F82A41A004E6370 /* fishhook.h in Headers */,
|
||||||
7D14E5A41F6447DB00D75132 /* AlfredManager.h in Headers */,
|
7D14E5A41F6447DB00D75132 /* Alfred.h in Headers */,
|
||||||
7D2194CB264701950068F4CC /* AntiRevoke.h in Headers */,
|
|
||||||
7DF842601F40590500D42D79 /* WeChatTweakHeaders.h in Headers */,
|
7DF842601F40590500D42D79 /* WeChatTweakHeaders.h in Headers */,
|
||||||
7DF842521F4058C600D42D79 /* TweakPreferencesController.h in Headers */,
|
7DF842521F4058C600D42D79 /* TweakPreferencesController.h in Headers */,
|
||||||
);
|
);
|
||||||
|
@ -320,14 +316,18 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
7D14E5A51F6447DB00D75132 /* AlfredManager.m in Sources */,
|
7D14E5A51F6447DB00D75132 /* Alfred.m in Sources */,
|
||||||
7DF842531F4058C600D42D79 /* TweakPreferencesController.m in Sources */,
|
7DF842531F4058C600D42D79 /* TweakPreferencesController.m in Sources */,
|
||||||
7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */,
|
7D9049F91F82B6FB004E6370 /* NSString+WeChatTweak.m in Sources */,
|
||||||
|
7D64150827A9469900A8A398 /* ContextMenu.m in Sources */,
|
||||||
7D2194CC264701950068F4CC /* AntiRevoke.m in Sources */,
|
7D2194CC264701950068F4CC /* AntiRevoke.m in Sources */,
|
||||||
7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */,
|
7DF842341F4058AB00D42D79 /* WeChatTweak.m in Sources */,
|
||||||
7DB8AFBF206211D900E683AE /* WTConfigManager.m in Sources */,
|
7D64150A27A9481C00A8A398 /* ContactData.m in Sources */,
|
||||||
7D9049F51F82A41A004E6370 /* fishhook.c in Sources */,
|
7D9049F51F82A41A004E6370 /* fishhook.c in Sources */,
|
||||||
|
7D64151027A94DE200A8A398 /* PreferencesWindow.m in Sources */,
|
||||||
|
7D64150E27A94BEA00A8A398 /* MultipleInstances.m in Sources */,
|
||||||
7DF8425C1F4058DD00D42D79 /* NSBundle+WeChatTweak.m in Sources */,
|
7DF8425C1F4058DD00D42D79 /* NSBundle+WeChatTweak.m in Sources */,
|
||||||
|
7D64150C27A94B9600A8A398 /* Directory.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
//
|
//
|
||||||
// AlfredManager.h
|
// Alfred.h
|
||||||
// WeChatTweak
|
// WeChatTweak
|
||||||
//
|
//
|
||||||
// Created by Sunnyyoung on 2017/9/10.
|
// Created by Sunnyyoung on 2017/9/10.
|
||||||
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
#import <objc/message.h>
|
|
||||||
#import <YYModel/YYModel.h>
|
#import <YYModel/YYModel.h>
|
||||||
#import <GCDWebServer/GCDWebServer.h>
|
#import <GCDWebServer/GCDWebServer.h>
|
||||||
#import <GCDWebServer/GCDWebServerDataResponse.h>
|
#import <GCDWebServer/GCDWebServerDataResponse.h>
|
|
@ -1,13 +1,13 @@
|
||||||
//
|
//
|
||||||
// AlfredManager.m
|
// Alfred.m
|
||||||
// WeChatTweak
|
// WeChatTweak
|
||||||
//
|
//
|
||||||
// Created by Sunnyyoung on 2017/9/10.
|
// Created by Sunnyyoung on 2017/9/10.
|
||||||
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "AlfredManager.h"
|
#import "Alfred.h"
|
||||||
#import "WeChatTweakHeaders.h"
|
#import "WeChatTweak.h"
|
||||||
|
|
||||||
@interface AlfredManager()
|
@interface AlfredManager()
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@
|
||||||
@implementation AlfredManager
|
@implementation AlfredManager
|
||||||
|
|
||||||
static int port = 48065;
|
static int port = 48065;
|
||||||
|
|
||||||
|
+ (void)load {
|
||||||
|
[AlfredManager.sharedInstance startListener];
|
||||||
|
}
|
||||||
|
|
||||||
+ (instancetype)sharedInstance {
|
+ (instancetype)sharedInstance {
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
|
@ -1,20 +0,0 @@
|
||||||
//
|
|
||||||
// AntiRevoke.h
|
|
||||||
// WeChatTweak
|
|
||||||
//
|
|
||||||
// Created by Sunny Young on 2021/5/9.
|
|
||||||
// Copyright © 2021 Sunnyyoung. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
#import <objc/message.h>
|
|
||||||
#import <JRSwizzle/JRSwizzle.h>
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
@interface NSObject (AntiRevoke)
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
|
@ -6,9 +6,7 @@
|
||||||
// Copyright © 2021 Sunnyyoung. All rights reserved.
|
// Copyright © 2021 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "AntiRevoke.h"
|
#import "WeChatTweak.h"
|
||||||
#import "WeChatTweakHeaders.h"
|
|
||||||
#import "WTConfigManager.h"
|
|
||||||
#import "NSString+WeChatTweak.h"
|
#import "NSString+WeChatTweak.h"
|
||||||
#import "NSBundle+WeChatTweak.h"
|
#import "NSBundle+WeChatTweak.h"
|
||||||
|
|
||||||
|
@ -39,7 +37,7 @@ static void __attribute__((constructor)) tweak(void) {
|
||||||
// Fallback to origin method
|
// Fallback to origin method
|
||||||
[self tweak_FFToNameFavChatZZ:message sessionMsgList:sessionMsgList];
|
[self tweak_FFToNameFavChatZZ:message sessionMsgList:sessionMsgList];
|
||||||
} else {
|
} else {
|
||||||
switch (WTConfigManager.sharedInstance.revokedMessageStyle) {
|
switch (WeChatTweak.revokedMessageStyle) {
|
||||||
case WTRevokedMessageStyleClassic:
|
case WTRevokedMessageStyleClassic:
|
||||||
[self handleRevokedMessageIntoClassicStyleWithSession:session messageData:messageData replaceMessage:replaceMessage];
|
[self handleRevokedMessageIntoClassicStyleWithSession:session messageData:messageData replaceMessage:replaceMessage];
|
||||||
break;
|
break;
|
||||||
|
|
48
WeChatTweak/ContactData.m
Normal file
48
WeChatTweak/ContactData.m
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// ContactData.m
|
||||||
|
// WeChatTweak
|
||||||
|
//
|
||||||
|
// Created by Sunny Young on 2022/2/1.
|
||||||
|
// Copyright © 2022 Sunnyyoung. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "WeChatTweak.h"
|
||||||
|
|
||||||
|
@implementation NSObject (ContactData)
|
||||||
|
|
||||||
|
static void __attribute__((constructor)) tweak(void) {
|
||||||
|
objc_property_attribute_t type = { "T", "@\"NSString\"" }; // NSString
|
||||||
|
objc_property_attribute_t atom = { "N", "" }; // nonatomic
|
||||||
|
objc_property_attribute_t ownership = { "&", "" }; // C = copy & = strong
|
||||||
|
objc_property_attribute_t backingivar = { "V", "_m_nsHeadImgUrl" }; // ivar name
|
||||||
|
objc_property_attribute_t attrs[] = { type, atom, ownership, backingivar };
|
||||||
|
class_addProperty(objc_getClass("WCContactData"), "wt_avatarPath", attrs, 4);
|
||||||
|
class_addMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath))), "@@:");
|
||||||
|
class_addMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:))), "v@:@");
|
||||||
|
class_addMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist), method_getImplementation(class_getClassMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist))), "v@:");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)wt_avatarPath {
|
||||||
|
if (![objc_getClass("PathUtility") respondsToSelector:@selector(GetCurUserDocumentPath)]) {
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
NSString *pathString = [NSString stringWithFormat:@"%@/Avatar/%@.jpg", [objc_getClass("PathUtility") GetCurUserDocumentPath], [((WCContactData *)self).m_nsUsrName md5String]];
|
||||||
|
return [NSFileManager.defaultManager fileExistsAtPath:pathString] ? pathString : @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setWt_avatarPath:(NSString *)avatarPath {
|
||||||
|
// For readonly
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray *)modelPropertyWhitelist {
|
||||||
|
NSArray *list =@[
|
||||||
|
@"wt_avatarPath",
|
||||||
|
@"m_nsRemark",
|
||||||
|
@"m_nsNickName",
|
||||||
|
@"m_nsUsrName"
|
||||||
|
];
|
||||||
|
return WeChatTweak.compressedJSONEnabled ? list : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
156
WeChatTweak/ContextMenu.m
Normal file
156
WeChatTweak/ContextMenu.m
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
//
|
||||||
|
// ContextMenu.m
|
||||||
|
// WeChatTweak
|
||||||
|
//
|
||||||
|
// Created by Sunny Young on 2022/2/1.
|
||||||
|
// Copyright © 2022 Sunnyyoung. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "WeChatTweak.h"
|
||||||
|
#import "NSBundle+WeChatTweak.h"
|
||||||
|
|
||||||
|
#import <CoreImage/CoreImage.h>
|
||||||
|
|
||||||
|
@implementation NSObject (ContextMenu)
|
||||||
|
|
||||||
|
static void __attribute__((constructor)) tweak(void) {
|
||||||
|
[objc_getClass("MMMessageCellView") jr_swizzleMethod:NSSelectorFromString(@"contextMenu") withMethod:@selector(tweak_contextMenu) error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)tweak_contextMenu {
|
||||||
|
NSMenu *menu = (NSMenu *)[self tweak_contextMenu];
|
||||||
|
if ([self isKindOfClass:objc_getClass("MMMessageCellView")]) {
|
||||||
|
switch (((MMMessageCellView *)self).messageTableItem.message.messageType) {
|
||||||
|
case MessageDataTypeAppUrl: {
|
||||||
|
ReaderWrap *wrap = ({
|
||||||
|
ReaderWrap *wrap = nil;
|
||||||
|
if ([self isKindOfClass:objc_getClass("MMAppSingleReaderMessageCellView")]) {
|
||||||
|
MMAppSingleReaderMessageCellView *cell = (MMAppSingleReaderMessageCellView *)self;
|
||||||
|
wrap = cell.readerData;
|
||||||
|
} else if ([self isKindOfClass:objc_getClass("MMAppMultipleReaderMessageCellView")]) {
|
||||||
|
MMAppMultipleReaderMessageCellView *cell = (MMAppMultipleReaderMessageCellView *)self;
|
||||||
|
wrap = (cell.selectedReaderWrapIndex < cell.readerMessages.count) ? cell.readerMessages[cell.selectedReaderWrapIndex] : nil;
|
||||||
|
} else {
|
||||||
|
wrap = nil;
|
||||||
|
}
|
||||||
|
wrap;
|
||||||
|
});
|
||||||
|
if (wrap) {
|
||||||
|
[menu addItem:NSMenuItem.separatorItem];
|
||||||
|
[menu addItem:({
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.CopyLink"]
|
||||||
|
action:@selector(tweakCopyLink:)
|
||||||
|
keyEquivalent:@"c"];
|
||||||
|
item.target = wrap;
|
||||||
|
item;
|
||||||
|
})];
|
||||||
|
[menu addItem:({
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.OpenInBrowser"]
|
||||||
|
action:@selector(tweakOpenLink:)
|
||||||
|
keyEquivalent:@"o"];
|
||||||
|
item.target = wrap;
|
||||||
|
item;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageDataTypeImage: {
|
||||||
|
[menu addItem:NSMenuItem.separatorItem];
|
||||||
|
[menu addItem:({
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.IdentifyQRCode"]
|
||||||
|
action:@selector(tweakIdentifyQRCode:)
|
||||||
|
keyEquivalent:@"i"];
|
||||||
|
item.target = self;
|
||||||
|
item;
|
||||||
|
})];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MessageDataTypeSticker: {
|
||||||
|
[menu addItem:NSMenuItem.separatorItem];
|
||||||
|
[menu addItem:({
|
||||||
|
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.ExportSticker"]
|
||||||
|
action:@selector(tweakExportSticker:)
|
||||||
|
keyEquivalent:@"e"];
|
||||||
|
item.target = self;
|
||||||
|
item;
|
||||||
|
})];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tweakCopyLink:(NSMenuItem *)sender {
|
||||||
|
ReaderWrap *wrap = sender.target;
|
||||||
|
if (!wrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wrap.m_nsUrl) {
|
||||||
|
[NSPasteboard.generalPasteboard clearContents];
|
||||||
|
[NSPasteboard.generalPasteboard setString:wrap.m_nsUrl forType:NSStringPboardType];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tweakOpenLink:(NSMenuItem *)sender {
|
||||||
|
ReaderWrap *wrap = sender.target;
|
||||||
|
if (!wrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wrap.m_nsUrl && [NSURL URLWithString:wrap.m_nsUrl]) {
|
||||||
|
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:wrap.m_nsUrl]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tweakIdentifyQRCode:(NSMenuItem *)sender {
|
||||||
|
NSImage *image = ((MMImageMessageCellView *)self).displayedImage;
|
||||||
|
if (image) {
|
||||||
|
NSData *imageData = [image TIFFRepresentation];
|
||||||
|
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
|
||||||
|
NSArray *results = [detector featuresInImage:[CIImage imageWithData:imageData]];
|
||||||
|
if (results.count) {
|
||||||
|
CIQRCodeFeature *result = results.firstObject;
|
||||||
|
NSString *content = result.messageString;
|
||||||
|
if (content.length) {
|
||||||
|
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||||
|
[pasteboard clearContents];
|
||||||
|
[pasteboard setString:content forType:NSStringPboardType];
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:({
|
||||||
|
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
||||||
|
notification.informativeText = [NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.IdentifyQRCodeNotification"];
|
||||||
|
notification;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)tweakExportSticker:(NSMenuItem *)sender {
|
||||||
|
MMMessageCellView *cell = (MMMessageCellView *)sender.target;
|
||||||
|
MessageData *messageData = cell.messageTableItem.message;
|
||||||
|
NSString *localID = [messageData savingImageFileNameWithLocalID];
|
||||||
|
NSString *md5 = [NSDictionary dictionaryWithXMLString:[messageData.msgContent componentsSeparatedByString:@"\n"].lastObject][@"emoji"][@"_md5"];
|
||||||
|
if (!localID.length || !md5.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSSavePanel *panel = [NSSavePanel savePanel];
|
||||||
|
[panel setNameFieldStringValue:localID];
|
||||||
|
[panel setAllowsOtherFileTypes:YES];
|
||||||
|
[panel setAllowedFileTypes:@[@"gif"]];
|
||||||
|
[panel setExtensionHidden:NO];
|
||||||
|
[panel setCanCreateDirectories:YES];
|
||||||
|
[panel beginSheetModalForWindow:cell.window completionHandler:^(NSModalResponse result) {
|
||||||
|
if (result == NSModalResponseOK) {
|
||||||
|
NSString *path = panel.URL.path;
|
||||||
|
MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter];
|
||||||
|
EmoticonMgr *emoticonMgr = [serviceCenter getService:objc_getClass("EmoticonMgr")];
|
||||||
|
NSData *stickerData = [emoticonMgr getEmotionDataWithMD5:md5];
|
||||||
|
[stickerData writeToFile:path atomically:YES];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -6,7 +6,7 @@
|
||||||
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "WeChatTweakHeaders.h"
|
#import "WeChatTweak.h"
|
||||||
|
|
||||||
@interface TweakPreferencesController : NSViewController
|
@interface TweakPreferencesController : NSViewController
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#import "TweakPreferencesController.h"
|
#import "TweakPreferencesController.h"
|
||||||
#import "NSBundle+WeChatTweak.h"
|
#import "NSBundle+WeChatTweak.h"
|
||||||
#import "WTConfigManager.h"
|
|
||||||
|
|
||||||
@interface TweakPreferencesController () <MASPreferencesViewController>
|
@interface TweakPreferencesController () <MASPreferencesViewController>
|
||||||
|
|
||||||
|
@ -30,12 +29,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reloadData {
|
- (void)reloadData {
|
||||||
WTConfigManager *configManager = WTConfigManager.sharedInstance;
|
|
||||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
||||||
RevokeNotificationType notificationType = [userDefaults integerForKey:WeChatTweakPreferenceRevokeNotificationTypeKey];
|
RevokeNotificationType notificationType = [userDefaults integerForKey:WeChatTweakPreferenceRevokeNotificationTypeKey];
|
||||||
[self.notificationTypeButton selectItemAtIndex:notificationType];
|
[self.notificationTypeButton selectItemAtIndex:notificationType];
|
||||||
[self.compressedJSONEnabledButton selectItemAtIndex:configManager.compressedJSONEnabled ? 0 : 1];
|
[self.compressedJSONEnabledButton selectItemAtIndex:WeChatTweak.compressedJSONEnabled ? 0 : 1];
|
||||||
[self.revokedMessageStyleButton selectItemAtIndex:configManager.revokedMessageStyle];
|
[self.revokedMessageStyleButton selectItemAtIndex:WeChatTweak.revokedMessageStyle];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Event method
|
#pragma mark - Event method
|
||||||
|
@ -47,11 +45,11 @@
|
||||||
|
|
||||||
- (IBAction)switchCompressedJSONEnabledAction:(NSPopUpButton *)sender {
|
- (IBAction)switchCompressedJSONEnabledAction:(NSPopUpButton *)sender {
|
||||||
BOOL enabled = sender.indexOfSelectedItem == 0;
|
BOOL enabled = sender.indexOfSelectedItem == 0;
|
||||||
WTConfigManager.sharedInstance.compressedJSONEnabled = enabled;
|
WeChatTweak.compressedJSONEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)switchRevokedMessageStyleButton:(NSPopUpButton *)sender {
|
- (IBAction)switchRevokedMessageStyleButton:(NSPopUpButton *)sender {
|
||||||
WTConfigManager.sharedInstance.revokedMessageStyle = sender.indexOfSelectedItem;
|
WeChatTweak.revokedMessageStyle = sender.indexOfSelectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - MASPreferencesViewController
|
#pragma mark - MASPreferencesViewController
|
||||||
|
|
41
WeChatTweak/Directory.m
Normal file
41
WeChatTweak/Directory.m
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// Directory.m
|
||||||
|
// WeChatTweak
|
||||||
|
//
|
||||||
|
// Created by Sunny Young on 2022/2/1.
|
||||||
|
// Copyright © 2022 Sunnyyoung. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "WeChatTweak.h"
|
||||||
|
#import "fishhook.h"
|
||||||
|
|
||||||
|
static NSString *(*original_NSHomeDirectory)(void);
|
||||||
|
static NSArray<NSString *> *(*original_NSSearchPathForDirectoriesInDomains)(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
|
||||||
|
NSString *tweak_NSHomeDirectory(void) {
|
||||||
|
return [original_NSHomeDirectory() stringByAppendingPathComponent:@"/Library/Containers/com.tencent.xinWeChat/Data/"];
|
||||||
|
}
|
||||||
|
NSArray<NSString *> *tweak_NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde) {
|
||||||
|
if (domainMask == NSUserDomainMask) {
|
||||||
|
NSMutableArray<NSString *> *directories = [original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde) mutableCopy];
|
||||||
|
[directories enumerateObjectsUsingBlock:^(NSString * _Nonnull object, NSUInteger index, BOOL * _Nonnull stop) {
|
||||||
|
switch (directory) {
|
||||||
|
case NSDocumentDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; break;
|
||||||
|
case NSLibraryDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library"]; break;
|
||||||
|
case NSApplicationSupportDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support"]; break;
|
||||||
|
case NSCachesDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
return directories;
|
||||||
|
} else {
|
||||||
|
return original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((constructor)) tweak(void) {
|
||||||
|
// Global Function Hook
|
||||||
|
rebind_symbols((struct rebinding[2]) {
|
||||||
|
{ "NSHomeDirectory", tweak_NSHomeDirectory, (void *)&original_NSHomeDirectory },
|
||||||
|
{ "NSSearchPathForDirectoriesInDomains", tweak_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains }
|
||||||
|
}, 2);
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
//
|
|
||||||
// WTConfigManager.h
|
|
||||||
// WeChatTweak
|
|
||||||
//
|
|
||||||
// Created by Sunny Young on 21/03/2018.
|
|
||||||
// Copyright © 2018 Sunnyyoung. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
#import <objc/message.h>
|
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, WTRevokedMessageStyle) {
|
|
||||||
WTRevokedMessageStyleClassic = 0,
|
|
||||||
WTRevokedMessageStyleMask
|
|
||||||
};
|
|
||||||
|
|
||||||
@interface WTConfigManager : NSObject
|
|
||||||
|
|
||||||
@property (nonatomic, assign) BOOL compressedJSONEnabled;
|
|
||||||
@property (nonatomic, assign) WTRevokedMessageStyle revokedMessageStyle;
|
|
||||||
|
|
||||||
+ (instancetype)sharedInstance;
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,57 +0,0 @@
|
||||||
//
|
|
||||||
// WTConfigManager.m
|
|
||||||
// WeChatTweak
|
|
||||||
//
|
|
||||||
// Created by Sunny Young on 21/03/2018.
|
|
||||||
// Copyright © 2018 Sunnyyoung. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "WTConfigManager.h"
|
|
||||||
|
|
||||||
static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompressedJSONEnabledKey";
|
|
||||||
static NSString * const WeChatTweakRevokedMessageStyleKey = @"WeChatTweakRevokedMessageStyleKey";
|
|
||||||
|
|
||||||
@interface WTConfigManager()
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation WTConfigManager
|
|
||||||
|
|
||||||
+ (instancetype)sharedInstance {
|
|
||||||
static dispatch_once_t onceToken;
|
|
||||||
static WTConfigManager *shared;
|
|
||||||
dispatch_once(&onceToken, ^{
|
|
||||||
shared = [[WTConfigManager alloc] init];
|
|
||||||
});
|
|
||||||
return shared;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)init {
|
|
||||||
self = [super init];
|
|
||||||
if (self) {
|
|
||||||
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
|
|
||||||
if ([userDefaults objectForKey:WeChatTweakCompressedJSONEnabledKey]) {
|
|
||||||
_compressedJSONEnabled = [userDefaults boolForKey:WeChatTweakCompressedJSONEnabledKey];
|
|
||||||
} else {
|
|
||||||
_compressedJSONEnabled = YES;
|
|
||||||
}
|
|
||||||
_revokedMessageStyle = [userDefaults integerForKey:WeChatTweakRevokedMessageStyleKey];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Property method
|
|
||||||
|
|
||||||
- (void)setCompressedJSONEnabled:(BOOL)compressedJSONEnabled {
|
|
||||||
_compressedJSONEnabled = compressedJSONEnabled;
|
|
||||||
[NSUserDefaults.standardUserDefaults setBool:compressedJSONEnabled forKey:WeChatTweakCompressedJSONEnabledKey];
|
|
||||||
[NSUserDefaults.standardUserDefaults synchronize];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setRevokedMessageStyle:(WTRevokedMessageStyle)revokedMessageStyle {
|
|
||||||
_revokedMessageStyle = revokedMessageStyle;
|
|
||||||
[NSUserDefaults.standardUserDefaults setInteger:revokedMessageStyle forKey:WeChatTweakRevokedMessageStyleKey];
|
|
||||||
[NSUserDefaults.standardUserDefaults synchronize];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
50
WeChatTweak/MultipleInstances.m
Normal file
50
WeChatTweak/MultipleInstances.m
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// MultipleInstances.m
|
||||||
|
// WeChatTweak
|
||||||
|
//
|
||||||
|
// Created by Sunny Young on 2022/2/1.
|
||||||
|
// Copyright © 2022 Sunnyyoung. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "WeChatTweak.h"
|
||||||
|
#import "NSBundle+WeChatTweak.h"
|
||||||
|
|
||||||
|
@implementation NSObject (MultipleInstances)
|
||||||
|
|
||||||
|
static void __attribute__((constructor)) tweak(void) {
|
||||||
|
[objc_getClass("CUtility") jr_swizzleClassMethod:NSSelectorFromString(@"HasWechatInstance") withClassMethod:@selector(tweak_HasWechatInstance) error:nil];
|
||||||
|
[objc_getClass("NSRunningApplication") jr_swizzleClassMethod:NSSelectorFromString(@"runningApplicationsWithBundleIdentifier:") withClassMethod:@selector(tweak_runningApplicationsWithBundleIdentifier:) error:nil];
|
||||||
|
class_addMethod(objc_getClass("AppDelegate"), @selector(applicationDockMenu:), method_getImplementation(class_getInstanceMethod(objc_getClass("AppDelegate"), @selector(tweak_applicationDockMenu:))), "@:@");
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)tweak_HasWechatInstance {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSRunningApplication *> *)tweak_runningApplicationsWithBundleIdentifier:(NSString *)bundleIdentifier {
|
||||||
|
if ([bundleIdentifier isEqualToString:NSBundle.mainBundle.bundleIdentifier] ) {
|
||||||
|
return @[NSRunningApplication.currentApplication];
|
||||||
|
} else {
|
||||||
|
return [self tweak_runningApplicationsWithBundleIdentifier:bundleIdentifier];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMenu *)tweak_applicationDockMenu:(NSApplication *)sender {
|
||||||
|
NSMenu *menu = [[NSMenu alloc] init];
|
||||||
|
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.LoginAnotherAccount"]
|
||||||
|
action:@selector(openNewWeChatInstace:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[menu insertItem:menuItem atIndex:0];
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)openNewWeChatInstace:(id)sender {
|
||||||
|
NSString *applicationPath = NSBundle.mainBundle.bundlePath;
|
||||||
|
NSTask *task = [[NSTask alloc] init];
|
||||||
|
task.launchPath = @"/usr/bin/open";
|
||||||
|
task.arguments = @[@"-n", applicationPath];
|
||||||
|
[task launch];
|
||||||
|
[task waitUntilExit];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
31
WeChatTweak/PreferencesWindow.m
Normal file
31
WeChatTweak/PreferencesWindow.m
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// PreferencesWindow.m
|
||||||
|
// WeChatTweak
|
||||||
|
//
|
||||||
|
// Created by Sunny Young on 2022/2/1.
|
||||||
|
// Copyright © 2022 Sunnyyoung. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "WeChatTweak.h"
|
||||||
|
#import "NSBundle+WeChatTweak.h"
|
||||||
|
#import "TweakPreferencesController.h"
|
||||||
|
|
||||||
|
@implementation NSObject (PreferencesWindow)
|
||||||
|
|
||||||
|
#pragma mark - Constructor
|
||||||
|
|
||||||
|
static void __attribute__((constructor)) tweak(void) {
|
||||||
|
[objc_getClass("MASPreferencesWindowController") jr_swizzleMethod:NSSelectorFromString(@"initWithViewControllers:") withMethod:@selector(tweak_initWithViewControllers:) error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Preferences Window
|
||||||
|
|
||||||
|
- (id)tweak_initWithViewControllers:(NSArray *)arg1 {
|
||||||
|
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:arg1];
|
||||||
|
TweakPreferencesController *controller = [[TweakPreferencesController alloc] initWithNibName:nil bundle:[NSBundle tweakBundle]];
|
||||||
|
[viewControllers addObject:controller];
|
||||||
|
return [self tweak_initWithViewControllers:viewControllers];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
#import <objc/message.h>
|
#import <objc/message.h>
|
||||||
|
#import <JRSwizzle/JRSwizzle.h>
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, RevokeNotificationType) {
|
typedef NS_ENUM(NSUInteger, RevokeNotificationType) {
|
||||||
RevokeNotificationTypeFollow = 0,
|
RevokeNotificationTypeFollow = 0,
|
||||||
|
|
|
@ -6,11 +6,19 @@
|
||||||
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
// Copyright © 2017年 Sunnyyoung. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import "WeChatTweakHeaders.h"
|
||||||
#import <objc/runtime.h>
|
|
||||||
#import <objc/message.h>
|
|
||||||
#import <JRSwizzle/JRSwizzle.h>
|
|
||||||
#import <CoreImage/CoreImage.h>
|
|
||||||
|
|
||||||
FOUNDATION_EXPORT double WeChatTweakVersionNumber;
|
FOUNDATION_EXPORT double WeChatTweakVersionNumber;
|
||||||
FOUNDATION_EXPORT const unsigned char WeChatTweakVersionString[];
|
FOUNDATION_EXPORT const unsigned char WeChatTweakVersionString[];
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, WTRevokedMessageStyle) {
|
||||||
|
WTRevokedMessageStyleClassic = 0,
|
||||||
|
WTRevokedMessageStyleMask
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface WeChatTweak : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign, class) BOOL compressedJSONEnabled;
|
||||||
|
@property (nonatomic, assign, class) WTRevokedMessageStyle revokedMessageStyle;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
|
@ -7,277 +7,28 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "WeChatTweak.h"
|
#import "WeChatTweak.h"
|
||||||
#import "WeChatTweakHeaders.h"
|
|
||||||
#import "fishhook.h"
|
|
||||||
#import "NSBundle+WeChatTweak.h"
|
|
||||||
#import "NSString+WeChatTweak.h"
|
|
||||||
#import "TweakPreferencesController.h"
|
|
||||||
#import "AlfredManager.h"
|
|
||||||
#import "WTConfigManager.h"
|
|
||||||
|
|
||||||
// Global Function
|
static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompressedJSONEnabledKey";
|
||||||
static NSString *(*original_NSHomeDirectory)(void);
|
static NSString * const WeChatTweakRevokedMessageStyleKey = @"WeChatTweakRevokedMessageStyleKey";
|
||||||
static NSArray<NSString *> *(*original_NSSearchPathForDirectoriesInDomains)(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
|
|
||||||
NSString *tweak_NSHomeDirectory(void) {
|
@implementation WeChatTweak
|
||||||
return [original_NSHomeDirectory() stringByAppendingPathComponent:@"/Library/Containers/com.tencent.xinWeChat/Data/"];
|
|
||||||
}
|
+ (BOOL)compressedJSONEnabled {
|
||||||
NSArray<NSString *> *tweak_NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde) {
|
return [NSUserDefaults.standardUserDefaults boolForKey:WeChatTweakCompressedJSONEnabledKey];
|
||||||
if (domainMask == NSUserDomainMask) {
|
|
||||||
NSMutableArray<NSString *> *directories = [original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde) mutableCopy];
|
|
||||||
[directories enumerateObjectsUsingBlock:^(NSString * _Nonnull object, NSUInteger index, BOOL * _Nonnull stop) {
|
|
||||||
switch (directory) {
|
|
||||||
case NSDocumentDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; break;
|
|
||||||
case NSLibraryDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library"]; break;
|
|
||||||
case NSApplicationSupportDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support"]; break;
|
|
||||||
case NSCachesDirectory: directories[index] = [tweak_NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
return directories;
|
|
||||||
} else {
|
|
||||||
return original_NSSearchPathForDirectoriesInDomains(directory, domainMask, expandTilde);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation NSObject (WeChatTweak)
|
+ (void)setCompressedJSONEnabled:(BOOL)compressedJSONEnabled {
|
||||||
|
[NSUserDefaults.standardUserDefaults setBool:compressedJSONEnabled forKey:WeChatTweakCompressedJSONEnabledKey];
|
||||||
#pragma mark - Constructor
|
[NSUserDefaults.standardUserDefaults synchronize];
|
||||||
|
|
||||||
static void __attribute__((constructor)) tweak(void) {
|
|
||||||
// Global Function Hook
|
|
||||||
rebind_symbols((struct rebinding[2]) {
|
|
||||||
{ "NSHomeDirectory", tweak_NSHomeDirectory, (void *)&original_NSHomeDirectory },
|
|
||||||
{ "NSSearchPathForDirectoriesInDomains", tweak_NSSearchPathForDirectoriesInDomains, (void *)&original_NSSearchPathForDirectoriesInDomains }
|
|
||||||
}, 2);
|
|
||||||
// Method Swizzling
|
|
||||||
class_addMethod(objc_getClass("AppDelegate"), @selector(applicationDockMenu:), method_getImplementation(class_getInstanceMethod(objc_getClass("AppDelegate"), @selector(tweak_applicationDockMenu:))), "@:@");
|
|
||||||
[objc_getClass("AppDelegate") jr_swizzleMethod:NSSelectorFromString(@"applicationDidFinishLaunching:") withMethod:@selector(tweak_applicationDidFinishLaunching:) error:nil];
|
|
||||||
[objc_getClass("CUtility") jr_swizzleClassMethod:NSSelectorFromString(@"HasWechatInstance") withClassMethod:@selector(tweak_HasWechatInstance) error:nil];
|
|
||||||
[objc_getClass("NSRunningApplication") jr_swizzleClassMethod:NSSelectorFromString(@"runningApplicationsWithBundleIdentifier:") withClassMethod:@selector(tweak_runningApplicationsWithBundleIdentifier:) error:nil];
|
|
||||||
[objc_getClass("MASPreferencesWindowController") jr_swizzleMethod:NSSelectorFromString(@"initWithViewControllers:") withMethod:@selector(tweak_initWithViewControllers:) error:nil];
|
|
||||||
|
|
||||||
[objc_getClass("MMMessageCellView") jr_swizzleMethod:NSSelectorFromString(@"contextMenu") withMethod:@selector(tweak_contextMenu) error:nil];
|
|
||||||
|
|
||||||
objc_property_attribute_t type = { "T", "@\"NSString\"" }; // NSString
|
|
||||||
objc_property_attribute_t atom = { "N", "" }; // nonatomic
|
|
||||||
objc_property_attribute_t ownership = { "&", "" }; // C = copy & = strong
|
|
||||||
objc_property_attribute_t backingivar = { "V", "_m_nsHeadImgUrl" }; // ivar name
|
|
||||||
objc_property_attribute_t attrs[] = { type, atom, ownership, backingivar };
|
|
||||||
class_addProperty(objc_getClass("WCContactData"), "wt_avatarPath", attrs, 4);
|
|
||||||
class_addMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(wt_avatarPath))), "@@:");
|
|
||||||
class_addMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:), method_getImplementation(class_getInstanceMethod(objc_getClass("WCContactData"), @selector(setWt_avatarPath:))), "v@:@");
|
|
||||||
class_addMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist), method_getImplementation(class_getClassMethod(objc_getClass("WCContactData"), @selector(modelPropertyWhitelist))), "v@:");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - AppUrlMessageMenu
|
+ (WTRevokedMessageStyle)revokedMessageStyle {
|
||||||
|
return [NSUserDefaults.standardUserDefaults integerForKey:WeChatTweakRevokedMessageStyleKey];
|
||||||
- (id)tweak_contextMenu {
|
|
||||||
NSMenu *menu = (NSMenu *)[self tweak_contextMenu];
|
|
||||||
if ([self isKindOfClass:objc_getClass("MMMessageCellView")]) {
|
|
||||||
switch (((MMMessageCellView *)self).messageTableItem.message.messageType) {
|
|
||||||
case MessageDataTypeAppUrl: {
|
|
||||||
ReaderWrap *wrap = ({
|
|
||||||
ReaderWrap *wrap = nil;
|
|
||||||
if ([self isKindOfClass:objc_getClass("MMAppSingleReaderMessageCellView")]) {
|
|
||||||
MMAppSingleReaderMessageCellView *cell = (MMAppSingleReaderMessageCellView *)self;
|
|
||||||
wrap = cell.readerData;
|
|
||||||
} else if ([self isKindOfClass:objc_getClass("MMAppMultipleReaderMessageCellView")]) {
|
|
||||||
MMAppMultipleReaderMessageCellView *cell = (MMAppMultipleReaderMessageCellView *)self;
|
|
||||||
wrap = (cell.selectedReaderWrapIndex < cell.readerMessages.count) ? cell.readerMessages[cell.selectedReaderWrapIndex] : nil;
|
|
||||||
} else {
|
|
||||||
wrap = nil;
|
|
||||||
}
|
|
||||||
wrap;
|
|
||||||
});
|
|
||||||
if (wrap) {
|
|
||||||
[menu addItem:NSMenuItem.separatorItem];
|
|
||||||
[menu addItem:({
|
|
||||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.CopyLink"]
|
|
||||||
action:@selector(tweakCopyLink:)
|
|
||||||
keyEquivalent:@"c"];
|
|
||||||
item.target = wrap;
|
|
||||||
item;
|
|
||||||
})];
|
|
||||||
[menu addItem:({
|
|
||||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.OpenInBrowser"]
|
|
||||||
action:@selector(tweakOpenLink:)
|
|
||||||
keyEquivalent:@"o"];
|
|
||||||
item.target = wrap;
|
|
||||||
item;
|
|
||||||
})];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MessageDataTypeImage: {
|
|
||||||
[menu addItem:NSMenuItem.separatorItem];
|
|
||||||
[menu addItem:({
|
|
||||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.IdentifyQRCode"]
|
|
||||||
action:@selector(tweakIdentifyQRCode:)
|
|
||||||
keyEquivalent:@"i"];
|
|
||||||
item.target = self;
|
|
||||||
item;
|
|
||||||
})];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MessageDataTypeSticker: {
|
|
||||||
[menu addItem:NSMenuItem.separatorItem];
|
|
||||||
[menu addItem:({
|
|
||||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.ExportSticker"]
|
|
||||||
action:@selector(tweakExportSticker:)
|
|
||||||
keyEquivalent:@"e"];
|
|
||||||
item.target = self;
|
|
||||||
item;
|
|
||||||
})];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return menu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)tweakCopyLink:(NSMenuItem *)sender {
|
+ (void)setRevokedMessageStyle:(WTRevokedMessageStyle)revokedMessageStyle {
|
||||||
ReaderWrap *wrap = sender.target;
|
[NSUserDefaults.standardUserDefaults setInteger:revokedMessageStyle forKey:WeChatTweakRevokedMessageStyleKey];
|
||||||
if (!wrap) {
|
[NSUserDefaults.standardUserDefaults synchronize];
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (wrap.m_nsUrl) {
|
|
||||||
[NSPasteboard.generalPasteboard clearContents];
|
|
||||||
[NSPasteboard.generalPasteboard setString:wrap.m_nsUrl forType:NSStringPboardType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)tweakOpenLink:(NSMenuItem *)sender {
|
|
||||||
ReaderWrap *wrap = sender.target;
|
|
||||||
if (!wrap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (wrap.m_nsUrl && [NSURL URLWithString:wrap.m_nsUrl]) {
|
|
||||||
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:wrap.m_nsUrl]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)tweakIdentifyQRCode:(NSMenuItem *)sender {
|
|
||||||
NSImage *image = ((MMImageMessageCellView *)self).displayedImage;
|
|
||||||
if (image) {
|
|
||||||
NSData *imageData = [image TIFFRepresentation];
|
|
||||||
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
|
|
||||||
NSArray *results = [detector featuresInImage:[CIImage imageWithData:imageData]];
|
|
||||||
if (results.count) {
|
|
||||||
CIQRCodeFeature *result = results.firstObject;
|
|
||||||
NSString *content = result.messageString;
|
|
||||||
if (content.length) {
|
|
||||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
|
||||||
[pasteboard clearContents];
|
|
||||||
[pasteboard setString:content forType:NSStringPboardType];
|
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:({
|
|
||||||
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
|
||||||
notification.informativeText = [NSBundle.tweakBundle localizedStringForKey:@"Tweak.MessageMenuItem.IdentifyQRCodeNotification"];
|
|
||||||
notification;
|
|
||||||
})];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)tweakExportSticker:(NSMenuItem *)sender {
|
|
||||||
MMMessageCellView *cell = (MMMessageCellView *)sender.target;
|
|
||||||
MessageData *messageData = cell.messageTableItem.message;
|
|
||||||
NSString *localID = [messageData savingImageFileNameWithLocalID];
|
|
||||||
NSString *md5 = [NSDictionary dictionaryWithXMLString:[messageData.msgContent componentsSeparatedByString:@"\n"].lastObject][@"emoji"][@"_md5"];
|
|
||||||
if (!localID.length || !md5.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NSSavePanel *panel = [NSSavePanel savePanel];
|
|
||||||
[panel setNameFieldStringValue:localID];
|
|
||||||
[panel setAllowsOtherFileTypes:YES];
|
|
||||||
[panel setAllowedFileTypes:@[@"gif"]];
|
|
||||||
[panel setExtensionHidden:NO];
|
|
||||||
[panel setCanCreateDirectories:YES];
|
|
||||||
[panel beginSheetModalForWindow:cell.window completionHandler:^(NSModalResponse result) {
|
|
||||||
if (result == NSModalResponseOK) {
|
|
||||||
NSString *path = panel.URL.path;
|
|
||||||
MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter];
|
|
||||||
EmoticonMgr *emoticonMgr = [serviceCenter getService:objc_getClass("EmoticonMgr")];
|
|
||||||
NSData *stickerData = [emoticonMgr getEmotionDataWithMD5:md5];
|
|
||||||
[stickerData writeToFile:path atomically:YES];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Mutiple Instance
|
|
||||||
|
|
||||||
+ (BOOL)tweak_HasWechatInstance {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSArray<NSRunningApplication *> *)tweak_runningApplicationsWithBundleIdentifier:(NSString *)bundleIdentifier {
|
|
||||||
if ([bundleIdentifier isEqualToString:NSBundle.mainBundle.bundleIdentifier] ) {
|
|
||||||
return @[NSRunningApplication.currentApplication];
|
|
||||||
} else {
|
|
||||||
return [self tweak_runningApplicationsWithBundleIdentifier:bundleIdentifier];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSMenu *)tweak_applicationDockMenu:(NSApplication *)sender {
|
|
||||||
NSMenu *menu = [[NSMenu alloc] init];
|
|
||||||
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.LoginAnotherAccount"]
|
|
||||||
action:@selector(openNewWeChatInstace:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[menu insertItem:menuItem atIndex:0];
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)openNewWeChatInstace:(id)sender {
|
|
||||||
NSString *applicationPath = NSBundle.mainBundle.bundlePath;
|
|
||||||
NSTask *task = [[NSTask alloc] init];
|
|
||||||
task.launchPath = @"/usr/bin/open";
|
|
||||||
task.arguments = @[@"-n", applicationPath];
|
|
||||||
[task launch];
|
|
||||||
[task waitUntilExit];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Alfred
|
|
||||||
|
|
||||||
- (void)tweak_applicationDidFinishLaunching:(NSNotification *)notification {
|
|
||||||
[AlfredManager.sharedInstance startListener];
|
|
||||||
[self tweak_applicationDidFinishLaunching:notification];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Preferences Window
|
|
||||||
|
|
||||||
- (id)tweak_initWithViewControllers:(NSArray *)arg1 {
|
|
||||||
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:arg1];
|
|
||||||
TweakPreferencesController *controller = [[TweakPreferencesController alloc] initWithNibName:nil bundle:[NSBundle tweakBundle]];
|
|
||||||
[viewControllers addObject:controller];
|
|
||||||
return [self tweak_initWithViewControllers:viewControllers];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - WCContact Data
|
|
||||||
|
|
||||||
- (NSString *)wt_avatarPath {
|
|
||||||
if (![objc_getClass("PathUtility") respondsToSelector:@selector(GetCurUserDocumentPath)]) {
|
|
||||||
return @"";
|
|
||||||
}
|
|
||||||
NSString *pathString = [NSString stringWithFormat:@"%@/Avatar/%@.jpg", [objc_getClass("PathUtility") GetCurUserDocumentPath], [((WCContactData *)self).m_nsUsrName md5String]];
|
|
||||||
return [NSFileManager.defaultManager fileExistsAtPath:pathString] ? pathString : @"";
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setWt_avatarPath:(NSString *)avatarPath {
|
|
||||||
// For readonly
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSArray *)modelPropertyWhitelist {
|
|
||||||
NSArray *list =@[
|
|
||||||
@"wt_avatarPath",
|
|
||||||
@"m_nsRemark",
|
|
||||||
@"m_nsNickName",
|
|
||||||
@"m_nsUsrName"
|
|
||||||
];
|
|
||||||
return WTConfigManager.sharedInstance.compressedJSONEnabled ? list : nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user