OSDN Git Service

swiftlint 'legacy_constructor' の警告を修正
[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 fileprivate extension Selector {
14     static let reloadContent = #selector(GameViewController.reloadContent(_:))
15     static let deleteCacheAndReload = #selector(GameViewController.deleteCacheAndReload(_:))
16     static let screenShot = #selector(GameViewController.screenShot(_:))
17 }
18
19 class GameViewController: NSViewController {
20     private static let gamePageURL = "http://www.dmm.com/netgame/social/-/gadgets/=/app_id=854854/"
21     private static let loginPageURLPrefix = "https://www.dmm.com/my/-/login/=/"
22     
23     @IBOutlet var webView: WebView!
24     
25     override var nibName: String! {
26         return "GameViewController"
27     }
28     
29     fileprivate var flashTopLeft = NSPoint(x: 2600, y: 1445)
30     private var clipView: NSClipView {
31         return view as! NSClipView
32     }
33     
34     override func viewDidLoad() {
35         super.viewDidLoad()
36         
37         clipView.documentView = webView
38         
39         adjustFlash()
40         
41         webView.mainFrame.frameView.allowsScrolling = false
42         
43         webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
44         webView.mainFrameURL = GameViewController.gamePageURL
45     }
46     func adjustFlash() {
47         webView.superview?.scroll(flashTopLeft)
48     }
49     
50     @IBAction func reloadContent(_ sender: AnyObject?) {
51         guard let _ = webView.mainFrameURL
52             else {
53                 webView.mainFrameURL = GameViewController.gamePageURL
54                 return
55         }
56         // ゲームページでない場合はゲームページを表示する
57         if webView.mainFrameURL != GameViewController.gamePageURL {
58             webView.mainFrameURL = GameViewController.gamePageURL
59             return
60         }
61         if webView.mainFrameURL.hasPrefix(GameViewController.loginPageURLPrefix) {
62             webView.reload(sender)
63             return
64         }
65         
66         adjustFlash()
67         
68         let prevDate = UserDefaults.standard.prevReloadDate
69         if prevDate != nil {
70             let now = Date(timeIntervalSinceNow: 0.0)
71             if now.timeIntervalSince(prevDate!) < 1 * 60 {
72                 let untilDate = prevDate?.addingTimeInterval(1 * 60)
73                 let date = DateFormatter.localizedString(from: untilDate!, dateStyle: .none, timeStyle: .medium)
74                 let alert = NSAlert()
75                 alert.messageText = NSLocalizedString("Reload interval is too short?", comment: "")
76                 alert.informativeText = String(format: NSLocalizedString("Reload interval is too short.\nWait until %@.", comment: ""), date)
77                 alert.runModal()
78                 
79                 return
80             }
81         }
82         
83         webView.reload(sender)
84         
85         UserDefaults.standard.prevReloadDate = Date(timeIntervalSinceNow: 0.0)
86     }
87     @IBAction func deleteCacheAndReload(_ sender: AnyObject?) {
88         let panel = ProgressPanel()
89         panel.title = ""
90         panel.message = NSLocalizedString("Deleting caches...", comment: "Deleting caches...")
91         panel.animate = true
92         
93         view.window?.beginSheet(panel.window!, completionHandler: { _ in
94             NSSound(named: "Submarine")?.play()
95         })
96         
97         AppDelegate.shared.clearCache()
98         
99         view.window?.endSheet(panel.window!)
100     }
101     @IBAction func screenShot(_ sender: AnyObject?) {
102         let frame = webView.visibleRect
103         let screenshotBorder = UserDefaults.standard.screenShotBorderWidth
104         let f = NSInsetRect(frame, -screenshotBorder, -screenshotBorder)
105         guard let rep = webView.bitmapImageRepForCachingDisplay(in: f) else { return }
106         webView.cacheDisplay(in: frame, to: rep)
107         AppDelegate.shared.screenshotListWindowController.registerScreenshot(rep, fromOnScreen: .zero)
108     }
109     
110     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
111         if menuItem.action == .reloadContent {
112             guard let _ = webView.mainFrame,
113                 let frameURL = webView.mainFrameURL
114                 else { return true }
115             switch frameURL {
116             case GameViewController.gamePageURL:
117                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
118             case let s where s.hasPrefix(GameViewController.loginPageURLPrefix):
119                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
120             default:
121                 menuItem.title = NSLocalizedString("Back To Game", comment: "Reload menu, back to game")
122             }
123             return true
124         }
125         if menuItem.action == .deleteCacheAndReload {
126             return true
127         }
128         if menuItem.action == .screenShot {
129             return true
130         }
131         return false
132     }
133 }
134
135 extension GameViewController: WebFrameLoadDelegate, WebUIDelegate {
136     private static let excludeMenuItemTag = [
137         WebMenuItemTagOpenLinkInNewWindow,
138         WebMenuItemTagDownloadLinkToDisk,
139         WebMenuItemTagOpenImageInNewWindow,
140         WebMenuItemTagOpenFrameInNewWindow,
141         WebMenuItemTagGoBack,
142         WebMenuItemTagGoForward,
143         WebMenuItemTagStop,
144         WebMenuItemTagReload
145     ]
146     
147     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
148         guard let path = frame.dataSource?.initialRequest.url?.path else { return }
149         
150         let handler: (JSContext?, JSValue?) -> Void = { (context, exception) in
151             print("Caught exception in evaluteScript -> \(exception)")
152         }
153         
154         if path.hasSuffix("gadgets/ifr") {
155             guard let context = frame.javaScriptContext else { return }
156             context.exceptionHandler = handler
157             context.evaluateScript(
158                 ["var emb = document.getElementById('flashWrap');",
159                  "var rect = emb.getBoundingClientRect();",
160                  "var atop = rect.top;",
161                  "var aleft = rect.left;"]
162                     .reduce("", +)
163             )
164             let top = context.objectForKeyedSubscript("atop").toDouble()
165             let left = context.objectForKeyedSubscript("aleft").toDouble()
166             flashTopLeft = NSPoint(x: CGFloat(left), y: webView.frame.size.height - CGFloat(top) - 480)
167         }
168         if path.hasSuffix("app_id=854854") {
169             guard let context = frame.javaScriptContext else { return }
170             context.exceptionHandler = handler
171             context.evaluateScript(
172                 ["var iframe = document.getElementById('game_frame');",
173                  "var validIframe = 0;",
174                  "if(iframe) {",
175                  "    validIframe = 1;",
176                  "    var rect = iframe.getBoundingClientRect();",
177                  "    var atop = rect.top;",
178                  "    var aleft = rect.left;",
179                  "}"]
180                     .reduce("", +)
181             )
182             let validIframe = context.objectForKeyedSubscript("validIframe").toInt32()
183             guard validIframe != 0 else { return }
184             let top = context.objectForKeyedSubscript("atop").toDouble()
185             let left = context.objectForKeyedSubscript("aleft").toDouble()
186             flashTopLeft = NSPoint(x: flashTopLeft.x + CGFloat(left), y: flashTopLeft.y - CGFloat(top))
187             adjustFlash()
188         }
189     }
190     
191     func webView(_ sender: WebView!, contextMenuItemsForElement element: [AnyHashable: Any]!, defaultMenuItems: [Any]!) -> [Any]! {
192         guard let menuItems = defaultMenuItems as? [NSMenuItem] else { return [] }
193         return menuItems.flatMap {
194             GameViewController.excludeMenuItemTag.contains($0.tag) ? nil : $0
195         }
196     }
197 }