Subversion Repositories TruePreview

[/] [trunk/] [Source/] [TruePreviewMessageViewer.m] - Blame information for rev 42

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jhriggs
/*
2 42 jhriggs
 * Copyright (c) 2009-2011, Jim Riggs, Christian Serving, L.L.C.
3 14 jhriggs
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are
7
 * met:
8
 *     * Redistributions of source code must retain the above copyright
9
 *       notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above
11
 *       copyright notice, this list of conditions and the following
12
 *       disclaimer in the documentation and/or other materials provided
13
 *       with the distribution.
14
 *     * Neither the name of Christian Serving, L.L.C. nor the names of
15
 *       its contributors may be used to endorse or promote products
16
 *       derived from this software without specific prior written
17
 *       permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 */
31
 
32
#import "TruePreviewMessageViewer.h"
33
 
34
@implementation TruePreviewMessageViewer
35
 
36
#pragma mark Class methods
37
 
38
+ (NSMutableDictionary*)truePreviewTimers {
39
  static NSMutableDictionary* sTimers = nil;
40
 
41
  if (sTimers == nil) {
42
    sTimers = [[NSMutableDictionary alloc] initWithCapacity:1];
43
  }
44
 
45
  return sTimers;
46
}
47
 
48
#pragma mark Swizzled instance methods
49
 
50
- (void)truePreviewDealloc {
51
  [self truePreviewReset];
52
  [[[self class] truePreviewTimers]
53
    removeObjectForKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
54
  ];
55
  [self truePreviewDealloc];
56
}
57
 
58 23 jhriggs
- (void)truePreviewForwardAsAttachment:(id)inSender {
59
  id theMessage = [self currentDisplayedMessage];
60
 
61
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
62
    NSDictionary* theSettings = [theMessage truePreviewSettings];
63
 
64
    if ([[theSettings objectForKey:@"forward"] boolValue]) {
65
      [self truePreviewReset];
66
      [theMessage truePreviewMarkAsViewed];
67
    }
68
  }
69
 
70
  [self truePreviewForwardAsAttachment:inSender];
71
}
72
 
73
- (void)truePreviewForwardMessage:(id)inSender {
74
  id theMessage = [self currentDisplayedMessage];
75
 
76
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
77
    NSDictionary* theSettings = [theMessage truePreviewSettings];
78
 
79
    if ([[theSettings objectForKey:@"forward"] boolValue]) {
80
      [self truePreviewReset];
81
      [theMessage truePreviewMarkAsViewed];
82
    }
83
  }
84
 
85
  [self truePreviewForwardMessage:inSender];
86
}
87
 
88 14 jhriggs
- (void)truePreviewMarkAsRead:(id)inSender {
89
  [self truePreviewReset];
90
  [self truePreviewMarkAsRead:inSender];
91
}
92
 
93
- (void)truePreviewMarkAsUnread:(id)inSender {
94
  [self truePreviewReset];
95
  [self truePreviewMarkAsUnread:inSender];
96
}
97
 
98 23 jhriggs
- (void)truePreviewMessageNoLongerDisplayedInTextView:(NSNotification*)inNotification {
99
  [self truePreviewMessageNoLongerDisplayedInTextView:inNotification];
100
 
101
  // we receive notifications from all MessageContentControllers
102
  if ([inNotification object] != object_getIvar(self, class_getInstanceVariable([self class], "_contentController"))) {
103
    return;
104
  }
105
 
106
  [self truePreviewReset];
107
}
108
 
109 14 jhriggs
- (void)truePreviewMessageWasDisplayedInTextView:(NSNotification*)inNotification {
110
  [self truePreviewMessageWasDisplayedInTextView:inNotification];
111
 
112 23 jhriggs
  // we receive notifications from all MessageContentControllers
113
  if ([inNotification object] != object_getIvar(self, class_getInstanceVariable([self class], "_contentController"))) {
114
    return;
115
  }
116
 
117 14 jhriggs
  id theMessage = [[inNotification userInfo] objectForKey:@"MessageKey"];
118
 
119
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
120
    NSDictionary* theSettings = [theMessage truePreviewSettings];
121
 
122
    if (
123
      ([[theSettings objectForKey:@"delay"] floatValue] == TRUEPREVIEW_DELAY_IMMEDIATE)
124
      || (
125
        [[theSettings objectForKey:@"window"] boolValue]
126
        && [self isKindOfClass:NSClassFromString(@"SingleMessageViewer")]
127
      )        
128
    ) {
129
      [self truePreviewReset];
130
      [theMessage truePreviewMarkAsViewed];
131
 
132
      return;
133
    }
134
 
135
    float theDelay = [[theSettings objectForKey:@"delay"] floatValue];
136
 
137
    if (theDelay > TRUEPREVIEW_DELAY_IMMEDIATE) {
138
      [self truePreviewReset];
139
      [self
140
        truePreviewSetTimer:[NSTimer
141
          scheduledTimerWithTimeInterval:theDelay
142
          target:self
143
          selector:@selector(truePreviewTimerFired:)
144
          userInfo:nil
145
          repeats:NO
146
        ]
147
      ];
148
    }
149
 
150 23 jhriggs
    if (
151
      ![self isKindOfClass:NSClassFromString(@"SingleMessageViewer")]
152
      && [[theSettings objectForKey:@"scroll"] boolValue]
153
    ) {
154 33 jhriggs
      // listen for selection change (mouse down) on message content view
155
      [[NSNotificationCenter defaultCenter]
156
        addObserver:self
157
        selector:@selector(truePreviewMessageClickedOrScrolled:)
158
        name:@"WebViewDidChangeSelectionNotification"
159
        object:[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView]
160
      ];
161
 
162 14 jhriggs
      // listen for bounds change notification on the message's clip view
163
      [[NSNotificationCenter defaultCenter]
164 23 jhriggs
        addObserver:self
165 33 jhriggs
        selector:@selector(truePreviewMessageClickedOrScrolled:)
166 23 jhriggs
        name:NSViewBoundsDidChangeNotification
167
        object:[[[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView] enclosingScrollView] contentView]
168
      ];
169 14 jhriggs
    }    
170
  }
171
}
172
 
173 23 jhriggs
- (void)truePreviewReplyAllMessage:(id)inSender {
174
  id theMessage = [self currentDisplayedMessage];
175
 
176
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
177
    NSDictionary* theSettings = [theMessage truePreviewSettings];
178
 
179
    if ([[theSettings objectForKey:@"reply"] boolValue]) {
180
      [self truePreviewReset];
181
      [theMessage truePreviewMarkAsViewed];
182
    }
183
  }
184
 
185
  [self truePreviewReplyAllMessage:inSender];
186 14 jhriggs
}
187
 
188 23 jhriggs
- (void)truePreviewReplyMessage:(id)inSender {
189
  id theMessage = [self currentDisplayedMessage];
190
 
191
  if ([theMessage isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
192
    NSDictionary* theSettings = [theMessage truePreviewSettings];
193
 
194
    if ([[theSettings objectForKey:@"reply"] boolValue]) {
195
      [self truePreviewReset];
196
      [theMessage truePreviewMarkAsViewed];
197
    }
198
  }
199
 
200
  [self truePreviewReplyMessage:inSender];
201
}
202
 
203 14 jhriggs
#pragma mark Accessors
204
 
205
- (NSTimer*)truePreviewTimer {
206
  return [[[self class] truePreviewTimers]
207
    objectForKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
208
  ];
209
}
210
 
211
- (void)truePreviewSetTimer:(NSTimer*)inTimer {
212
  [[[self class] truePreviewTimers]
213
    setObject:inTimer
214
    forKey:[NSNumber numberWithUnsignedLong:(unsigned long)self]
215
  ];
216
}
217
 
218
#pragma mark Instance methods
219
 
220
- (void)truePreviewReset {
221
  NSTimer* theTimer = [self truePreviewTimer];
222
 
223
  if ((theTimer != nil) && [theTimer isValid]) {
224
    [theTimer invalidate];
225
  }
226
 
227
  // stop observing when changed
228
  [[NSNotificationCenter defaultCenter]
229
    removeObserver:self
230 33 jhriggs
    name:@"WebViewDidChangeSelectionNotification"
231
    object:[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView]
232
  ];
233
  [[NSNotificationCenter defaultCenter]
234
    removeObserver:self
235 14 jhriggs
    name:NSViewBoundsDidChangeNotification
236
    object:[[[[object_getIvar(self, class_getInstanceVariable([self class], "_contentController")) currentDisplay] contentView] enclosingScrollView] contentView]
237
  ];
238
}
239
 
240
- (void)truePreviewTimerFired:(NSTimer*)inTimer {
241
  [self truePreviewReset];
242
 
243
  if ([[self currentDisplayedMessage] isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
244
    [[self currentDisplayedMessage] truePreviewMarkAsViewed];
245
  }
246
}
247
 
248 33 jhriggs
- (void)truePreviewMessageClickedOrScrolled:(NSNotification*)inNotification {
249 14 jhriggs
  // ignore the first time we get the notification; it may be an initial scroll
250
  // to the origin after changing messages
251
  static BOOL sIsFirstTime = YES;
252
 
253 33 jhriggs
  if ([NSViewBoundsDidChangeNotification isEqualToString:[inNotification name]] && sIsFirstTime) {
254 14 jhriggs
    sIsFirstTime = NO;
255
 
256
    return;
257
  }
258
 
259
  sIsFirstTime = YES;
260
 
261
  [self truePreviewReset];
262
 
263
  if ([[self currentDisplayedMessage] isKindOfClass:NSClassFromString(@"LibraryMessage")]) {
264
    [[self currentDisplayedMessage] truePreviewMarkAsViewed];
265
  }
266
}
267
 
268
@end