MessageSplitViewController.swift 10.2 KB
Newer Older
1
////////////////////////////////////////////////////////////////////////////////
2
3
4
5
6
7
8
//
//  MessageSplitViewController.swift
//  MessageTextEntrySpike
//
//  Created by Aral Balkan on 03/01/2015.
//  Copyright (c) 2015 ind.ie. All rights reserved.
//
9
////////////////////////////////////////////////////////////////////////////////
10
11

import Cocoa
12

13
14
class MessageSplitViewController: NSSplitViewController
{
15

16
    var sendMessageNotificationHandler:NotificationHandler?
17
    
18
19
20
21
22
23
24
    //
    // MARK: - View lifecycle
    //
    
    override func viewWillAppear()
    {
        createConstraints()
25
26
        
        addNotificationHandlers()
27
28
29
    }
    
    
30
    override func viewWillDisappear()
31
    {
32
        removeNotificationHandlers()
33
34
35
    }
    
    //
36
    // MARK: - Notification handlers
37
38
    //
    
39
    func addNotificationHandlers()
40
    {
41
42
43
44
45
46
47
48
        println("\(self): adding notification handlers.")
        
        if (sendMessageNotificationHandler != nil)
        {
            println("\(self): CORRECTION: not adding notification handlers as sendMessageNotificationHandler already exists.")
            return
        }
        
Aral Balkan's avatar
Aral Balkan committed
49
50
51
        //
        // MARK: - .SendMessage
        //
52
        sendMessageNotificationHandler = handle(MessageNotification.named(.SendMessage))
53
        {
54
            /* as */ notification in
55
            
56
57
58
            println("SEND MESSAGE NOTIFICATION HANDLER!!!!")
            println(notification.userInfo)
            
59
            if let userInfo = (notification.userInfo as Dictionary!), messageAttributedString = userInfo["message"] as? NSAttributedString
60
            {
61
62
63
64
65
66
                println("Send message: received text: \(messageAttributedString)")
                
                //
                // Get the folder to save the message to based on the current timeline
                //
                
67
                if CurrentTimeline.path == nil
68
69
70
71
                {
                    fatalError("Conversation messages not implemented yet. Panicing!")
                }
                
72
                println("Current timeline path = \(CurrentTimeline.path)")
73
74
75
76
                
                //
                // Get the correct web prefix
                //
77
                if CurrentTimeline.relativeWebPrefix == nil
78
                {
79
                    fatalError("Could not get relative web prefix for current timeline — not implemented. Only Private, All Friends, and Public timelines implemented at the moment.")
80
81
                }
                
82
                println("Current timeline relative web prefix: \(CurrentTimeline.relativeWebPrefix)")
83
84
85
86
87
88
                
                //
                // Create a file wrapper to save the contents as a directory.
                //
                let messageDirectoryWrapper:NSFileWrapper? = messageAttributedString.fileWrapperFromRange(NSMakeRange(0, messageAttributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding, NSExcludedElementsDocumentAttribute: ["xml", "html", "head", "body", "font", "span"], NSPrefixSpacesDocumentAttribute: 4], error: nil)
                
89
90
91
                // The file name of the message folder (this is the unique ID — unique per message folder):
                // Local message clock (padding to 9 digits — which should be large enough for any timeline as it would take 
                // about a thousand years to fill it up at ten seconds a message, every ten seconds, eight hours a day, continuously) + current timestamp in ISO 8601 format
92

93
94
                CurrentTimeline.messageClock++
                let messageFileName = String(format:"%09d-\(ISO8601DateString())", CurrentTimeline.messageClock)
95
96
                
                // This is the URL that will be prefixed to all assets in the HTML (images, etc.)
97
                let assetURLPrefix = CurrentTimeline.relativeWebPrefix!.stringByAppendingPathComponent(messageFileName)
98
                
99
100
                println("Asset URL Prefix: \(assetURLPrefix)")
                
101
102
                println("Message file name: \(messageFileName)")
                
103
                let filePath = NSHomeDirectory().stringByAppendingPathComponent("Pulse/Sync").stringByAppendingPathComponent(CurrentTimeline.path!).stringByAppendingPathComponent(messageFileName)
104
105
106
107
                
                println("About to save message at path: \(filePath)")
                
                let fileURL:NSURL? = NSURL(fileURLWithPath: filePath, isDirectory: true)
108
                
109
                if let messageDirectoryWrapper = messageDirectoryWrapper, fileURL = fileURL
110
                {
111
112
113
                    let messageFileWrappers:[NSObject:AnyObject] = messageDirectoryWrapper.fileWrappers
                    
                    for (fileName, fileWrapper) in messageFileWrappers
114
                    {
115
116
                        println(" * \(fileName): \(fileWrapper)")
                        if fileName == "index.html"
117
                        {
118
119
                            let indexData:NSData? = fileWrapper.regularFileContents
                            if let indexData = indexData
120
                            {
121
122
                                let indexHTML = NSString(data: indexData, encoding: NSUTF8StringEncoding)
                                if var indexHTML = indexHTML
123
                                {
Aral Balkan's avatar
Aral Balkan committed
124
125
                                    // TODO: Parse markdown (?)
                                    
126
127
128
129
                                    //
                                    // Massage the HTML.
                                    //
                                    
130
131
                                    println(indexHTML)
                                    
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
                                    // Fix image URLs
                                    indexHTML = indexHTML.stringByReplacingOccurrencesOfString("file:///", withString: assetURLPrefix.stringByAppendingString("/"))
                                    
                                    // Remove redundant empty lines.
                                    indexHTML = indexHTML.stringByReplacingOccurrencesOfString("<p><br></p>", withString: "")
                                    
                                    //
                                    // Update the index.html.
                                    //
                                    
                                    // Remove the index.html file wrapper.
                                    messageDirectoryWrapper.removeFileWrapper(fileWrapper as! NSFileWrapper)
                                    
                                    // And replace it with the new index.html we created.
                                    let newIndexHTMLData:NSData? = indexHTML.dataUsingEncoding(NSUTF8StringEncoding)
                                    
                                    if let newIndexHTMLData = newIndexHTMLData
                                    {
                                        let newIndexHTMLFileWrapper = NSFileWrapper(regularFileWithContents: newIndexHTMLData)
                                        newIndexHTMLFileWrapper.preferredFilename = "index.html"
                                        messageDirectoryWrapper.addFileWrapper(newIndexHTMLFileWrapper)
                                    }
                                    
                                    // TODO: Error checking.
                                    messageDirectoryWrapper.writeToURL(fileURL, options: NSFileWrapperWritingOptions.Atomic, originalContentsURL: nil, error: nil)
                                    println(messageDirectoryWrapper)
                                    
                                    //
160
                                    // Create the message object and broadcast it.
161
162
                                    //
                                    let message = Message(id: messageFileName, assetURLPrefix: assetURLPrefix, folderURL: fileURL, html: indexHTML as String, synced: false)
163
                            
164
165
166
167
168
169
170
171
172
173
                                    //
                                    // Inform Node that it should post the message to the timeline
                                    // (TODO: Research: should we base this on the Pulse event flow instead? Which is cleaner?)
                                    //
                                    // Note: In the arguments, below:
                                    // * message file name is the message ID
                                    // * message body is the indexHTML
                                    // *
                                    //
                                    Node.sharedInstance.call(remoteFunction.named(.postMessage), withArguments: [messageFileName, indexHTML, CurrentTimeline.id!])
174
175
176
177
178
                                        {
                                            /* and handle callback with */ result in
                                            
                                            println("<<<<< POST MESSAGE CALLBACK!!!! >>>>>")
                                            println(result)
179
                                    }
180
181
182
183
184
185
186

                                    
                                    //
                                    // Notify that we need to have the message displayed in the respective timeline
                                    //
                                    post(MessageNotification.named(.ShowMessage), from: self, with: ["message": message])
                                    
187
                                    
188
                                    break
189
190
191
192
193
194
195
196
                                }
                            }
                        }
                    }
                }
            }
        }
    }
197
198
199
200
    
    
    func removeNotificationHandlers()
    {
201
202
        println("\(self): removing notification handlers")
        
203
        sendMessageNotificationHandler?.remove()
204
        sendMessageNotificationHandler = nil
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    }
    
    
    //
    // MARK: - Layout
    //
    
    func createConstraints()
    {
        view.removeConstraints(view.constraints)
        
        layout(view)
        {
            /* as */ view in
            
            view.width == view.superview!.width
            view.height == view.superview!.height
        }
    }
    
225
}