| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:meta/meta.dart'; |
| |
| import '../base/config.dart'; |
| import '../base/file_system.dart'; |
| import '../base/logger.dart'; |
| import '../base/platform.dart'; |
| import '../cache.dart'; |
| import 'custom_device_config.dart'; |
| |
| /// Represents the custom devices config file on disk which in turn |
| /// contains a list of individual custom device configs. |
| class CustomDevicesConfig { |
| /// Load a [CustomDevicesConfig] from a (possibly non-existent) location on disk. |
| /// |
| /// The config is loaded on construction. Any error while loading will be logged |
| /// but will not result in an exception being thrown. The file will not be deleted |
| /// when it's not valid JSON (which other configurations do) and will not |
| /// be implicitly created when it doesn't exist. |
| CustomDevicesConfig({ |
| required FileSystem fileSystem, |
| required Logger logger, |
| required Platform platform |
| }) : _fileSystem = fileSystem, |
| _config = Config( |
| _kCustomDevicesConfigName, |
| fileSystem: fileSystem, |
| logger: logger, |
| platform: platform, |
| deleteFileOnFormatException: false |
| ) |
| { |
| ensureFileExists(); |
| } |
| |
| @visibleForTesting |
| CustomDevicesConfig.test({ |
| required FileSystem fileSystem, |
| Directory? directory, |
| required Logger logger |
| }) : _fileSystem = fileSystem, |
| _config = Config.test( |
| name: _kCustomDevicesConfigName, |
| directory: directory, |
| logger: logger, |
| deleteFileOnFormatException: false |
| ) |
| { |
| ensureFileExists(); |
| } |
| |
| static const String _kCustomDevicesConfigName = 'custom_devices.json'; |
| static const String _kCustomDevicesConfigKey = 'custom-devices'; |
| static const String _kSchema = r'$schema'; |
| static const String _kCustomDevices = 'custom-devices'; |
| |
| final FileSystem _fileSystem; |
| final Config _config; |
| |
| String get _defaultSchema { |
| final Uri uri = _fileSystem |
| .directory(Cache.flutterRoot) |
| .childDirectory('packages') |
| .childDirectory('flutter_tools') |
| .childDirectory('static') |
| .childFile('custom-devices.schema.json') |
| .uri; |
| |
| // otherwise it won't contain the Uri schema, so the file:// at the start |
| // will be missing |
| assert(uri.isAbsolute); |
| |
| return uri.toString(); |
| } |
| |
| /// Ensure the config file exists on disk by creating one with default values |
| /// if it doesn't exist yet. |
| /// |
| /// The config file should always be present so we can give the user a path |
| /// to a file they can edit. |
| void ensureFileExists() { |
| if (!_fileSystem.file(_config.configPath).existsSync()) { |
| _config.setValue(_kSchema, _defaultSchema); |
| _config.setValue(_kCustomDevices, <dynamic>[CustomDeviceConfig.example.toJson()]); |
| } |
| } |
| |
| /// Get the list of [CustomDeviceConfig]s that are listed in the config file |
| /// including disabled ones. |
| /// |
| /// Returns an empty list when the config could not be loaded. |
| List<CustomDeviceConfig> get devices { |
| final dynamic json = _config.getValue(_kCustomDevicesConfigKey); |
| |
| if (json == null) { |
| return <CustomDeviceConfig>[]; |
| } |
| |
| final List<dynamic> typedList = json as List<dynamic>; |
| |
| return typedList.map((dynamic e) => CustomDeviceConfig.fromJson(e)).toList(); |
| } |
| |
| // We don't have a setter for devices here because we don't need it and |
| // it also may overwrite any things done by the user that aren't explicitly |
| // tracked by the JSON-representation. For example comments (not possible right now, |
| // but they'd be useful so maybe in the future) or formatting. |
| } |