diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart index b1f5c792b54..2b38ee562e3 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart @@ -104,13 +104,13 @@ class _AppSizeBodyState extends State Future maybeLoadAppSizeFiles() async { final queryParams = loadQueryParams(); - final baseFilePath = queryParams[baseAppSizeFilePropertyName]; + final baseFilePath = queryParams[AppSizeApi.baseAppSizeFilePropertyName]; if (baseFilePath != null) { // TODO(kenz): does this have to be in a setState()? _preLoadingData = true; final baseAppSizeFile = await server.requestBaseAppSizeFile(baseFilePath); DevToolsJsonFile? testAppSizeFile; - final testFilePath = queryParams[testAppSizeFilePropertyName]; + final testFilePath = queryParams[AppSizeApi.testAppSizeFilePropertyName]; if (testFilePath != null) { testAppSizeFile = await server.requestTestAppSizeFile(testFilePath); } diff --git a/packages/devtools_app/lib/src/shared/server/_app_size_api.dart b/packages/devtools_app/lib/src/shared/server/_app_size_api.dart index 6ec55ac8761..889ddedb8b6 100644 --- a/packages/devtools_app/lib/src/shared/server/_app_size_api.dart +++ b/packages/devtools_app/lib/src/shared/server/_app_size_api.dart @@ -6,16 +6,16 @@ part of 'server.dart'; Future requestBaseAppSizeFile(String path) { return requestFile( - api: apiGetBaseAppSizeFile, - fileKey: baseAppSizeFilePropertyName, + api: AppSizeApi.getBaseAppSizeFile, + fileKey: AppSizeApi.baseAppSizeFilePropertyName, filePath: path, ); } Future requestTestAppSizeFile(String path) { return requestFile( - api: apiGetTestAppSizeFile, - fileKey: testAppSizeFilePropertyName, + api: AppSizeApi.getTestAppSizeFile, + fileKey: AppSizeApi.testAppSizeFilePropertyName, filePath: path, ); } diff --git a/packages/devtools_app/lib/src/shared/server/_release_notes_api.dart b/packages/devtools_app/lib/src/shared/server/_release_notes_api.dart index 9cc21416f11..913c7b8523d 100644 --- a/packages/devtools_app/lib/src/shared/server/_release_notes_api.dart +++ b/packages/devtools_app/lib/src/shared/server/_release_notes_api.dart @@ -10,11 +10,11 @@ part of 'server.dart'; Future getLastShownReleaseNotesVersion() async { String version = ''; if (isDevToolsServerAvailable) { - final resp = await request(apiGetLastReleaseNotesVersion); + final resp = await request(ReleaseNotesApi.getLastReleaseNotesVersion); if (resp?.statusOk ?? false) { version = json.decode(resp!.body); } else { - logWarning(resp, apiGetLastReleaseNotesVersion); + logWarning(resp, ReleaseNotesApi.getLastReleaseNotesVersion); } } return version; @@ -26,11 +26,11 @@ Future getLastShownReleaseNotesVersion() async { Future setLastShownReleaseNotesVersion(String version) async { if (isDevToolsServerAvailable) { final resp = await request( - '$apiSetLastReleaseNotesVersion' - '?$lastReleaseNotesVersionPropertyName=$version', + '${ReleaseNotesApi.setLastReleaseNotesVersion}' + '?$apiParameterValueKey=$version', ); - if (resp == null || !resp.statusOk || !(json.decode(resp.body) as bool)) { - logWarning(resp, apiSetLastReleaseNotesVersion); + if (resp == null || !resp.statusOk) { + logWarning(resp, ReleaseNotesApi.setLastReleaseNotesVersion); } } } diff --git a/packages/devtools_shared/CHANGELOG.md b/packages/devtools_shared/CHANGELOG.md index 7e4f748f68b..eba6c30a560 100644 --- a/packages/devtools_shared/CHANGELOG.md +++ b/packages/devtools_shared/CHANGELOG.md @@ -1,3 +1,12 @@ +# 10.1.0 +* Deprecate `apiGetLastReleaseNotesVersion` in favor of `ReleaseNotesApi.getLastReleaseNotesVersion`. +* Deprecate `apiSetLastReleaseNotesVersion` in favor of `ReleaseNotesApi.setLastReleaseNotesVersion`. +* Deprecate `lastReleaseNotesVersionPropertyName`. +* Deprecate `apiGetBaseAppSizeFile` in favor of `AppSizeApi.getBaseAppSizeFile`. +* Deprecate `apiGetTestAppSizeFile` in favor of `AppSizeApi.getTestAppSizeFile`. +* Deprecate `baseAppSizeFilePropertyName` in favor of `AppSizeApi.baseAppSizeFilePropertyName`. +* Deprecate `testAppSizeFilePropertyName` in favor of `AppSizeApi.testAppSizeFilePropertyName`. + # 10.0.2 * Update dependency `web_socket_channel: '>=2.4.0 <4.0.0'`. diff --git a/packages/devtools_shared/lib/src/devtools_api.dart b/packages/devtools_shared/lib/src/devtools_api.dart index 4bb67c379ab..b14a35d24c2 100644 --- a/packages/devtools_shared/lib/src/devtools_api.dart +++ b/packages/devtools_shared/lib/src/devtools_api.dart @@ -52,27 +52,87 @@ const apiGetSurveyShownCount = '${apiPrefix}getSurveyShownCount'; /// Increments the surveyShownCount of the of the activeSurvey (apiSetActiveSurvey). const apiIncrementSurveyShownCount = '${apiPrefix}incrementSurveyShownCount'; -const lastReleaseNotesVersionPropertyName = 'lastReleaseNotesVersion'; - -/// Returns the last DevTools version for which we have shown release notes. -const apiGetLastReleaseNotesVersion = '${apiPrefix}getLastReleaseNotesVersion'; - -/// Sets the last DevTools version for which we have shown release notes. -const apiSetLastReleaseNotesVersion = '${apiPrefix}setLastReleaseNotesVersion'; - -/// Returns the base app size file, if present. -const apiGetBaseAppSizeFile = '${apiPrefix}getBaseAppSizeFile'; - -/// Returns the test app size file used for comparing two files in a diff, if -/// present. -const apiGetTestAppSizeFile = '${apiPrefix}getTestAppSizeFile'; - -const baseAppSizeFilePropertyName = 'appSizeBase'; +@Deprecated( + 'Use apiParameterValueKey for the query parameter of the ' + 'ReleaseNotesApi.setLastReleaseNotesVersion request instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const lastReleaseNotesVersionPropertyName = apiParameterValueKey; + +@Deprecated( + 'Use ReleaseNotesApi.getLastReleaseNotesVersion instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const apiGetLastReleaseNotesVersion = + ReleaseNotesApi.getLastReleaseNotesVersion; + +@Deprecated( + 'Use ReleaseNotesApi.setLastReleaseNotesVersion instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const apiSetLastReleaseNotesVersion = + ReleaseNotesApi.setLastReleaseNotesVersion; + +abstract class ReleaseNotesApi { + /// Returns the last DevTools version for which we have shown release notes. + static const getLastReleaseNotesVersion = + '${apiPrefix}getLastReleaseNotesVersion'; + + /// Sets the last DevTools version for which we have shown release notes. + static const setLastReleaseNotesVersion = + '${apiPrefix}setLastReleaseNotesVersion'; +} -const testAppSizeFilePropertyName = 'appSizeTest'; +@Deprecated( + 'Use AppSizeApi.getBaseAppSizeFile instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const apiGetBaseAppSizeFile = AppSizeApi.getBaseAppSizeFile; + +@Deprecated( + 'Use AppSizeApi.getTestAppSizeFile instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const apiGetTestAppSizeFile = AppSizeApi.getTestAppSizeFile; + +@Deprecated( + 'Use AppSizeApi.baseAppSizeFilePropertyName instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const baseAppSizeFilePropertyName = AppSizeApi.baseAppSizeFilePropertyName; + +@Deprecated( + 'Use AppSizeApi.testAppSizeFilePropertyName instead. ' + 'This field will be removed in devtools_shared >= 11.0.0.', +) +const testAppSizeFilePropertyName = AppSizeApi.testAppSizeFilePropertyName; + +abstract class AppSizeApi { + /// Returns the base app size file, if present. + static const getBaseAppSizeFile = '${apiPrefix}getBaseAppSizeFile'; + + /// Returns the test app size file used for comparing two files in a diff, if + /// present. + static const getTestAppSizeFile = '${apiPrefix}getTestAppSizeFile'; + + /// The property name for the query parameter passed along with the + /// [getBaseAppSizeFile] request. + static const baseAppSizeFilePropertyName = 'appSizeBase'; + + /// The property name for the query parameter passed along with the + /// [getTestAppSizeFile] request. + static const testAppSizeFilePropertyName = 'appSizeTest'; +} abstract class DtdApi { + /// Gets the DTD URI from the DevTools server. + /// + /// DTD is either started from the user's IDE and passed to the DevTools + /// server, or it is started directly from the DevTools server. static const apiGetDtdUri = '${apiPrefix}getDtdUri'; + + /// The property name for the response that the server sends back upon + /// receiving an [apiGetDtdUri] request. static const uriPropertyName = 'dtdUri'; } diff --git a/packages/devtools_shared/lib/src/server/devtools_store.dart b/packages/devtools_shared/lib/src/server/devtools_store.dart index 40df531e3e0..daa6ff91e90 100644 --- a/packages/devtools_shared/lib/src/server/devtools_store.dart +++ b/packages/devtools_shared/lib/src/server/devtools_store.dart @@ -4,6 +4,28 @@ import 'file_system.dart'; +enum DevToolsStoreKeys { + /// The key holding the value for whether Google Analytics (legacy) for + /// DevTools have been enabled. + analyticsEnabled, + + /// The key holding the value for whether this is a user's first run of + /// DevTools. + isFirstRun, + + /// The key holding the value for the last DevTools version that the user + /// viewed release notes for. + lastReleaseNotesVersion, + + /// The key holding the value for whether the user has taken action on the + /// DevTools survey prompt. + surveyActionTaken, + + /// The key holding the value for number of times the user has seen the + /// DevTools survey prompt without taking action. + surveyShownCount, +} + /// Provides access to the local DevTools store (~/.flutter-devtools/.devtools). class DevToolsUsage { DevToolsUsage() { @@ -33,47 +55,23 @@ class DevToolsUsage { late IOPersistentProperties properties; - static const _surveyActionTaken = 'surveyActionTaken'; - static const _surveyShownCount = 'surveyShownCount'; - void reset() { - // TODO(kenz): remove this in Feb 2022. See - // https://github.com/flutter/devtools/issues/3264. The `firstRun` property - // has been replaced by `isFirstRun`. This is to force all users to answer - // the analytics dialog again. The 'enabled' property has been replaced by - // 'analyticsEnabled' for better naming. - properties.remove('firstRun'); - properties.remove('enabled'); - - properties.remove('firstDevToolsRun'); - properties['analyticsEnabled'] = false; + properties.remove(DevToolsStoreKeys.isFirstRun.name); + properties[DevToolsStoreKeys.analyticsEnabled.name] = false; } bool get isFirstRun { - // TODO(kenz): remove this in Feb 2022. See - // https://github.com/flutter/devtools/issues/3264.The `firstRun` property - // has been replaced by `isFirstRun`. This is to force all users to answer - // the analytics dialog again. - properties.remove('firstRun'); - - return properties['isFirstRun'] = properties['isFirstRun'] == null; + return properties[DevToolsStoreKeys.isFirstRun.name] = + properties[DevToolsStoreKeys.isFirstRun.name] == null; } bool get analyticsEnabled { - // TODO(kenz): remove this in Feb 2022. See - // https://github.com/flutter/devtools/issues/3264. The `enabled` property - // has been replaced by `analyticsEnabled` for better naming. - if (properties['enabled'] != null) { - properties['analyticsEnabled'] = properties['enabled']; - properties.remove('enabled'); - } - - return properties['analyticsEnabled'] = - properties['analyticsEnabled'] == true; + return properties[DevToolsStoreKeys.analyticsEnabled.name] = + properties[DevToolsStoreKeys.analyticsEnabled.name] == true; } set analyticsEnabled(bool value) { - properties['analyticsEnabled'] = value; + properties[DevToolsStoreKeys.analyticsEnabled.name] = value; } bool surveyNameExists(String surveyName) => properties[surveyName] != null; @@ -100,8 +98,8 @@ class DevToolsUsage { void rewriteActiveSurvey(bool actionTaken, int shownCount) { assert(activeSurvey != null); properties[activeSurvey!] = { - _surveyActionTaken: actionTaken, - _surveyShownCount: shownCount, + DevToolsStoreKeys.surveyActionTaken.name: actionTaken, + DevToolsStoreKeys.surveyShownCount.name: shownCount, }; } @@ -141,15 +139,18 @@ class DevToolsUsage { } String get lastReleaseNotesVersion { - return (properties['lastReleaseNotesVersion'] ??= '') as String; + return (properties[DevToolsStoreKeys.lastReleaseNotesVersion.name] ??= '') + as String; } set lastReleaseNotesVersion(String value) { - properties['lastReleaseNotesVersion'] = value; + properties[DevToolsStoreKeys.lastReleaseNotesVersion.name] = value; } } extension type _ActiveSurveyJson(Map json) { - bool get surveyActionTaken => json[DevToolsUsage._surveyActionTaken] as bool; - int? get surveyShownCount => json[DevToolsUsage._surveyShownCount] as int?; + bool get surveyActionTaken => + json[DevToolsStoreKeys.surveyActionTaken.name] as bool; + int? get surveyShownCount => + json[DevToolsStoreKeys.surveyShownCount.name] as int?; } diff --git a/packages/devtools_shared/lib/src/server/handlers/_app_size.dart b/packages/devtools_shared/lib/src/server/handlers/_app_size.dart new file mode 100644 index 00000000000..da5c41c2f11 --- /dev/null +++ b/packages/devtools_shared/lib/src/server/handlers/_app_size.dart @@ -0,0 +1,49 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_classes_with_only_static_members + +part of '../server_api.dart'; + +abstract class _AppSizeHandler { + static shelf.Response getBaseAppSizeFile( + ServerApi api, + Map queryParams, + ) { + final missingRequiredParams = ServerApi._checkRequiredParameters( + [AppSizeApi.baseAppSizeFilePropertyName], + queryParams: queryParams, + api: api, + requestName: AppSizeApi.getBaseAppSizeFile, + ); + if (missingRequiredParams != null) return missingRequiredParams; + + final filePath = queryParams[AppSizeApi.baseAppSizeFilePropertyName]!; + final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); + if (fileJson == null) { + return api.badRequest('No JSON file available at $filePath.'); + } + return api.success(fileJson); + } + + static shelf.Response getTestAppSizeFile( + ServerApi api, + Map queryParams, + ) { + final missingRequiredParams = ServerApi._checkRequiredParameters( + [AppSizeApi.testAppSizeFilePropertyName], + queryParams: queryParams, + api: api, + requestName: AppSizeApi.getTestAppSizeFile, + ); + if (missingRequiredParams != null) return missingRequiredParams; + + final filePath = queryParams[AppSizeApi.testAppSizeFilePropertyName]!; + final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); + if (fileJson == null) { + return api.badRequest('No JSON file available at $filePath.'); + } + return api.success(fileJson); + } +} diff --git a/packages/devtools_shared/lib/src/server/handlers/_release_notes.dart b/packages/devtools_shared/lib/src/server/handlers/_release_notes.dart new file mode 100644 index 00000000000..8e0b6396772 --- /dev/null +++ b/packages/devtools_shared/lib/src/server/handlers/_release_notes.dart @@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_classes_with_only_static_members + +part of '../server_api.dart'; + +abstract class _ReleaseNotesHandler { + static shelf.Response getLastReleaseNotesVersion( + ServerApi api, + DevToolsUsage devToolsStore, + ) { + return _StorageHandler.handleGetStorageValue( + api, + devToolsStore, + key: DevToolsStoreKeys.lastReleaseNotesVersion.name, + defaultValue: '', + ); + } + + static shelf.Response setLastReleaseNotesVersion( + ServerApi api, + Map queryParams, + DevToolsUsage devToolsStore, + ) { + final missingRequiredParams = ServerApi._checkRequiredParameters( + [apiParameterValueKey], + queryParams: queryParams, + api: api, + requestName: ReleaseNotesApi.setLastReleaseNotesVersion, + ); + if (missingRequiredParams != null) return missingRequiredParams; + + return _StorageHandler.handleSetStorageValue( + api, + devToolsStore, + key: DevToolsStoreKeys.lastReleaseNotesVersion.name, + value: queryParams[apiParameterValueKey]!, + ); + } +} diff --git a/packages/devtools_shared/lib/src/server/handlers/_storage.dart b/packages/devtools_shared/lib/src/server/handlers/_storage.dart new file mode 100644 index 00000000000..fe80eaccd02 --- /dev/null +++ b/packages/devtools_shared/lib/src/server/handlers/_storage.dart @@ -0,0 +1,32 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_classes_with_only_static_members + +part of '../server_api.dart'; + +abstract class _StorageHandler { + static shelf.Response handleGetStorageValue( + ServerApi api, + DevToolsUsage devToolsStore, { + required String key, + required T defaultValue, + }) { + final T value = (devToolsStore.properties[key] as T?) ?? defaultValue; + return ServerApi._encodeResponse( + value, + api: api, + ); + } + + static shelf.Response handleSetStorageValue( + ServerApi api, + DevToolsUsage devToolsStore, { + required String key, + required T value, + }) { + devToolsStore.properties[key] = value; + return ServerApi._encodeResponse(devToolsStore.properties[key], api: api); + } +} diff --git a/packages/devtools_shared/lib/src/server/server_api.dart b/packages/devtools_shared/lib/src/server/server_api.dart index ba9d1c67d02..99ca0d85d70 100644 --- a/packages/devtools_shared/lib/src/server/server_api.dart +++ b/packages/devtools_shared/lib/src/server/server_api.dart @@ -28,10 +28,13 @@ import 'flutter_store.dart'; // TODO(kenz): consider using Dart augmentation libraries instead of part files // if there is a clear benefit. +part 'handlers/_app_size.dart'; part 'handlers/_deeplink.dart'; part 'handlers/_devtools_extensions.dart'; part 'handlers/_dtd.dart'; part 'handlers/_general.dart'; +part 'handlers/_release_notes.dart'; +part 'handlers/_storage.dart'; /// The DevTools server API. /// @@ -180,49 +183,26 @@ class ServerApi { // ----- Release notes api. ----- - case apiGetLastReleaseNotesVersion: - return _encodeResponse( - _devToolsStore.lastReleaseNotesVersion, - api: api, + case ReleaseNotesApi.getLastReleaseNotesVersion: + return _ReleaseNotesHandler.getLastReleaseNotesVersion( + api, + _devToolsStore, + ); + + case ReleaseNotesApi.setLastReleaseNotesVersion: + return _ReleaseNotesHandler.setLastReleaseNotesVersion( + api, + queryParams, + _devToolsStore, ); - case apiSetLastReleaseNotesVersion: - if (queryParams.containsKey(lastReleaseNotesVersionPropertyName)) { - _devToolsStore.lastReleaseNotesVersion = - queryParams[lastReleaseNotesVersionPropertyName]!; - return _encodeResponse(true, api: api); - } - return _encodeResponse(false, api: api); // ----- App size api. ----- - case apiGetBaseAppSizeFile: - if (queryParams.containsKey(baseAppSizeFilePropertyName)) { - final filePath = queryParams[baseAppSizeFilePropertyName]!; - final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); - if (fileJson == null) { - return api.badRequest('No JSON file available at $filePath.'); - } - return api.success(fileJson); - } - return api.badRequest( - 'Request for base app size file does not ' - 'contain a query parameter with the expected key: ' - '$baseAppSizeFilePropertyName', - ); - case apiGetTestAppSizeFile: - if (queryParams.containsKey(testAppSizeFilePropertyName)) { - final filePath = queryParams[testAppSizeFilePropertyName]!; - final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); - if (fileJson == null) { - return api.badRequest('No JSON file available at $filePath.'); - } - return api.success(fileJson); - } - return api.badRequest( - 'Request for test app size file does not ' - 'contain a query parameter with the expected key: ' - '$testAppSizeFilePropertyName', - ); + case AppSizeApi.getBaseAppSizeFile: + return _AppSizeHandler.getBaseAppSizeFile(api, queryParams); + + case AppSizeApi.getTestAppSizeFile: + return _AppSizeHandler.getTestAppSizeFile(api, queryParams); // ----- Extensions api. ----- @@ -269,8 +249,14 @@ class ServerApi { queryParams, deeplinkManager, ); + + // ----- DTD api. ----- + case DtdApi.apiGetDtdUri: return _DtdApiHandler.handleGetDtdUri(api, dtd); + + // ----- Unimplemented. ----- + default: return api.notImplemented(); } diff --git a/packages/devtools_shared/pubspec.yaml b/packages/devtools_shared/pubspec.yaml index aed0fb7849d..3c9593686e1 100644 --- a/packages/devtools_shared/pubspec.yaml +++ b/packages/devtools_shared/pubspec.yaml @@ -1,7 +1,7 @@ name: devtools_shared description: Package of shared Dart structures between devtools_app, dds, and other tools. -version: 10.0.2 +version: 10.1.0 repository: https://github.com/flutter/devtools/tree/master/packages/devtools_shared