| 14 | import { Context } from "./workspace"; |
| 15 | |
| 16 | export class FlutterDeviceManager implements IAmDisposable { |
| 17 | private readonly unresponsiveTimeoutPeriodSeconds = 5; |
| 18 | private subscriptions: IAmDisposable[] = []; |
| 19 | private statusBarItem: vs.StatusBarItem; |
| 20 | public currentDevice?: f.Device; |
| 21 | private devices: f.Device[] = []; |
| 22 | private emulators: Emulator[] = []; |
| 23 | private readonly knownEmulatorNames: Record<string, string> = {}; |
| 24 | protected readonly onCurrentDeviceChangedEmitter = new vs.EventEmitter<f.Device | undefined>(); |
| 25 | public readonly onCurrentDeviceChanged = this.onCurrentDeviceChangedEmitter.event; |
| 26 | protected readonly onDevicesChangedEmitter = new vs.EventEmitter<void>(); |
| 27 | public readonly onDevicesChanged = this.onDevicesChangedEmitter.event; |
| 28 | protected readonly onDeviceAddedEmitter = new vs.EventEmitter<f.Device>(); |
| 29 | public readonly onDeviceAdded = this.onDeviceAddedEmitter.event; |
| 30 | protected readonly onDeviceRemovedEmitter = new vs.EventEmitter<string>(); |
| 31 | public readonly onDeviceRemoved = this.onDeviceRemovedEmitter.event; |
| 32 | protected readonly onDeviceChangedEmitter = new vs.EventEmitter<f.Device>(); |
| 33 | public readonly onDeviceChanged = this.onDeviceChangedEmitter.event; |
| 34 | |
| 35 | constructor( |
| 36 | private readonly logger: Logger, |
| 37 | private daemon: IFlutterDaemon, |
| 38 | private readonly config: { flutterCustomEmulators: CustomEmulatorDefinition[], flutterRememberSelectedDevice: boolean, flutterSelectDeviceWhenConnected: boolean, flutterShowEmulators: "local" | "always" | "never", projectSearchDepth: number }, |
| 39 | private readonly workspaceContext: WorkspaceContext, |
| 40 | private readonly extContext: Context, |
| 41 | runIfNoDevices?: () => void, |
| 42 | readonly daemonPortOverride?: number |
| 43 | ) { |
| 44 | this.statusBarItem = vs.window.createStatusBarItem("dartStatusFlutterDevice", vs.StatusBarAlignment.Right, 1); |
| 45 | this.statusBarItem.name = "Flutter Device"; |
| 46 | this.statusBarItem.tooltip = "Flutter"; |
| 47 | this.statusBarItem.command = "flutter.selectDevice"; |
| 48 | this.statusBarItem.show(); |
| 49 | void this.updateStatusBar(); |
| 50 | |
| 51 | // Force a request for emulators to stash their names, so we can display |
| 52 | // the better name if the automatically-selected device happens to be an |
| 53 | // emulator. |
| 54 | this.getEmulators().then(() => this.updateStatusBar()).catch((e) => this.logger.error(e)); |
| 55 | |
| 56 | this.subscriptions.push(this.statusBarItem); |
| 57 | |
| 58 | daemon.registerForDeviceAdded(this.deviceAdded.bind(this)); |
| 59 | daemon.registerForDeviceRemoved(this.deviceRemoved.bind(this)); |
| 60 | if (runIfNoDevices) { |
| 61 | setTimeout(() => { |
| 62 | if (this.devices.length === 0) { |
| 63 | runIfNoDevices(); |
| 64 | } |
| 65 | }, 10000).unref(); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | public dispose() { |
| 70 | disposeAll(this.subscriptions); |
| 71 | } |
| 72 | |
| 73 | public isSupported(types: f.PlatformType[] | undefined, device: { platformType?: f.PlatformType | null | undefined } | undefined) { |
nothing calls this directly
no outgoing calls
no test coverage detected