OSDN Git Service

guard の書き方を統一した
[kcd/KCD.git] / KCD / GameViewController.swift
1 //
2 //  GameViewController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/31.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import WebKit
11 import JavaScriptCore
12
13 private extension Selector {
14     
15     static let reloadContent = #selector(GameViewController.reloadContent(_:))
16     static let deleteCacheAndReload = #selector(GameViewController.deleteCacheAndReload(_:))
17     static let screenShot = #selector(GameViewController.screenShot(_:))
18 }
19
20 final class GameViewController: NSViewController {
21     
22     private static let gamePageURL = "http://www.dmm.com/netgame/social/-/gadgets/=/app_id=854854/"
23     private static let loginPageURLPrefix = "https://www.dmm.com/my/-/login/=/"
24     
25     @IBOutlet var webView: WebView!
26     
27     override var nibName: NSNib.Name {
28         
29         return .nibName(instanceOf: self)
30     }
31     
32     private var flashTopLeft = NSPoint(x: 2600, y: 1445)
33     private var clipView: NSClipView {
34         
35         return view as! NSClipView  // swiftlint:disable:this force_cast
36     }
37     
38     override func viewDidLoad() {
39         
40         super.viewDidLoad()
41         
42         clipView.documentView = webView
43         
44         adjustFlash()
45         
46         webView.mainFrame.frameView.allowsScrolling = false
47         
48         webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
49         webView.mainFrameURL = GameViewController.gamePageURL
50     }
51     
52     func adjustFlash() {
53         
54         webView.superview?.scroll(flashTopLeft)
55     }
56     
57     @IBAction func reloadContent(_ sender: AnyObject?) {
58         
59         guard let _ = webView.mainFrameURL else {
60             
61             webView.mainFrameURL = GameViewController.gamePageURL
62             return
63         }
64         
65         // ゲームページでない場合はゲームページを表示する
66         if webView.mainFrameURL != GameViewController.gamePageURL {
67             
68             webView.mainFrameURL = GameViewController.gamePageURL
69             
70             return
71         }
72         if webView.mainFrameURL.hasPrefix(GameViewController.loginPageURLPrefix) {
73             
74             webView.reload(sender)
75             
76             return
77         }
78         
79         adjustFlash()
80         
81         let prevDate = UserDefaults.standard[.prevReloadDate]
82         if Date(timeIntervalSinceNow: 0.0).timeIntervalSince(prevDate) < 1 * 60 {
83             
84             let untilDate = prevDate.addingTimeInterval(1 * 60)
85             let date = DateFormatter.localizedString(from: untilDate, dateStyle: .none, timeStyle: .medium)
86             let alert = NSAlert()
87             alert.messageText = NSLocalizedString("Reload interval is too short?", comment: "")
88             let format = NSLocalizedString("Reload interval is too short.\nWait until %@.", comment: "")
89             alert.informativeText = String(format: format, date)
90             alert.runModal()
91             
92             return
93         }
94         
95         webView.reload(sender)
96         
97         UserDefaults.standard[.prevReloadDate] = Date(timeIntervalSinceNow: 0.0)
98     }
99     
100     @IBAction func deleteCacheAndReload(_ sender: AnyObject?) {
101         
102         let panel = ProgressPanel()
103         
104         guard let window = view.window else { return }
105         guard let panelWindow = panel.window else { return }
106         
107         panel.title = ""
108         panel.message = NSLocalizedString("Deleting caches...", comment: "Deleting caches...")
109         panel.animate = true
110         
111         window.beginSheet(panelWindow) { _ in NSSound(named: NSSound.Name("Submarine"))?.play() }
112         
113         AppDelegate.shared.clearCache()
114         
115         window.endSheet(panelWindow)
116     }
117     
118     @IBAction func screenShot(_ sender: AnyObject?) {
119         
120         let frame = webView.visibleRect
121         let screenshotBorder = UserDefaults.standard[.screenShotBorderWidth]
122         let f = frame.insetBy(dx: -screenshotBorder, dy: -screenshotBorder)
123         
124         guard let rep = webView.bitmapImageRepForCachingDisplay(in: f) else { return }
125         
126         webView.cacheDisplay(in: frame, to: rep)
127         AppDelegate.shared.registerScreenshot(rep, fromOnScreen: .zero)
128     }
129     
130     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
131         
132         if menuItem.action == .reloadContent {
133             
134             guard let _ = webView.mainFrame else { return true }
135             guard let frameURL = webView.mainFrameURL else { return true }
136             
137             switch frameURL {
138             case GameViewController.gamePageURL:
139                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
140                 
141             case let s where s.hasPrefix(GameViewController.loginPageURLPrefix):
142                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
143                 
144             default:
145                 menuItem.title = NSLocalizedString("Back To Game", comment: "Reload menu, back to game")
146             }
147             
148             return true
149         }
150         
151         if menuItem.action == .deleteCacheAndReload {
152             
153             return true
154         }
155         
156         if menuItem.action == .screenShot {
157             
158             return true
159         }
160         
161         return false
162     }
163 }
164
165 extension GameViewController: WebFrameLoadDelegate, WebUIDelegate {
166     
167     private static let excludeMenuItemTag = [
168         WebMenuItemTagOpenLinkInNewWindow,
169         WebMenuItemTagDownloadLinkToDisk,
170         WebMenuItemTagOpenImageInNewWindow,
171         WebMenuItemTagOpenFrameInNewWindow,
172         WebMenuItemTagGoBack,
173         WebMenuItemTagGoForward,
174         WebMenuItemTagStop,
175         WebMenuItemTagReload
176     ]
177     
178     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
179         
180         guard let path = frame.dataSource?.initialRequest.url?.path else { return }
181         
182         let handler: (JSContext?, JSValue?) -> Void = { (_, exception) in
183             
184             if let exception = exception {
185                 
186                 print("Caught exception in evaluteScript -> \(exception)")
187                 
188             } else {
189                 
190                 print("Caught exception in evaluteScript")
191                 
192             }
193         }
194         
195         if path.hasSuffix("gadgets/ifr") {
196             
197             guard let context = frame.javaScriptContext else { return }
198             
199             context.exceptionHandler = handler
200             context.evaluateScript(
201                 ["var emb = document.getElementById('flashWrap');",
202                  "var rect = emb.getBoundingClientRect();",
203                  "var atop = rect.top;",
204                  "var aleft = rect.left;"]
205                     .reduce("", +)
206             )
207             let top = context.objectForKeyedSubscript("atop").toDouble()
208             let left = context.objectForKeyedSubscript("aleft").toDouble()
209             flashTopLeft = NSPoint(x: CGFloat(left), y: webView.frame.size.height - CGFloat(top) - 480)
210         }
211         
212         if path.hasSuffix("app_id=854854") {
213             
214             guard let context = frame.javaScriptContext else { return }
215             
216             context.exceptionHandler = handler
217             context.evaluateScript(
218                 ["var iframe = document.getElementById('game_frame');",
219                  "var validIframe = 0;",
220                  "if(iframe) {",
221                  "    validIframe = 1;",
222                  "    var rect = iframe.getBoundingClientRect();",
223                  "    var atop = rect.top;",
224                  "    var aleft = rect.left;",
225                  "}"]
226                     .reduce("", +)
227             )
228             let validIframe = context.objectForKeyedSubscript("validIframe").toInt32()
229             
230             guard validIframe != 0 else { return }
231             
232             let top = context.objectForKeyedSubscript("atop").toDouble()
233             let left = context.objectForKeyedSubscript("aleft").toDouble()
234             flashTopLeft = NSPoint(x: flashTopLeft.x + CGFloat(left), y: flashTopLeft.y - CGFloat(top))
235             
236             adjustFlash()
237         }
238     }
239     
240     func webView(_ sender: WebView!, contextMenuItemsForElement element: [AnyHashable: Any]!, defaultMenuItems: [Any]!) -> [Any]! {
241         
242         guard let menuItems = defaultMenuItems as? [NSMenuItem] else { return [] }
243         
244         return menuItems.filter { !GameViewController.excludeMenuItemTag.contains($0.tag) }
245     }
246 }