Skip to content

Commit

Permalink
Add new toast UI and operation hint message (PlayCover#82)
Browse files Browse the repository at this point in the history
* add new hint toast

* limit toast number to four
  • Loading branch information
XuYicong authored Feb 12, 2023
1 parent b22ec3f commit 51ab649
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
12 changes: 12 additions & 0 deletions PlayTools/Controls/ControlMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class ControlMode {
if !editor.editorMode {
if show {
if !visible {
NotificationCenter.default.post(name: NSNotification.Name.playtoolsKeymappingWillDisable,
object: nil, userInfo: [:])
if screen.fullscreen {
screen.switchDock(true)
}
Expand All @@ -26,6 +28,8 @@ public class ControlMode {
}
} else {
if visible {
NotificationCenter.default.post(name: NSNotification.Name.playtoolsKeymappingWillEnable,
object: nil, userInfo: [:])
if PlaySettings.shared.mouseMapping {
AKInterface.shared!.hideCursor()
}
Expand All @@ -40,3 +44,11 @@ public class ControlMode {
}
}
}

extension NSNotification.Name {
public static let playtoolsKeymappingWillEnable: NSNotification.Name
= NSNotification.Name("playtools.keymappingWillEnable")

public static let playtoolsKeymappingWillDisable: NSNotification.Name
= NSNotification.Name("playtools.keymappingWillDisable")
}
15 changes: 15 additions & 0 deletions PlayTools/Controls/PlayInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,21 @@ class PlayInput {
}

setupShortcuts()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
if !settings.mouseMapping || !mode.visible {
return
}
Toast.showHint(title: "Keymapping Disabled", text: ["Press ", "option ⌥", " to enable keymapping"],
notification: NSNotification.Name.playtoolsKeymappingWillEnable)
let center = NotificationCenter.default
var token: NSObjectProtocol?
token = center.addObserver(forName: NSNotification.Name.playtoolsKeymappingWillEnable,
object: nil, queue: OperationQueue.main) { _ in
center.removeObserver(token!)
Toast.showHint(title: "Keymapping Enabled", text: ["Press ", "option ⌥", " to disable keymapping"],
notification: NSNotification.Name.playtoolsKeymappingWillDisable)
}
}

// Fix beep sound
AKInterface.shared!
Expand Down
7 changes: 5 additions & 2 deletions PlayTools/Keymap/EditorController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@ class EditorController {
previousWindow?.makeKeyAndVisible()
PlayInput.shared.toggleEditor(show: false)
focusedControl = nil
Toast.showOver(msg: "Keymapping saved")
Toast.showHint(title: "Keymap Saved")
} else {
PlayInput.shared.toggleEditor(show: true)
previousWindow = screen.keyWindow
editorWindow = initWindow()
editorWindow?.makeKeyAndVisible()
showButtons()
Toast.showOver(msg: "Click to start keymmaping edit")
Toast.showHint(title: "Keymapping Editor",
text: ["Click a button to edit its position or key bind\n" +
"Click an empty area to open input menu"],
notification: NSNotification.Name.playtoolsKeymappingWillEnable)
}
// Toast.showOver(msg: "\(UIApplication.shared.windows.count)")
lock.unlock()
Expand Down
95 changes: 95 additions & 0 deletions PlayTools/Utils/Toast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,101 @@ class Toast {
Toast.show(message: msg, parent: parent)
}
}
static var hintView: [UIView] = []

private static let gap: CGFloat = 40

public static func hideHint(hint: UIView) {
guard let id = hintView.firstIndex(of: hint) else {return}
for index in 0..<hintView.count {
if index < id {
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseOut, animations: {
hintView[index].layer.position.y -= hint.frame.size.height + gap
})
} else if index > id {
hintView[index-1] = hintView[index]
}
}
hintView.removeLast()
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseOut, animations: {
hint.alpha = 0.0
}, completion: {_ in
hint.removeFromSuperview()
})
}

private static func getAttributedString(title: String, text: [String]) -> NSMutableAttributedString {
var heading = title
if !text.isEmpty {
heading += "\n"
}
let txt = NSMutableAttributedString(string: text.reduce(into: heading, { result, string in
result += string
}))
var messageLength = 0
var highlight = false
for msg in text {
txt.addAttribute(.foregroundColor, value: highlight ? UIColor.cyan: UIColor.white,
range: NSRange(location: heading.count + messageLength, length: msg.count))
highlight = !highlight
messageLength += msg.count
}
let style = NSMutableParagraphStyle()
style.alignment = .center
txt.addAttribute(.paragraphStyle, value: style,
range: NSRange(location: 0, length: heading.count + messageLength))
txt.addAttribute(.font, value: UIFont.systemFont(ofSize: 28, weight: .bold),
range: NSRange(location: 0, length: heading.count))
txt.addAttribute(.foregroundColor, value: UIColor.white,
range: NSRange(location: 0, length: heading.count))
txt.addAttribute(.font, value: UIFont.systemFont(ofSize: 28),
range: NSRange(location: heading.count, length: messageLength))
return txt
}

public static func showHint(title: String, text: [String] = [], timeout: Double = 3,
notification: NSNotification.Name? = nil) {
let parent = screen.keyWindow!

// Width and height here serve as an upper limit.
// Text would fill width first, then wrap, then fill height, then scroll
let messageLabel = UITextView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))
messageLabel.attributedText = getAttributedString(title: title, text: text)
messageLabel.backgroundColor = UIColor.black.withAlphaComponent(0.5)
messageLabel.alpha = 1.0
messageLabel.clipsToBounds = true
messageLabel.isUserInteractionEnabled = false
messageLabel.frame.size = messageLabel.sizeThatFits(messageLabel.frame.size)
messageLabel.layer.cornerCurve = CALayerCornerCurve.continuous
messageLabel.layer.cornerRadius = messageLabel.frame.size.height / 4
messageLabel.frame.size.width += messageLabel.layer.cornerRadius * 2
messageLabel.center.x = parent.center.x
messageLabel.center.y = -messageLabel.frame.size.height / 2

hintView.append(messageLabel)
parent.addSubview(messageLabel)

if hintView.count > 4 {
hideHint(hint: hintView.first!)
}
if let note = notification {
let center = NotificationCenter.default
var token: NSObjectProtocol?
token = center.addObserver(forName: note, object: nil, queue: OperationQueue.main) { _ in
center.removeObserver(token!)
hideHint(hint: messageLabel)
}
} else {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5 + timeout) {
hideHint(hint: messageLabel)
}
}
for view in hintView {
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: {
view.layer.position.y += messageLabel.frame.size.height + gap
})
}
}

// swiftlint:disable function_body_length

Expand Down

0 comments on commit 51ab649

Please sign in to comment.