OSDN Git Service

UAをVersion/10.0.3 Safari/602.4.8に変更
[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  // swiftlint:disable:this force_cast
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 let prevDate = prevDate {
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                 let format = NSLocalizedString("Reload interval is too short.\nWait until %@.", comment: "")
77                 alert.informativeText = String(format: format, date)
78                 alert.runModal()
79                 
80                 return
81             }
82         }
83         
84         webView.reload(sender)
85         
86         UserDefaults.standard.prevReloadDate = Date(timeIntervalSinceNow: 0.0)
87     }
88     @IBAction func deleteCacheAndReload(_ sender: AnyObject?) {
89         let panel = ProgressPanel()
90         guard let window = view.window,
91             let panelWindow = panel.window
92             else { return }
93         panel.title = ""
94         panel.message = NSLocalizedString("Deleting caches...", comment: "Deleting caches...")
95         panel.animate = true
96         
97         window.beginSheet(panelWindow) { _ in NSSound(named: "Submarine")?.play() }
98         
99         AppDelegate.shared.clearCache()
100         
101         window.endSheet(panelWindow)
102     }
103     @IBAction func screenShot(_ sender: AnyObject?) {
104         let frame = webView.visibleRect
105         let screenshotBorder = UserDefaults.standard.screenShotBorderWidth
106         let f = frame.insetBy(dx: -screenshotBorder, dy: -screenshotBorder)
107         guard let rep = webView.bitmapImageRepForCachingDisplay(in: f) else { return }
108         webView.cacheDisplay(in: frame, to: rep)
109         AppDelegate.shared.screenshotListWindowController.registerScreenshot(rep, fromOnScreen: .zero)
110     }
111     
112     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
113         if menuItem.action == .reloadContent {
114             guard let _ = webView.mainFrame,
115                 let frameURL = webView.mainFrameURL
116                 else { return true }
117             switch frameURL {
118             case GameViewController.gamePageURL:
119                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
120             case let s where s.hasPrefix(GameViewController.loginPageURLPrefix):
121                 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
122             default:
123                 menuItem.title = NSLocalizedString("Back To Game", comment: "Reload menu, back to game")
124             }
125             return true
126         }
127         if menuItem.action == .deleteCacheAndReload {
128             return true
129         }
130         if menuItem.action == .screenShot {
131             return true
132         }
133         return false
134     }
135 }
136
137 extension GameViewController: WebFrameLoadDelegate, WebUIDelegate {
138     private static let excludeMenuItemTag = [
139         WebMenuItemTagOpenLinkInNewWindow,
140         WebMenuItemTagDownloadLinkToDisk,
141         WebMenuItemTagOpenImageInNewWindow,
142         WebMenuItemTagOpenFrameInNewWindow,
143         WebMenuItemTagGoBack,
144         WebMenuItemTagGoForward,
145         WebMenuItemTagStop,
146         WebMenuItemTagReload
147     ]
148     
149     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
150         guard let path = frame.dataSource?.initialRequest.url?.path else { return }
151         
152         let handler: (JSContext?, JSValue?) -> Void = { (context, exception) in
153             print("Caught exception in evaluteScript -> \(exception)")
154         }
155         
156         if path.hasSuffix("gadgets/ifr") {
157             guard let context = frame.javaScriptContext else { return }
158             context.exceptionHandler = handler
159             context.evaluateScript(
160                 ["var emb = document.getElementById('flashWrap');",
161                  "var rect = emb.getBoundingClientRect();",
162                  "var atop = rect.top;",
163                  "var aleft = rect.left;"]
164                     .reduce("", +)
165             )
166             let top = context.objectForKeyedSubscript("atop").toDouble()
167             let left = context.objectForKeyedSubscript("aleft").toDouble()
168             flashTopLeft = NSPoint(x: CGFloat(left), y: webView.frame.size.height - CGFloat(top) - 480)
169         }
170         if path.hasSuffix("app_id=854854") {
171             guard let context = frame.javaScriptContext else { return }
172             context.exceptionHandler = handler
173             context.evaluateScript(
174                 ["var iframe = document.getElementById('game_frame');",
175                  "var validIframe = 0;",
176                  "if(iframe) {",
177                  "    validIframe = 1;",
178                  "    var rect = iframe.getBoundingClientRect();",
179                  "    var atop = rect.top;",
180                  "    var aleft = rect.left;",
181                  "}"]
182                     .reduce("", +)
183             )
184             let validIframe = context.objectForKeyedSubscript("validIframe").toInt32()
185             guard validIframe != 0 else { return }
186             let top = context.objectForKeyedSubscript("atop").toDouble()
187             let left = context.objectForKeyedSubscript("aleft").toDouble()
188             flashTopLeft = NSPoint(x: flashTopLeft.x + CGFloat(left), y: flashTopLeft.y - CGFloat(top))
189             adjustFlash()
190         }
191     }
192     
193     func webView(_ sender: WebView!,
194                  contextMenuItemsForElement element: [AnyHashable: Any]!,
195                  defaultMenuItems: [Any]!) -> [Any]! {
196         guard let menuItems = defaultMenuItems as? [NSMenuItem] else { return [] }
197         return menuItems.flatMap {
198             GameViewController.excludeMenuItemTag.contains($0.tag) ? nil : $0
199         }
200     }
201 }