diff --git a/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferencesController.nib b/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferencesController.nib index 999ac62..eb6894e 100644 Binary files a/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferencesController.nib and b/WeChatTweak.framework/Versions/A/Resources/Base.lproj/TweakPreferencesController.nib differ diff --git a/WeChatTweak.framework/Versions/A/Resources/Info.plist b/WeChatTweak.framework/Versions/A/Resources/Info.plist index 95bff03..a3a2205 100644 --- a/WeChatTweak.framework/Versions/A/Resources/Info.plist +++ b/WeChatTweak.framework/Versions/A/Resources/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 19B88 + 19C57 CFBundleDevelopmentRegion en CFBundleExecutable @@ -27,17 +27,17 @@ DTCompiler com.apple.compilers.llvm.clang.1_0 DTPlatformBuild - 11B500 + 11C29 DTPlatformVersion GM DTSDKBuild - 19B89 + 19B90 DTSDKName macosx10.15 DTXcode - 1120 + 1130 DTXcodeBuild - 11B500 + 11C29 LSMinimumSystemVersion 10.10 NSHumanReadableCopyright diff --git a/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferencesController.strings b/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferencesController.strings index 0059bf3..000734f 100644 --- a/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferencesController.strings +++ b/WeChatTweak.framework/Versions/A/Resources/en.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON compressing:"; + +"7wK-v5-BgQ.title" = "Revoked message style:"; +"wRC-UO-k1G.title" = "Classic"; +"gH0-wV-Bx0.title" = "Mask"; +"ftV-1F-OnB.title" = "Experimental feature" diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferencesController.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferencesController.strings index 0c7eff4..e711431 100644 --- a/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferencesController.strings +++ b/WeChatTweak.framework/Versions/A/Resources/zh-Hans.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON 压缩:"; + +"7wK-v5-BgQ.title" = "消息撤回样式:"; +"wRC-UO-k1G.title" = "经典"; +"gH0-wV-Bx0.title" = "遮罩"; +"ftV-1F-OnB.title" = "试验性功能" diff --git a/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferencesController.strings b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferencesController.strings index 9649c05..5623ecf 100644 --- a/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferencesController.strings +++ b/WeChatTweak.framework/Versions/A/Resources/zh-Hant.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON 壓縮:"; + +"7wK-v5-BgQ.title" = "消息撤回樣式:"; +"wRC-UO-k1G.title" = "經典"; +"gH0-wV-Bx0.title" = "遮罩"; +"ftV-1F-OnB.title" = "試驗性功能" diff --git a/WeChatTweak.framework/Versions/A/WeChatTweak b/WeChatTweak.framework/Versions/A/WeChatTweak index 4f0042a..b3955dd 100755 Binary files a/WeChatTweak.framework/Versions/A/WeChatTweak and b/WeChatTweak.framework/Versions/A/WeChatTweak differ diff --git a/WeChatTweak/Controller/Base.lproj/TweakPreferencesController.xib b/WeChatTweak/Controller/Base.lproj/TweakPreferencesController.xib index b975b21..eb20580 100644 --- a/WeChatTweak/Controller/Base.lproj/TweakPreferencesController.xib +++ b/WeChatTweak/Controller/Base.lproj/TweakPreferencesController.xib @@ -1,8 +1,8 @@ - + - + @@ -11,17 +11,18 @@ + - + - + @@ -29,7 +30,7 @@ - + @@ -37,10 +38,10 @@ - + - + @@ -57,10 +58,10 @@ - + - + @@ -80,18 +81,26 @@ - + + + + + + + + + - + - + @@ -108,36 +117,72 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/WeChatTweak/Controller/TweakPreferencesController.m b/WeChatTweak/Controller/TweakPreferencesController.m index b06b890..e398966 100644 --- a/WeChatTweak/Controller/TweakPreferencesController.m +++ b/WeChatTweak/Controller/TweakPreferencesController.m @@ -15,6 +15,7 @@ @property (weak) IBOutlet NSPopUpButton *autoAuthButton; @property (weak) IBOutlet NSPopUpButton *notificationTypeButton; @property (weak) IBOutlet NSPopUpButton *compressedJSONEnabledButton; +@property (weak) IBOutlet NSPopUpButton *revokedMessageStyleButton; @end @@ -37,6 +38,7 @@ [self.autoAuthButton selectItemAtIndex:enabledAutoAuth ? 1 : 0]; [self.notificationTypeButton selectItemAtIndex:notificationType]; [self.compressedJSONEnabledButton selectItemAtIndex:configManager.compressedJSONEnabled ? 0 : 1]; + [self.revokedMessageStyleButton selectItemAtIndex:configManager.revokedMessageStyle]; } #pragma mark - Event method @@ -57,6 +59,10 @@ WTConfigManager.sharedInstance.compressedJSONEnabled = enabled; } +- (IBAction)switchRevokedMessageStyleButton:(NSPopUpButton *)sender { + WTConfigManager.sharedInstance.revokedMessageStyle = sender.indexOfSelectedItem; +} + #pragma mark - MASPreferencesViewController - (NSString *)identifier { diff --git a/WeChatTweak/Controller/en.lproj/TweakPreferencesController.strings b/WeChatTweak/Controller/en.lproj/TweakPreferencesController.strings index 0059bf3..000734f 100644 --- a/WeChatTweak/Controller/en.lproj/TweakPreferencesController.strings +++ b/WeChatTweak/Controller/en.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON compressing:"; + +"7wK-v5-BgQ.title" = "Revoked message style:"; +"wRC-UO-k1G.title" = "Classic"; +"gH0-wV-Bx0.title" = "Mask"; +"ftV-1F-OnB.title" = "Experimental feature" diff --git a/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferencesController.strings b/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferencesController.strings index 0c7eff4..e711431 100644 --- a/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferencesController.strings +++ b/WeChatTweak/Controller/zh-Hans.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON 压缩:"; + +"7wK-v5-BgQ.title" = "消息撤回样式:"; +"wRC-UO-k1G.title" = "经典"; +"gH0-wV-Bx0.title" = "遮罩"; +"ftV-1F-OnB.title" = "试验性功能" diff --git a/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferencesController.strings b/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferencesController.strings index 9649c05..5623ecf 100644 --- a/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferencesController.strings +++ b/WeChatTweak/Controller/zh-Hant.lproj/TweakPreferencesController.strings @@ -31,3 +31,8 @@ /* Class = "NSTextFieldCell"; title = "Alfred JSON compressing:"; ObjectID = "jHw-2a-B2t"; */ "jHw-2a-B2t.title" = "Alfred JSON 壓縮:"; + +"7wK-v5-BgQ.title" = "消息撤回樣式:"; +"wRC-UO-k1G.title" = "經典"; +"gH0-wV-Bx0.title" = "遮罩"; +"ftV-1F-OnB.title" = "試驗性功能" diff --git a/WeChatTweak/Manager/RecallCacheManager.m b/WeChatTweak/Manager/RecallCacheManager.m index 2a9053d..c3ac013 100644 --- a/WeChatTweak/Manager/RecallCacheManager.m +++ b/WeChatTweak/Manager/RecallCacheManager.m @@ -35,12 +35,12 @@ } + (void)insertRevokedMessage:(MessageData *)message { - NSString *identifer = [NSString stringWithFormat:@"%lld-%ud", message.mesSvrID, message.msgCreateTime]; + NSString *identifer = [NSString stringWithFormat:@"%ud-%lld-%ud", message.mesLocalID, message.mesSvrID, message.msgCreateTime]; [RecallCacheManager.sharedInstance.kv setBool:YES forKey:identifer]; } + (BOOL)containsRevokedMessage:(MessageData *)message { - NSString *identifer = [NSString stringWithFormat:@"%lld-%ud", message.mesSvrID, message.msgCreateTime]; + NSString *identifer = [NSString stringWithFormat:@"%ud-%lld-%ud", message.mesLocalID, message.mesSvrID, message.msgCreateTime]; return [RecallCacheManager.sharedInstance.kv containsKey:identifer]; } diff --git a/WeChatTweak/Manager/WTConfigManager.h b/WeChatTweak/Manager/WTConfigManager.h index 2d21970..11e7283 100644 --- a/WeChatTweak/Manager/WTConfigManager.h +++ b/WeChatTweak/Manager/WTConfigManager.h @@ -10,9 +10,15 @@ #import #import +typedef NS_ENUM(NSUInteger, WTRevokedMessageStyle) { + WTRevokedMessageStylePlain = 0, + WTRevokedMessageStyleMask +}; + @interface WTConfigManager : NSObject @property (nonatomic, assign) BOOL compressedJSONEnabled; +@property (nonatomic, assign) WTRevokedMessageStyle revokedMessageStyle; + (instancetype)sharedInstance; diff --git a/WeChatTweak/Manager/WTConfigManager.m b/WeChatTweak/Manager/WTConfigManager.m index 9529c81..9b928a7 100644 --- a/WeChatTweak/Manager/WTConfigManager.m +++ b/WeChatTweak/Manager/WTConfigManager.m @@ -9,6 +9,7 @@ #import "WTConfigManager.h" static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompressedJSONEnabledKey"; +static NSString * const WeChatTweakRevokedMessageStyleKey = @"WeChatTweakRevokedMessageStyleKey"; @interface WTConfigManager() @@ -34,6 +35,7 @@ static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompr } else { _compressedJSONEnabled = YES; } + _revokedMessageStyle = [userDefaults integerForKey:WeChatTweakRevokedMessageStyleKey]; } return self; } @@ -46,4 +48,10 @@ static NSString * const WeChatTweakCompressedJSONEnabledKey = @"WeChatTweakCompr [NSUserDefaults.standardUserDefaults synchronize]; } +- (void)setRevokedMessageStyle:(WTRevokedMessageStyle)revokedMessageStyle { + _revokedMessageStyle = revokedMessageStyle; + [NSUserDefaults.standardUserDefaults setInteger:revokedMessageStyle forKey:WeChatTweakRevokedMessageStyleKey]; + [NSUserDefaults.standardUserDefaults synchronize]; +} + @end diff --git a/WeChatTweak/WeChatTweak.m b/WeChatTweak/WeChatTweak.m index 52ba467..3b34aab 100755 --- a/WeChatTweak/WeChatTweak.m +++ b/WeChatTweak/WeChatTweak.m @@ -142,15 +142,114 @@ static void __attribute__((constructor)) tweak(void) { } - (void)tweak_onRevokeMsg:(MessageData *)message sessionMessageList:(nullable id)sessionMessageList { + switch (WTConfigManager.sharedInstance.revokedMessageStyle) { + case WTRevokedMessageStylePlain: + [self handleRevokedMessageIntoClassicStyle:message]; break; + case WTRevokedMessageStyleMask: + [self handleRevokedMessageIntoMaskStyle:message]; break; + default: + break; + } +} + +- (void)handleRevokedMessageIntoClassicStyle:(MessageData *)message { // Decode message NSString *session = [message.msgContent tweak_subStringFrom:@"" to:@""]; NSUInteger newMessageID = [message.msgContent tweak_subStringFrom:@"" to:@""].longLongValue; NSString *replaceMessage = [message.msgContent tweak_subStringFrom:@""]; - - // Get message data - MessageData *messageData = [((MessageService *)self) GetMsgData:session svrId:newMessageID]; - [RecallCacheManager insertRevokedMessage:messageData]; - + // Prepare message data + MessageData *localMessageData = [((MessageService *)self) GetMsgData:session svrId:newMessageID]; + MessageData *promptMessageData = ({ + MessageData *data = [[objc_getClass("MessageData") alloc] initWithMsgType:10000]; + data.msgStatus = 4; + data.toUsrName = localMessageData.toUsrName; + data.fromUsrName = localMessageData.fromUsrName; + data.mesSvrID = localMessageData.mesSvrID; + data.mesLocalID = localMessageData.mesLocalID; + data.msgCreateTime = localMessageData.msgCreateTime; + if ([localMessageData isSendFromSelf]) { + data.msgContent = replaceMessage; + } else { + NSString *fromUserName = [replaceMessage componentsSeparatedByString:@" "].firstObject; + NSString *userRevoke = [NSString stringWithFormat:@"%@ %@ ", fromUserName, [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Recalled"]]; + NSString *tips = [NSString stringWithFormat:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.InterceptedARecalledMessage"], userRevoke]; + NSMutableString *msgContent = [NSMutableString stringWithString:tips]; + switch (localMessageData.messageType) { + case MessageDataTypeText: { + if (localMessageData.msgContent.length) { + if ([session rangeOfString:@"@chatroom"].location == NSNotFound) { + [msgContent appendFormat:@"\"%@\"", localMessageData.msgContent]; + } else { + [msgContent appendFormat:@"\"%@\"", [localMessageData.msgContent componentsSeparatedByString:@":\n"].lastObject]; + } + } else { + [msgContent appendString:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.AMessage"]]; + } + break; + } + case MessageDataTypeImage: + [msgContent appendFormat:@"<%@>", [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Image"]]; break; + case MessageDataTypeVoice: + [msgContent appendFormat:@"<%@>", [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Voice"]]; break; + case MessageDataTypeVideo: + [msgContent appendFormat:@"<%@>", [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Video"]]; break; + case MessageDataTypeSticker: + [msgContent appendFormat:@"<%@>", [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Sticker"]]; break; + case MessageDataTypeAppUrl: + [msgContent appendFormat:@"<%@>", [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.Link"]]; break; + default: + [msgContent appendString:[NSBundle.tweakBundle localizedStringForKey:@"Tweak.Message.AMessage"]]; break; + } + data.msgContent = msgContent; + } + data; + }); + // Prepare notification information + MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter]; + NSUserNotification *userNotification = [[NSUserNotification alloc] init]; + BOOL isChatStatusNotifyOpen = YES; + if ([session rangeOfString:@"@chatroom"].location == NSNotFound) { + ContactStorage *contactStorage = [serviceCenter getService:objc_getClass("ContactStorage")]; + WCContactData *contact = [contactStorage GetContact:session]; + isChatStatusNotifyOpen = [contact isChatStatusNotifyOpen]; + userNotification.informativeText = replaceMessage; + } else { + GroupStorage *groupStorage = [serviceCenter getService:objc_getClass("GroupStorage")]; + WCContactData *groupContact = [groupStorage GetGroupContact:session]; + isChatStatusNotifyOpen = [groupContact isChatStatusNotifyOpen]; + NSString *groupName = groupContact.m_nsNickName.length ? groupContact.m_nsNickName : [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.Group"]; + userNotification.informativeText = [NSString stringWithFormat:@"%@: %@", groupName, replaceMessage]; + } + // Delete message if it is revoke from myself + if ([localMessageData isSendFromSelf]) { + [((MessageService *)self) DelMsg:session msgList:@[localMessageData] isDelAll:NO isManual:YES]; + [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; + } else { + if (localMessageData.messageType == MessageDataTypeText) { + [((MessageService *)self) DelMsg:session msgList:@[localMessageData] isDelAll:NO isManual:YES]; + } + [((MessageService *)self) AddLocalMsg:session msgData:promptMessageData]; + } + // Dispatch notification + dispatch_async(dispatch_get_main_queue(), ^{ + // Deliver notification + if (![localMessageData isSendFromSelf]) { + RevokeNotificationType notificationType = [[NSUserDefaults standardUserDefaults] integerForKey:WeChatTweakPreferenceRevokeNotificationTypeKey]; + if (notificationType == RevokeNotificationTypeReceiveAll || (notificationType == RevokeNotificationTypeFollow && isChatStatusNotifyOpen)) { + [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification]; + } + } + }); +} + +- (void)handleRevokedMessageIntoMaskStyle:(MessageData *)message { + // Decode message + NSString *session = [message.msgContent tweak_subStringFrom:@"" to:@""]; + NSUInteger newMessageID = [message.msgContent tweak_subStringFrom:@"" to:@""].longLongValue; + NSString *replaceMessage = [message.msgContent tweak_subStringFrom:@""]; + // Get message data + MessageData *messageData = [((MessageService *)self) GetMsgData:session svrId:newMessageID]; + [RecallCacheManager insertRevokedMessage:messageData]; // Prepare notification information MMServiceCenter *serviceCenter = [objc_getClass("MMServiceCenter") defaultCenter]; NSUserNotification *userNotification = [[NSUserNotification alloc] init]; @@ -167,7 +266,6 @@ static void __attribute__((constructor)) tweak(void) { NSString *groupName = groupContact.m_nsNickName.length ? groupContact.m_nsNickName : [NSBundle.tweakBundle localizedStringForKey:@"Tweak.Title.Group"]; userNotification.informativeText = [NSString stringWithFormat:@"%@: %@", groupName, replaceMessage]; } - if ([messageData isSendFromSelf]) { MessageData *promptMessageData = ({ MessageData *data = [[objc_getClass("MessageData") alloc] initWithMsgType:MessageDataTypePrompt]; @@ -188,7 +286,6 @@ static void __attribute__((constructor)) tweak(void) { [((MessageService *)self) notifyDelMsgOnMainThread:messageData.getChatNameForCurMsg msgData:messageData]; [((MessageService *)self) notifyAddRevokePromptMsgOnMainThread:messageData.getChatNameForCurMsg msgData:messageData]; } - // Dispatch notification dispatch_async(dispatch_get_main_queue(), ^{ // Deliver notification