[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macOS] platform_channel sample style cleanups #123569

Merged
merged 3 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 52 additions & 31 deletions examples/platform_channel/macos/Runner/MainFlutterWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,54 @@
import Cocoa
import FlutterMacOS

class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeDelegate {
enum ChannelName {
static let battery = "samples.flutter.io/battery"
static let charging = "samples.flutter.io/charging"
}

enum BatteryState {
static let charging = "charging"
static let discharging = "discharging"
static let unavailable = "UNAVAILABLE"
}

enum ErrorCode {
static let noBattery = "NO_BATTERY"
static let unavailable = "UNAVAILABLE"
}
cbracken marked this conversation as resolved.
Show resolved Hide resolved

class MainFlutterWindow: NSWindow {
private let powerSource = PowerSource()
private let stateChangeSource = PowerSourceStateChangeHandler()
private let stateChangeHandler = PowerSourceStateChangeHandler()
private var eventSink: FlutterEventSink?

override func awakeFromNib() {
let flutterViewController = FlutterViewController.init()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.displayIfNeeded()
self.setFrame(windowFrame, display: true)

// Register battery method channel.
let registrar = flutterViewController.registrar(forPlugin: "BatteryLevel")
let batteryChannel = FlutterMethodChannel(
name: "samples.flutter.io/battery",
name: ChannelName.battery,
binaryMessenger: registrar.messenger)
batteryChannel.setMethodCallHandler({ [weak self] (call, result) in
batteryChannel.setMethodCallHandler { [powerSource = self.powerSource] (call, result) in
switch call.method {
case "getBatteryLevel":
if self?.powerSource.hasBattery() == false {
result(FlutterError(
code: "NO_BATTERY",
message: "Device does not have a battery",
details: nil))
guard powerSource.hasBattery() else {
result(
FlutterError(
code: ErrorCode.noBattery,
message: "Device does not have a battery",
details: nil))
return
}
let level = self?.powerSource.getCurrentCapacity()
if level == -1 {
guard let level = powerSource.getCurrentCapacity() else {
result(
FlutterError(
code: "UNAVAILABLE",
code: ErrorCode.unavailable,
message: "Battery info unavailable",
details: nil))
return
Expand All @@ -44,11 +61,11 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD
default:
result(FlutterMethodNotImplemented)
}
})
}

// Register charging event channel.
let chargingChannel = FlutterEventChannel(
name: "samples.flutter.io/charging",
name: ChannelName.charging,
binaryMessenger: registrar.messenger)
chargingChannel.setStreamHandler(self)

Expand All @@ -57,36 +74,40 @@ class MainFlutterWindow: NSWindow, FlutterStreamHandler, PowerSourceStateChangeD
super.awakeFromNib()
}

/// Emit a power status event to the registered event sink.
func emitPowerStatusEvent() {
if let sink = self.eventSink {
switch self.powerSource.getPowerState() {
case .ac:
sink(BatteryState.charging)
case .battery:
sink(BatteryState.discharging)
case .unknown:
sink(BatteryState.unavailable)
}
}
}
}

extension MainFlutterWindow: FlutterStreamHandler {
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink)
-> FlutterError?
{
self.eventSink = events
self.emitPowerStatusEvent()
self.stateChangeSource.delegate = self
self.stateChangeHandler.delegate = self
return nil
}

func onCancel(withArguments arguments: Any?) -> FlutterError? {
self.stateChangeSource.delegate = nil
self.stateChangeHandler.delegate = nil
self.eventSink = nil
return nil
}
}

func onPowerSourceStateChanged() {
extension MainFlutterWindow: PowerSourceStateChangeDelegate {
func didChangePowerSourceState() {
self.emitPowerStatusEvent()
}

func emitPowerStatusEvent() {
if let sink = self.eventSink {
switch self.powerSource.getPowerState() {
case .ac:
sink("charging")
case .battery:
sink("discharging")
case .unknown:
sink("UNAVAILABLE")
}
}
}

}
18 changes: 9 additions & 9 deletions examples/platform_channel/macos/Runner/PowerSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ enum PowerState {
}

/// A convenience wrapper for an IOKit power source.
class PowerSource {
let info = IOPSCopyPowerSourcesInfo().takeRetainedValue()
lazy var sources = IOPSCopyPowerSourcesList(info).takeRetainedValue() as Array
final class PowerSource {
private let info = IOPSCopyPowerSourcesInfo().takeRetainedValue()
private lazy var sources = IOPSCopyPowerSourcesList(info).takeRetainedValue() as Array
cbracken marked this conversation as resolved.
Show resolved Hide resolved

func hasBattery() -> Bool {
return !sources.isEmpty
}

/// Returns the current power source capacity. Apple-defined power sources will return this value
/// as a percentage.
func getCurrentCapacity() -> Int {
func getCurrentCapacity() -> Int? {
if let source = sources.first {
let description =
IOPSGetPowerSourceDescription(info, source).takeUnretainedValue() as! [String: AnyObject]
if let level = description[kIOPSCurrentCapacityKey] as? Int {
return level
}
}
return -1
return nil
}

/// Returns whether the device is drawing battery power or connected to an external power source.
Expand All @@ -54,22 +54,22 @@ class PowerSource {
}

protocol PowerSourceStateChangeDelegate: AnyObject {
func onPowerSourceStateChanged()
func didChangePowerSourceState()
}

/// A listener for system power source state change events. Notifies the delegate on each event.
class PowerSourceStateChangeHandler {
final class PowerSourceStateChangeHandler {
private var runLoopSource: CFRunLoopSource?
weak var delegate: PowerSourceStateChangeDelegate?

init() {
let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
self.runLoopSource = IOPSNotificationCreateRunLoopSource(
{ (context: UnsafeMutableRawPointer?) in
let weakSelf = Unmanaged<PowerSourceStateChangeHandler>.fromOpaque(
let unownedSelf = Unmanaged<PowerSourceStateChangeHandler>.fromOpaque(
UnsafeRawPointer(context!)
).takeUnretainedValue()
weakSelf.delegate?.onPowerSourceStateChanged()
unownedSelf.delegate?.didChangePowerSourceState()
}, context
).takeRetainedValue()
CFRunLoopAddSource(CFRunLoopGetCurrent(), self.runLoopSource, .defaultMode)
Expand Down