2 // GameViewController.swift
5 // Created by Hori,Masaki on 2016/12/31.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
13 private extension Selector {
15 static let reloadContent = #selector(GameViewController.reloadContent(_:))
16 static let deleteCacheAndReload = #selector(GameViewController.deleteCacheAndReload(_:))
17 static let screenShot = #selector(GameViewController.screenShot(_:))
20 final class GameViewController: NSViewController {
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/=/"
25 @IBOutlet var webView: WebView!
27 override var nibName: NSNib.Name {
29 return .nibName(instanceOf: self)
32 private var flashTopLeft = NSPoint(x: 2600, y: 1445)
33 private var clipView: NSClipView {
35 return view as! NSClipView // swiftlint:disable:this force_cast
38 override func viewDidLoad() {
42 clipView.documentView = webView
46 webView.mainFrame.frameView.allowsScrolling = false
48 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
49 webView.mainFrameURL = GameViewController.gamePageURL
54 webView.superview?.scroll(flashTopLeft)
57 @IBAction func reloadContent(_ sender: AnyObject?) {
59 guard let _ = webView.mainFrameURL else {
61 webView.mainFrameURL = GameViewController.gamePageURL
65 // ゲームページでない場合はゲームページを表示する
66 if webView.mainFrameURL != GameViewController.gamePageURL {
68 webView.mainFrameURL = GameViewController.gamePageURL
72 if webView.mainFrameURL.hasPrefix(GameViewController.loginPageURLPrefix) {
74 webView.reload(sender)
81 let prevDate = UserDefaults.standard[.prevReloadDate]
82 if Date(timeIntervalSinceNow: 0.0).timeIntervalSince(prevDate) < 1 * 60 {
84 let untilDate = prevDate.addingTimeInterval(1 * 60)
85 let date = DateFormatter.localizedString(from: untilDate, dateStyle: .none, timeStyle: .medium)
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)
95 webView.reload(sender)
97 UserDefaults.standard[.prevReloadDate] = Date(timeIntervalSinceNow: 0.0)
100 @IBAction func deleteCacheAndReload(_ sender: AnyObject?) {
102 let panel = ProgressPanel()
104 guard let window = view.window else { return }
105 guard let panelWindow = panel.window else { return }
108 panel.message = NSLocalizedString("Deleting caches...", comment: "Deleting caches...")
111 window.beginSheet(panelWindow) { _ in NSSound(named: NSSound.Name("Submarine"))?.play() }
113 AppDelegate.shared.clearCache()
115 window.endSheet(panelWindow)
118 @IBAction func screenShot(_ sender: AnyObject?) {
120 let frame = webView.visibleRect
121 let screenshotBorder = UserDefaults.standard[.screenShotBorderWidth]
122 let f = frame.insetBy(dx: -screenshotBorder, dy: -screenshotBorder)
124 guard let rep = webView.bitmapImageRepForCachingDisplay(in: f) else { return }
126 webView.cacheDisplay(in: frame, to: rep)
127 AppDelegate.shared.registerScreenshot(rep, fromOnScreen: .zero)
130 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
132 if menuItem.action == .reloadContent {
134 guard let _ = webView.mainFrame else { return true }
135 guard let frameURL = webView.mainFrameURL else { return true }
138 case GameViewController.gamePageURL:
139 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
141 case let s where s.hasPrefix(GameViewController.loginPageURLPrefix):
142 menuItem.title = NSLocalizedString("Reload", comment: "Reload menu, reload")
145 menuItem.title = NSLocalizedString("Back To Game", comment: "Reload menu, back to game")
151 if menuItem.action == .deleteCacheAndReload {
156 if menuItem.action == .screenShot {
165 extension GameViewController: WebFrameLoadDelegate, WebUIDelegate {
167 private static let excludeMenuItemTag = [
168 WebMenuItemTagOpenLinkInNewWindow,
169 WebMenuItemTagDownloadLinkToDisk,
170 WebMenuItemTagOpenImageInNewWindow,
171 WebMenuItemTagOpenFrameInNewWindow,
172 WebMenuItemTagGoBack,
173 WebMenuItemTagGoForward,
178 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
180 guard let path = frame.dataSource?.initialRequest.url?.path else { return }
182 let handler: (JSContext?, JSValue?) -> Void = { (_, exception) in
184 if let exception = exception {
186 print("Caught exception in evaluteScript -> \(exception)")
190 print("Caught exception in evaluteScript")
195 if path.hasSuffix("gadgets/ifr") {
197 guard let context = frame.javaScriptContext else { return }
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;"]
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)
212 if path.hasSuffix("app_id=854854") {
214 guard let context = frame.javaScriptContext else { return }
216 context.exceptionHandler = handler
217 context.evaluateScript(
218 ["var iframe = document.getElementById('game_frame');",
219 "var validIframe = 0;",
222 " var rect = iframe.getBoundingClientRect();",
223 " var atop = rect.top;",
224 " var aleft = rect.left;",
228 let validIframe = context.objectForKeyedSubscript("validIframe").toInt32()
230 guard validIframe != 0 else { return }
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))
240 func webView(_ sender: WebView!, contextMenuItemsForElement element: [AnyHashable: Any]!, defaultMenuItems: [Any]!) -> [Any]! {
242 guard let menuItems = defaultMenuItems as? [NSMenuItem] else { return [] }
244 return menuItems.filter { !GameViewController.excludeMenuItemTag.contains($0.tag) }