diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index b5ff9da6..5230e39f 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -4,7 +4,8 @@ import 'package:apidash/consts.dart'; import 'providers.dart'; import '../models/models.dart'; import '../services/services.dart' show hiveHandler, HiveHandler, request; -import '../utils/utils.dart' show getNewUuid, collectionToHAR; +import '../utils/utils.dart' + show getNewUuid, collectionToHAR, substituteHttpRequestModel; final selectedIdStateProvider = StateProvider((ref) => null); @@ -205,6 +206,9 @@ class CollectionStateNotifier return; } + HttpRequestModel substitutedHttpRequestModel = + getSubstitutedHttpRequestModel(requestModel.httpRequestModel!); + // set current model's isWorking to true and update state var map = {...state!}; map[id] = requestModel.copyWith( @@ -214,7 +218,7 @@ class CollectionStateNotifier state = map; (http.Response?, Duration?, String?)? responseRec = await request( - requestModel.httpRequestModel!, + substitutedHttpRequestModel, defaultUriScheme: defaultUriScheme, ); late final RequestModel newRequestModel; @@ -311,4 +315,16 @@ class CollectionStateNotifier // "data": state!.map((e) => e.toJson(includeResponse: false)).toList() // }; } + + HttpRequestModel getSubstitutedHttpRequestModel( + HttpRequestModel httpRequestModel) { + var envMap = ref.read(availableEnvironmentVariablesStateProvider); + var activeEnvId = ref.read(activeEnvironmentIdStateProvider); + + return substituteHttpRequestModel( + httpRequestModel, + envMap, + activeEnvId, + ); + } } diff --git a/lib/providers/settings_providers.dart b/lib/providers/settings_providers.dart index fe49ff8a..69ec4f1a 100644 --- a/lib/providers/settings_providers.dart +++ b/lib/providers/settings_providers.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../models/models.dart' show SettingsModel; +import '../models/models.dart'; +import 'environment_provider.dart'; import '../services/services.dart' show hiveHandler, HiveHandler; import '../consts.dart'; @@ -10,6 +11,26 @@ final codegenLanguageStateProvider = StateProvider((ref) => final activeEnvironmentIdStateProvider = StateProvider((ref) => ref.watch(settingsProvider.select((value) => value.activeEnvironmentId))); +final availableEnvironmentVariablesStateProvider = + StateProvider>>((ref) { + Map> result = {}; + final environments = ref.watch(environmentsStateNotifierProvider); + final activeEnviormentId = ref.watch(activeEnvironmentIdStateProvider); + if (activeEnviormentId != null) { + result[activeEnviormentId] = environments?[activeEnviormentId] + ?.values + .where((element) => element.enabled) + .toList() ?? + []; + } + result[kGlobalEnvironmentId] = environments?[kGlobalEnvironmentId] + ?.values + .where((element) => element.enabled) + .toList() ?? + []; + return result; +}); + final StateNotifierProvider settingsProvider = StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler)); diff --git a/lib/screens/common/main_editor_widgets.dart b/lib/screens/common/main_editor_widgets.dart index 21f71b89..5453d226 100644 --- a/lib/screens/common/main_editor_widgets.dart +++ b/lib/screens/common/main_editor_widgets.dart @@ -85,6 +85,7 @@ class EnvironmentDropdown extends ConsumerWidget { environments: environmentsList, onChanged: (value) { ref.read(activeEnvironmentIdStateProvider.notifier).state = value?.id; + ref.read(hasUnsavedChangesProvider.notifier).state = true; }, ), ); diff --git a/lib/screens/envvar/editor_pane/secrets_pane.dart b/lib/screens/envvar/editor_pane/secrets_pane.dart index fb990d45..dcbec52e 100644 --- a/lib/screens/envvar/editor_pane/secrets_pane.dart +++ b/lib/screens/envvar/editor_pane/secrets_pane.dart @@ -89,8 +89,10 @@ class EditEnvironmentSecretsState ? null : (value) { if (value != null) { - secretRows[index] = - secretRows[index].copyWith(enabled: value); + setState(() { + secretRows[index] = + secretRows[index].copyWith(enabled: value); + }); } _onFieldChange(selectedId!); }, diff --git a/lib/screens/envvar/editor_pane/variables_pane.dart b/lib/screens/envvar/editor_pane/variables_pane.dart index 078be4b2..639fe9f5 100644 --- a/lib/screens/envvar/editor_pane/variables_pane.dart +++ b/lib/screens/envvar/editor_pane/variables_pane.dart @@ -89,8 +89,10 @@ class EditEnvironmentVariablesState ? null : (value) { if (value != null) { - variableRows[index] = - variableRows[index].copyWith(enabled: value); + setState(() { + variableRows[index] = + variableRows[index].copyWith(enabled: value); + }); } _onFieldChange(selectedId!); }, diff --git a/lib/screens/home_page/editor_pane/details_card/code_pane.dart b/lib/screens/home_page/editor_pane/details_card/code_pane.dart index 7cc39ef6..f61c10a6 100644 --- a/lib/screens/home_page/editor_pane/details_card/code_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/code_pane.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; final Codegen codegen = Codegen(); @@ -19,8 +20,15 @@ class CodePane extends ConsumerWidget { final defaultUriScheme = ref.watch(settingsProvider.select((value) => value.defaultUriScheme)); + var envMap = ref.watch(availableEnvironmentVariablesStateProvider); + var activeEnvId = ref.watch(activeEnvironmentIdStateProvider); + + final substitutedRequestModel = selectedRequestModel?.copyWith( + httpRequestModel: substituteHttpRequestModel( + selectedRequestModel.httpRequestModel!, envMap, activeEnvId)); + final code = codegen.getCode( - codegenLanguage, selectedRequestModel!, defaultUriScheme); + codegenLanguage, substitutedRequestModel!, defaultUriScheme); if (code == null) { return const ErrorMessage( message: "An error was encountered while generating code. $kRaiseIssue", diff --git a/lib/utils/envvar_utils.dart b/lib/utils/envvar_utils.dart index 80d1bb35..7057d7f2 100644 --- a/lib/utils/envvar_utils.dart +++ b/lib/utils/envvar_utils.dart @@ -35,3 +35,53 @@ List getEnvironmentSecrets( (removeEmptyModels ? element != kEnvironmentSecretEmptyModel : true)) .toList(); } + +String? substituteVariables( + String? input, + Map> envMap, + String? activeEnvironmentId) { + if (input == null) return null; + + final Map combinedMap = {}; + final activeEnv = envMap[activeEnvironmentId] ?? []; + final globalEnv = envMap[kGlobalEnvironmentId] ?? []; + + for (var variable in globalEnv) { + combinedMap[variable.key] = variable.value; + } + for (var variable in activeEnv) { + combinedMap[variable.key] = variable.value; + } + + final regex = RegExp(r'{{(.*?)}}'); + String result = input.replaceAllMapped(regex, (match) { + final key = match.group(1)?.trim() ?? ''; + return combinedMap[key] ?? ''; + }); + + return result; +} + +HttpRequestModel substituteHttpRequestModel( + HttpRequestModel httpRequestModel, + Map> envMap, + String? activeEnvironmentId) { + var newRequestModel = httpRequestModel.copyWith( + url: substituteVariables( + httpRequestModel.url, + envMap, + activeEnvironmentId, + )!, + headers: httpRequestModel.headers?.map((header) { + return header.copyWith( + value: substituteVariables(header.value, envMap, activeEnvironmentId), + ); + }).toList(), + params: httpRequestModel.params?.map((param) { + return param.copyWith( + value: substituteVariables(param.value, envMap, activeEnvironmentId), + ); + }).toList(), + ); + return newRequestModel; +}