OSDN Git Service

洋上補給の補強増設用のショートネームをつけた
[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 final class GameViewController: NSViewController {
14     
15     private static let gamePageURL = "http://www.dmm.com/netgame/social/-/gadgets/=/app_id=854854/"
16     private static let loginPageURLPrefix = "https://www.dmm.com/my/-/login/=/"
17     
18     @IBOutlet private var webView: WebView!
19     
20     override var nibName: NSNib.Name {
21         
22         return .nibName(instanceOf: self)
23     }
24     
25     private var flashTopLeft = NSPoint(x: 2600, y: 1445)
26     private var clipView: NSClipView {
27         
28         return view as! NSClipView  // swiftlint:disable:this force_cast
29     }
30     
31     override func viewDidLoad() {
32         
33         super.viewDidLoad()
34         
35         clipView.documentView = webView
36         
37         adjustFlash()
38         
39         webView.mainFrame.frameView.allowsScrolling = false
40         
41         webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
42         webView.mainFrameURL = GameViewController.gamePageURL
43     }
44     
45     func adjustFlash() {
46         
47         webView.superview?.scroll(flashTopLeft)
48     }
49     
50     @IBAction func reloadContent(_ sender: AnyObject?) {
51         
52         guard let _ = webView.mainFrameURL else {
53             
54             webView.mainFrameURL = GameViewController.gamePageURL
55             return
56         }
57         
58         // ゲームページでない場合はゲームページを表示する
59         if webView.mainFrameURL != GameViewController.gamePageURL {
60             
61             webView.mainFrameURL = GameViewController.gamePageURL
62             
63             return
64         }
65         if webView.mainFrameURL.hasPrefix(GameViewController.loginPageURLPrefix) {
66             
67             webView.reload(sender)
68             
69             return
70         }
71         
72         adjustFlash()
73         
74         let prevDate = UserDefaults.standard[.prevReloadDate]
75         if Date(timeIntervalSinceNow: 0.0).timeIntervalSince(prevDate) < 1 * 60 {
76             
77             let untilDate = prevDate.addingTimeInterval(1 * 60)
78             let date = DateFormatter.localizedString(from: untilDate, dateStyle: .none, timeStyle: .medium)
79             let alert = NSAlert()
80             alert.messageText = LocalizedStrings.reloadTimeShortenMessage.string
81             let format = LocalizedStrings.reloadTimeShortenInfo.string
82             alert.informativeText = String(format: format, date)
83             alert.runModal()
84             
85             return
86         }
87         
88         webView.reload(sender)
89         
90         UserDefaults.standard[.prevReloadDate] = Date(timeIntervalSinceNow: 0.0)
91     }
92     
93     @IBAction func deleteCacheAndReload(_ sender: AnyObject?) {
94         
95         let panel = ProgressPanel()
96         
97         guard let window = view.window else { return }
98         guard let panelWindow = panel.window else { return }
99         
100         panel.title = ""
101         panel.message = LocalizedStrings.deletingCacheInfo.string
102         panel.animate = true
103         
104         window.beginSheet(panelWindow) { _ in NSSound(named: NSSound.Name("Submarine"))?.play() }
105         
106         AppDelegate.shared.clearCache()
107         
108         window.endSheet(panelWindow)
109     }
110     
111     func screenshotOld() {
112         
113         let frame = webView.visibleRect
114         let screenshotBorder = UserDefaults.standard[.screenShotBorderWidth]
115         let f = frame.insetBy(dx: -screenshotBorder, dy: -screenshotBorder)
116         
117         guard let rep = webView.bitmapImageRepForCachingDisplay(in: f) else { return }
118         
119         webView.cacheDisplay(in: frame, to: rep)
120         
121         ScreenshotRegister(ApplicationDirecrories.screenshotSaveDirectoryURL)
122             .registerScreenshot(rep, name: localizedAppName())
123     }
124     
125     @available(OSX 10.13, *)
126     func screenshot() {
127         
128         let frame = view.visibleRect
129         let screenshotBorder = UserDefaults.standard[.screenShotBorderWidth]
130         let f = frame.insetBy(dx: -screenshotBorder, dy: -screenshotBorder)
131         let windowCoordinateFrame = view.convert(f, to: nil)
132         
133         guard let window = view.window else { return Logger.shared.log("Can not get window") }
134         let screenCoordinsteFrame = window.convertToScreen(windowCoordinateFrame)
135         
136         guard let screen = NSScreen.main else { return Logger.shared.log("Can not get Screen") }
137         let scFrame = screen.frame
138         
139         guard let cxt = window.graphicsContext?.cgContext else { return Logger.shared.log("Cannot get Context") }
140         let deviceCoordinateFrame = cxt.convertToDeviceSpace(screenCoordinsteFrame)
141         let raio = deviceCoordinateFrame.size.width / screenCoordinsteFrame.size.width
142         
143         let trimRect = CGRect(x: raio * screenCoordinsteFrame.origin.x,
144                               y: raio * (scFrame.size.height - screenCoordinsteFrame.origin.y - screenCoordinsteFrame.size.height),
145                               width: raio * screenCoordinsteFrame.size.width,
146                               height: raio * screenCoordinsteFrame.size.height)
147         
148         guard let fullSizeImage = CGDisplayCreateImage(CGMainDisplayID()) else { return Logger.shared.log("Can not get Image") }
149         
150         guard let image = fullSizeImage.cropping(to: trimRect) else { return Logger.shared.log("Can not trim image") }
151         
152         let rep = NSBitmapImageRep(cgImage: image)
153         
154         if rep.size != NSSize(width: 800, height: 480) {
155             rep.size = NSSize(width: 800, height: 480)
156         }
157         
158         ScreenshotRegister(ApplicationDirecrories.screenshotSaveDirectoryURL)
159             .registerScreenshot(rep, name: localizedAppName())
160     }
161     
162     @IBAction func screenShot(_ sender: AnyObject?) {
163         
164         if #available(OSX 10.13, *) {
165             
166             screenshot()
167             
168         } else {
169             
170             screenshotOld()
171         }
172     }
173     
174     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
175         
176         guard let action: Selector = menuItem.action else { return false }
177         
178         switch action {
179             
180         case #selector(GameViewController.reloadContent(_:)):
181             guard let _ = webView.mainFrame else { return true }
182             guard let frameURL = webView.mainFrameURL else { return true }
183             
184             switch frameURL {
185             case GameViewController.gamePageURL:
186                 menuItem.title = LocalizedStrings.reload.string
187                 
188             case let s where s.hasPrefix(GameViewController.loginPageURLPrefix):
189                 menuItem.title = LocalizedStrings.reload.string
190                 
191             default:
192                 menuItem.title = LocalizedStrings.backToGame.string
193             }
194             
195             return true
196             
197         case #selector(GameViewController.deleteCacheAndReload(_:)):
198             return true
199             
200         case #selector(GameViewController.screenShot(_:)):
201             return true
202             
203         default: return false
204         }
205     }
206 }
207
208 extension GameViewController: WebFrameLoadDelegate, WebUIDelegate {
209     
210     private static let excludeMenuItemTag = [
211         WebMenuItemTagOpenLinkInNewWindow,
212         WebMenuItemTagDownloadLinkToDisk,
213         WebMenuItemTagOpenImageInNewWindow,
214         WebMenuItemTagOpenFrameInNewWindow,
215         WebMenuItemTagGoBack,
216         WebMenuItemTagGoForward,
217         WebMenuItemTagStop,
218         WebMenuItemTagReload
219     ]
220     
221     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
222         
223         guard let path = frame.dataSource?.initialRequest.url?.path else { return }
224         
225         let handler: (JSContext?, JSValue?) -> Void = { (_, exception) in
226             
227             if let exception = exception {
228                 
229                 print("Caught exception in evaluteScript -> \(exception)")
230                 
231             } else {
232                 
233                 print("Caught exception in evaluteScript")
234             }
235         }
236         
237         if path.hasSuffix("gadgets/ifr") {
238             
239             guard let context = frame.javaScriptContext else { return }
240             
241             context.exceptionHandler = handler
242             context.evaluateScript(
243                 ["var emb = document.getElementById('flashWrap');",
244                  "var rect = emb.getBoundingClientRect();",
245                  "var atop = rect.top;",
246                  "var aleft = rect.left;"]
247                     .reduce("", +)
248             )
249             let top = context.objectForKeyedSubscript("atop").toDouble()
250             let left = context.objectForKeyedSubscript("aleft").toDouble()
251             flashTopLeft = NSPoint(x: CGFloat(left), y: webView.frame.size.height - CGFloat(top) - 480)
252         }
253         
254         if path.hasSuffix("app_id=854854") {
255             
256             guard let context = frame.javaScriptContext else { return }
257             
258             context.exceptionHandler = handler
259             context.evaluateScript(
260                 ["var iframe = document.getElementById('game_frame');",
261                  "var validIframe = 0;",
262                  "if(iframe) {",
263                  "    validIframe = 1;",
264                  "    var rect = iframe.getBoundingClientRect();",
265                  "    var atop = rect.top;",
266                  "    var aleft = rect.left;",
267                  "}"]
268                     .reduce("", +)
269             )
270             let validIframe = context.objectForKeyedSubscript("validIframe").toInt32()
271             
272             guard validIframe != 0 else { return }
273             
274             let top = context.objectForKeyedSubscript("atop").toDouble()
275             let left = context.objectForKeyedSubscript("aleft").toDouble()
276             flashTopLeft = NSPoint(x: flashTopLeft.x + CGFloat(left), y: flashTopLeft.y - CGFloat(top))
277             
278             adjustFlash()
279         }
280     }
281     
282     func webView(_ sender: WebView!, contextMenuItemsForElement element: [AnyHashable: Any]!, defaultMenuItems: [Any]!) -> [Any]! {
283         
284         guard let menuItems = defaultMenuItems as? [NSMenuItem] else { return [] }
285         
286         return menuItems.filter { !GameViewController.excludeMenuItemTag.contains($0.tag) }
287     }
288 }