diff --git a/Classes/Headers/TVCLogController.h b/Classes/Headers/TVCLogController.h
index 6d66ce7ac5..efc6be98e6 100755
--- a/Classes/Headers/TVCLogController.h
+++ b/Classes/Headers/TVCLogController.h
@@ -37,10 +37,9 @@
#import "TextualApplication.h"
-typedef BOOL (^TVCLogMessageBlock)(void);
+typedef id (^TVCLogMessageBlock)(void);
@interface TVCLogController : NSObject
-@property (nonatomic, strong) NSString *html;
@property (nonatomic, weak) IRCWorld *world;
@property (nonatomic, weak) IRCClient *client;
@property (nonatomic, weak) IRCChannel *channel;
@@ -69,7 +68,8 @@ typedef BOOL (^TVCLogMessageBlock)(void);
@property (nonatomic, assign) NSInteger lastVisitedHighlight;
@property (nonatomic, strong) NSMutableArray *highlightedLineNumbers;
-@property (strong) NSMutableArray *messageQueue;
+@property (strong) NSMutableArray *normalMessageQueue; // Priority: Low
+@property (strong) NSMutableArray *specialMessageQueue; // Priority: High
@property (assign) BOOL queueInProgress;
- (void)setUp;
@@ -93,8 +93,9 @@ typedef BOOL (^TVCLogMessageBlock)(void);
- (void)unmark;
- (void)goToMark;
+- (void)clear TEXTUAL_DEPRECATED; // See IRCWorld.h for replacements.
+
- (void)reloadTheme;
-- (void)clear;
- (void)changeTextSize:(BOOL)bigger;
diff --git a/Classes/IRC/IRCWorld.m b/Classes/IRC/IRCWorld.m
index 198e4a2473..f2da32b8d8 100755
--- a/Classes/IRC/IRCWorld.m
+++ b/Classes/IRC/IRCWorld.m
@@ -156,7 +156,9 @@ - (void)setChannelMenuItem:(NSMenuItem *)item
- (void)fireMessageQueue:(TVCLogController *)log
{
- if (log.messageQueue.count >= 25) {
+ if (log.normalMessageQueue.count >= 25 ||
+ log.specialMessageQueue.count >= 25) {
+
static dispatch_once_t once;
/* Not 100% sure dispatch_once is
diff --git a/Classes/Views/Channel View/TVCLogController.m b/Classes/Views/Channel View/TVCLogController.m
index 5ef9e6b7fc..e5326df877 100755
--- a/Classes/Views/Channel View/TVCLogController.m
+++ b/Classes/Views/Channel View/TVCLogController.m
@@ -50,8 +50,9 @@ - (id)init
if ((self = [super init])) {
self.bottom = YES;
self.maxLines = 300;
-
- self.messageQueue = [NSMutableArray new];
+
+ self.normalMessageQueue = [NSMutableArray new];
+ self.specialMessageQueue = [NSMutableArray new];
self.highlightedLineNumbers = [NSMutableArray new];
[[WebPreferences standardPreferences] setCacheModel:WebCacheModelDocumentViewer];
@@ -135,28 +136,97 @@ - (void)setUp
- (void)runMessageQueueLoop
{
self.queueInProgress = YES;
+
+ [self runMessageQueueLoop:self.specialMessageQueue honorLoopDelay:NO];
+ [self runMessageQueueLoop:self.normalMessageQueue honorLoopDelay:YES];
+
+ self.queueInProgress = NO;
+}
+
+- (void)runMessageQueueLoop:(NSMutableArray *)messageQueue honorLoopDelay:(BOOL)delayLoop
+{
+ NSMutableString *result;
+
+ if (delayLoop == NO) {
+ result = [NSMutableString string];
+ }
- while (NSObjectIsNotEmpty(self.messageQueue)) {
+ while (NSObjectIsNotEmpty(messageQueue)) {
dispatch_async(dispatch_get_main_queue(), ^{
- if ([self.view isLoading] == NO) {
- if (NSObjectIsNotEmpty(self.messageQueue)) {
- BOOL srslt = ((TVCLogMessageBlock)(self.messageQueue)[0])();
+ if (NSObjectIsNotEmpty(messageQueue)) {
+ if ([self.view isLoading] == NO) {
+ // Internally, TVCLogMessageBlock should only return a
+ // BOOL as NSValue or NSString absolute value.
+
+ BOOL rrslt = NO;
+
+ // ---- //
+
+ id stslt = ((TVCLogMessageBlock)messageQueue[0])();
+
+ // ---- //
- if (srslt) {
- [self.messageQueue removeObjectAtIndex:0];
+ if ([stslt isKindOfClass:NSString.class]) {
+ if (PointerIsNotEmpty(stslt)) {
+ if (delayLoop == NO) {
+ [result appendString:stslt];
+ } else {
+ [self appendToDocumentBody:stslt];
+ }
+
+ rrslt = YES;
+ }
+ } else {
+ rrslt = [stslt boolValue];
+ }
+
+ // ---- //
+
+ if (rrslt) {
+ [messageQueue removeObjectAtIndex:0];
}
}
}
});
- if (self.channel) {
- [NSThread sleepForTimeInterval:[TPCPreferences viewLoopChannelDelay]];
- } else {
- [NSThread sleepForTimeInterval:[TPCPreferences viewLoopConsoleDelay]];
+ // ---- //
+
+ if (delayLoop) {
+ if (self.channel) {
+ [NSThread sleepForTimeInterval:[TPCPreferences viewLoopChannelDelay]];
+ } else {
+ [NSThread sleepForTimeInterval:[TPCPreferences viewLoopConsoleDelay]];
+ }
}
}
- self.queueInProgress = NO;
+ // ---- //
+
+ if (delayLoop == NO && NSObjectIsNotEmpty(result)) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self appendToDocumentBody:result];
+ });
+ }
+}
+
+#pragma mark -
+
+- (void)appendToDocumentBody:(NSString *)html
+{
+ DOMDocument *doc = [self mainFrameDocument];
+ if (PointerIsEmpty(doc)) return;
+
+ DOMElement *body = [self body:doc];
+ if (PointerIsEmpty(body)) return;
+
+ // ---- //
+
+ DOMDocumentFragment *frag = [(id)doc createDocumentFragmentWithMarkupString:html
+ baseURL:self.theme.baseUrl];
+
+ // ---- //
+
+ [body appendChild:frag];
}
- (void)loadAlternateHTML:(NSString *)newHTML
@@ -248,20 +318,20 @@ - (void)setTopic:(NSString *)topic
resultInfo:NULL];
DOMDocument *doc = [self mainFrameDocument];
- if (PointerIsEmpty(doc)) return NO;
+ if (PointerIsEmpty(doc)) return @(NO);
DOMElement *topic_body = [self topic:doc];
- if (PointerIsEmpty(topic_body)) return NO;
+ if (PointerIsEmpty(topic_body)) return @(NO);
[(id)topic_body setInnerHTML:body];
[self executeScriptCommand:@"topicBarValueChanged" withArguments:@[topic]];
}
- return YES;
+ return @(YES);
} copy];
-
- [self.messageQueue safeAddObject:messageBlock];
+
+ [self.normalMessageQueue safeAddObject:messageBlock];
[self.world runMessageQueueLoop:self];
}
@@ -343,12 +413,12 @@ - (void)restorePosition
- (void)mark
{
TVCLogMessageBlock (^messageBlock)(void) = [^{
- if (self.loaded == NO) return NO;
+ if (self.loaded == NO) return @(NO);
[self savePosition];
DOMDocument *doc = [self mainFrameDocument];
- if (PointerIsEmpty(doc)) return NO;
+ if (PointerIsEmpty(doc)) return @(NO);
DOMElement *body = [self body:doc];
@@ -366,10 +436,10 @@ - (void)mark
[self executeScriptCommand:@"historyIndicatorAddedToView" withArguments:@[]];
- return YES;
+ return @(YES);
} copy];
- [self.messageQueue safeAddObject:messageBlock];
+ [self.normalMessageQueue safeAddObject:messageBlock];
[self.world runMessageQueueLoop:self];
}
@@ -377,10 +447,10 @@ - (void)mark
- (void)unmark
{
TVCLogMessageBlock (^messageBlock)(void) = [^{
- if (self.loaded == NO) return NO;
+ if (self.loaded == NO) return @(NO);
DOMDocument *doc = [self mainFrameDocument];
- if (PointerIsEmpty(doc)) return NO;
+ if (PointerIsEmpty(doc)) return @(NO);
DOMElement *e = [doc getElementById:@"mark"];
@@ -392,10 +462,10 @@ - (void)unmark
[self executeScriptCommand:@"historyIndicatorRemovedFromView" withArguments:@[]];
- return YES;
+ return @(YES);
} copy];
- [self.messageQueue safeAddObject:messageBlock];
+ [self.normalMessageQueue safeAddObject:messageBlock];
[self.world runMessageQueueLoop:self];
}
@@ -429,31 +499,31 @@ - (void)goToMark
- (void)reloadTheme
{
- DOMDocument *doc = [self mainFrameDocument];
- if (PointerIsEmpty(doc)) return;
-
- DOMElement *body = [self body:doc];
- if (PointerIsEmpty(body)) return;
+ [self loadAlternateHTML:[self initialDocument:[self topicValue]]];
- self.html = [(id)body innerHTML];
+ // ---- //
+
+ NSDictionary *oldLines = self.logFile.data;
- self.scrollBottom = [self viewingBottom];
- self.scrollTop = [[[doc body] valueForKey:@"scrollTop"] integerValue];
+ if (NSObjectIsNotEmpty(oldLines)) {
+ NSArray *keys = oldLines.sortedDictionaryKeys;
+
+ for (NSString *key in keys) {
+ NSDictionary *lineDic = [oldLines objectForKey:key];
- [self loadAlternateHTML:[self initialDocument:[self topicValue]]];
-}
+ TVCLogLine *line = [TVCLogLine.alloc initWithDictionary:lineDic];
-- (void)clear
-{
- self.html = nil;
- self.loaded = NO;
- self.count = 0;
+ if (PointerIsNotEmpty(line)) {
+ BOOL rawHTML = (line.lineType == TVCLogLineRawHTMLType);
+
+ [self print:line withHTML:rawHTML specialWrite:YES];
+ }
+ }
+ }
- [self.logFile reset];
+ // ---- //
- [self executeScriptCommand:@"viewContentsBeingCleared" withArguments:@[]];
-
- [self loadAlternateHTML:[self initialDocument:[self topicValue]]];
+ [self moveToBottom];
}
- (void)changeTextSize:(BOOL)bigger
@@ -660,7 +730,7 @@ - (NSString *)renderedBodyForTranscriptLog:(TVCLogLine *)line
[s appendString:time];
}
-
+
if (NSObjectIsNotEmpty(line.nick)) {
NSString *nick = [line formattedNickname:self.channel];
@@ -679,7 +749,12 @@ - (BOOL)print:(TVCLogLine *)line
return [self print:line withHTML:NO];
}
-- (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)rawHTML
+- (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)stripHTML
+{
+ return [self print:line withHTML:stripHTML specialWrite:NO];
+}
+
+- (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)rawHTML specialWrite:(BOOL)isSpecial
{
if (NSObjectIsEmpty(line.body)) {
return NO;
@@ -801,7 +876,7 @@ - (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)rawHTML
// ---- //
- if (line.nick) {
+ if (NSObjectIsNotEmpty(line.nick)) {
attributes[@"isNicknameAvailable"] = @(YES);
attributes[@"nicknameColorNumber"] = @(line.nickColorNumber);
@@ -830,13 +905,13 @@ - (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)rawHTML
id templateRaw = [self.theme.other templateWithLineType:line.lineType];
- [self writeLine:templateRaw attributes:attributes contextInfo:line];
+ [self writeLine:templateRaw attributes:attributes contextInfo:line specialWrite:isSpecial];
// ************************************************************************** /
// Log highlight (if any). /
// ************************************************************************** /
- if (highlighted) {
+ if (highlighted && isSpecial == NO) {
NSString *messageBody;
NSString *nicknameBody = [line formattedNickname:self.channel];
@@ -856,7 +931,10 @@ - (BOOL)print:(TVCLogLine *)line withHTML:(BOOL)rawHTML
return highlighted;
}
-- (void)writeLine:(id)line attributes:(NSMutableDictionary *)attrs contextInfo:(TVCLogLine *)context
+- (void)writeLine:(id)line
+ attributes:(NSMutableDictionary *)attrs
+ contextInfo:(TVCLogLine *)context
+ specialWrite:(BOOL)isSpecial
{
TVCLogMessageBlock (^messageBlock)(void) = [^{
[self savePosition];
@@ -867,10 +945,10 @@ - (void)writeLine:(id)line attributes:(NSMutableDictionary *)attrs contextInfo:(
// ---- //
DOMDocument *doc = [self mainFrameDocument];
- if (PointerIsEmpty(doc)) return NO;
+ if (PointerIsEmpty(doc)) return nil;
DOMElement *body = [self body:doc];
- if (PointerIsEmpty(body)) return NO;
+ if (PointerIsEmpty(body)) return nil;
// ---- //
@@ -879,43 +957,46 @@ - (void)writeLine:(id)line attributes:(NSMutableDictionary *)attrs contextInfo:(
// ---- //
- NSString *aHtml = [line renderObject:attrs];
+ NSString *html = [line renderObject:attrs];
- if (NSObjectIsEmpty(aHtml)) {
- return NO;
+ if (NSObjectIsEmpty(html)) {
+ return nil;
}
// ---- //
- DOMDocumentFragment *frag = [(id)doc createDocumentFragmentWithMarkupString:aHtml
- baseURL:self.theme.baseUrl];
-
- [body appendChild:frag];
- }
+ if (self.maxLines > 0 && (self.count - 10) > self.maxLines) {
+ [self setNeedsLimitNumberOfLines];
+ }
- // ---- //
-
- if (self.maxLines > 0 && (self.count - 10) > self.maxLines) {
- [self setNeedsLimitNumberOfLines];
- }
-
- if ([attrs[@"highlightAttributeRepresentation"] isEqualToString:@"true"]) {
- [self.highlightedLineNumbers safeAddObject:@(self.lineNumber)];
- }
-
- [self executeScriptCommand:@"newMessagePostedToDisplay" withArguments:@[@(self.lineNumber)]];
+ if ([attrs[@"highlightAttributeRepresentation"] isEqualToString:@"true"]) {
+ [self.highlightedLineNumbers safeAddObject:@(self.lineNumber)];
+ }
- // ---- //
+ [self executeScriptCommand:@"newMessagePostedToDisplay" withArguments:@[@(self.lineNumber)]];
- [self.logFile writePropertyListEntry:[context dictionaryValue]
- toKey:[NSNumberWithInteger(self.lineNumber) integerWithLeadingZero:10]];
+ // ---- //
+ if (isSpecial == NO) {
+ [self.logFile writePropertyListEntry:[context dictionaryValue]
+ toKey:[NSNumberWithInteger(self.lineNumber) integerWithLeadingZero:10]];
+ }
+
+ return (__bridge void *)html;
+ }
+
// ---- //
- return YES;
+ return nil;
} copy];
-
- [self.messageQueue safeAddObject:messageBlock];
+
+ // ---- //
+
+ if (isSpecial) {
+ [self.specialMessageQueue safeAddObject:messageBlock];
+ } else {
+ [self.normalMessageQueue safeAddObject:messageBlock];
+ }
[self.world runMessageQueueLoop:self];
}
@@ -933,8 +1014,6 @@ - (NSString *)initialDocument:(NSString *)topic
templateTokens[@"activeStyleAbsolutePath"] = self.theme.other.path;
templateTokens[@"applicationResourcePath"] = [TPCPreferences whereResourcePath];
- templateTokens[@"existingBody"] = NSStringNilValueSubstitute(self.html);
-
// ---- //
if (self.channel) {
@@ -1184,4 +1263,12 @@ - (void)logViewDidResize
[self restorePosition];
}
+#pragma mark -
+#pragma mark Deprecated
+
+- (void)clear
+{
+ // ---- //
+}
+
@end
diff --git a/Resources/Info.plist b/Resources/Info.plist
index 4b65bac6bb..829e711822 100755
--- a/Resources/Info.plist
+++ b/Resources/Info.plist
@@ -47,8 +47,8 @@
TXBundleBuildCodeName
Turtle Soup
TXBundleBuildNumber
- 12269
+ 12291
TXBundleBuildReference
- 2.1.1-275-g410ffa5-debug
+ 2.1.1-276-g6e71f93-debug