From 8e0ee4bbf65ee076186c22660219a9d40674097b Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Thu, 29 Jun 2023 10:24:17 +0300 Subject: [PATCH 001/123] build(mobile): new mobile dashboard feature initial commit, added ios build target --- ios/.gitignore | 34 ++ ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 2 + ios/Flutter/Release.xcconfig | 2 + ios/Podfile | 42 ++ ios/Podfile.lock | 41 ++ ios/Runner.xcodeproj/project.pbxproj | 551 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 +++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 51 ++ ios/Runner/Runner-Bridging-Header.h | 1 + 40 files changed, 1112 insertions(+) create mode 100644 ios/.gitignore create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.swift create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/Runner-Bridging-Header.h diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 00000000..9c906428 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,42 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '11.0' +source 'https://github.com/CocoaPods/Specs.git' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..08c7040e --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,41 @@ +PODS: + - audio_session (0.0.1): + - Flutter + - Flutter (1.0.0) + - just_audio (0.0.1): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter + +DEPENDENCIES: + - audio_session (from `.symlinks/plugins/audio_session/ios`) + - Flutter (from `Flutter`) + - just_audio (from `.symlinks/plugins/just_audio/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + +EXTERNAL SOURCES: + audio_session: + :path: ".symlinks/plugins/audio_session/ios" + Flutter: + :path: Flutter + just_audio: + :path: ".symlinks/plugins/just_audio/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + +SPEC CHECKSUMS: + audio_session: 4f3e461722055d21515cf3261b64c973c062f345 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + +PODFILE CHECKSUM: 573c4ea1167348931c3d9a31971139a55cab6029 + +COCOAPODS: 1.12.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..dceff570 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,551 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 08F22E759ADC5C0B76CBB3A2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 717666EAF6B4580D48C979ED /* Pods_Runner.framework */; }; + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4902DCBF505CC6698CC70186 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 717666EAF6B4580D48C979ED /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8EEFA741D4633D3C2EADC0C6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E3763D9A908EC8889184D711 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 08F22E759ADC5C0B76CBB3A2 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5947B4F736D6415AF252D197 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 717666EAF6B4580D48C979ED /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 9C8C61B15A9C2F6CBB0953BC /* Pods */, + 5947B4F736D6415AF252D197 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 9C8C61B15A9C2F6CBB0953BC /* Pods */ = { + isa = PBXGroup; + children = ( + 8EEFA741D4633D3C2EADC0C6 /* Pods-Runner.debug.xcconfig */, + 4902DCBF505CC6698CC70186 /* Pods-Runner.release.xcconfig */, + E3763D9A908EC8889184D711 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + E9449F64D842EB363A741306 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + E20FAFEB8BCD43526DB88C02 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + E20FAFEB8BCD43526DB88C02 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E9449F64D842EB363A741306 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..c87d15a3 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_xN#0001NP)t-s|Ns9~ z#rXRE|M&d=0au&!`~QyF`q}dRnBDt}*!qXo`c{v z{Djr|@Adh0(D_%#_&mM$D6{kE_x{oE{l@J5@%H*?%=t~i_`ufYOPkAEn!pfkr2$fs z652Tz0001XNklqeeKN4RM4i{jKqmiC$?+xN>3Apn^ z0QfuZLym_5b<*QdmkHjHlj811{If)dl(Z2K0A+ekGtrFJb?g|wt#k#pV-#A~bK=OT ts8>{%cPtyC${m|1#B1A6#u!Q;umknL1chzTM$P~L002ovPDHLkV1lTfnu!1a literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 zcmV;526g#~P){YQnis^a@{&-nmRmq)<&%Mztj67_#M}W?l>kYSliK<%xAp;0j{!}J0!o7b zE>q9${Lb$D&h7k=+4=!ek^n+`0zq>LL1O?lVyea53S5x`Nqqo2YyeuIrQrJj9XjOp z{;T5qbj3}&1vg1VK~#9!?b~^C5-}JC@Pyrv-6dSEqJqT}#j9#dJ@GzT@B8}x zU&J@bBI>f6w6en+CeI)3^kC*U?}X%OD8$Fd$H&LV$H&LV$H&LV#|K5~mLYf|VqzOc zkc7qL~0sOYuM{tG`rYEDV{DWY`Z8&)kW*hc2VkBuY+^Yx&92j&StN}Wp=LD zxoGxXw6f&8sB^u})h@b@z0RBeD`K7RMR9deyL(ZJu#39Z>rT)^>v}Khq8U-IbIvT> z?4pV9qGj=2)TNH3d)=De<+^w;>S7m_eFKTvzeaBeir45xY!^m!FmxnljbSS_3o=g( z->^wC9%qkR{kbGnW8MfFew_o9h3(r55Is`L$8KI@d+*%{=Nx+FXJ98L0PjFIu;rGnnfY zn1R5Qnp<{Jq0M1vX=X&F8gtLmcWv$1*M@4ZfF^9``()#hGTeKeP`1!iED ztNE(TN}M5}3Bbc*d=FIv`DNv&@|C6yYj{sSqUj5oo$#*0$7pu|Dd2TLI>t5%I zIa4Dvr(iayb+5x=j*Vum9&irk)xV1`t509lnPO0%skL8_1c#Xbamh(2@f?4yUI zhhuT5<#8RJhGz4%b$`PJwKPAudsm|at?u;*hGgnA zU1;9gnxVBC)wA(BsB`AW54N{|qmikJR*%x0c`{LGsSfa|NK61pYH(r-UQ4_JXd!Rsz)=k zL{GMc5{h138)fF5CzHEDM>+FqY)$pdN3}Ml+riTgJOLN0F*Vh?{9ESR{SVVg>*>=# zix;VJHPtvFFCRY$Ks*F;VX~%*r9F)W`PmPE9F!(&s#x07n2<}?S{(ygpXgX-&B&OM zONY&BRQ(#%0%jeQs?oJ4P!p*R98>qCy5p8w>_gpuh39NcOlp)(wOoz0sY-Qz55eB~ z7OC-fKBaD1sE3$l-6QgBJO!n?QOTza`!S_YK z_v-lm^7{VO^8Q@M_^8F)09Ki6%=s?2_5eupee(w1FB%aqSweusQ-T+CH0Xt{` zFjMvW{@C&TB)k25()nh~_yJ9coBRL(0oO@HK~z}7?bm5j;y@69;bvlHb2tf!$ReA~x{22wTq550 z?f?Hnw(;m3ip30;QzdV~7pi!wyMYhDtXW#cO7T>|f=bdFhu+F!zMZ2UFj;GUKX7tI z;hv3{q~!*pMj75WP_c}>6)IWvg5_yyg<9Op()eD1hWC19M@?_9_MHec{Z8n3FaF{8 z;u`Mw0ly(uE>*CgQYv{be6ab2LWhlaH1^iLIM{olnag$78^Fd}%dR7;JECQ+hmk|o z!u2&!3MqPfP5ChDSkFSH8F2WVOEf0(E_M(JL17G}Y+fg0_IuW%WQ zG(mG&u?|->YSdk0;8rc{yw2@2Z&GA}z{Wb91Ooz9VhA{b2DYE7RmG zjL}?eq#iX%3#k;JWMx_{^2nNax`xPhByFiDX+a7uTGU|otOvIAUy|dEKkXOm-`aWS z27pUzD{a)Ct<6p{{3)+lq@i`t@%>-wT4r?*S}k)58e09WZYP0{{R3FC5Sl00039P)t-s|Ns9~ z#rP?<_5oL$Q^olD{r_0T`27C={r>*`|Nj71npVa5OTzc(_WfbW_({R{p56NV{r*M2 z_xt?)2V0#0NsfV0u>{42ctGP(8vQj-Btk1n|O0ZD=YLwd&R{Ko41Gr9H= zY@z@@bOAMB5Ltl$E>bJJ{>JP30ZxkmI%?eW{k`b?Wy<&gOo;dS`~CR$Vwb@XWtR|N zi~t=w02?-0&j0TD{>bb6sNwsK*!p?V`RMQUl(*DVjk-9Cx+-z1KXab|Ka2oXhX5f% z`$|e!000AhNklrxs)5QTeTVRiEmz~MKK1WAjCw(c-JK6eox;2O)?`? zTG`AHia671e^vgmp!llKp|=5sVHk#C7=~epA~VAf-~%aPC=%Qw01h8mnSZ|p?hz91 z7p83F3%LVu9;S$tSI$C^%^yud1dfTM_6p2|+5Ejp$bd`GDvbR|xit>i!ZD&F>@CJrPmu*UjD&?DfZs=$@e3FQA(vNiU+$A*%a} z?`XcG2jDxJ_ZQ#Md`H{4Lpf6QBDp81_KWZ6Tk#yCy1)32zO#3<7>b`eT7UyYH1eGz z;O(rH$=QR*L%%ZcBpc=eGua?N55nD^K(8<#gl2+pN_j~b2MHs4#mcLmv%DkspS-3< zpI1F=^9siI0s-;IN_IrA;5xm~3?3!StX}pUv0vkxMaqm+zxrg7X7(I&*N~&dEd0kD z-FRV|g=|QuUsuh>-xCI}vD2imzYIOIdcCVV=$Bz@*u0+Bs<|L^)32nN*=wu3n%Ynw z@1|eLG>!8ruU1pFXUfb`j>(=Gy~?Rn4QJ-c3%3T|(Frd!bI`9u&zAnyFYTqlG#&J7 zAkD(jpw|oZLNiA>;>hgp1KX7-wxC~31II47gc zHcehD6Uxlf%+M^^uN5Wc*G%^;>D5qT{>=uxUhX%WJu^Z*(_Wq9y}npFO{Hhb>s6<9 zNi0pHXWFaVZnb)1+RS&F)xOv6&aeILcI)`k#0YE+?e)5&#r7J#c`3Z7x!LpTc01dx zrdC3{Z;joZ^KN&))zB_i)I9fWedoN>Zl-6_Iz+^G&*ak2jpF07*qoM6N<$f;w%0(f|Me literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 00000000..b2de7a21 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Apidash + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + apidash + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" From 4b12223b80eb9b9f3b27f371bcd99b9ba71f4d3b Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Thu, 29 Jun 2023 10:25:35 +0300 Subject: [PATCH 002/123] feat(mobile): added mobile specific platform consts --- lib/consts.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/consts.dart b/lib/consts.dart index f1390a3c..78eeb27f 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -16,6 +16,10 @@ final kIsApple = !kIsWeb && (Platform.isIOS || Platform.isMacOS); final kIsDesktop = !kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isLinux); +final kIsIOS = !kIsWeb && Platform.isIOS; +final kIsAndroid = !kIsWeb && Platform.isAndroid; +final kIsMobile = !kIsWeb && (Platform.isIOS || Platform.isAndroid); + final kColorTransparentState = MaterialStateProperty.all(Colors.transparent); const kColorTransparent = Colors.transparent; From 0d4ad47ab8f13fa5cf5ec2c487a005a7cb25a904 Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Sat, 1 Jul 2023 12:04:26 +0300 Subject: [PATCH 003/123] feat(mobile): added MobileDashboard widget with Drawer config Created new dynamic MobileDashboard widget with basic home, requests and settigns navigations within the side drawer --- lib/widgets/mobile_dashboard.dart | 83 +++++++++++++++++++++++++++++++ lib/widgets/widgets.dart | 1 + 2 files changed, 84 insertions(+) create mode 100644 lib/widgets/mobile_dashboard.dart diff --git a/lib/widgets/mobile_dashboard.dart b/lib/widgets/mobile_dashboard.dart new file mode 100644 index 00000000..8a2e49a6 --- /dev/null +++ b/lib/widgets/mobile_dashboard.dart @@ -0,0 +1,83 @@ +import 'package:apidash/screens/home_page/collection_pane.dart'; +import 'package:apidash/screens/intro_page.dart'; +import 'package:apidash/screens/settings_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class MobileDashboard extends ConsumerStatefulWidget { + const MobileDashboard( + {required this.scaffoldBody, required this.title, super.key}); + + final Widget scaffoldBody; + final String title; + + @override + ConsumerState createState() => _MobileDashboardState(); +} + +class _MobileDashboardState extends ConsumerState { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + drawer: Drawer( + child: ListView( + padding: EdgeInsets.zero, + children: [ + const SizedBox( + height: 70, + ), + ListTile( + title: const Text('Home'), + leading: const Icon(Icons.home_outlined), + onTap: () { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => const MobileDashboard( + title: 'Home', + scaffoldBody: IntroPage(), + ), + ), + (Route route) => false); + }, + ), + ListTile( + title: const Text('Requests'), + leading: const Icon(Icons.auto_awesome_mosaic_outlined), + onTap: () { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => const MobileDashboard( + title: 'Requests', + scaffoldBody: CollectionPane(), + ), + ), + (Route route) => false); + }, + ), + ListTile( + title: const Text('Settings'), + leading: const Icon(Icons.settings_outlined), + onTap: () { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => const MobileDashboard( + title: 'Settings', + scaffoldBody: SettingsPage(), + ), + ), + (Route route) => false); + }, + ), + const Divider(), + ], + ), + ), + body: SafeArea( + child: widget.scaffoldBody, + ), + ); + } +} diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index b259e7bf..6b54c386 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -17,3 +17,4 @@ export 'response_widgets.dart'; export 'snackbars.dart'; export 'markdown.dart'; export 'uint8_audio_player.dart'; +export 'mobile_dashboard.dart'; From eebd1dec7023a4e2801b83efa3b9a95b463f8b0f Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Sat, 1 Jul 2023 12:05:10 +0300 Subject: [PATCH 004/123] feat(mobile): logic checks to display MobileDashboard if the platform is Mobile --- lib/app.dart | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index ca9e7be0..951b548e 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,9 +1,12 @@ +import 'package:apidash/screens/home_page/collection_pane.dart'; +import 'package:apidash/widgets/mobile_dashboard.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:window_manager/window_manager.dart'; import 'providers/providers.dart'; import 'screens/screens.dart'; -import 'consts.dart' show kFontFamily, kFontFamilyFallback, kColorSchemeSeed; +import 'consts.dart' + show kFontFamily, kFontFamilyFallback, kColorSchemeSeed, kIsMobile; class App extends ConsumerStatefulWidget { const App({super.key}); @@ -63,6 +66,7 @@ class _DashAppState extends ConsumerState { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( + visualDensity: VisualDensity.adaptivePlatformDensity, fontFamily: kFontFamily, fontFamilyFallback: kFontFamilyFallback, colorSchemeSeed: kColorSchemeSeed, @@ -77,7 +81,12 @@ class _DashAppState extends ConsumerState { brightness: Brightness.dark, ), themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light, - home: const Dashboard(), + home: kIsMobile + ? const MobileDashboard( + title: 'Requests', + scaffoldBody: CollectionPane(), + ) + : const Dashboard(), ); } } From 47fb5220a2e1d4fa9eaa8c4cd9a26329b8180a40 Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Sat, 1 Jul 2023 12:06:22 +0300 Subject: [PATCH 005/123] fix(mobile): removed Settings headline and divider in case of mobile platform using in widget terenary operators --- lib/screens/settings_page.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/screens/settings_page.dart b/lib/screens/settings_page.dart index bc4e22f8..15639e17 100644 --- a/lib/screens/settings_page.dart +++ b/lib/screens/settings_page.dart @@ -26,9 +26,11 @@ class _SettingsPageState extends ConsumerState { padding: kPh20t40, shrinkWrap: true, children: [ - Text("Settings", - style: Theme.of(context).textTheme.headlineLarge), - const Divider(), + kIsDesktop + ? Text("Settings", + style: Theme.of(context).textTheme.headlineLarge) + : const SizedBox.shrink(), + kIsDesktop ? const Divider() : const SizedBox.shrink(), SwitchListTile( contentPadding: EdgeInsets.zero, hoverColor: kColorTransparent, From 685de8697d5d92559ac6b87d404cf44d286a0344 Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Tue, 4 Jul 2023 21:50:20 +0300 Subject: [PATCH 006/123] refactor(mobile): moved MobileDashboard screen from widgets to new screens/mobile dir (following mobile/ desktop ui segregation) and cleaned imports --- lib/app.dart | 2 +- .../mobile_dashboard.dart => screens/mobile/dashboard.dart} | 0 lib/screens/mobile/mobile.dart | 1 + lib/widgets/widgets.dart | 1 - 4 files changed, 2 insertions(+), 2 deletions(-) rename lib/{widgets/mobile_dashboard.dart => screens/mobile/dashboard.dart} (100%) create mode 100644 lib/screens/mobile/mobile.dart diff --git a/lib/app.dart b/lib/app.dart index 951b548e..ae0250ba 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,5 +1,5 @@ import 'package:apidash/screens/home_page/collection_pane.dart'; -import 'package:apidash/widgets/mobile_dashboard.dart'; +import 'package:apidash/screens/mobile/mobile.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:window_manager/window_manager.dart'; diff --git a/lib/widgets/mobile_dashboard.dart b/lib/screens/mobile/dashboard.dart similarity index 100% rename from lib/widgets/mobile_dashboard.dart rename to lib/screens/mobile/dashboard.dart diff --git a/lib/screens/mobile/mobile.dart b/lib/screens/mobile/mobile.dart new file mode 100644 index 00000000..1b8c3333 --- /dev/null +++ b/lib/screens/mobile/mobile.dart @@ -0,0 +1 @@ +export 'dashboard.dart'; diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index 6b54c386..b259e7bf 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -17,4 +17,3 @@ export 'response_widgets.dart'; export 'snackbars.dart'; export 'markdown.dart'; export 'uint8_audio_player.dart'; -export 'mobile_dashboard.dart'; From c18e11957ef691c7491246cc16423a4ff1cfba84 Mon Sep 17 00:00:00 2001 From: Kirollos Nayrouz Date: Wed, 5 Jul 2023 21:24:20 +0300 Subject: [PATCH 007/123] refactor(mobile): further cleaned up imports throught a single file, reorder imports and pivoted to relative imports according to convention --- lib/app.dart | 2 -- lib/screens/mobile/dashboard.dart | 6 +++--- lib/screens/screens.dart | 4 +++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index ae0250ba..47e2a933 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,5 +1,3 @@ -import 'package:apidash/screens/home_page/collection_pane.dart'; -import 'package:apidash/screens/mobile/mobile.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:window_manager/window_manager.dart'; diff --git a/lib/screens/mobile/dashboard.dart b/lib/screens/mobile/dashboard.dart index 8a2e49a6..b6f25041 100644 --- a/lib/screens/mobile/dashboard.dart +++ b/lib/screens/mobile/dashboard.dart @@ -1,8 +1,8 @@ -import 'package:apidash/screens/home_page/collection_pane.dart'; -import 'package:apidash/screens/intro_page.dart'; -import 'package:apidash/screens/settings_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../intro_page.dart'; +import '../settings_page.dart'; +import '../home_page/collection_pane.dart'; class MobileDashboard extends ConsumerStatefulWidget { const MobileDashboard( diff --git a/lib/screens/screens.dart b/lib/screens/screens.dart index c3c70a99..c647c90d 100644 --- a/lib/screens/screens.dart +++ b/lib/screens/screens.dart @@ -1 +1,3 @@ -export "dashboard.dart"; +export 'dashboard.dart'; +export 'mobile/mobile.dart'; +export 'home_page/collection_pane.dart'; From 715e7af3ff14dcbd5eaa9f547ab9314816a77c3e Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Wed, 29 Nov 2023 17:40:50 +0530 Subject: [PATCH 008/123] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 134abbba..112a730c 100644 --- a/README.md +++ b/README.md @@ -27,35 +27,35 @@ API Dash can be downloaded from the links below: .dmg Link Apple Silicon & Intel - Link + Link Windows .exe Link 64-bit - Link + Link Linux .deb Link amd64 - Link + Link arm64 - Link + Link .rpm Link x86_64 - Link + Link aarch64 - Link + Link From 9cbd6ca5a281a95f3a8fed05e8686f672effa6cc Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Wed, 29 Nov 2023 17:58:09 +0530 Subject: [PATCH 009/123] Update INSTALLATION.md --- INSTALLATION.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/INSTALLATION.md b/INSTALLATION.md index 05740be7..5673a691 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -3,7 +3,11 @@ ## Windows Download the latest Windows Installer (64 bit) from [here](https://github.com/foss42/apidash/releases/latest) -To install it, simply double click on the installer and follow the step by step installation wizard. +To install it, simply double click on the installer. + +If prompted by Windows that **Windows prevented an unrecognized app from running**, click on **Run anyway**. + +Now, follow the step by step installation wizard. ## MacOS From c32938f2c93cd8a6faa57061ad7be7863370122b Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 1 Dec 2023 04:57:13 +0530 Subject: [PATCH 010/123] bump printing --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index b0f13300..9b51dee4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,7 +39,7 @@ dependencies: just_audio_windows: ^0.2.0 freezed_annotation: ^2.4.1 json_annotation: ^4.8.1 - printing: ^5.11.0 + printing: ^5.11.1 package_info_plus: ^4.1.0 flutter_typeahead: ^4.8.0 provider: ^6.0.5 From 290fee92ce0d4bcfa5a419b139c883b28d442fa4 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 1 Dec 2023 04:57:16 +0530 Subject: [PATCH 011/123] Update pubspec.lock --- pubspec.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 60631a20..2d72cab4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -828,10 +828,10 @@ packages: dependency: "direct main" description: name: printing - sha256: e7c383dca95ee7b88c02dc1c66638628d3dcdc2fb2cc47e7a595facd47e46b56 + sha256: ad39a42a5f83125952457dfd94f395c8cf0eb1f7759583dadb769be5c7f99d24 url: "https://pub.dev" source: hosted - version: "5.11.0" + version: "5.11.1" provider: dependency: "direct main" description: From 1008262699cba313e5daf13081afaf4579dc5952 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 1 Dec 2023 05:05:39 +0530 Subject: [PATCH 012/123] Platform specific window flows through MaterialApp --- lib/app.dart | 7 ++++--- lib/main.dart | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index ca9e7be0..ae70328c 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -3,7 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:window_manager/window_manager.dart'; import 'providers/providers.dart'; import 'screens/screens.dart'; -import 'consts.dart' show kFontFamily, kFontFamilyFallback, kColorSchemeSeed; +import 'consts.dart' + show kIsLinux, kFontFamily, kFontFamilyFallback, kColorSchemeSeed; class App extends ConsumerStatefulWidget { const App({super.key}); @@ -38,7 +39,7 @@ class _AppState extends ConsumerState with WindowListener { @override Widget build(BuildContext context) { - return const DashApp(); + return const Dashboard(); } @override @@ -77,7 +78,7 @@ class _DashAppState extends ConsumerState { brightness: Brightness.dark, ), themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light, - home: const Dashboard(), + home: kIsLinux ? const Dashboard() : const App(), ); } } diff --git a/lib/main.dart b/lib/main.dart index 3f72d775..f99a58d5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,8 +16,8 @@ void main() async { await setupWindow(sz: win.$1, off: win.$2); } runApp( - ProviderScope( - child: kIsLinux ? const DashApp() : const App(), + const ProviderScope( + child: DashApp(), ), ); } From 5ea07b6c506a3da166aaa7e58986ebc8be6228d4 Mon Sep 17 00:00:00 2001 From: A Arif A S Date: Fri, 1 Dec 2023 07:09:16 +0700 Subject: [PATCH 013/123] feat(windows): custom title bar --- lib/app.dart | 55 +++++++---- lib/main.dart | 7 +- .../home_page/editor_pane/editor_pane.dart | 2 +- lib/services/window_services.dart | 2 +- lib/widgets/window_caption.dart | 98 +++++++++++++++++++ 5 files changed, 142 insertions(+), 22 deletions(-) create mode 100644 lib/widgets/window_caption.dart diff --git a/lib/app.dart b/lib/app.dart index ae70328c..b4a7dc6f 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,10 +1,16 @@ +import 'package:apidash/widgets/window_caption.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:window_manager/window_manager.dart'; +import 'package:window_manager/window_manager.dart' hide WindowCaption; import 'providers/providers.dart'; import 'screens/screens.dart'; import 'consts.dart' - show kIsLinux, kFontFamily, kFontFamilyFallback, kColorSchemeSeed; + show + kIsWindows, + kIsLinux, + kFontFamily, + kFontFamilyFallback, + kColorSchemeSeed; class App extends ConsumerStatefulWidget { const App({super.key}); @@ -63,22 +69,37 @@ class _DashAppState extends ConsumerState { ref.watch(settingsProvider.select((value) => value.isDark)); return MaterialApp( debugShowCheckedModeBanner: false, - theme: ThemeData( - fontFamily: kFontFamily, - fontFamilyFallback: kFontFamilyFallback, - colorSchemeSeed: kColorSchemeSeed, - useMaterial3: true, - brightness: Brightness.light, + home: Stack( + children: [ + MaterialApp( + debugShowCheckedModeBanner: false, + theme: ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.light, + ), + darkTheme: ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.dark, + ), + themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light, + home: kIsLinux ? const Dashboard() : const App(), + ), + if (kIsWindows) + SizedBox( + height: 29, + child: WindowCaption( + backgroundColor: Colors.transparent, + brightness: isDarkMode ? Brightness.dark : Brightness.light, + ), + ), + ], ), - darkTheme: ThemeData( - fontFamily: kFontFamily, - fontFamilyFallback: kFontFamilyFallback, - colorSchemeSeed: kColorSchemeSeed, - useMaterial3: true, - brightness: Brightness.dark, - ), - themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light, - home: kIsLinux ? const Dashboard() : const App(), ); } } diff --git a/lib/main.dart b/lib/main.dart index f99a58d5..faec2f27 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,13 +11,14 @@ void main() async { await openBoxes(); if (kIsLinux) { await setupInitialWindow(); - } else { - var win = getInitialSize(); - await setupWindow(sz: win.$1, off: win.$2); } runApp( const ProviderScope( child: DashApp(), ), ); + if (!kIsLinux) { + var win = getInitialSize(); + await setupWindow(sz: win.$1, off: win.$2); + } } diff --git a/lib/screens/home_page/editor_pane/editor_pane.dart b/lib/screens/home_page/editor_pane/editor_pane.dart index 9a391279..ec7d87d0 100644 --- a/lib/screens/home_page/editor_pane/editor_pane.dart +++ b/lib/screens/home_page/editor_pane/editor_pane.dart @@ -27,7 +27,7 @@ class _RequestEditorPaneState extends ConsumerState { return const RequestEditorDefault(); } else { return Padding( - padding: kIsMacOS ? kPt24o8 : kP8, + padding: kIsMacOS || kIsWindows ? kPt24o8 : kP8, child: const Column( children: [ EditorPaneRequestURLCard(), diff --git a/lib/services/window_services.dart b/lib/services/window_services.dart index 60b13f50..0b430e53 100644 --- a/lib/services/window_services.dart +++ b/lib/services/window_services.dart @@ -62,7 +62,7 @@ Future setupWindow({Size? sz, Offset? off, bool center = false}) async { minimumSize: kMinWindowSize, skipTaskbar: false, title: kWindowTitle, - titleBarStyle: kIsMacOS ? TitleBarStyle.hidden : null, + titleBarStyle: kIsMacOS || kIsWindows ? TitleBarStyle.hidden : null, ); if (off != null) { await windowManager.setPosition(off); diff --git a/lib/widgets/window_caption.dart b/lib/widgets/window_caption.dart new file mode 100644 index 00000000..f26e7539 --- /dev/null +++ b/lib/widgets/window_caption.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; + +import 'package:window_manager/window_manager.dart'; + +const double kWindowCaptionHeight = 30; + +class WindowCaption extends StatefulWidget { + const WindowCaption({ + super.key, + this.backgroundColor, + this.brightness, + }); + + final Color? backgroundColor; + final Brightness? brightness; + + @override + State createState() => _WindowCaptionState(); +} + +class _WindowCaptionState extends State with WindowListener { + @override + void initState() { + windowManager.addListener(this); + super.initState(); + } + + @override + void dispose() { + windowManager.removeListener(this); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onPanStart: (details) { + windowManager.startDragging(); + }, + child: const SizedBox( + height: double.infinity, + ), + ), + ), + WindowCaptionButton.minimize( + brightness: widget.brightness, + onPressed: () async { + bool isMinimized = await windowManager.isMinimized(); + if (isMinimized) { + windowManager.restore(); + } else { + windowManager.minimize(); + } + }, + ), + FutureBuilder( + future: windowManager.isMaximized(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data == true) { + return WindowCaptionButton.unmaximize( + brightness: widget.brightness, + onPressed: () { + windowManager.unmaximize(); + }, + ); + } + return WindowCaptionButton.maximize( + brightness: widget.brightness, + onPressed: () { + windowManager.maximize(); + }, + ); + }, + ), + WindowCaptionButton.close( + brightness: widget.brightness, + onPressed: () { + windowManager.close(); + }, + ), + ], + ); + } + + @override + void onWindowMaximize() { + setState(() {}); + } + + @override + void onWindowUnmaximize() { + setState(() {}); + } +} From 1690096212c2759458d8902afd4a40cce6fec68f Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 1 Dec 2023 23:42:03 +0530 Subject: [PATCH 014/123] Add Arch Linux Package --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 112a730c..45ae8ec9 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ API Dash can be downloaded from the links below: Link - Linux + Linux .deb Link amd64 @@ -56,6 +56,12 @@ API Dash can be downloaded from the links below: aarch64 Link + + + PKGBUILD (Arch Linux) + Link + x86_64 + Link From 2dbdf1e893dcd83a2260d0316fc295459be8ceba Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 1 Dec 2023 23:44:42 +0530 Subject: [PATCH 015/123] Update Arch Linux Support --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 45ae8ec9..d26478e4 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,9 @@ API Dash can be downloaded from the links below: aarch64 Link - - PKGBUILD (Arch Linux) - Link + + PKGBUILD (Arch Linux) + Link x86_64 Link From 114f5073f94d1892ff3885e6b4edf2777a0f32c6 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Wed, 6 Dec 2023 01:57:26 +0530 Subject: [PATCH 016/123] Add text selection to JSON previewer --- lib/widgets/json_previewer.dart | 2 +- pubspec.lock | 45 +++++++++++++++++---------------- pubspec.yaml | 5 +++- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/widgets/json_previewer.dart b/lib/widgets/json_previewer.dart index 06d0067b..49b1eb10 100644 --- a/lib/widgets/json_previewer.dart +++ b/lib/widgets/json_previewer.dart @@ -333,7 +333,7 @@ class _JsonPreviewerState extends State { horizontal: 4, vertical: 2, ), - child: Text( + child: SelectableText( node.isClass ? '{${node.childrenCount}}' : '[${node.childrenCount}]', style: kCodeStyle, ), diff --git a/pubspec.lock b/pubspec.lock index 2d72cab4..88c0a2a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: "direct main" description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -523,11 +523,12 @@ packages: json_data_explorer: dependency: "direct main" description: - name: json_data_explorer - sha256: "303a00037b23963fd01be1b2dc509f14e9db2a40f852b0ce042d7635c22fd154" - url: "https://pub.dev" - source: hosted - version: "0.1.0" + path: "." + ref: HEAD + resolved-ref: "9e279ee9862c4fc4050dbcb5074529b22e67a7c3" + url: "https://github.com/foss42/json_data_explorer.git" + source: git + version: "0.1.1" json_serializable: dependency: "direct dev" description: @@ -628,10 +629,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -985,10 +986,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" state_notifier: dependency: transitive description: @@ -1001,10 +1002,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1033,26 +1034,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" textwrap: dependency: transitive description: @@ -1177,10 +1178,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1247,5 +1248,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9b51dee4..96ab5fbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -43,7 +43,10 @@ dependencies: package_info_plus: ^4.1.0 flutter_typeahead: ^4.8.0 provider: ^6.0.5 - json_data_explorer: ^0.1.0 + json_data_explorer: + git: + url: https://github.com/foss42/json_data_explorer.git + version: ^0.1.1 scrollable_positioned_list: ^0.2.3 dev_dependencies: From 8a15170d0edf7595ddd9d78a0c54db4ec330ab66 Mon Sep 17 00:00:00 2001 From: damywise Date: Sat, 9 Dec 2023 23:23:06 +0700 Subject: [PATCH 017/123] fix: macos startup layout issue - Only fixes it visually, partially, until the hidden at launch feature is possible somehow. --- lib/app.dart | 15 +++++++++++++++ lib/main.dart | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index b4a7dc6f..0551b54f 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -69,6 +69,21 @@ class _DashAppState extends ConsumerState { ref.watch(settingsProvider.select((value) => value.isDark)); return MaterialApp( debugShowCheckedModeBanner: false, + theme: ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.light, + ), + darkTheme: ThemeData( + fontFamily: kFontFamily, + fontFamilyFallback: kFontFamilyFallback, + colorSchemeSeed: kColorSchemeSeed, + useMaterial3: true, + brightness: Brightness.dark, + ), + themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light, home: Stack( children: [ MaterialApp( diff --git a/lib/main.dart b/lib/main.dart index faec2f27..15fd4fa6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; import 'services/services.dart'; -import 'consts.dart' show kIsLinux; +import 'consts.dart' show kIsLinux, kIsMacOS, kIsWindows; import 'app.dart'; void main() async { @@ -17,7 +17,7 @@ void main() async { child: DashApp(), ), ); - if (!kIsLinux) { + if (kIsWindows || kIsMacOS) { var win = getInitialSize(); await setupWindow(sz: win.$1, off: win.$2); } From fb88d09654d5b3d78b38fe3464fc4ff3d1102ada Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Tue, 12 Dec 2023 01:19:20 +0530 Subject: [PATCH 018/123] Update Podfile --- ios/Podfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ios/Podfile b/ios/Podfile index 9c906428..fdcc671e 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,6 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' -source 'https://github.com/CocoaPods/Specs.git' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -33,6 +32,9 @@ target 'Runner' do use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end end post_install do |installer| From bed105333165ab3af532c585d48962085ef90c99 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Tue, 12 Dec 2023 01:19:51 +0530 Subject: [PATCH 019/123] remove ios platform folder --- ios/.gitignore | 34 -- ios/Flutter/AppFrameworkInfo.plist | 26 - ios/Flutter/Debug.xcconfig | 2 - ios/Flutter/Release.xcconfig | 2 - ios/Podfile | 44 -- ios/Podfile.lock | 41 -- ios/Runner.xcodeproj/project.pbxproj | 551 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 87 --- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 122 ---- .../Icon-App-1024x1024@1x.png | Bin 10932 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 295 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 406 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 450 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 282 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 462 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 704 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 406 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 586 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 862 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 862 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 1674 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 762 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 1226 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 1418 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 -- ios/Runner/Base.lproj/Main.storyboard | 26 - ios/Runner/Info.plist | 51 -- ios/Runner/Runner-Bridging-Header.h | 1 - 40 files changed, 1114 deletions(-) delete mode 100644 ios/.gitignore delete mode 100644 ios/Flutter/AppFrameworkInfo.plist delete mode 100644 ios/Flutter/Debug.xcconfig delete mode 100644 ios/Flutter/Release.xcconfig delete mode 100644 ios/Podfile delete mode 100644 ios/Podfile.lock delete mode 100644 ios/Runner.xcodeproj/project.pbxproj delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 ios/Runner/AppDelegate.swift delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 ios/Runner/Base.lproj/Main.storyboard delete mode 100644 ios/Runner/Info.plist delete mode 100644 ios/Runner/Runner-Bridging-Header.h diff --git a/ios/.gitignore b/ios/.gitignore deleted file mode 100644 index 7a7f9873..00000000 --- a/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 9625e105..00000000 --- a/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 11.0 - - diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f..00000000 --- a/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe..00000000 --- a/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile deleted file mode 100644 index fdcc671e..00000000 --- a/ios/Podfile +++ /dev/null @@ -1,44 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '11.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index 08c7040e..00000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,41 +0,0 @@ -PODS: - - audio_session (0.0.1): - - Flutter - - Flutter (1.0.0) - - just_audio (0.0.1): - - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_ios (0.0.1): - - Flutter - -DEPENDENCIES: - - audio_session (from `.symlinks/plugins/audio_session/ios`) - - Flutter (from `Flutter`) - - just_audio (from `.symlinks/plugins/just_audio/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - -EXTERNAL SOURCES: - audio_session: - :path: ".symlinks/plugins/audio_session/ios" - Flutter: - :path: Flutter - just_audio: - :path: ".symlinks/plugins/just_audio/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/ios" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - -SPEC CHECKSUMS: - audio_session: 4f3e461722055d21515cf3261b64c973c062f345 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa - path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 - url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 - -PODFILE CHECKSUM: 573c4ea1167348931c3d9a31971139a55cab6029 - -COCOAPODS: 1.12.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index dceff570..00000000 --- a/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,551 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 08F22E759ADC5C0B76CBB3A2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 717666EAF6B4580D48C979ED /* Pods_Runner.framework */; }; - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 4902DCBF505CC6698CC70186 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 717666EAF6B4580D48C979ED /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8EEFA741D4633D3C2EADC0C6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E3763D9A908EC8889184D711 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 08F22E759ADC5C0B76CBB3A2 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 5947B4F736D6415AF252D197 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 717666EAF6B4580D48C979ED /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 9C8C61B15A9C2F6CBB0953BC /* Pods */, - 5947B4F736D6415AF252D197 /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - 9C8C61B15A9C2F6CBB0953BC /* Pods */ = { - isa = PBXGroup; - children = ( - 8EEFA741D4633D3C2EADC0C6 /* Pods-Runner.debug.xcconfig */, - 4902DCBF505CC6698CC70186 /* Pods-Runner.release.xcconfig */, - E3763D9A908EC8889184D711 /* Pods-Runner.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - E9449F64D842EB363A741306 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - E20FAFEB8BCD43526DB88C02 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1300; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - E20FAFEB8BCD43526DB88C02 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - E9449F64D842EB363A741306 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apidash; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index c87d15a3..00000000 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift deleted file mode 100644 index 70693e4a..00000000 --- a/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab..00000000 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4725e9b0ddb1deab583e5b5102493aa332..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_xN#0001NP)t-s|Ns9~ z#rXRE|M&d=0au&!`~QyF`q}dRnBDt}*!qXo`c{v z{Djr|@Adh0(D_%#_&mM$D6{kE_x{oE{l@J5@%H*?%=t~i_`ufYOPkAEn!pfkr2$fs z652Tz0001XNklqeeKN4RM4i{jKqmiC$?+xN>3Apn^ z0QfuZLym_5b<*QdmkHjHlj811{If)dl(Z2K0A+ekGtrFJb?g|wt#k#pV-#A~bK=OT ts8>{%cPtyC${m|1#B1A6#u!Q;umknL1chzTM$P~L002ovPDHLkV1lTfnu!1a diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452e458972bab9d994556c8305db4c827017..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d933e1120817fe9182483a228007b18ab6ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b0099ca80c806f8fe495613e8d6c69460d76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe730945a01f64a61e2235dbe3f45b08f7729182..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463a9bc882b461c96aadf492d1729e49e725..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec303439225b78712f49115768196d8d76f6790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea27c705180eb716271f41b582e76dcbd90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1674 zcmV;526g#~P){YQnis^a@{&-nmRmq)<&%Mztj67_#M}W?l>kYSliK<%xAp;0j{!}J0!o7b zE>q9${Lb$D&h7k=+4=!ek^n+`0zq>LL1O?lVyea53S5x`Nqqo2YyeuIrQrJj9XjOp z{;T5qbj3}&1vg1VK~#9!?b~^C5-}JC@Pyrv-6dSEqJqT}#j9#dJ@GzT@B8}x zU&J@bBI>f6w6en+CeI)3^kC*U?}X%OD8$Fd$H&LV$H&LV$H&LV#|K5~mLYf|VqzOc zkc7qL~0sOYuM{tG`rYEDV{DWY`Z8&)kW*hc2VkBuY+^Yx&92j&StN}Wp=LD zxoGxXw6f&8sB^u})h@b@z0RBeD`K7RMR9deyL(ZJu#39Z>rT)^>v}Khq8U-IbIvT> z?4pV9qGj=2)TNH3d)=De<+^w;>S7m_eFKTvzeaBeir45xY!^m!FmxnljbSS_3o=g( z->^wC9%qkR{kbGnW8MfFew_o9h3(r55Is`L$8KI@d+*%{=Nx+FXJ98L0PjFIu;rGnnfY zn1R5Qnp<{Jq0M1vX=X&F8gtLmcWv$1*M@4ZfF^9``()#hGTeKeP`1!iED ztNE(TN}M5}3Bbc*d=FIv`DNv&@|C6yYj{sSqUj5oo$#*0$7pu|Dd2TLI>t5%I zIa4Dvr(iayb+5x=j*Vum9&irk)xV1`t509lnPO0%skL8_1c#Xbamh(2@f?4yUI zhhuT5<#8RJhGz4%b$`PJwKPAudsm|at?u;*hGgnA zU1;9gnxVBC)wA(BsB`AW54N{|qmikJR*%x0c`{LGsSfa|NK61pYH(r-UQ4_JXd!Rsz)=k zL{GMc5{h138)fF5CzHEDM>+FqY)$pdN3}Ml+riTgJOLN0F*Vh?{9ESR{SVVg>*>=# zix;VJHPtvFFCRY$Ks*F;VX~%*r9F)W`PmPE9F!(&s#x07n2<}?S{(ygpXgX-&B&OM zONY&BRQ(#%0%jeQs?oJ4P!p*R98>qCy5p8w>_gpuh39NcOlp)(wOoz0sY-Qz55eB~ z7OC-fKBaD1sE3$l-6QgBJO!n?QOTza`!S_YK z_v-lm^7{VO^8Q@M_^8F)09Ki6%=s?2_5eupee(w1FB%aqSweusQ-T+CH0Xt{` zFjMvW{@C&TB)k25()nh~_yJ9coBRL(0oO@HK~z}7?bm5j;y@69;bvlHb2tf!$ReA~x{22wTq550 z?f?Hnw(;m3ip30;QzdV~7pi!wyMYhDtXW#cO7T>|f=bdFhu+F!zMZ2UFj;GUKX7tI z;hv3{q~!*pMj75WP_c}>6)IWvg5_yyg<9Op()eD1hWC19M@?_9_MHec{Z8n3FaF{8 z;u`Mw0ly(uE>*CgQYv{be6ab2LWhlaH1^iLIM{olnag$78^Fd}%dR7;JECQ+hmk|o z!u2&!3MqPfP5ChDSkFSH8F2WVOEf0(E_M(JL17G}Y+fg0_IuW%WQ zG(mG&u?|->YSdk0;8rc{yw2@2Z&GA}z{Wb91Ooz9VhA{b2DYE7RmG zjL}?eq#iX%3#k;JWMx_{^2nNax`xPhByFiDX+a7uTGU|otOvIAUy|dEKkXOm-`aWS z27pUzD{a)Ct<6p{{3)+lq@i`t@%>-wT4r?*S}k)58e09WZYP0{{R3FC5Sl00039P)t-s|Ns9~ z#rP?<_5oL$Q^olD{r_0T`27C={r>*`|Nj71npVa5OTzc(_WfbW_({R{p56NV{r*M2 z_xt?)2V0#0NsfV0u>{42ctGP(8vQj-Btk1n|O0ZD=YLwd&R{Ko41Gr9H= zY@z@@bOAMB5Ltl$E>bJJ{>JP30ZxkmI%?eW{k`b?Wy<&gOo;dS`~CR$Vwb@XWtR|N zi~t=w02?-0&j0TD{>bb6sNwsK*!p?V`RMQUl(*DVjk-9Cx+-z1KXab|Ka2oXhX5f% z`$|e!000AhNklrxs)5QTeTVRiEmz~MKK1WAjCw(c-JK6eox;2O)?`? zTG`AHia671e^vgmp!llKp|=5sVHk#C7=~epA~VAf-~%aPC=%Qw01h8mnSZ|p?hz91 z7p83F3%LVu9;S$tSI$C^%^yud1dfTM_6p2|+5Ejp$bd`GDvbR|xit>i!ZD&F>@CJrPmu*UjD&?DfZs=$@e3FQA(vNiU+$A*%a} z?`XcG2jDxJ_ZQ#Md`H{4Lpf6QBDp81_KWZ6Tk#yCy1)32zO#3<7>b`eT7UyYH1eGz z;O(rH$=QR*L%%ZcBpc=eGua?N55nD^K(8<#gl2+pN_j~b2MHs4#mcLmv%DkspS-3< zpI1F=^9siI0s-;IN_IrA;5xm~3?3!StX}pUv0vkxMaqm+zxrg7X7(I&*N~&dEd0kD z-FRV|g=|QuUsuh>-xCI}vD2imzYIOIdcCVV=$Bz@*u0+Bs<|L^)32nN*=wu3n%Ynw z@1|eLG>!8ruU1pFXUfb`j>(=Gy~?Rn4QJ-c3%3T|(Frd!bI`9u&zAnyFYTqlG#&J7 zAkD(jpw|oZLNiA>;>hgp1KX7-wxC~31II47gc zHcehD6Uxlf%+M^^uN5Wc*G%^;>D5qT{>=uxUhX%WJu^Z*(_Wq9y}npFO{Hhb>s6<9 zNi0pHXWFaVZnb)1+RS&F)xOv6&aeILcI)`k#0YE+?e)5&#r7J#c`3Z7x!LpTc01dx zrdC3{Z;joZ^KN&))zB_i)I9fWedoN>Zl-6_Iz+^G&*ak2jpF07*qoM6N<$f;w%0(f|Me diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf12aa4d28f374bb26596605a46dcbb3e7c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2f..00000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist deleted file mode 100644 index b2de7a21..00000000 --- a/ios/Runner/Info.plist +++ /dev/null @@ -1,51 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Apidash - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - apidash - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - - diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a56..00000000 --- a/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" From b7dedb28a4d126fe4f5adf8976d372d20057b0e8 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Tue, 12 Dec 2023 02:20:04 +0530 Subject: [PATCH 020/123] Fix for macOS --- lib/main.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 15fd4fa6..9232b5ab 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,12 +12,16 @@ void main() async { if (kIsLinux) { await setupInitialWindow(); } + if (kIsMacOS) { + var win = getInitialSize(); + await setupWindow(sz: win.$1, off: win.$2); + } runApp( const ProviderScope( child: DashApp(), ), ); - if (kIsWindows || kIsMacOS) { + if (kIsWindows) { var win = getInitialSize(); await setupWindow(sz: win.$1, off: win.$2); } From 221b6b7cca3f4f14cc63e4d0358d80cc33667770 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 12 Dec 2023 09:01:35 +0530 Subject: [PATCH 021/123] Fixed to obey window size constraints on Windows --- lib/main.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9232b5ab..5ac878aa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,7 @@ void main() async { if (kIsLinux) { await setupInitialWindow(); } - if (kIsMacOS) { + if (kIsMacOS || kIsWindows) { var win = getInitialSize(); await setupWindow(sz: win.$1, off: win.$2); } @@ -21,8 +21,4 @@ void main() async { child: DashApp(), ), ); - if (kIsWindows) { - var win = getInitialSize(); - await setupWindow(sz: win.$1, off: win.$2); - } } From ce8a7dc9447dc33c523ccbd0a7804bd465f1c807 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 15 Dec 2023 04:08:12 +0530 Subject: [PATCH 022/123] CheckBox and Filtering --- lib/codegen/kotlin/okhttp.dart | 6 ++- lib/codegen/python/http_client.dart | 6 ++- lib/codegen/python/requests.dart | 6 ++- lib/models/request_model.dart | 31 +++++++++++++- lib/providers/collection_providers.dart | 6 ++- .../request_pane/request_headers.dart | 40 +++++++++++++++--- .../request_pane/request_params.dart | 41 ++++++++++++++++--- lib/services/http_service.dart | 1 + lib/utils/convert_utils.dart | 8 ++++ lib/utils/har_utils.dart | 1 + lib/utils/http_utils.dart | 7 ++-- lib/widgets/checkbox.dart | 41 +++++++++++++++++++ lib/widgets/widgets.dart | 1 + pubspec.lock | 34 +++++++-------- test/utils/http_utils_test.dart | 17 ++++---- 15 files changed, 201 insertions(+), 45 deletions(-) create mode 100644 lib/widgets/checkbox.dart diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index 09cd2ce9..e28e7e7f 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -77,7 +77,11 @@ import okhttp3.MediaType.Companion.toMediaType"""; url = "$defaultUriScheme://$url"; } - var rec = getValidRequestUri(url, requestModel.requestParams); + var rec = getValidRequestUri( + url, + requestModel.requestParams, + requestModel.enabledParams, + ); Uri? uri = rec.$1; if (uri != null) { diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 83d02676..169de25e 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -71,7 +71,11 @@ print(data.decode("utf-8")) } result += kTemplateStart; - var rec = getValidRequestUri(url, requestModel.requestParams); + var rec = getValidRequestUri( + url, + requestModel.requestParams, + requestModel.enabledParams, + ); Uri? uri = rec.$1; if (uri != null) { diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index af8b3fbe..e2e5f050 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -75,7 +75,11 @@ print('Response Body:', response.text) url = "$defaultUriScheme://$url"; } - var rec = getValidRequestUri(url, requestModel.requestParams); + var rec = getValidRequestUri( + url, + requestModel.requestParams, + requestModel.enabledParams, + ); Uri? uri = rec.$1; if (uri != null) { var templateStartUrl = jj.Template(kTemplateStart); diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index a928dac1..78947792 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,3 +1,4 @@ +import 'package:apidash/utils/convert_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show mapToRows, rowsToMap; @@ -15,6 +16,8 @@ class RequestModel { this.requestTabIndex = 0, this.requestHeaders, this.requestParams, + this.enabledHeaders, + this.enabledParams, this.requestBodyContentType = ContentType.json, this.requestBody, this.responseStatus, @@ -30,14 +33,18 @@ class RequestModel { final int requestTabIndex; final List? requestHeaders; final List? requestParams; + final List? enabledHeaders; + final List? enabledParams; final ContentType requestBodyContentType; final String? requestBody; final int? responseStatus; final String? message; final ResponseModel? responseModel; - Map get headersMap => rowsToMap(requestHeaders) ?? {}; - Map get paramsMap => rowsToMap(requestParams) ?? {}; + Map get headersMap => + rowsToMap(getEnabledRows(requestHeaders, enabledHeaders)) ?? {}; + Map get paramsMap => + rowsToMap(getEnabledRows(requestParams, enabledParams)) ?? {}; RequestModel duplicate({ required String id, @@ -50,6 +57,8 @@ class RequestModel { description: description, requestHeaders: requestHeaders != null ? [...requestHeaders!] : null, requestParams: requestParams != null ? [...requestParams!] : null, + enabledHeaders: enabledHeaders != null ? [...enabledHeaders!] : null, + enabledParams: enabledParams != null ? [...enabledParams!] : null, requestBodyContentType: requestBodyContentType, requestBody: requestBody, ); @@ -64,6 +73,8 @@ class RequestModel { int? requestTabIndex, List? requestHeaders, List? requestParams, + List? enabledHeaders, + List? enabledParams, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, @@ -72,6 +83,8 @@ class RequestModel { }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; + var eHeaders = enabledHeaders ?? this.enabledHeaders; + var eParams = enabledParams ?? this.enabledParams; return RequestModel( id: id ?? this.id, method: method ?? this.method, @@ -81,6 +94,8 @@ class RequestModel { requestTabIndex: requestTabIndex ?? this.requestTabIndex, requestHeaders: headers != null ? [...headers] : null, requestParams: params != null ? [...params] : null, + enabledHeaders: eHeaders != null ? [...eHeaders] : null, + enabledParams: eParams != null ? [...eParams] : null, requestBodyContentType: requestBodyContentType ?? this.requestBodyContentType, requestBody: requestBody ?? this.requestBody, @@ -106,6 +121,8 @@ class RequestModel { final description = data["description"] as String?; final requestHeaders = data["requestHeaders"]; final requestParams = data["requestParams"]; + final enabledHeaders = data["enabledHeaders"] as List?; + final enabledParams = data["enabledParams"] as List?; try { requestBodyContentType = ContentType.values.byName(data["requestBodyContentType"] as String); @@ -136,6 +153,8 @@ class RequestModel { requestParams: requestParams != null ? mapToRows(Map.from(requestParams)) : null, + enabledHeaders: enabledHeaders, + enabledParams: enabledParams, requestBodyContentType: requestBodyContentType, requestBody: requestBody, responseStatus: responseStatus, @@ -153,6 +172,8 @@ class RequestModel { "description": description, "requestHeaders": rowsToMap(requestHeaders), "requestParams": rowsToMap(requestParams), + "enabledHeaders": enabledHeaders, + "enabledParams": enabledParams, "requestBodyContentType": requestBodyContentType.name, "requestBody": requestBody, "responseStatus": includeResponse ? responseStatus : null, @@ -171,7 +192,9 @@ class RequestModel { "Request Description: $description", "Request Tab Index: ${requestTabIndex.toString()}", "Request Headers: ${requestHeaders.toString()}", + "Enabled Headers: ${enabledHeaders.toString()}", "Request Params: ${requestParams.toString()}", + "Enabled Params: ${enabledParams.toString()}", "Request Body Content Type: ${requestBodyContentType.toString()}", "Request Body: ${requestBody.toString()}", "Response Status: $responseStatus", @@ -192,6 +215,8 @@ class RequestModel { other.requestTabIndex == requestTabIndex && listEquals(other.requestHeaders, requestHeaders) && listEquals(other.requestParams, requestParams) && + listEquals(other.enabledHeaders, enabledHeaders) && + listEquals(other.enabledParams, enabledParams) && other.requestBodyContentType == requestBodyContentType && other.requestBody == requestBody && other.responseStatus == responseStatus && @@ -211,6 +236,8 @@ class RequestModel { requestTabIndex, requestHeaders, requestParams, + enabledHeaders, + enabledParams, requestBodyContentType, requestBody, responseStatus, diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index e0273a34..8bf8c97f 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -123,6 +123,8 @@ class CollectionStateNotifier int? requestTabIndex, List? requestHeaders, List? requestParams, + List? enabledHeaders, + List? enabledParams, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, @@ -137,12 +139,13 @@ class CollectionStateNotifier requestTabIndex: requestTabIndex, requestHeaders: requestHeaders, requestParams: requestParams, + enabledHeaders: enabledHeaders, + enabledParams: enabledParams, requestBodyContentType: requestBodyContentType, requestBody: requestBody, responseStatus: responseStatus, message: message, responseModel: responseModel); - //print(newModel); var map = {...state!}; map[id] = newModel; state = map; @@ -175,7 +178,6 @@ class CollectionStateNotifier responseModel: responseModel, ); } - //print(newRequestModel); ref.read(sentRequestIdStateProvider.notifier).state = null; var map = {...state!}; map[id] = newRequestModel; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 82138db5..191655fc 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -16,6 +16,7 @@ class EditRequestHeaders extends ConsumerStatefulWidget { class EditRequestHeadersState extends ConsumerState { late List rows; + late List enabledRows; final random = Random.secure(); late int seed; @@ -26,9 +27,11 @@ class EditRequestHeadersState extends ConsumerState { } void _onFieldChange(String activeId) { - ref - .read(collectionStateNotifierProvider.notifier) - .update(activeId, requestHeaders: rows); + ref.read(collectionStateNotifierProvider.notifier).update( + activeId, + requestHeaders: rows, + enabledHeaders: enabledRows, + ); } @override @@ -42,10 +45,30 @@ class EditRequestHeadersState extends ConsumerState { kNameValueEmptyModel, ] : rH; + enabledRows = ref.read(activeRequestModelProvider)?.enabledHeaders ?? + List.filled(rows.length, true, growable: true); DaviModel model = DaviModel( rows: rows, columns: [ + DaviColumn( + name: 'Checkbox', + width: 36, + cellBuilder: (_, row) { + int idx = row.index; + return CheckBox( + keyId: "$activeId-$idx-headers-c-$seed", + value: enabledRows[idx], + onChanged: (value) { + setState(() { + enabledRows[idx] = value!; + }); + _onFieldChange(activeId!); + }, + colorScheme: Theme.of(context).colorScheme, + ); + }, + ), DaviColumn( name: 'Header Name', grow: 1, @@ -106,9 +129,13 @@ class EditRequestHeadersState extends ConsumerState { rows = [ kNameValueEmptyModel, ]; + enabledRows = [true]; }); } else { - rows.removeAt(row.index); + setState(() { + enabledRows.removeAt(row.index); + rows.removeAt(row.index); + }); } _onFieldChange(activeId!); }, @@ -142,7 +169,10 @@ class EditRequestHeadersState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - rows.add(kNameValueEmptyModel); + setState(() { + rows.add(kNameValueEmptyModel); + enabledRows.add(true); + }); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 9a8961c6..6bdf3cac 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -17,6 +17,7 @@ class EditRequestURLParams extends ConsumerStatefulWidget { class EditRequestURLParamsState extends ConsumerState { late List rows; + late List enabledRows; final random = Random.secure(); late int seed; @@ -27,9 +28,11 @@ class EditRequestURLParamsState extends ConsumerState { } void _onFieldChange(String activeId) { - ref - .read(collectionStateNotifierProvider.notifier) - .update(activeId, requestParams: rows); + ref.read(collectionStateNotifierProvider.notifier).update( + activeId, + requestParams: rows, + enabledParams: enabledRows, + ); } @override @@ -43,10 +46,31 @@ class EditRequestURLParamsState extends ConsumerState { kNameValueEmptyModel, ] : rP; + enabledRows = ref.read(activeRequestModelProvider)?.enabledParams ?? + List.filled(rows.length, true, growable: true); DaviModel model = DaviModel( rows: rows, columns: [ + DaviColumn( + name: 'Checkbox', + width: 36, + cellBuilder: (_, row) { + int idx = row.index; + + return CheckBox( + keyId: "$activeId-$idx-params-c-$seed", + value: enabledRows[idx], + onChanged: (value) { + setState(() { + enabledRows[idx] = value!; + }); + _onFieldChange(activeId!); + }, + colorScheme: Theme.of(context).colorScheme, + ); + }, + ), DaviColumn( name: 'URL Parameter', grow: 1, @@ -107,9 +131,13 @@ class EditRequestURLParamsState extends ConsumerState { rows = [ kNameValueEmptyModel, ]; + enabledRows = [true]; }); } else { - rows.removeAt(row.index); + setState(() { + enabledRows.removeAt(row.index); + rows.removeAt(row.index); + }); } _onFieldChange(activeId!); }, @@ -143,7 +171,10 @@ class EditRequestURLParamsState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - rows.add(kNameValueEmptyModel); + setState(() { + rows.add(kNameValueEmptyModel); + enabledRows.add(true); + }); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 8265a299..c02af612 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -13,6 +13,7 @@ Future<(http.Response?, Duration?, String?)> request( (Uri?, String?) uriRec = getValidRequestUri( requestModel.url, requestModel.requestParams, + requestModel.enabledParams, defaultUriScheme: defaultUriScheme, ); if (uriRec.$1 != null) { diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index e12f2dcc..d3021253 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -109,3 +109,11 @@ Uint8List jsonMapToBytes(Map? map) { return bytes; } } + +List getEnabledRows( + List? rows, List? enabledList) { + if (rows == null || enabledList == null) { + return rows ?? []; + } + return rows.where((element) => enabledList[rows.indexOf(element)]).toList(); +} diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f0838807..15efa7f4 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -81,6 +81,7 @@ Map requestModelToHARJsonRequest( var rec = getValidRequestUri( requestModel.url, requestModel.requestParams, + requestModel.enabledParams, defaultUriScheme: defaultUriScheme, ); diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 63aa6181..927cdc24 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -4,7 +4,7 @@ import 'package:collection/collection.dart' show mergeMaps; import 'package:http_parser/http_parser.dart'; import 'package:xml/xml.dart'; import '../models/models.dart'; -import 'convert_utils.dart' show rowsToMap; +import 'convert_utils.dart' show getEnabledRows, rowsToMap; import '../consts.dart'; String getRequestTitleFromUrl(String? url) { @@ -63,7 +63,7 @@ String stripUrlParams(String url) { } (Uri?, String?) getValidRequestUri( - String? url, List? requestParams, + String? url, List? requestParams, List? enabledParams, {String defaultUriScheme = kDefaultUriScheme}) { url = url?.trim(); if (url == null || url == "") { @@ -88,7 +88,8 @@ String stripUrlParams(String url) { uri = uri.removeFragment(); } - Map? queryParams = rowsToMap(requestParams); + Map? queryParams = + rowsToMap(getEnabledRows(requestParams, enabledParams)); if (queryParams != null) { if (uri.hasQuery) { Map urlQueryParams = uri.queryParameters; diff --git a/lib/widgets/checkbox.dart b/lib/widgets/checkbox.dart new file mode 100644 index 00000000..22c3869f --- /dev/null +++ b/lib/widgets/checkbox.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; + +class CheckBox extends StatelessWidget { + final String keyId; + final bool value; + final ValueChanged onChanged; + final ColorScheme? colorScheme; + const CheckBox({ + super.key, + required this.keyId, + required this.value, + required this.onChanged, + this.colorScheme, + }); + + @override + Widget build(BuildContext context) { + var colorScheme = this.colorScheme ?? Theme.of(context).colorScheme; + return Checkbox( + key: Key(keyId), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3), + ), + side: BorderSide( + color: colorScheme.surfaceVariant, + width: 1.5, + ), + splashRadius: 0, + value: value, + onChanged: onChanged, + checkColor: colorScheme.onPrimary, + fillColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.selected)) { + return colorScheme.primary; + } + return null; + }, + )); + } +} diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index 23929f62..94cf84b5 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -8,6 +8,7 @@ export 'error_message.dart'; export 'dropdowns.dart'; export 'splitviews.dart'; export 'texts.dart'; +export 'checkbox.dart'; export 'textfields.dart'; export 'headerfield.dart'; export 'menus.dart'; diff --git a/pubspec.lock b/pubspec.lock index 88c0a2a2..5fccd48b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: "direct main" description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.2" convert: dependency: transitive description: @@ -629,10 +629,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" mime: dependency: transitive description: @@ -986,10 +986,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" state_notifier: dependency: transitive description: @@ -1002,10 +1002,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -1034,26 +1034,26 @@ packages: dependency: "direct dev" description: name: test - sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f + sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" url: "https://pub.dev" source: hosted - version: "1.24.9" + version: "1.24.3" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.0" test_core: dependency: transitive description: name: test_core - sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a + sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.5.3" textwrap: dependency: transitive description: @@ -1178,10 +1178,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -1248,5 +1248,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.1.0 <4.0.0" flutter: ">=3.13.0" diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 2cc04763..274e925b 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -182,15 +182,16 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url1, [kvRow1]), (uri1Expected, null)); + expect(getValidRequestUri(url1, [kvRow1], null), (uri1Expected, null)); }); test('Testing getValidRequestUri for null url value', () { const kvRow2 = NameValueModel(name: "code", value: "US"); - expect(getValidRequestUri(null, [kvRow2]), (null, "URL is missing!")); + expect( + getValidRequestUri(null, [kvRow2], null), (null, "URL is missing!")); }); test('Testing getValidRequestUri for empty url value', () { const kvRow3 = NameValueModel(name: "", value: ""); - expect(getValidRequestUri("", [kvRow3]), (null, "URL is missing!")); + expect(getValidRequestUri("", [kvRow3], null), (null, "URL is missing!")); }); test('Testing getValidRequestUri when https is not provided in url', () { String url4 = "api.foss42.com/country/data"; @@ -200,7 +201,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url4, [kvRow4]), (uri4Expected, null)); + expect(getValidRequestUri(url4, [kvRow4], null), (uri4Expected, null)); }); test('Testing getValidRequestUri when url has fragment', () { String url5 = "https://dart.dev/guides/libraries/library-tour#numbers"; @@ -208,11 +209,11 @@ void main() { scheme: 'https', host: 'dart.dev', path: '/guides/libraries/library-tour'); - expect(getValidRequestUri(url5, null), (uri5Expected, null)); + expect(getValidRequestUri(url5, null, null), (uri5Expected, null)); }); test('Testing getValidRequestUri when uri scheme is not supported', () { String url5 = "mailto:someone@example.com"; - expect(getValidRequestUri(url5, null), + expect(getValidRequestUri(url5, null, null), (null, "Unsupported URL Scheme (mailto)")); }); test('Testing getValidRequestUri when query params in both url and kvrow', @@ -224,7 +225,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null)); + expect(getValidRequestUri(url6, [kvRow6], null), (uri6Expected, null)); }); test('Testing getValidRequestUri when kvrow is null', () { String url7 = "api.foss42.com/country/data?code=US"; @@ -233,7 +234,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url7, null), (uri7Expected, null)); + expect(getValidRequestUri(url7, null, null), (uri7Expected, null)); }); }); From 92c610dbf528316a71a3bff8a614843ce4e74c13 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 15 Dec 2023 04:21:55 +0530 Subject: [PATCH 023/123] Update request_model_test.dart --- test/models/request_model_test.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index 1f03e809..3c73b9d4 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -106,7 +106,9 @@ void main() { 'content-length': '18', 'content-type': 'application/json; charset=utf-8' }, + 'enabledHeaders': null, 'requestParams': null, + 'enabledParams': null, "requestBodyContentType": 'json', "requestBody": '''{ "text":"WORLD" @@ -140,7 +142,9 @@ void main() { "Request Description: ", "Request Tab Index: 0", "Request Headers: [NameValueModel(name: content-length, value: 18), NameValueModel(name: content-type, value: application/json; charset=utf-8)]", + "Enabled Headers: null", "Request Params: null", + "Enabled Params: null", "Request Body Content Type: ContentType.json", 'Request Body: {\n"text":"WORLD"\n}', "Response Status: null", From 862d6ecc2041a5b64277399b1ddaf3289c5ae02e Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 15 Dec 2023 04:24:54 +0530 Subject: [PATCH 024/123] Update convert_utils.dart --- lib/utils/convert_utils.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index d3021253..a7350257 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -110,10 +110,12 @@ Uint8List jsonMapToBytes(Map? map) { } } -List getEnabledRows( +List? getEnabledRows( List? rows, List? enabledList) { if (rows == null || enabledList == null) { - return rows ?? []; + return rows; } - return rows.where((element) => enabledList[rows.indexOf(element)]).toList(); + List finalRows = + rows.where((element) => enabledList[rows.indexOf(element)]).toList(); + return finalRows == [] ? null : finalRows; } From 88be365f391942002e1783a03897e17f0e80412d Mon Sep 17 00:00:00 2001 From: mmjsmohit Date: Fri, 15 Dec 2023 11:12:36 +0530 Subject: [PATCH 025/123] Update SVG rendering and add error messages --- android/.gitignore | 13 ++++ android/app/build.gradle | 67 ++++++++++++++++++ android/app/src/debug/AndroidManifest.xml | 7 ++ android/app/src/main/AndroidManifest.xml | 33 +++++++++ .../com/example/apidash/MainActivity.kt | 6 ++ .../res/drawable-v21/launch_background.xml | 12 ++++ .../main/res/drawable/launch_background.xml | 12 ++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 +++++ android/app/src/main/res/values/styles.xml | 18 +++++ android/app/src/profile/AndroidManifest.xml | 7 ++ android/build.gradle | 30 ++++++++ android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 ++ android/settings.gradle | 29 ++++++++ lib/consts.dart | 5 +- lib/widgets/previewer.dart | 7 ++ pubspec.lock | 32 +++++++++ pubspec.yaml | 1 + 23 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 android/.gitignore create mode 100644 android/app/build.gradle create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/kotlin/com/example/apidash/MainActivity.kt create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values-night/styles.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 00000000..6f568019 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 00000000..125535f5 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.example.apidash" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.apidash" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..55ac0a22 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt b/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt new file mode 100644 index 00000000..cc1318d9 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.apidash + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..06952be7 --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..cb1ef880 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 00000000..e83fb5da --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,30 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..598d13fe --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..3c472b99 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 00000000..7cd71285 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,29 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } + + plugins { + id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false +} + +include ":app" diff --git a/lib/consts.dart b/lib/consts.dart index 2dcb12ab..b73cba25 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -342,7 +342,7 @@ const Map>> }, kTypeImage: { kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, - kSubTypeSvg: kCodeRawBodyViewOptions, + kSubTypeSvg: kPreviewCodeRawBodyViewOptions, }, kTypeAudio: { kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, @@ -459,6 +459,9 @@ const kUnexpectedRaiseIssue = const kImageError = "There seems to be an issue rendering this image. Please raise an issue in API Dash GitHub repo so that we can resolve it."; +const kSvgError = + "There seems to be an issue rendering this SVG image. Please raise an issue in API Dash GitHub repo so that we can resolve it."; + const kPdfError = "There seems to be an issue rendering this pdf. Please raise an issue in API Dash GitHub repo so that we can resolve it."; diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart index db7d9edb..b4be8852 100644 --- a/lib/widgets/previewer.dart +++ b/lib/widgets/previewer.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'error_message.dart'; import 'package:apidash/consts.dart'; import 'package:printing/printing.dart'; @@ -40,6 +41,12 @@ class _PreviewerState extends State { // pass } } + if (widget.type == kTypeImage && widget.subtype == kSubTypeSvg) { + final String rawSvg = widget.body; + return SvgPicture.string( + rawSvg, + ); + } if (widget.type == kTypeImage) { return Image.memory( widget.bytes, diff --git a/pubspec.lock b/pubspec.lock index 88c0a2a2..26efe709 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -358,6 +358,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" + source: hosted + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -1150,6 +1158,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 96ab5fbf..91380388 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: url: https://github.com/foss42/json_data_explorer.git version: ^0.1.1 scrollable_positioned_list: ^0.2.3 + flutter_svg: ^2.0.9 dev_dependencies: flutter_test: From 8bbdea78e8769ecf07952e41e1e9dccd80c14183 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 04:56:48 +0530 Subject: [PATCH 026/123] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9268964a..4bdfd329 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ macos/ windows/ web/ ios/ +android/ .vscode/* icons/ coverage/* From c7df69c5ea8d2601748b84da1083959732e842ed Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 04:59:46 +0530 Subject: [PATCH 027/123] remove android platform specific code --- android/.gitignore | 13 ---- android/app/build.gradle | 67 ------------------ android/app/src/debug/AndroidManifest.xml | 7 -- android/app/src/main/AndroidManifest.xml | 33 --------- .../com/example/apidash/MainActivity.kt | 6 -- .../res/drawable-v21/launch_background.xml | 12 ---- .../main/res/drawable/launch_background.xml | 12 ---- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../app/src/main/res/values-night/styles.xml | 18 ----- android/app/src/main/res/values/styles.xml | 18 ----- android/app/src/profile/AndroidManifest.xml | 7 -- android/build.gradle | 30 -------- android/gradle.properties | 3 - .../gradle/wrapper/gradle-wrapper.properties | 5 -- android/settings.gradle | 29 -------- 19 files changed, 260 deletions(-) delete mode 100644 android/.gitignore delete mode 100644 android/app/build.gradle delete mode 100644 android/app/src/debug/AndroidManifest.xml delete mode 100644 android/app/src/main/AndroidManifest.xml delete mode 100644 android/app/src/main/kotlin/com/example/apidash/MainActivity.kt delete mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml delete mode 100644 android/app/src/main/res/drawable/launch_background.xml delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/values-night/styles.xml delete mode 100644 android/app/src/main/res/values/styles.xml delete mode 100644 android/app/src/profile/AndroidManifest.xml delete mode 100644 android/build.gradle delete mode 100644 android/gradle.properties delete mode 100644 android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 android/settings.gradle diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index 6f568019..00000000 --- a/android/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties -**/*.keystore -**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle deleted file mode 100644 index 125535f5..00000000 --- a/android/app/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - namespace "com.example.apidash" - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.apidash" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies {} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 55ac0a22..00000000 --- a/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - diff --git a/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt b/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt deleted file mode 100644 index cc1318d9..00000000 --- a/android/app/src/main/kotlin/com/example/apidash/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.example.apidash - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3..00000000 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb28e45604e46eeda8dd24651419bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be7..00000000 --- a/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef880..00000000 --- a/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index e83fb5da..00000000 --- a/android/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index 598d13fe..00000000 --- a/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -android.useAndroidX=true -android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 3c472b99..00000000 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 7cd71285..00000000 --- a/android/settings.gradle +++ /dev/null @@ -1,29 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - } - settings.ext.flutterSdkPath = flutterSdkPath() - - includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } - - plugins { - id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false -} - -include ":app" From a0d739b0e1938a80ab03303dc36a8a36b1eafd3e Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 16:09:41 +0530 Subject: [PATCH 028/123] SVG parser error handling --- lib/widgets/previewer.dart | 19 +++++++++++++------ pubspec.lock | 2 +- pubspec.yaml | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart index b4be8852..9841ac5b 100644 --- a/lib/widgets/previewer.dart +++ b/lib/widgets/previewer.dart @@ -1,12 +1,13 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'error_message.dart'; -import 'package:apidash/consts.dart'; import 'package:printing/printing.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'; +import 'error_message.dart'; import 'uint8_audio_player.dart'; import 'json_previewer.dart'; +import '../consts.dart'; class Previewer extends StatefulWidget { const Previewer({ @@ -43,9 +44,15 @@ class _PreviewerState extends State { } if (widget.type == kTypeImage && widget.subtype == kSubTypeSvg) { final String rawSvg = widget.body; - return SvgPicture.string( - rawSvg, - ); + try { + parseWithoutOptimizers(rawSvg); + var svgImg = SvgPicture.string( + rawSvg, + ); + return svgImg; + } catch (e) { + return const ErrorMessage(message: kSvgError); + } } if (widget.type == kTypeImage) { return Image.memory( diff --git a/pubspec.lock b/pubspec.lock index 26efe709..190d8316 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1175,7 +1175,7 @@ packages: source: hosted version: "1.1.9+1" vector_graphics_compiler: - dependency: transitive + dependency: "direct main" description: name: vector_graphics_compiler sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 diff --git a/pubspec.yaml b/pubspec.yaml index 91380388..b02083ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,7 @@ dependencies: version: ^0.1.1 scrollable_positioned_list: ^0.2.3 flutter_svg: ^2.0.9 + vector_graphics_compiler: ^1.1.9+1 dev_dependencies: flutter_test: From 08fe8cedcb0a300a6be5adc4feb62729a9fc3810 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 16:14:47 +0530 Subject: [PATCH 029/123] Update SVG preview options --- lib/consts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/consts.dart b/lib/consts.dart index b73cba25..895c0460 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -342,7 +342,7 @@ const Map>> }, kTypeImage: { kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, - kSubTypeSvg: kPreviewCodeRawBodyViewOptions, + kSubTypeSvg: kPreviewRawBodyViewOptions, }, kTypeAudio: { kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, From f2366bb9a0ba6e4a1435cf35c802a4c542583378 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 16:19:05 +0530 Subject: [PATCH 030/123] Update http_utils_test.dart --- test/utils/http_utils_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 2cc04763..55129bcc 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -268,7 +268,7 @@ void main() { test('Testing getResponseBodyViewOptions for image/svg+xml', () { MediaType mediaType5 = MediaType("image", "svg+xml"); var result5 = getResponseBodyViewOptions(mediaType5); - expect(result5.$1, kCodeRawBodyViewOptions); + expect(result5.$1, kPreviewRawBodyViewOptions); expect(result5.$2, "xml"); }); test('Testing getResponseBodyViewOptions for application/xhtml+xml', () { From 9280e2f957cf38819036777a44070256ec862790 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 16 Dec 2023 16:27:03 +0530 Subject: [PATCH 031/123] Add tests for SVG Previewer --- test/widgets/previewer_test.dart | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/widgets/previewer_test.dart b/test/widgets/previewer_test.dart index c98a9070..0d2f68cd 100644 --- a/test/widgets/previewer_test.dart +++ b/test/widgets/previewer_test.dart @@ -4,6 +4,7 @@ import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/consts.dart'; import 'package:flutter/foundation.dart'; import 'package:printing/printing.dart' show PdfPreview; +import 'package:flutter_svg/flutter_svg.dart' show SvgPicture; import '../test_consts.dart'; void main() { @@ -169,4 +170,65 @@ void main() { await tester.pumpAndSettle(); expect(find.text(kAudioError), findsOneWidget); }); + + testWidgets('Testing when type/subtype is image/svg+xml', (tester) async { + String rawSvg = + """ + + + + + + + + + + + + + + + + + + +"""; + + await tester.pumpWidget( + MaterialApp( + title: 'Previewer', + home: Scaffold( + body: Previewer( + type: 'image', + subtype: 'svg+xml', + bytes: Uint8List.fromList([]), + body: rawSvg, + ), + ), + ), + ); + await tester.pumpAndSettle(); + expect(find.text(kSvgError), findsNothing); + expect(find.byType(SvgPicture), findsOneWidget); + }); + + testWidgets('Testing when type/subtype is image/svg+xml corrupted', + (tester) async { + String rawSvg = "rwsjhdws"; + await tester.pumpWidget( + MaterialApp( + title: 'Previewer', + home: Scaffold( + body: Previewer( + type: 'image', + subtype: 'svg+xml', + bytes: Uint8List.fromList([]), + body: rawSvg, + ), + ), + ), + ); + await tester.pumpAndSettle(); + expect(find.text(kSvgError), findsOneWidget); + }); } From 1af24fad17d6d909593c1315f97596125d503d7e Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sat, 16 Dec 2023 16:39:56 +0530 Subject: [PATCH 032/123] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d26478e4..f67c8f17 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Here is the complete list of mimetypes that can be directly previewed in API Das | Image | `image/portable-anymap` | `.pnm` | | | Image | `image/png` | `.png` | | | Image | `image/sgi` | `.sgi` | | -| Image | `image/svg+xml` | `.svg` | Partial support. See issue https://github.com/foss42/apidash/issues/20 | +| Image | `image/svg+xml` | `.svg` | | | Image | `image/tiff` | `.tiff` | | | Image | `image/targa` | `.tga` | | | Image | `image/vnd.wap.wbmp` | `.wbmp` | | From e1ae22bdcd85ddcf5510f8a08acdce91949662b9 Mon Sep 17 00:00:00 2001 From: vidya-hub Date: Tue, 19 Dec 2023 20:55:44 +0530 Subject: [PATCH 033/123] wip: added basic methods --- lib/consts.dart | 14 +- lib/models/form_data_model.dart | 23 +++ lib/models/form_data_model.freezed.dart | 188 ++++++++++++++++++ lib/models/form_data_model.g.dart | 26 +++ lib/models/name_value_model.freezed.dart | 43 ++-- lib/models/name_value_model.g.dart | 7 +- lib/models/request_model.dart | 16 +- .../request_pane/request_body.dart | 121 +++++++++-- lib/utils/convert_utils.dart | 33 ++- lib/widgets/dropdowns.dart | 4 +- 10 files changed, 429 insertions(+), 46 deletions(-) create mode 100644 lib/models/form_data_model.dart create mode 100644 lib/models/form_data_model.freezed.dart create mode 100644 lib/models/form_data_model.g.dart diff --git a/lib/consts.dart b/lib/consts.dart index 2dcb12ab..ef7ed6f4 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -1,9 +1,10 @@ -import 'dart:io'; import 'dart:convert'; +import 'dart:io'; + +import 'package:davi/davi.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:davi/davi.dart'; const kDiscordUrl = "https://bit.ly/heyfoss"; const kGitUrl = "https://github.com/foss42/apidash"; @@ -224,7 +225,9 @@ enum RequestItemMenuOption { edit, delete, duplicate } enum HTTPVerb { get, head, post, put, patch, delete } -enum ContentType { json, text } +enum ContentType { json, text, formdata } + +enum FormDataType { text, file } const kSupportedUriSchemes = ["https", "http"]; const kDefaultUriScheme = "https"; @@ -294,6 +297,11 @@ const kSubTypeDefaultViewOptions = 'all'; const kContentTypeMap = { ContentType.json: "$kTypeApplication/$kSubTypeJson", ContentType.text: "$kTypeText/$kSubTypePlain", + ContentType.formdata: "multipart/form-data", +}; +const kFormDataTypeMap = { + FormDataType.file: "File", + FormDataType.text: "Text", }; enum ResponseBodyView { preview, code, raw, none } diff --git a/lib/models/form_data_model.dart b/lib/models/form_data_model.dart new file mode 100644 index 00000000..edbcd113 --- /dev/null +++ b/lib/models/form_data_model.dart @@ -0,0 +1,23 @@ +import 'package:apidash/consts.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'form_data_model.freezed.dart'; +part 'form_data_model.g.dart'; + +@freezed +class FormDataModel with _$FormDataModel { + const factory FormDataModel({ + required String name, + required dynamic value, + required FormDataType type, + }) = _FormDataModel; + + factory FormDataModel.fromJson(Map json) => + _$FormDataModelFromJson(json); +} + +const kNameValueEmptyModel = FormDataModel( + name: "", + value: "", + type: FormDataType.text, +); diff --git a/lib/models/form_data_model.freezed.dart b/lib/models/form_data_model.freezed.dart new file mode 100644 index 00000000..e1babd78 --- /dev/null +++ b/lib/models/form_data_model.freezed.dart @@ -0,0 +1,188 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'form_data_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +FormDataModel _$FormDataModelFromJson(Map json) { + return _FormDataModel.fromJson(json); +} + +/// @nodoc +mixin _$FormDataModel { + String get name => throw _privateConstructorUsedError; + dynamic get value => throw _privateConstructorUsedError; + FormDataType get type => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $FormDataModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $FormDataModelCopyWith<$Res> { + factory $FormDataModelCopyWith( + FormDataModel value, $Res Function(FormDataModel) then) = + _$FormDataModelCopyWithImpl<$Res, FormDataModel>; + @useResult + $Res call({String name, dynamic value, FormDataType type}); +} + +/// @nodoc +class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel> + implements $FormDataModelCopyWith<$Res> { + _$FormDataModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? value = freezed, + Object? type = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as FormDataType, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$FormDataModelImplCopyWith<$Res> + implements $FormDataModelCopyWith<$Res> { + factory _$$FormDataModelImplCopyWith( + _$FormDataModelImpl value, $Res Function(_$FormDataModelImpl) then) = + __$$FormDataModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, dynamic value, FormDataType type}); +} + +/// @nodoc +class __$$FormDataModelImplCopyWithImpl<$Res> + extends _$FormDataModelCopyWithImpl<$Res, _$FormDataModelImpl> + implements _$$FormDataModelImplCopyWith<$Res> { + __$$FormDataModelImplCopyWithImpl( + _$FormDataModelImpl _value, $Res Function(_$FormDataModelImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? value = freezed, + Object? type = null, + }) { + return _then(_$FormDataModelImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as FormDataType, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$FormDataModelImpl implements _FormDataModel { + const _$FormDataModelImpl( + {required this.name, required this.value, required this.type}); + + factory _$FormDataModelImpl.fromJson(Map json) => + _$$FormDataModelImplFromJson(json); + + @override + final String name; + @override + final dynamic value; + @override + final FormDataType type; + + @override + String toString() { + return 'FormDataModel(name: $name, value: $value, type: $type)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FormDataModelImpl && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other.value, value) && + (identical(other.type, type) || other.type == type)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, name, const DeepCollectionEquality().hash(value), type); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$FormDataModelImplCopyWith<_$FormDataModelImpl> get copyWith => + __$$FormDataModelImplCopyWithImpl<_$FormDataModelImpl>(this, _$identity); + + @override + Map toJson() { + return _$$FormDataModelImplToJson( + this, + ); + } +} + +abstract class _FormDataModel implements FormDataModel { + const factory _FormDataModel( + {required final String name, + required final dynamic value, + required final FormDataType type}) = _$FormDataModelImpl; + + factory _FormDataModel.fromJson(Map json) = + _$FormDataModelImpl.fromJson; + + @override + String get name; + @override + dynamic get value; + @override + FormDataType get type; + @override + @JsonKey(ignore: true) + _$$FormDataModelImplCopyWith<_$FormDataModelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/models/form_data_model.g.dart b/lib/models/form_data_model.g.dart new file mode 100644 index 00000000..7d9d353b --- /dev/null +++ b/lib/models/form_data_model.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'form_data_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$FormDataModelImpl _$$FormDataModelImplFromJson(Map json) => + _$FormDataModelImpl( + name: json['name'] as String, + value: json['value'], + type: $enumDecode(_$FormDataTypeEnumMap, json['type']), + ); + +Map _$$FormDataModelImplToJson(_$FormDataModelImpl instance) => + { + 'name': instance.name, + 'value': instance.value, + 'type': _$FormDataTypeEnumMap[instance.type]!, + }; + +const _$FormDataTypeEnumMap = { + FormDataType.text: 'text', + FormDataType.file: 'file', +}; diff --git a/lib/models/name_value_model.freezed.dart b/lib/models/name_value_model.freezed.dart index e7d9e8e0..b224f596 100644 --- a/lib/models/name_value_model.freezed.dart +++ b/lib/models/name_value_model.freezed.dart @@ -68,22 +68,22 @@ class _$NameValueModelCopyWithImpl<$Res, $Val extends NameValueModel> } /// @nodoc -abstract class _$$_NameValueModelCopyWith<$Res> +abstract class _$$NameValueModelImplCopyWith<$Res> implements $NameValueModelCopyWith<$Res> { - factory _$$_NameValueModelCopyWith( - _$_NameValueModel value, $Res Function(_$_NameValueModel) then) = - __$$_NameValueModelCopyWithImpl<$Res>; + factory _$$NameValueModelImplCopyWith(_$NameValueModelImpl value, + $Res Function(_$NameValueModelImpl) then) = + __$$NameValueModelImplCopyWithImpl<$Res>; @override @useResult $Res call({String name, dynamic value}); } /// @nodoc -class __$$_NameValueModelCopyWithImpl<$Res> - extends _$NameValueModelCopyWithImpl<$Res, _$_NameValueModel> - implements _$$_NameValueModelCopyWith<$Res> { - __$$_NameValueModelCopyWithImpl( - _$_NameValueModel _value, $Res Function(_$_NameValueModel) _then) +class __$$NameValueModelImplCopyWithImpl<$Res> + extends _$NameValueModelCopyWithImpl<$Res, _$NameValueModelImpl> + implements _$$NameValueModelImplCopyWith<$Res> { + __$$NameValueModelImplCopyWithImpl( + _$NameValueModelImpl _value, $Res Function(_$NameValueModelImpl) _then) : super(_value, _then); @pragma('vm:prefer-inline') @@ -92,7 +92,7 @@ class __$$_NameValueModelCopyWithImpl<$Res> Object? name = null, Object? value = freezed, }) { - return _then(_$_NameValueModel( + return _then(_$NameValueModelImpl( name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -107,13 +107,13 @@ class __$$_NameValueModelCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$_NameValueModel +class _$NameValueModelImpl with DiagnosticableTreeMixin implements _NameValueModel { - const _$_NameValueModel({required this.name, required this.value}); + const _$NameValueModelImpl({required this.name, required this.value}); - factory _$_NameValueModel.fromJson(Map json) => - _$$_NameValueModelFromJson(json); + factory _$NameValueModelImpl.fromJson(Map json) => + _$$NameValueModelImplFromJson(json); @override final String name; @@ -138,7 +138,7 @@ class _$_NameValueModel bool operator ==(dynamic other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$_NameValueModel && + other is _$NameValueModelImpl && (identical(other.name, name) || other.name == name) && const DeepCollectionEquality().equals(other.value, value)); } @@ -151,12 +151,13 @@ class _$_NameValueModel @JsonKey(ignore: true) @override @pragma('vm:prefer-inline') - _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => - __$$_NameValueModelCopyWithImpl<_$_NameValueModel>(this, _$identity); + _$$NameValueModelImplCopyWith<_$NameValueModelImpl> get copyWith => + __$$NameValueModelImplCopyWithImpl<_$NameValueModelImpl>( + this, _$identity); @override Map toJson() { - return _$$_NameValueModelToJson( + return _$$NameValueModelImplToJson( this, ); } @@ -165,10 +166,10 @@ class _$_NameValueModel abstract class _NameValueModel implements NameValueModel { const factory _NameValueModel( {required final String name, - required final dynamic value}) = _$_NameValueModel; + required final dynamic value}) = _$NameValueModelImpl; factory _NameValueModel.fromJson(Map json) = - _$_NameValueModel.fromJson; + _$NameValueModelImpl.fromJson; @override String get name; @@ -176,6 +177,6 @@ abstract class _NameValueModel implements NameValueModel { dynamic get value; @override @JsonKey(ignore: true) - _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => + _$$NameValueModelImplCopyWith<_$NameValueModelImpl> get copyWith => throw _privateConstructorUsedError; } diff --git a/lib/models/name_value_model.g.dart b/lib/models/name_value_model.g.dart index 25867df8..5fb91b66 100644 --- a/lib/models/name_value_model.g.dart +++ b/lib/models/name_value_model.g.dart @@ -6,13 +6,14 @@ part of 'name_value_model.dart'; // JsonSerializableGenerator // ************************************************************************** -_$_NameValueModel _$$_NameValueModelFromJson(Map json) => - _$_NameValueModel( +_$NameValueModelImpl _$$NameValueModelImplFromJson(Map json) => + _$NameValueModelImpl( name: json['name'] as String, value: json['value'], ); -Map _$$_NameValueModelToJson(_$_NameValueModel instance) => +Map _$$NameValueModelImplToJson( + _$NameValueModelImpl instance) => { 'name': instance.name, 'value': instance.value, diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index a928dac1..fda03ea1 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,6 +1,8 @@ -import 'package:flutter/foundation.dart'; import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' show mapToRows, rowsToMap; +import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:flutter/foundation.dart'; + import 'name_value_model.dart'; import 'response_model.dart'; @@ -20,6 +22,7 @@ class RequestModel { this.responseStatus, this.message, this.responseModel, + this.formDataList, }); final String id; @@ -30,6 +33,7 @@ class RequestModel { final int requestTabIndex; final List? requestHeaders; final List? requestParams; + final List? formDataList; final ContentType requestBodyContentType; final String? requestBody; final int? responseStatus; @@ -52,6 +56,7 @@ class RequestModel { requestParams: requestParams != null ? [...requestParams!] : null, requestBodyContentType: requestBodyContentType, requestBody: requestBody, + formDataList: formDataList != null ? [...formDataList!] : null, ); } @@ -69,6 +74,7 @@ class RequestModel { int? responseStatus, String? message, ResponseModel? responseModel, + List? formDataList, }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; @@ -87,6 +93,7 @@ class RequestModel { responseStatus: responseStatus ?? this.responseStatus, message: message ?? this.message, responseModel: responseModel ?? this.responseModel, + formDataList: formDataList ?? this.formDataList, ); } @@ -116,6 +123,8 @@ class RequestModel { final responseStatus = data["responseStatus"] as int?; final message = data["message"] as String?; final responseModelJson = data["responseModel"]; + final formDataList = data["formDataList"]; + if (responseModelJson != null) { responseModel = ResponseModel.fromJson(Map.from(responseModelJson)); @@ -141,6 +150,9 @@ class RequestModel { responseStatus: responseStatus, message: message, responseModel: responseModel, + formDataList: formDataList != null + ? mapToFormRows(Map.from(formDataList)) + : null, ); } diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 07c5bf53..07a3eee4 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,8 +1,12 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'dart:math'; + +import 'package:apidash/consts.dart'; +import 'package:apidash/models/name_value_model.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/consts.dart'; +import 'package:davi/davi.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class EditRequestBody extends ConsumerStatefulWidget { const EditRequestBody({super.key}); @@ -12,12 +16,99 @@ class EditRequestBody extends ConsumerStatefulWidget { } class _EditRequestBodyState extends ConsumerState { + late List rows; + final random = Random.secure(); + late int seed; + @override + void initState() { + super.initState(); + seed = random.nextInt(kRandMax); + } + @override Widget build(BuildContext context) { final activeId = ref.watch(activeIdStateProvider); final requestModel = ref .read(collectionStateNotifierProvider.notifier) .getRequestModel(activeId!); + ContentType? requestBodyStateWatcher = (ref + .watch(collectionStateNotifierProvider)![activeId] + ?.requestBodyContentType) ?? + ContentType.values.first; + DaviModel model = DaviModel( + rows: rows, + columns: [ + DaviColumn( + name: 'Header Name', + grow: 1, + cellBuilder: (_, row) { + int idx = row.index; + return HeaderField( + keyId: "$activeId-$idx-headers-k-$seed", + initialValue: rows[idx].name, + hintText: "Add Header Name", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(name: value); + // _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + ); + }, + sortable: false, + ), + DaviColumn( + width: 30, + cellBuilder: (_, row) { + return Text( + "=", + style: kCodeStyle, + ); + }, + ), + DaviColumn( + name: 'Header Value', + grow: 1, + cellBuilder: (_, row) { + int idx = row.index; + return CellField( + keyId: "$activeId-$idx-headers-v-$seed", + initialValue: rows[idx].value, + hintText: " Add Header Value", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(value: value); + // _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + ); + }, + sortable: false, + ), + DaviColumn( + pinStatus: PinStatus.none, + width: 30, + cellBuilder: (_, row) { + return InkWell( + child: Theme.of(context).brightness == Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [ + kNameValueEmptyModel, + ]; + }); + } else { + rows.removeAt(row.index); + } + // _onFieldChange(activeId); + }, + ); + }, + ), + ], + ); return Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.background, @@ -38,16 +129,20 @@ class _EditRequestBodyState extends ConsumerState { ), ), Expanded( - child: TextFieldEditor( - key: Key("$activeId-body"), - fieldKey: "$activeId-body-editor", - initialValue: requestModel?.requestBody, - onChanged: (String value) { - ref - .read(collectionStateNotifierProvider.notifier) - .update(activeId, requestBody: value); - }, - ), + child: requestBodyStateWatcher == ContentType.formdata + ? Container( + child: const Text("Vidya"), + ) + : TextFieldEditor( + key: Key("$activeId-body"), + fieldKey: "$activeId-body-editor", + initialValue: requestModel?.requestBody, + onChanged: (String value) { + ref + .read(collectionStateNotifierProvider.notifier) + .update(activeId, requestBody: value); + }, + ), ) ], ), diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index e12f2dcc..97d8cc4d 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -1,7 +1,10 @@ -import 'dart:typed_data'; import 'dart:convert'; -import '../models/models.dart'; +import 'dart:typed_data'; + +import 'package:apidash/models/form_data_model.dart'; + import '../consts.dart'; +import '../models/models.dart'; String humanizeDuration(Duration? duration) { if (duration == null) { @@ -78,6 +81,17 @@ Map? rowsToMap(List? kvRows, return finalMap; } +Map? rowsToFormDataMap( + List? kvRows, +) { + if (kvRows == null) { + return null; + } + Map finalMap = {}; + for (var row in kvRows) {} + return finalMap; +} + List? mapToRows(Map? kvMap) { if (kvMap == null) { return null; @@ -89,6 +103,21 @@ List? mapToRows(Map? kvMap) { return finalRows; } +List? mapToFormRows(Map? kvMap) { + if (kvMap == null) { + return null; + } + List finalRows = []; + for (var k in kvMap.keys) { + finalRows.add(FormDataModel( + name: k, + value: kvMap[k], + type: FormDataType.text, + )); + } + return finalRows; +} + Uint8List? stringToBytes(String? text) { if (text == null) { return null; diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index e8290714..29f18b0a 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -1,6 +1,6 @@ -import 'package:flutter/material.dart'; -import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; +import 'package:apidash/utils/utils.dart'; +import 'package:flutter/material.dart'; class DropdownButtonHttpMethod extends StatefulWidget { const DropdownButtonHttpMethod({ From ffb9681958dccd721886958b36c5e9596866acc2 Mon Sep 17 00:00:00 2001 From: vidya-hub Date: Tue, 19 Dec 2023 23:29:47 +0530 Subject: [PATCH 034/123] wip: added necessary function to pick the files --- lib/consts.dart | 5 + lib/models/form_data_model.dart | 2 +- lib/models/request_model.dart | 11 +- lib/providers/collection_providers.dart | 35 ++-- lib/screens/home_page/collection_pane.dart | 70 ++++---- .../request_pane/request_body.dart | 165 ++++++++++++++---- lib/services/hive_services.dart | 5 +- lib/utils/convert_utils.dart | 28 +-- lib/utils/extensions/file_extension.dart | 5 + lib/widgets/dropdowns.dart | 51 ++++++ lib/widgets/form_data_field.dart | 87 +++++++++ pubspec.yaml | 1 + 12 files changed, 368 insertions(+), 97 deletions(-) create mode 100644 lib/utils/extensions/file_extension.dart create mode 100644 lib/widgets/form_data_field.dart diff --git a/lib/consts.dart b/lib/consts.dart index ef7ed6f4..05d0e6e8 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -58,6 +58,7 @@ const kP1 = EdgeInsets.all(1); const kP5 = EdgeInsets.all(5); const kP8 = EdgeInsets.all(8); const kPs8 = EdgeInsets.only(left: 8); +const kPs2 = EdgeInsets.only(left: 2); const kPh20v5 = EdgeInsets.symmetric(horizontal: 20, vertical: 5); const kPh20v10 = EdgeInsets.symmetric(horizontal: 20, vertical: 10); const kP10 = EdgeInsets.all(10); @@ -303,6 +304,10 @@ const kFormDataTypeMap = { FormDataType.file: "File", FormDataType.text: "Text", }; +const kMapFormDataType = { + "File": FormDataType.file, + "Text": FormDataType.text, +}; enum ResponseBodyView { preview, code, raw, none } diff --git a/lib/models/form_data_model.dart b/lib/models/form_data_model.dart index edbcd113..90991419 100644 --- a/lib/models/form_data_model.dart +++ b/lib/models/form_data_model.dart @@ -16,7 +16,7 @@ class FormDataModel with _$FormDataModel { _$FormDataModelFromJson(json); } -const kNameValueEmptyModel = FormDataModel( +const kFormDataEmptyModel = FormDataModel( name: "", value: "", type: FormDataType.text, diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index fda03ea1..2e58015a 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -150,9 +150,8 @@ class RequestModel { responseStatus: responseStatus, message: message, responseModel: responseModel, - formDataList: formDataList != null - ? mapToFormRows(Map.from(formDataList)) - : null, + formDataList: + formDataList != null ? listToFormDataModel(formDataList) : null, ); } @@ -170,6 +169,7 @@ class RequestModel { "responseStatus": includeResponse ? responseStatus : null, "message": includeResponse ? message : null, "responseModel": includeResponse ? responseModel?.toJson() : null, + "formDataList": rowsToFormDataMap(formDataList) }; } @@ -189,6 +189,7 @@ class RequestModel { "Response Status: $responseStatus", "Response Message: $message", "Response: ${responseModel.toString()}" + "FormData: ${formDataList.toString()}" ].join("\n"); } @@ -208,7 +209,8 @@ class RequestModel { other.requestBody == requestBody && other.responseStatus == responseStatus && other.message == message && - other.responseModel == responseModel; + other.responseModel == responseModel && + other.formDataList == formDataList; } @override @@ -228,6 +230,7 @@ class RequestModel { responseStatus, message, responseModel, + formDataList, ); } } diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index e0273a34..cd905e79 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,10 +1,12 @@ +import 'package:apidash/models/form_data_model.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'settings_providers.dart'; -import 'ui_providers.dart'; + +import '../consts.dart'; import '../models/models.dart'; import '../services/services.dart' show hiveHandler, HiveHandler, request; import '../utils/utils.dart' show uuid, collectionToHAR; -import '../consts.dart'; +import 'settings_providers.dart'; +import 'ui_providers.dart'; final activeIdStateProvider = StateProvider((ref) => null); @@ -128,20 +130,23 @@ class CollectionStateNotifier int? responseStatus, String? message, ResponseModel? responseModel, + List? formDataList, }) { final newModel = state![id]!.copyWith( - method: method, - url: url, - name: name, - description: description, - requestTabIndex: requestTabIndex, - requestHeaders: requestHeaders, - requestParams: requestParams, - requestBodyContentType: requestBodyContentType, - requestBody: requestBody, - responseStatus: responseStatus, - message: message, - responseModel: responseModel); + method: method, + url: url, + name: name, + description: description, + requestTabIndex: requestTabIndex, + requestHeaders: requestHeaders, + requestParams: requestParams, + requestBodyContentType: requestBodyContentType, + requestBody: requestBody, + responseStatus: responseStatus, + message: message, + responseModel: responseModel, + formDataList: formDataList, + ); //print(newModel); var map = {...state!}; map[id] = newModel; diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 0ea875fb..6f0b0bde 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,9 +1,9 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:apidash/consts.dart'; +import 'package:apidash/models/models.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/consts.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class CollectionPane extends ConsumerWidget { const CollectionPane({ @@ -108,36 +108,40 @@ class _RequestListState extends ConsumerState { controller: controller, thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), - child: ReorderableListView.builder( - padding: kPr8CollectionPane, - scrollController: controller, - buildDefaultDragHandles: false, - itemCount: requestSequence.length, - onReorder: (int oldIndex, int newIndex) { - if (oldIndex < newIndex) { - newIndex -= 1; - } - if (oldIndex != newIndex) { - ref - .read(collectionStateNotifierProvider.notifier) - .reorder(oldIndex, newIndex); - } - }, - itemBuilder: (context, index) { - var id = requestSequence[index]; - return ReorderableDragStartListener( - key: ValueKey(id), - index: index, - child: Padding( - padding: kP1, - child: RequestItem( - id: id, - requestModel: requestItems[id]!, - ), + child: requestSequence.isNotEmpty + ? ReorderableListView.builder( + padding: kPr8CollectionPane, + scrollController: controller, + buildDefaultDragHandles: false, + itemCount: requestSequence.length, + onReorder: (int oldIndex, int newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + if (oldIndex != newIndex) { + ref + .read(collectionStateNotifierProvider.notifier) + .reorder(oldIndex, newIndex); + } + }, + itemBuilder: (context, index) { + var id = requestSequence[index]; + return ReorderableDragStartListener( + key: ValueKey(id), + index: index, + child: Padding( + padding: kP1, + child: RequestItem( + id: id, + requestModel: requestItems[id]!, + ), + ), + ); + }, + ) + : const Center( + child: Text("No Requests found"), ), - ); - }, - ), ); } } diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 07a3eee4..da1d15d7 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,10 +1,13 @@ import 'dart:math'; import 'package:apidash/consts.dart'; -import 'package:apidash/models/name_value_model.dart'; +import 'package:apidash/models/form_data_model.dart'; import 'package:apidash/providers/providers.dart'; +import 'package:apidash/utils/extensions/file_extension.dart'; +import 'package:apidash/widgets/form_data_field.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:davi/davi.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -16,13 +19,15 @@ class EditRequestBody extends ConsumerStatefulWidget { } class _EditRequestBodyState extends ConsumerState { - late List rows; + List rows = []; final random = Random.secure(); late int seed; + late FilePicker filePicker; @override void initState() { super.initState(); seed = random.nextInt(kRandMax); + filePicker = FilePicker.platform; } @override @@ -35,29 +40,41 @@ class _EditRequestBodyState extends ConsumerState { .watch(collectionStateNotifierProvider)![activeId] ?.requestBodyContentType) ?? ContentType.values.first; - DaviModel model = DaviModel( + DaviModel model = DaviModel( rows: rows, columns: [ DaviColumn( - name: 'Header Name', + name: 'Key', grow: 1, cellBuilder: (_, row) { int idx = row.index; - return HeaderField( - keyId: "$activeId-$idx-headers-k-$seed", - initialValue: rows[idx].name, - hintText: "Add Header Name", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(name: value); - // _onFieldChange(activeId); - }, - colorScheme: Theme.of(context).colorScheme, + return SizedBox( + child: FormDataField( + keyId: "$activeId-$idx-form-v-$seed", + initialValue: rows[idx].value, + hintText: " Key", + onChanged: (value) { + rows[idx] = rows[idx].copyWith( + name: value, + ); + _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + formDataType: rows[idx].type, + onFormDataTypeChanged: (value) { + rows[idx] = rows[idx].copyWith( + type: value ?? FormDataType.text, + ); + rows[idx] = rows[idx].copyWith(value: ""); + _onFieldChange(activeId); + }, + ), ); }, sortable: false, ), DaviColumn( - width: 30, + width: 10, cellBuilder: (_, row) { return Text( "=", @@ -66,20 +83,66 @@ class _EditRequestBodyState extends ConsumerState { }, ), DaviColumn( - name: 'Header Value', - grow: 1, + name: 'Value', + grow: 4, cellBuilder: (_, row) { int idx = row.index; - return CellField( - keyId: "$activeId-$idx-headers-v-$seed", - initialValue: rows[idx].value, - hintText: " Add Header Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - // _onFieldChange(activeId); - }, - colorScheme: Theme.of(context).colorScheme, - ); + return rows[idx].type == FormDataType.file + ? Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: kPs2, + child: Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () async { + FilePickerResult? pickedResult = + await filePicker.pickFiles(); + if (pickedResult != null && + pickedResult.files.isNotEmpty) { + rows[idx] = rows[idx].copyWith( + value: pickedResult.files.first.path, + ); + _onFieldChange(activeId); + } + }, + child: Text( + "Select File", + style: kTextStyleButton.copyWith( + fontSize: 10, + ), + ), + ), + ), + Expanded( + child: Padding( + padding: kPs2, + child: Text( + rows[idx].type == FormDataType.file + ? (rows[idx].value != null + ? rows[idx].value.toString().fileName + : "") + : "", + style: kTextStyleButton, + overflow: TextOverflow.ellipsis, + ), + ), + ) + ], + ), + ), + ) + : CellField( + keyId: "$activeId-$idx-form-v-$seed", + initialValue: rows[idx].value, + hintText: " Value", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(value: value); + _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + ); }, sortable: false, ), @@ -96,13 +159,13 @@ class _EditRequestBodyState extends ConsumerState { if (rows.length == 1) { setState(() { rows = [ - kNameValueEmptyModel, + kFormDataEmptyModel, ]; }); } else { rows.removeAt(row.index); } - // _onFieldChange(activeId); + _onFieldChange(activeId); }, ); }, @@ -130,8 +193,43 @@ class _EditRequestBodyState extends ConsumerState { ), Expanded( child: requestBodyStateWatcher == ContentType.formdata - ? Container( - child: const Text("Vidya"), + ? Stack( + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: kBorderRadius12, + ), + margin: kP10, + child: Column( + children: [ + Expanded( + child: DaviTheme( + data: kTableThemeData, + child: Davi(model), + ), + ), + ], + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(bottom: 30), + child: ElevatedButton.icon( + onPressed: () { + rows.add(kFormDataEmptyModel); + _onFieldChange(activeId); + }, + icon: const Icon(Icons.add), + label: const Text( + "Add Form Data", + style: kTextStyleButton, + ), + ), + ), + ), + ], ) : TextFieldEditor( key: Key("$activeId-body"), @@ -148,6 +246,13 @@ class _EditRequestBodyState extends ConsumerState { ), ); } + + void _onFieldChange(String activeId) { + ref.read(collectionStateNotifierProvider.notifier).update( + activeId, + formDataList: rows, + ); + } } class DropdownButtonBodyContentType extends ConsumerStatefulWidget { diff --git a/lib/services/hive_services.dart b/lib/services/hive_services.dart index 3052024e..9d7b108c 100644 --- a/lib/services/hive_services.dart +++ b/lib/services/hive_services.dart @@ -48,8 +48,9 @@ class HiveHandler { dynamic getRequestModel(String id) => dataBox.get(id); Future setRequestModel( - String id, Map? requestModelJson) => - dataBox.put(id, requestModelJson); + String id, Map? requestModelJson) { + return dataBox.put(id, requestModelJson); + } Future clear() => dataBox.clear(); diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 97d8cc4d..81c5bff8 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -81,14 +81,19 @@ Map? rowsToMap(List? kvRows, return finalMap; } -Map? rowsToFormDataMap( +List>? rowsToFormDataMap( List? kvRows, ) { if (kvRows == null) { return null; } - Map finalMap = {}; - for (var row in kvRows) {} + List> finalMap = kvRows + .map((FormDataModel formData) => { + "name": formData.name, + "value": formData.value, + "type": formData.type.name, + }) + .toList(); return finalMap; } @@ -103,18 +108,17 @@ List? mapToRows(Map? kvMap) { return finalRows; } -List? mapToFormRows(Map? kvMap) { +List? listToFormDataModel(List? kvMap) { if (kvMap == null) { return null; } - List finalRows = []; - for (var k in kvMap.keys) { - finalRows.add(FormDataModel( - name: k, - value: kvMap[k], - type: FormDataType.text, - )); - } + List finalRows = kvMap + .map((formData) => FormDataModel( + name: formData["name"], + value: formData["value"], + type: kMapFormDataType[formData["type"]] ?? FormDataType.text, + )) + .toList(); return finalRows; } diff --git a/lib/utils/extensions/file_extension.dart b/lib/utils/extensions/file_extension.dart new file mode 100644 index 00000000..797a2ec9 --- /dev/null +++ b/lib/utils/extensions/file_extension.dart @@ -0,0 +1,5 @@ +extension FileExtension on String { + String get fileName { + return split(r'\').last; + } +} diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index 29f18b0a..98bd10d4 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -110,6 +110,57 @@ class _DropdownButtonContentTypeState extends State { } } +class DropdownButtonFormData extends StatefulWidget { + const DropdownButtonFormData({ + super.key, + this.formDataType, + this.onChanged, + }); + + final FormDataType? formDataType; + final void Function(FormDataType?)? onChanged; + + @override + State createState() => _DropdownButtonFormData(); +} + +class _DropdownButtonFormData extends State { + @override + Widget build(BuildContext context) { + final surfaceColor = Theme.of(context).colorScheme.surface; + return DropdownButton( + focusColor: surfaceColor, + value: widget.formDataType, + icon: const Icon( + Icons.unfold_more_rounded, + size: 16, + ), + elevation: 4, + style: kCodeStyle.copyWith( + color: Theme.of(context).colorScheme.primary, + ), + underline: Container( + height: 0, + ), + onChanged: widget.onChanged, + borderRadius: kBorderRadius12, + items: FormDataType.values + .map>((FormDataType value) { + return DropdownMenuItem( + value: value, + child: Padding( + padding: kPs8, + child: Text( + value.name, + style: kTextStyleButton, + ), + ), + ); + }).toList(), + ); + } +} + class DropdownButtonCodegenLanguage extends StatefulWidget { const DropdownButtonCodegenLanguage({ super.key, diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart new file mode 100644 index 00000000..d00dd70b --- /dev/null +++ b/lib/widgets/form_data_field.dart @@ -0,0 +1,87 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/widgets/widgets.dart'; +import 'package:flutter/material.dart'; + +class FormDataField extends StatefulWidget { + const FormDataField({ + super.key, + required this.keyId, + this.initialValue, + this.hintText, + this.onChanged, + this.colorScheme, + this.formDataType, + this.onFormDataTypeChanged, + }); + + final String keyId; + final String? initialValue; + final String? hintText; + final void Function(String)? onChanged; + final ColorScheme? colorScheme; + final FormDataType? formDataType; + final void Function(FormDataType?)? onFormDataTypeChanged; + + @override + State createState() => _FormDataFieldState(); +} + +class _FormDataFieldState extends State { + TextEditingController valueController = TextEditingController(); + @override + void initState() { + valueController.text = widget.initialValue ?? ""; + super.initState(); + } + + @override + Widget build(BuildContext context) { + var colorScheme = widget.colorScheme ?? Theme.of(context).colorScheme; + return Row( + children: [ + Expanded( + flex: 1, + child: TextFormField( + controller: valueController, + key: Key(widget.keyId), + style: kCodeStyle.copyWith( + color: colorScheme.onSurface, + ), + decoration: InputDecoration( + hintStyle: kCodeStyle.copyWith( + color: colorScheme.outline.withOpacity( + kHintOpacity, + ), + ), + hintText: widget.hintText, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: colorScheme.primary.withOpacity( + kHintOpacity, + ), + ), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: colorScheme.surfaceVariant, + ), + ), + ), + onChanged: widget.onChanged, + ), + ), + Expanded( + child: DropdownButtonFormData( + formDataType: widget.formDataType, + onChanged: (p0) { + if (widget.onFormDataTypeChanged != null) { + widget.onFormDataTypeChanged!(p0); + valueController.clear(); + } + }, + ), + ) + ], + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 96ab5fbf..0d696d1d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: url: https://github.com/foss42/json_data_explorer.git version: ^0.1.1 scrollable_positioned_list: ^0.2.3 + file_picker: ^6.1.1 dev_dependencies: flutter_test: From 73f415c667e60d7da1de70de0bc19d975857aeb9 Mon Sep 17 00:00:00 2001 From: laiiihz Date: Wed, 20 Dec 2023 17:31:42 +0800 Subject: [PATCH 035/123] feat:add dio code gen --- lib/codegen/codegen.dart | 3 + lib/codegen/dart/dio.dart | 125 +++++++++++++++++++++++++ lib/codegen/dart/shared.dart | 26 ++++++ lib/consts.dart | 1 + pubspec.lock | 172 +++++++++++++++++------------------ pubspec.yaml | 2 + 6 files changed, 243 insertions(+), 86 deletions(-) create mode 100644 lib/codegen/dart/dio.dart create mode 100644 lib/codegen/dart/shared.dart diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 356854f6..45b72014 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -1,6 +1,7 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; import 'dart/http.dart'; +import 'dart/dio.dart'; import 'kotlin/okhttp.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; @@ -22,6 +23,8 @@ class Codegen { return HARCodeGen().getCode(requestModel, defaultUriScheme); case CodegenLanguage.dartHttp: return DartHttpCodeGen().getCode(requestModel, defaultUriScheme); + case CodegenLanguage.dartDio: + return DartDioCodeGen().getCode(requestModel, defaultUriScheme); case CodegenLanguage.jsAxios: return AxiosCodeGen().getCode(requestModel, defaultUriScheme); case CodegenLanguage.jsFetch: diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart new file mode 100644 index 00000000..7c603716 --- /dev/null +++ b/lib/codegen/dart/dio.dart @@ -0,0 +1,125 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/models/request_model.dart' show RequestModel; +import 'package:code_builder/code_builder.dart'; +import 'package:dart_style/dart_style.dart'; + +import 'shared.dart'; + +class DartDioCodeGen { + String? getCode( + RequestModel requestModel, + String defaultUriScheme, + ) { + try { + String url = requestModel.url; + if (!url.contains("://") && url.isNotEmpty) { + url = "$defaultUriScheme://$url"; + } + final next = generatedDartCode( + url: url, + method: requestModel.method.name, + queryParams: requestModel.paramsMap, + headers: requestModel.headersMap, + body: requestModel.requestBody, + contentType: requestModel.requestBodyContentType, + ); + return next; + } catch (e) { + return null; + } + } + + String generatedDartCode({ + required String url, + required String method, + required Map queryParams, + required Map headers, + required String? body, + required ContentType contentType, + }) { + final sbf = StringBuffer(); + final emitter = DartEmitter(); + final dioImport = Directive.import('package:dio/dio.dart', as: 'dio'); + sbf.writeln(dioImport.accept(emitter)); + + Expression? queryParamExp; + if (queryParams.isNotEmpty) { + queryParamExp = declareFinal('queryParams').assign( + literalMap(queryParams.map((key, value) => MapEntry(key, value))), + ); + } + Expression? headerExp; + if (headers.isNotEmpty) { + headerExp = declareFinal('headers').assign( + literalMap(headers.map((key, value) => MapEntry(key, value))), + ); + } + + Expression? dataExp; + if (body != null) { + final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); + switch (contentType) { + case ContentType.json: + final convertImport = Directive.import('dart:convert', as: 'convert'); + sbf.writeln(convertImport.accept(emitter)); + dataExp = declareFinal('data') + .assign(refer('convert.json.decode').call([strContent])); + case ContentType.text: + dataExp = declareFinal('data').assign(strContent); + } + } + final responseExp = declareFinal('response').assign(InvokeExpression.newOf( + refer('dio.Dio'), + [literalString(url)], + { + if (queryParamExp != null) 'queryParameters': refer('queryParams'), + if (headerExp != null) + 'options': refer('Options').newInstance( + [], + {'headers': refer('headers')}, + ), + if (dataExp != null) 'data': refer('data'), + }, + [], + method, + ).awaited); + + final mainFunction = Method((m) { + final content = declareTryCatch( + showStackStrace: true, + body: [ + if (queryParamExp != null) queryParamExp, + if (headerExp != null) headerExp, + if (dataExp != null) dataExp, + responseExp, + refer('print').call([refer('response').property('statusCode')]), + refer('print').call([refer('response').property('data')]), + ], + onError: { + 'DioException': [ + refer('print').call([ + refer('e').property('response').nullSafeProperty('statusCode'), + ]), + refer('print').call([ + refer('e').property('response').nullSafeProperty('data'), + ]), + refer('print').call([refer('s')]), + ], + null: [ + refer('print').call([refer('e')]), + refer('print').call([refer('s')]), + ], + }, + ); + m + ..name = 'main' + ..returns = refer('void') + ..modifier = MethodModifier.async + ..body = content; + }); + + sbf.writeln(mainFunction.accept(emitter)); + + return DartFormatter(pageWidth: 160).format(sbf.toString()); + } +} diff --git a/lib/codegen/dart/shared.dart b/lib/codegen/dart/shared.dart new file mode 100644 index 00000000..9938750c --- /dev/null +++ b/lib/codegen/dart/shared.dart @@ -0,0 +1,26 @@ +import 'package:code_builder/code_builder.dart'; + +Block declareTryCatch({ + required List body, + required Map> onError, + bool showStackStrace = false, +}) { + return Block((b) { + b.statements.add(const Code('try')); + b.statements.add(const Code('{')); + b.statements.addAll(body.map((e) => e.statement).toList()); + final entries = onError.entries; + + for (var error in entries) { + b.statements.add(const Code('}')); + if (error.key != null) { + b.statements.add(Code('on ${error.key}')); + } + b.statements.add(Code(showStackStrace ? 'catch(e,s)' : 'catch(e)')); + + b.statements.add(const Code('{')); + b.statements.addAll(error.value.map((e) => e.statement).toList()); + if (entries.last.key == error.key) b.statements.add(const Code('}')); + } + }); +} diff --git a/lib/consts.dart b/lib/consts.dart index 895c0460..ff44e9f5 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -242,6 +242,7 @@ enum CodegenLanguage { curl("cURL", "bash", "curl"), har("HAR", "json", "har"), dartHttp("Dart (http)", "dart", "dart"), + dartDio("Dart (dio)", "dart", "dart"), jsAxios("JavaScript (axios)", "javascript", "js"), jsFetch("JavaScript (fetch)", "javascript", "js"), nodejsAxios("node.js (axios)", "javascript", "js"), diff --git a/pubspec.lock b/pubspec.lock index 190d8316..1845e975 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,26 +5,26 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 url: "https://pub.dev" source: hosted - version: "61.0.0" + version: "64.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" url: "https://pub.dev" source: hosted - version: "5.13.0" + version: "6.2.0" archive: dependency: transitive description: name: archive - sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03" + sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" url: "https://pub.dev" source: hosted - version: "3.4.6" + version: "3.4.9" args: dependency: transitive description: @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: audio_session - sha256: "8a2bc5e30520e18f3fb0e366793d78057fb64cd5287862c76af0c8771f2a52ad" + sha256: "6fdf255ed3af86535c96452c33ecff1245990bb25a605bfb1958661ccc3d467f" url: "https://pub.dev" source: hosted - version: "0.1.16" + version: "0.1.18" axis_layout: dependency: transitive description: @@ -61,10 +61,10 @@ packages: dependency: transitive description: name: barcode - sha256: "789f898eef0bd88312470bdb2cc996f895ad7dd5f89e9adde84b204546a90b45" + sha256: "2a8b2ee065f419c2aeda141436cc556d91ae772d220fd80679f4d431d6c2ab43" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.5" bidi: dependency: transitive description: @@ -101,26 +101,26 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.7" build_runner_core: dependency: transitive description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: built_value - sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74 + sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 url: "https://pub.dev" source: hosted - version: "8.6.3" + version: "8.8.1" characters: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: cli_util - sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.4.1" clock: dependency: transitive description: @@ -178,13 +178,13 @@ packages: source: hosted version: "1.1.1" code_builder: - dependency: transitive + dependency: "direct main" description: name: code_builder - sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" + sha256: feee43a5c05e7b3199bb375a86430b8ada1b04104f2923d0e03cc01ca87b6d84 url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.9.0" collection: dependency: "direct main" description: @@ -205,10 +205,10 @@ packages: dependency: transitive description: name: coverage - sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.4" + version: "1.7.2" crypto: dependency: transitive description: @@ -218,13 +218,13 @@ packages: source: hosted version: "3.0.3" dart_style: - dependency: transitive + dependency: "direct main" description: name: dart_style - sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.4" davi: dependency: "direct main" description: @@ -338,26 +338,26 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: ad76540d21c066228ee3f9d1dad64a9f7e46530e8bb7c85011a88bc1fd874bc5 + sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" flutter_markdown: dependency: "direct main" description: name: flutter_markdown - sha256: "8afc9a6aa6d8e8063523192ba837149dbf3d377a37c0b0fc579149a1fbd4a619" + sha256: "35108526a233cc0755664d445f8a6b4b61e6f8fe993b3658b80b4a26827fc196" url: "https://pub.dev" source: hosted - version: "0.6.18" + version: "0.6.18+2" flutter_riverpod: dependency: "direct main" description: name: flutter_riverpod - sha256: bdba94be666ecb1beeb0f5a748d96cdd6a37215f27e6b48c7673b95cecb800c8 + sha256: da9591d1f8d5881628ccd5c25c40e74fc3eef50ba45e40c3905a06e1712412d5 url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.9" flutter_svg: dependency: "direct main" description: @@ -388,10 +388,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "21bf2825311de65501d22e563e3d7605dff57fb5e6da982db785ae5372ff018a" + sha256: "6c5031daae12c7072b3a87eff98983076434b4889ef2a44384d0cae3f82372ba" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.6" freezed_annotation: dependency: "direct main" description: @@ -468,10 +468,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" http_multi_server: dependency: transitive description: @@ -549,10 +549,10 @@ packages: dependency: "direct main" description: name: just_audio - sha256: "5ed0cd723e17dfd8cd4b0253726221e67f6546841ea4553635cf895061fc335b" + sha256: b607cd1a43bac03d85c3aaee00448ff4a589ef2a77104e3d409889ff079bf823 url: "https://pub.dev" source: hosted - version: "0.9.35" + version: "0.9.36" just_audio_mpv: dependency: "direct main" description: @@ -565,18 +565,18 @@ packages: dependency: transitive description: name: just_audio_platform_interface - sha256: d8409da198bbc59426cd45d4c92fca522a2ec269b576ce29459d6d6fcaeb44df + sha256: c3dee0014248c97c91fe6299edb73dc4d6c6930a2f4f713579cd692d9e47f4a1 url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.2.2" just_audio_web: dependency: transitive description: name: just_audio_web - sha256: ff62f733f437b25a0ff590f0e295fa5441dcb465f1edbdb33b3dea264705bc13 + sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70" url: "https://pub.dev" source: hosted - version: "0.4.8" + version: "0.4.9" just_audio_windows: dependency: "direct main" description: @@ -741,10 +741,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_foundation: dependency: transitive description: @@ -781,18 +781,18 @@ packages: dependency: transitive description: name: pdf - sha256: "9f75fc7f5580ea5e635b5724de58fb27f684c9ad03ed46fdc1aac768e4557315" + sha256: "93cbb2c06de9bab91844550f19896b2373e7a5ce25173995e7e5ec5e1741429d" url: "https://pub.dev" source: hosted - version: "3.10.4" + version: "3.10.7" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" platform: dependency: transitive description: @@ -805,18 +805,18 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" pointer_interceptor: dependency: transitive description: name: pointer_interceptor - sha256: "7626e034489820fd599380d2bb4d3f4a0a5e3529370b62bfce53ab736b91adb2" + sha256: adf7a637f97c077041d36801b43be08559fd4322d2127b3f20bb7be1b9eebc22 url: "https://pub.dev" source: hosted - version: "0.9.3+6" + version: "0.9.3+7" pointycastle: dependency: transitive description: @@ -845,10 +845,10 @@ packages: dependency: "direct main" description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.1" pub_semver: dependency: transitive description: @@ -877,10 +877,10 @@ packages: dependency: transitive description: name: riverpod - sha256: "2af3d127a6e4e34b89b8f1f018086f5ded04b8e538174f0510bba3e4c0d878b1" + sha256: "942999ee48b899f8a46a860f1e13cee36f2f77609eb54c5b7a669bb20d550b11" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.9" rxdart: dependency: transitive description: @@ -946,10 +946,10 @@ packages: dependency: transitive description: name: source_gen - sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" source_helper: dependency: transitive description: @@ -1090,74 +1090,74 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 url: "https://pub.dev" source: hosted - version: "6.1.14" + version: "6.2.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.2.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" + sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" url: "https://pub.dev" source: hosted - version: "2.0.20" + version: "2.2.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.1.1" uuid: dependency: "direct main" description: name: uuid - sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 + sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.2.2" vector_graphics: dependency: transitive description: @@ -1194,10 +1194,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "13.0.0" watcher: dependency: transitive description: @@ -1234,10 +1234,10 @@ packages: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.1.1" window_manager: dependency: "direct main" description: @@ -1267,10 +1267,10 @@ packages: dependency: "direct main" description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" yaml: dependency: transitive description: @@ -1280,5 +1280,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index b02083ae..a32322ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,8 @@ dependencies: scrollable_positioned_list: ^0.2.3 flutter_svg: ^2.0.9 vector_graphics_compiler: ^1.1.9+1 + code_builder: ^4.9.0 + dart_style: ^2.3.4 dev_dependencies: flutter_test: From c04507f93a76bfaed6603b247597f726e83ed306 Mon Sep 17 00:00:00 2001 From: vidya-hub Date: Wed, 20 Dec 2023 21:51:27 +0530 Subject: [PATCH 036/123] feat: Multi Part Request Feature Added --- lib/consts.dart | 8 +- lib/providers/collection_providers.dart | 19 +- .../request_pane/request_body.dart | 190 +--------------- lib/services/http_service.dart | 64 +++++- lib/utils/convert_utils.dart | 18 ++ lib/widgets/form_data_widget.dart | 212 ++++++++++++++++++ 6 files changed, 316 insertions(+), 195 deletions(-) create mode 100644 lib/widgets/form_data_widget.dart diff --git a/lib/consts.dart b/lib/consts.dart index 05d0e6e8..cba29ab6 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -301,12 +301,12 @@ const kContentTypeMap = { ContentType.formdata: "multipart/form-data", }; const kFormDataTypeMap = { - FormDataType.file: "File", - FormDataType.text: "Text", + FormDataType.file: "file", + FormDataType.text: "text", }; const kMapFormDataType = { - "File": FormDataType.file, - "Text": FormDataType.text, + "file": FormDataType.file, + "text": FormDataType.text, }; enum ResponseBodyView { preview, code, raw, none } diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index cd905e79..dc059913 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,5 +1,7 @@ import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/services/http_service.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:http/http.dart' as http; import '../consts.dart'; import '../models/models.dart'; @@ -158,10 +160,20 @@ class CollectionStateNotifier ref.read(codePaneVisibleStateProvider.notifier).state = false; final defaultUriScheme = ref.read(settingsProvider.select((value) => value.defaultUriScheme)); - + (http.Response?, Duration?, String?)? responseRec; RequestModel requestModel = state![id]!; - var responseRec = - await request(requestModel, defaultUriScheme: defaultUriScheme); + if (requestModel.formDataList != null && + requestModel.formDataList!.isNotEmpty) { + responseRec = await multiPartRequest( + requestModel, + defaultUriScheme: defaultUriScheme, + ); + } else { + responseRec = await request( + requestModel, + defaultUriScheme: defaultUriScheme, + ); + } late final RequestModel newRequestModel; if (responseRec.$1 == null) { newRequestModel = requestModel.copyWith( @@ -180,7 +192,6 @@ class CollectionStateNotifier responseModel: responseModel, ); } - //print(newRequestModel); ref.read(sentRequestIdStateProvider.notifier).state = null; var map = {...state!}; map[id] = newRequestModel; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index da1d15d7..21dd63c6 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,13 +1,9 @@ import 'dart:math'; import 'package:apidash/consts.dart'; -import 'package:apidash/models/form_data_model.dart'; import 'package:apidash/providers/providers.dart'; -import 'package:apidash/utils/extensions/file_extension.dart'; -import 'package:apidash/widgets/form_data_field.dart'; +import 'package:apidash/widgets/form_data_widget.dart'; import 'package:apidash/widgets/widgets.dart'; -import 'package:davi/davi.dart'; -import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -19,15 +15,12 @@ class EditRequestBody extends ConsumerStatefulWidget { } class _EditRequestBodyState extends ConsumerState { - List rows = []; final random = Random.secure(); late int seed; - late FilePicker filePicker; @override void initState() { super.initState(); seed = random.nextInt(kRandMax); - filePicker = FilePicker.platform; } @override @@ -40,138 +33,6 @@ class _EditRequestBodyState extends ConsumerState { .watch(collectionStateNotifierProvider)![activeId] ?.requestBodyContentType) ?? ContentType.values.first; - DaviModel model = DaviModel( - rows: rows, - columns: [ - DaviColumn( - name: 'Key', - grow: 1, - cellBuilder: (_, row) { - int idx = row.index; - return SizedBox( - child: FormDataField( - keyId: "$activeId-$idx-form-v-$seed", - initialValue: rows[idx].value, - hintText: " Key", - onChanged: (value) { - rows[idx] = rows[idx].copyWith( - name: value, - ); - _onFieldChange(activeId); - }, - colorScheme: Theme.of(context).colorScheme, - formDataType: rows[idx].type, - onFormDataTypeChanged: (value) { - rows[idx] = rows[idx].copyWith( - type: value ?? FormDataType.text, - ); - rows[idx] = rows[idx].copyWith(value: ""); - _onFieldChange(activeId); - }, - ), - ); - }, - sortable: false, - ), - DaviColumn( - width: 10, - cellBuilder: (_, row) { - return Text( - "=", - style: kCodeStyle, - ); - }, - ), - DaviColumn( - name: 'Value', - grow: 4, - cellBuilder: (_, row) { - int idx = row.index; - return rows[idx].type == FormDataType.file - ? Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: kPs2, - child: Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: () async { - FilePickerResult? pickedResult = - await filePicker.pickFiles(); - if (pickedResult != null && - pickedResult.files.isNotEmpty) { - rows[idx] = rows[idx].copyWith( - value: pickedResult.files.first.path, - ); - _onFieldChange(activeId); - } - }, - child: Text( - "Select File", - style: kTextStyleButton.copyWith( - fontSize: 10, - ), - ), - ), - ), - Expanded( - child: Padding( - padding: kPs2, - child: Text( - rows[idx].type == FormDataType.file - ? (rows[idx].value != null - ? rows[idx].value.toString().fileName - : "") - : "", - style: kTextStyleButton, - overflow: TextOverflow.ellipsis, - ), - ), - ) - ], - ), - ), - ) - : CellField( - keyId: "$activeId-$idx-form-v-$seed", - initialValue: rows[idx].value, - hintText: " Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(activeId); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - pinStatus: PinStatus.none, - width: 30, - cellBuilder: (_, row) { - return InkWell( - child: Theme.of(context).brightness == Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [ - kFormDataEmptyModel, - ]; - }); - } else { - rows.removeAt(row.index); - } - _onFieldChange(activeId); - }, - ); - }, - ), - ], - ); return Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.background, @@ -193,43 +54,11 @@ class _EditRequestBodyState extends ConsumerState { ), Expanded( child: requestBodyStateWatcher == ContentType.formdata - ? Stack( - children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - borderRadius: kBorderRadius12, - ), - margin: kP10, - child: Column( - children: [ - Expanded( - child: DaviTheme( - data: kTableThemeData, - child: Davi(model), - ), - ), - ], - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.only(bottom: 30), - child: ElevatedButton.icon( - onPressed: () { - rows.add(kFormDataEmptyModel); - _onFieldChange(activeId); - }, - icon: const Icon(Icons.add), - label: const Text( - "Add Form Data", - style: kTextStyleButton, - ), - ), - ), - ), - ], + ? FormDataWidget( + seed: seed, + onFormDataRemove: () { + seed = random.nextInt(kRandMax); + }, ) : TextFieldEditor( key: Key("$activeId-body"), @@ -246,13 +75,6 @@ class _EditRequestBodyState extends ConsumerState { ), ); } - - void _onFieldChange(String activeId) { - ref.read(collectionStateNotifierProvider.notifier).update( - activeId, - formDataList: rows, - ); - } } class DropdownButtonBodyContentType extends ConsumerStatefulWidget { diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 8265a299..d49656a0 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:http/http.dart' as http; -import 'package:apidash/utils/utils.dart'; -import 'package:apidash/models/models.dart'; + import 'package:apidash/consts.dart'; +import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/utils/utils.dart'; +import 'package:http/http.dart' as http; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { @@ -63,3 +65,59 @@ Future<(http.Response?, Duration?, String?)> request( return (null, null, uriRec.$2); } } + +Future<(http.Response?, Duration?, String?)> multiPartRequest( + RequestModel requestModel, { + String defaultUriScheme = kDefaultUriScheme, +}) async { + (Uri?, String?) uriRec = getValidRequestUri( + requestModel.url, + requestModel.requestParams, + defaultUriScheme: defaultUriScheme, + ); + if (uriRec.$1 != null) { + Uri requestUrl = uriRec.$1!; + Map headers = requestModel.headersMap; + try { + var requestBody = requestModel.requestBody; + if (kMethodsWithBody.contains(requestModel.method) && + requestBody != null) { + var contentLength = utf8.encode(requestBody).length; + if (contentLength > 0) { + headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + } + } + Stopwatch stopwatch = Stopwatch()..start(); + + var request = http.MultipartRequest( + requestModel.method.name.toUpperCase(), + requestUrl, + ); + for (FormDataModel formData in (requestModel.formDataList ?? [])) { + if (formData.type == FormDataType.text) { + request.fields.addAll({formData.name: formData.value}); + } else { + request.files.add( + await http.MultipartFile.fromPath( + formData.name, + formData.value, + ), + ); + } + } + + http.StreamedResponse response = await request.send(); + + stopwatch.stop(); + http.Response convertedHttpResponse = + await convertStreamedResponse(response); + return (convertedHttpResponse, stopwatch.elapsed, null); + } catch (e) { + return (null, null, e.toString()); + } + } else { + return (null, null, uriRec.$2); + } +} diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 81c5bff8..63b1f3eb 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:apidash/models/form_data_model.dart'; +import 'package:http/http.dart' as http; import '../consts.dart'; import '../models/models.dart'; @@ -142,3 +143,20 @@ Uint8List jsonMapToBytes(Map? map) { return bytes; } } + +Future convertStreamedResponse( + http.StreamedResponse streamedResponse, +) async { + Uint8List bodyBytes = await streamedResponse.stream.toBytes(); + + http.Response response = http.Response.bytes( + bodyBytes, + streamedResponse.statusCode, + headers: streamedResponse.headers, + persistentConnection: streamedResponse.persistentConnection, + reasonPhrase: streamedResponse.reasonPhrase, + request: streamedResponse.request, + ); + + return response; +} diff --git a/lib/widgets/form_data_widget.dart b/lib/widgets/form_data_widget.dart new file mode 100644 index 00000000..85318d70 --- /dev/null +++ b/lib/widgets/form_data_widget.dart @@ -0,0 +1,212 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/providers/collection_providers.dart'; +import 'package:apidash/widgets/form_data_field.dart'; +import 'package:apidash/widgets/textfields.dart'; +import 'package:davi/davi.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class FormDataWidget extends ConsumerStatefulWidget { + const FormDataWidget({ + super.key, + required this.seed, + required this.onFormDataRemove, + }); + final int seed; + final Function onFormDataRemove; + @override + ConsumerState createState() => _FormDataBodyState(); +} + +class _FormDataBodyState extends ConsumerState { + @override + Widget build(BuildContext context) { + final activeId = ref.watch(activeIdStateProvider); + final requestModel = ref + .read(collectionStateNotifierProvider.notifier) + .getRequestModel(activeId!); + List rows = requestModel?.formDataList ?? []; + DaviModel model = DaviModel( + rows: rows, + columns: [ + DaviColumn( + name: 'Key', + grow: 1, + cellBuilder: (_, row) { + int idx = row.index; + return SizedBox( + child: FormDataField( + keyId: "$activeId-$idx-form-v-${widget.seed}", + initialValue: rows[idx].name, + hintText: " Key", + onChanged: (value) { + rows[idx] = rows[idx].copyWith( + name: value, + ); + _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + formDataType: rows[idx].type, + onFormDataTypeChanged: (value) { + rows[idx] = rows[idx].copyWith( + type: value ?? FormDataType.text, + ); + rows[idx] = rows[idx].copyWith(value: ""); + _onFieldChange(activeId); + }, + ), + ); + }, + sortable: false, + ), + DaviColumn( + width: 10, + cellBuilder: (_, row) { + return Text( + "=", + style: kCodeStyle, + ); + }, + ), + DaviColumn( + name: 'Value', + grow: 4, + cellBuilder: (_, row) { + int idx = row.index; + return rows[idx].type == FormDataType.file + ? Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: kPs8, + child: Row( + children: [ + Expanded( + child: ElevatedButtonTheme( + data: const ElevatedButtonThemeData(), + child: ElevatedButton.icon( + onPressed: () async { + FilePickerResult? pickedResult = + await FilePicker.platform.pickFiles(); + if (pickedResult != null && + pickedResult.files.isNotEmpty) { + rows[idx] = rows[idx].copyWith( + value: pickedResult.files.first.path, + ); + _onFieldChange(activeId); + } + }, + icon: const Icon( + Icons.snippet_folder_rounded, + size: 18, + ), + label: Text( + rows[idx].type == FormDataType.file + ? (rows[idx].value != null + ? rows[idx].value.toString() + : "Select File") + : "Select File", + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: kTextStyleButton.copyWith( + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + ], + ), + ), + ) + : CellField( + keyId: "$activeId-$idx-form-v-${widget.seed}", + initialValue: rows[idx].value, + hintText: " Value", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(value: value); + _onFieldChange(activeId); + }, + colorScheme: Theme.of(context).colorScheme, + ); + }, + sortable: false, + ), + DaviColumn( + pinStatus: PinStatus.none, + width: 30, + cellBuilder: (_, row) { + return InkWell( + child: Theme.of(context).brightness == Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + widget.onFormDataRemove(); + if (rows.length == 1) { + setState(() { + rows = [ + kFormDataEmptyModel, + ]; + }); + } else { + rows.removeAt(row.index); + } + _onFieldChange(activeId); + }, + ); + }, + ), + ], + ); + return Stack( + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: kBorderRadius12, + ), + margin: kP10, + child: Column( + children: [ + Expanded( + child: DaviTheme( + data: kTableThemeData, + child: Davi(model), + ), + ), + ], + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(bottom: 30), + child: ElevatedButton.icon( + onPressed: () { + rows.add(kFormDataEmptyModel); + _onFieldChange(activeId); + }, + icon: const Icon(Icons.add), + label: const Text( + "Add Form Data", + style: kTextStyleButton, + ), + ), + ), + ), + ], + ); + } + + void _onFieldChange(String activeId) { + List formDataList = + ref.read(collectionStateNotifierProvider)?[activeId]?.formDataList ?? + []; + ref.read(collectionStateNotifierProvider.notifier).update( + activeId, + formDataList: formDataList, + ); + } +} From a9bbe208d461abc0bc75be832d82fd240cabede4 Mon Sep 17 00:00:00 2001 From: vidya-hub Date: Wed, 20 Dec 2023 22:10:14 +0530 Subject: [PATCH 037/123] chore: added imports for multi part request --- lib/providers/collection_providers.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index dc059913..d5acd609 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,11 +1,11 @@ import 'package:apidash/models/form_data_model.dart'; -import 'package:apidash/services/http_service.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart' as http; import '../consts.dart'; import '../models/models.dart'; -import '../services/services.dart' show hiveHandler, HiveHandler, request; +import '../services/services.dart' + show hiveHandler, HiveHandler, request, multiPartRequest; import '../utils/utils.dart' show uuid, collectionToHAR; import 'settings_providers.dart'; import 'ui_providers.dart'; From 906cf8384709d36e6d443785a2d0d2718c092331 Mon Sep 17 00:00:00 2001 From: vidya-hub Date: Wed, 20 Dec 2023 22:28:03 +0530 Subject: [PATCH 038/123] chore: reverted name value model files --- lib/models/name_value_model.dart | 3 +- lib/models/name_value_model.freezed.dart | 43 ++++++++++++------------ lib/models/name_value_model.g.dart | 7 ++-- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/lib/models/name_value_model.dart b/lib/models/name_value_model.dart index 886fbbe8..f99b7a60 100644 --- a/lib/models/name_value_model.dart +++ b/lib/models/name_value_model.dart @@ -1,8 +1,7 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; part 'name_value_model.freezed.dart'; - part 'name_value_model.g.dart'; @freezed diff --git a/lib/models/name_value_model.freezed.dart b/lib/models/name_value_model.freezed.dart index b224f596..e7d9e8e0 100644 --- a/lib/models/name_value_model.freezed.dart +++ b/lib/models/name_value_model.freezed.dart @@ -68,22 +68,22 @@ class _$NameValueModelCopyWithImpl<$Res, $Val extends NameValueModel> } /// @nodoc -abstract class _$$NameValueModelImplCopyWith<$Res> +abstract class _$$_NameValueModelCopyWith<$Res> implements $NameValueModelCopyWith<$Res> { - factory _$$NameValueModelImplCopyWith(_$NameValueModelImpl value, - $Res Function(_$NameValueModelImpl) then) = - __$$NameValueModelImplCopyWithImpl<$Res>; + factory _$$_NameValueModelCopyWith( + _$_NameValueModel value, $Res Function(_$_NameValueModel) then) = + __$$_NameValueModelCopyWithImpl<$Res>; @override @useResult $Res call({String name, dynamic value}); } /// @nodoc -class __$$NameValueModelImplCopyWithImpl<$Res> - extends _$NameValueModelCopyWithImpl<$Res, _$NameValueModelImpl> - implements _$$NameValueModelImplCopyWith<$Res> { - __$$NameValueModelImplCopyWithImpl( - _$NameValueModelImpl _value, $Res Function(_$NameValueModelImpl) _then) +class __$$_NameValueModelCopyWithImpl<$Res> + extends _$NameValueModelCopyWithImpl<$Res, _$_NameValueModel> + implements _$$_NameValueModelCopyWith<$Res> { + __$$_NameValueModelCopyWithImpl( + _$_NameValueModel _value, $Res Function(_$_NameValueModel) _then) : super(_value, _then); @pragma('vm:prefer-inline') @@ -92,7 +92,7 @@ class __$$NameValueModelImplCopyWithImpl<$Res> Object? name = null, Object? value = freezed, }) { - return _then(_$NameValueModelImpl( + return _then(_$_NameValueModel( name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable @@ -107,13 +107,13 @@ class __$$NameValueModelImplCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$NameValueModelImpl +class _$_NameValueModel with DiagnosticableTreeMixin implements _NameValueModel { - const _$NameValueModelImpl({required this.name, required this.value}); + const _$_NameValueModel({required this.name, required this.value}); - factory _$NameValueModelImpl.fromJson(Map json) => - _$$NameValueModelImplFromJson(json); + factory _$_NameValueModel.fromJson(Map json) => + _$$_NameValueModelFromJson(json); @override final String name; @@ -138,7 +138,7 @@ class _$NameValueModelImpl bool operator ==(dynamic other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$NameValueModelImpl && + other is _$_NameValueModel && (identical(other.name, name) || other.name == name) && const DeepCollectionEquality().equals(other.value, value)); } @@ -151,13 +151,12 @@ class _$NameValueModelImpl @JsonKey(ignore: true) @override @pragma('vm:prefer-inline') - _$$NameValueModelImplCopyWith<_$NameValueModelImpl> get copyWith => - __$$NameValueModelImplCopyWithImpl<_$NameValueModelImpl>( - this, _$identity); + _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => + __$$_NameValueModelCopyWithImpl<_$_NameValueModel>(this, _$identity); @override Map toJson() { - return _$$NameValueModelImplToJson( + return _$$_NameValueModelToJson( this, ); } @@ -166,10 +165,10 @@ class _$NameValueModelImpl abstract class _NameValueModel implements NameValueModel { const factory _NameValueModel( {required final String name, - required final dynamic value}) = _$NameValueModelImpl; + required final dynamic value}) = _$_NameValueModel; factory _NameValueModel.fromJson(Map json) = - _$NameValueModelImpl.fromJson; + _$_NameValueModel.fromJson; @override String get name; @@ -177,6 +176,6 @@ abstract class _NameValueModel implements NameValueModel { dynamic get value; @override @JsonKey(ignore: true) - _$$NameValueModelImplCopyWith<_$NameValueModelImpl> get copyWith => + _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => throw _privateConstructorUsedError; } diff --git a/lib/models/name_value_model.g.dart b/lib/models/name_value_model.g.dart index 5fb91b66..25867df8 100644 --- a/lib/models/name_value_model.g.dart +++ b/lib/models/name_value_model.g.dart @@ -6,14 +6,13 @@ part of 'name_value_model.dart'; // JsonSerializableGenerator // ************************************************************************** -_$NameValueModelImpl _$$NameValueModelImplFromJson(Map json) => - _$NameValueModelImpl( +_$_NameValueModel _$$_NameValueModelFromJson(Map json) => + _$_NameValueModel( name: json['name'] as String, value: json['value'], ); -Map _$$NameValueModelImplToJson( - _$NameValueModelImpl instance) => +Map _$$_NameValueModelToJson(_$_NameValueModel instance) => { 'name': instance.name, 'value': instance.value, From a792e0fb357172a77c660c18cb0723ba14c8c740 Mon Sep 17 00:00:00 2001 From: laiiihz Date: Thu, 21 Dec 2023 13:20:41 +0800 Subject: [PATCH 039/123] feat: rewrite dart http code gen with dart code builder & format --- lib/codegen/dart/dio.dart | 10 +- lib/codegen/dart/http.dart | 273 ++++++++++++----------- lib/codegen/dart/shared.dart | 34 ++- test/codegen/dart_http_codegen_test.dart | 223 ++++++++++-------- 4 files changed, 317 insertions(+), 223 deletions(-) diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index 7c603716..fcaa8314 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -17,7 +17,7 @@ class DartDioCodeGen { } final next = generatedDartCode( url: url, - method: requestModel.method.name, + method: requestModel.method, queryParams: requestModel.paramsMap, headers: requestModel.headersMap, body: requestModel.requestBody, @@ -31,7 +31,7 @@ class DartDioCodeGen { String generatedDartCode({ required String url, - required String method, + required HTTPVerb method, required Map queryParams, required Map headers, required String? body, @@ -56,9 +56,10 @@ class DartDioCodeGen { } Expression? dataExp; - if (body != null) { + if (kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false)) { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); switch (contentType) { + // dio dosen't need pass `content-type` header when body is json or plain text case ContentType.json: final convertImport = Directive.import('dart:convert', as: 'convert'); sbf.writeln(convertImport.accept(emitter)); @@ -66,6 +67,7 @@ class DartDioCodeGen { .assign(refer('convert.json.decode').call([strContent])); case ContentType.text: dataExp = declareFinal('data').assign(strContent); + // when add new type of [ContentType], need update [dataExp]. } } final responseExp = declareFinal('response').assign(InvokeExpression.newOf( @@ -81,7 +83,7 @@ class DartDioCodeGen { if (dataExp != null) 'data': refer('data'), }, [], - method, + method.name, ).awaited); final mainFunction = Method((m) { diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 2c0e016c..6beccac8 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -1,147 +1,164 @@ import 'dart:io'; -import 'dart:convert'; -import 'package:jinja/jinja.dart' as jj; + import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' show padMultilineString; import 'package:apidash/models/models.dart' show RequestModel; +import 'package:code_builder/code_builder.dart'; +import 'package:dart_style/dart_style.dart'; + +import 'shared.dart'; class DartHttpCodeGen { - String kTemplateStart = """import 'package:http/http.dart' as http; - -void main() async { - var uri = Uri.parse('{{url}}'); - -"""; - - String kTemplateParams = """ - - var queryParams = {{params}}; -"""; - int kParamsPadding = 20; - - String kStringUrlParams = """ - - var urlQueryParams = Map.from(uri.queryParameters); - urlQueryParams.addAll(queryParams); - uri = uri.replace(queryParameters: urlQueryParams); -"""; - - String kStringNoUrlParams = """ - - uri = uri.replace(queryParameters: queryParams); -"""; - - String kTemplateBody = """ - - String body = r'''{{body}}'''; - -"""; - - String kTemplateHeaders = """ - - var headers = {{headers}}; - -"""; - int kHeadersPadding = 16; - - String kTemplateRequest = """ - - final response = await http.{{method}}(uri"""; - - String kStringRequestHeaders = """, - headers: headers"""; - - String kStringRequestBody = """, - body: body"""; - String kStringRequestEnd = r"""); - - int statusCode = response.statusCode; - if (statusCode >= 200 && statusCode < 300) { - print('Status Code: $statusCode'); - print('Response Body: ${response.body}'); - } - else{ - print('Error Status Code: $statusCode'); - print('Error Response Body: ${response.body}'); - } -} -"""; - String? getCode( RequestModel requestModel, String defaultUriScheme, ) { try { - String result = ""; - bool hasHeaders = false; - bool hasBody = false; - String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; } - var templateStartUrl = jj.Template(kTemplateStart); - result += templateStartUrl.render({"url": url}); - - var paramsList = requestModel.requestParams; - if (paramsList != null) { - var params = requestModel.paramsMap; - if (params.isNotEmpty) { - var templateParams = jj.Template(kTemplateParams); - var paramsString = kEncoder.convert(params); - paramsString = padMultilineString(paramsString, kParamsPadding); - result += templateParams.render({"params": paramsString}); - Uri uri = Uri.parse(url); - if (uri.hasQuery) { - result += kStringUrlParams; - } else { - result += kStringNoUrlParams; - } - } - } - - var method = requestModel.method; - var requestBody = requestModel.requestBody; - if (kMethodsWithBody.contains(method) && requestBody != null) { - var contentLength = utf8.encode(requestBody).length; - if (contentLength > 0) { - hasBody = true; - var templateBody = jj.Template(kTemplateBody); - result += templateBody.render({"body": requestBody}); - } - } - - var headersList = requestModel.requestHeaders; - if (headersList != null || hasBody) { - var headers = requestModel.headersMap; - if (headers.isNotEmpty || hasBody) { - hasHeaders = true; - if (hasBody) { - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; - } - var headersString = kEncoder.convert(headers); - headersString = padMultilineString(headersString, kHeadersPadding); - var templateHeaders = jj.Template(kTemplateHeaders); - result += templateHeaders.render({"headers": headersString}); - } - } - - var templateRequest = jj.Template(kTemplateRequest); - result += templateRequest.render({"method": method.name}); - - if (hasHeaders) { - result += kStringRequestHeaders; - } - - if (hasBody) { - result += kStringRequestBody; - } - - result += kStringRequestEnd; - return result; + final next = generatedDartCode( + url: url, + method: requestModel.method, + queryParams: requestModel.paramsMap, + headers: requestModel.headersMap, + body: requestModel.requestBody, + contentType: requestModel.requestBodyContentType, + ); + return next; } catch (e) { + print(e); return null; } } + + String generatedDartCode({ + required String url, + required HTTPVerb method, + required Map queryParams, + required Map headers, + required String? body, + required ContentType contentType, + }) { + final uri = Uri.parse(url); + + final sbf = StringBuffer(); + final emitter = DartEmitter(); + final dioImport = Directive.import('package:http/http.dart', as: 'http'); + sbf.writeln(dioImport.accept(emitter)); + + final uriExp = + declareVar('uri').assign(refer('Uri.parse').call([literalString(url)])); + + final composeHeaders = headers; + Expression? dataExp; + if (kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false)) { + final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); + dataExp = declareVar('body', type: refer('String')).assign(strContent); + + composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, + () => kContentTypeMap[contentType] ?? ''); + } + + Expression? queryParamExp; + List? uriReassignExps; + // var urlQueryParams = Map.from(uri.queryParameters); + // urlQueryParams.addAll(queryParams); + // uri = uri.replace(queryParameters: urlQueryParams); + + if (queryParams.isNotEmpty) { + queryParamExp = declareVar('queryParams').assign( + literalMap(queryParams.map((key, value) => MapEntry(key, value))), + ); + + uriReassignExps = [ + if (uri.hasQuery) + declareVar('urlQueryParams').assign( + InvokeExpression.newOf( + refer('Map'), + [refer('uri.queryParameters')], + {}, + [], + 'from', + ), + ), + if (uri.hasQuery) + refer('urlQueryParams') + .property('addAll') + .call([refer('queryParams')], {}), + refer('uri').assign(refer('uri').property('replace').call([], { + 'queryParameters': + uri.hasQuery ? refer('urlQueryParams') : refer('queryParams'), + })) + ]; + } + + Expression? headerExp; + if (headers.isNotEmpty) { + headerExp = declareVar('headers').assign( + literalMap(headers.map((key, value) => MapEntry(key, value))), + ); + } + final responseExp = declareFinal('response').assign(InvokeExpression.newOf( + refer('http.${method.name}'), + [refer('uri')], + { + if (headerExp != null) 'headers': refer('headers'), + if (dataExp != null) 'body': refer('body'), + }, + [], + ).awaited); + + final mainFunction = Method((m) { + final statusRef = refer('statusCode'); + m + ..name = 'main' + ..returns = refer('void') + ..modifier = MethodModifier.async + ..body = Block((b) { + b.statements.add(uriExp.statement); + if (queryParamExp != null) { + b.statements.add(const Code('\n')); + b.statements.add(queryParamExp.statement); + } + if (uriReassignExps != null) { + b.statements.addAll(uriReassignExps.map((e) => e.statement)); + } + if (dataExp != null) { + b.statements.add(const Code('\n')); + b.statements.add(dataExp.statement); + } + if (headerExp != null) { + b.statements.add(const Code('\n')); + b.statements.add(headerExp.statement); + } + b.statements.add(const Code('\n')); + b.statements.add(responseExp.statement); + b.statements.add(const Code('\n')); + b.statements.add(declareVar('statusCode', type: refer('int')) + .assign(refer('response').property('statusCode')) + .statement); + b.statements.add(declareIfElse( + condition: statusRef + .greaterOrEqualTo(literalNum(200)) + .and(statusRef.lessThan(literalNum(300))), + body: [ + refer('print').call([literalString(r'Status Code: $statusCode')]), + refer('print') + .call([literalString(r'Response Body: ${response.body}')]), + ], + elseBody: [ + refer('print') + .call([literalString(r'Error Status Code: $statusCode')]), + refer('print').call( + [literalString(r'Error Response Body: ${response.body}')]), + ], + )); + }); + }); + + sbf.writeln(mainFunction.accept(emitter)); + + return DartFormatter(pageWidth: 160).format(sbf.toString()); + } } diff --git a/lib/codegen/dart/shared.dart b/lib/codegen/dart/shared.dart index 9938750c..073112dd 100644 --- a/lib/codegen/dart/shared.dart +++ b/lib/codegen/dart/shared.dart @@ -1,14 +1,24 @@ import 'package:code_builder/code_builder.dart'; +Code _toStatement(Spec spec) { + if (spec is Expression) { + return spec.statement; + } else if (spec is Code) { + return spec; + } else { + throw UnimplementedError(); + } +} + Block declareTryCatch({ - required List body, - required Map> onError, + required List body, + required Map> onError, bool showStackStrace = false, }) { return Block((b) { b.statements.add(const Code('try')); b.statements.add(const Code('{')); - b.statements.addAll(body.map((e) => e.statement).toList()); + b.statements.addAll(body.map(_toStatement).toList()); final entries = onError.entries; for (var error in entries) { @@ -19,8 +29,24 @@ Block declareTryCatch({ b.statements.add(Code(showStackStrace ? 'catch(e,s)' : 'catch(e)')); b.statements.add(const Code('{')); - b.statements.addAll(error.value.map((e) => e.statement).toList()); + b.statements.addAll(error.value.map(_toStatement).toList()); if (entries.last.key == error.key) b.statements.add(const Code('}')); } }); } + +Block declareIfElse({ + required Expression condition, + required List body, + required List elseBody, +}) { + return Block.of([ + const Code('if('), + condition.code, + const Code('){'), + ...body.map(_toStatement), + const Code('} else {'), + ...elseBody.map(_toStatement), + const Code('}'), + ]); +} diff --git a/test/codegen/dart_http_codegen_test.dart b/test/codegen/dart_http_codegen_test.dart index e384b628..0bdc5f60 100644 --- a/test/codegen/dart_http_codegen_test.dart +++ b/test/codegen/dart_http_codegen_test.dart @@ -1,7 +1,17 @@ import 'package:apidash/codegen/dart/http.dart'; +import 'package:dart_style/dart_style.dart'; import 'package:test/test.dart'; import '../request_models.dart'; +final _formatter = DartFormatter(fixes: [ + StyleFix.singleCascadeStatements +]); + +extension on String { + // format code before compare + String get format => _formatter.format(this); +} + void main() { final dartHttpCodeGen = DartHttpCodeGen(); @@ -25,7 +35,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet1, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet1, "https"), + expectedCode.format, + ); }); test('GET 2', () { @@ -34,9 +47,7 @@ void main() async { void main() async { var uri = Uri.parse('https://api.foss42.com/country/data'); - var queryParams = { - "code": "US" - }; + var queryParams = {'code': 'US'}; uri = uri.replace(queryParameters: queryParams); final response = await http.get(uri); @@ -52,18 +63,18 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet2, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet2, "https"), + expectedCode.format, + ); }); test('GET 3', () { const expectedCode = r"""import 'package:http/http.dart' as http; - void main() async { var uri = Uri.parse('https://api.foss42.com/country/data?code=US'); - var queryParams = { - "code": "IND" - }; + var queryParams = {'code': 'IND'}; var urlQueryParams = Map.from(uri.queryParameters); urlQueryParams.addAll(queryParams); uri = uri.replace(queryParameters: urlQueryParams); @@ -81,7 +92,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet3, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet3, "https"), + expectedCode.format, + ); }); test('GET 4', () { @@ -91,12 +105,12 @@ void main() async { var uri = Uri.parse('https://api.foss42.com/humanize/social'); var queryParams = { - "num": "8700000", - "digits": "3", - "system": "SS", - "add_space": "true", - "trailing_zeros": "true" - }; + 'num': '8700000', + 'digits': '3', + 'system': 'SS', + 'add_space': 'true', + 'trailing_zeros': 'true', + }; uri = uri.replace(queryParameters: queryParams); final response = await http.get(uri); @@ -112,7 +126,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet4, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet4, "https"), + expectedCode.format, + ); }); test('GET 5', () { @@ -121,12 +138,12 @@ void main() async { void main() async { var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); - var headers = { - "User-Agent": "Test Agent" - }; + var headers = {'User-Agent': 'Test Agent'}; - final response = await http.get(uri, - headers: headers); + final response = await http.get( + uri, + headers: headers, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -139,7 +156,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet5, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet5, "https"), + expectedCode.format, + ); }); test('GET 6', () { @@ -148,17 +168,15 @@ void main() async { void main() async { var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); - var queryParams = { - "raw": "true" - }; + var queryParams = {'raw': 'true'}; uri = uri.replace(queryParameters: queryParams); - var headers = { - "User-Agent": "Test Agent" - }; + var headers = {'User-Agent': 'Test Agent'}; - final response = await http.get(uri, - headers: headers); + final response = await http.get( + uri, + headers: headers, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -171,7 +189,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet6, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet6, "https"), + expectedCode.format, + ); }); test('GET 7', () { @@ -193,7 +214,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet7, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet7, "https"), + expectedCode.format, + ); }); test('GET 8', () { @@ -202,17 +226,15 @@ void main() async { void main() async { var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); - var queryParams = { - "raw": "true" - }; + var queryParams = {'raw': 'true'}; uri = uri.replace(queryParameters: queryParams); - var headers = { - "User-Agent": "Test Agent" - }; + var headers = {'User-Agent': 'Test Agent'}; - final response = await http.get(uri, - headers: headers); + final response = await http.get( + uri, + headers: headers, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -225,7 +247,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelGet8, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelGet8, "https"), + expectedCode.format, + ); }); }); @@ -249,7 +274,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelHead1, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelHead1, "https"), + expectedCode.format, + ); }); test('HEAD 2', () { @@ -271,7 +299,8 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelHead2, "http"), expectedCode); + expect(dartHttpCodeGen.getCode(requestModelHead2, "http"), + expectedCode.format); }); }); @@ -286,13 +315,13 @@ void main() async { "text": "I LOVE Flutter" }'''; - var headers = { - "content-type": "text/plain" - }; + var headers = {'content-type': 'text/plain'}; - final response = await http.post(uri, - headers: headers, - body: body); + final response = await http.post( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -305,7 +334,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelPost1, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelPost1, "https"), + expectedCode.format, + ); }); test('POST 2', () { @@ -318,13 +350,13 @@ void main() async { "text": "I LOVE Flutter" }'''; - var headers = { - "content-type": "application/json" - }; + var headers = {'content-type': 'application/json'}; - final response = await http.post(uri, - headers: headers, - body: body); + final response = await http.post( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -337,7 +369,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelPost2, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelPost2, "https"), + expectedCode.format, + ); }); test('POST 3', () { @@ -351,13 +386,15 @@ void main() async { }'''; var headers = { - "User-Agent": "Test Agent", - "content-type": "application/json" - }; + 'User-Agent': 'Test Agent', + 'content-type': 'application/json', + }; - final response = await http.post(uri, - headers: headers, - body: body); + final response = await http.post( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -370,7 +407,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelPost3, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelPost3, "https"), + expectedCode.format, + ); }); }); group('PUT Request', () { @@ -385,13 +425,13 @@ void main() async { "job": "zion resident" }'''; - var headers = { - "content-type": "application/json" - }; + var headers = {'content-type': 'application/json'}; - final response = await http.put(uri, - headers: headers, - body: body); + final response = await http.put( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -404,7 +444,10 @@ void main() async { } } """; - expect(dartHttpCodeGen.getCode(requestModelPut1, "https"), expectedCode); + expect( + dartHttpCodeGen.getCode(requestModelPut1, "https"), + expectedCode.format, + ); }); }); @@ -420,13 +463,13 @@ void main() async { "job": "accountant" }'''; - var headers = { - "content-type": "application/json" - }; + var headers = {'content-type': 'application/json'}; - final response = await http.patch(uri, - headers: headers, - body: body); + final response = await http.patch( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -440,7 +483,9 @@ void main() async { } """; expect( - dartHttpCodeGen.getCode(requestModelPatch1, "https"), expectedCode); + dartHttpCodeGen.getCode(requestModelPatch1, "https"), + expectedCode.format, + ); }); }); @@ -465,7 +510,9 @@ void main() async { } """; expect( - dartHttpCodeGen.getCode(requestModelDelete1, "https"), expectedCode); + dartHttpCodeGen.getCode(requestModelDelete1, "https"), + expectedCode.format, + ); }); test('DELETE 2', () { @@ -479,13 +526,13 @@ void main() async { "job": "accountant" }'''; - var headers = { - "content-type": "application/json" - }; + var headers = {'content-type': 'application/json'}; - final response = await http.delete(uri, - headers: headers, - body: body); + final response = await http.delete( + uri, + headers: headers, + body: body, + ); int statusCode = response.statusCode; if (statusCode >= 200 && statusCode < 300) { @@ -499,7 +546,9 @@ void main() async { } """; expect( - dartHttpCodeGen.getCode(requestModelDelete2, "https"), expectedCode); + dartHttpCodeGen.getCode(requestModelDelete2, "https"), + expectedCode.format, + ); }); }); } From 67f80563aab6e80042f448083a1dade3d4d338f5 Mon Sep 17 00:00:00 2001 From: laiiihz Date: Thu, 21 Dec 2023 16:16:39 +0800 Subject: [PATCH 040/123] test:add dart dio code gen tests --- lib/codegen/dart/http.dart | 1 - test/codegen/dart_dio_codegen_test.dart | 514 ++++++++++++++++++++++++ 2 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 test/codegen/dart_dio_codegen_test.dart diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 6beccac8..67184c25 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -27,7 +27,6 @@ class DartHttpCodeGen { ); return next; } catch (e) { - print(e); return null; } } diff --git a/test/codegen/dart_dio_codegen_test.dart b/test/codegen/dart_dio_codegen_test.dart new file mode 100644 index 00000000..274511b4 --- /dev/null +++ b/test/codegen/dart_dio_codegen_test.dart @@ -0,0 +1,514 @@ +import 'package:apidash/codegen/dart/dio.dart'; +import 'package:dart_style/dart_style.dart'; +import 'package:test/test.dart'; +import '../request_models.dart'; + +final _formatter = DartFormatter(fixes: [ + StyleFix.singleCascadeStatements +]); + +extension on String { + // format code before compare + String get format => _formatter.format(this); +} + +void main() { + final dartDioCodeGen = DartDioCodeGen(); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.get('https://api.foss42.com'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet1, "https"), + expectedCode.format, + ); + }); + + test('GET 2', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = {'code': 'US'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/country/data', + queryParameters: queryParams, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet2, "https"), + expectedCode.format, + ); + }); + + test('GET 3', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = {'code': 'IND'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/country/data?code=US', + queryParameters: queryParams, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet3, "https"), + expectedCode.format, + ); + }); + + test('GET 4', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = { + 'num': '8700000', + 'digits': '3', + 'system': 'SS', + 'add_space': 'true', + 'trailing_zeros': 'true', + }; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + queryParameters: queryParams, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet4, "https"), + expectedCode.format, + ); + }); + + test('GET 5', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.github.com/repos/foss42/apidash', + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet5, "https"), + expectedCode.format, + ); + }); + + test('GET 6', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = {'raw': 'true'}; + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.github.com/repos/foss42/apidash', + queryParameters: queryParams, + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet6, "https"), + expectedCode.format, + ); + }); + + test('GET 7', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.get('https://api.foss42.com'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet7, "https"), + expectedCode.format, + ); + }); + + test('GET 8', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = {'raw': 'true'}; + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.github.com/repos/foss42/apidash', + queryParameters: queryParams, + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelGet8, "https"), + expectedCode.format, + ); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.head('https://api.foss42.com'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelHead1, "https"), + expectedCode.format, + ); + }); + + test('HEAD 2', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.head('http://api.foss42.com'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelHead2, "http"), + expectedCode.format); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final data = r'''{ +"text": "I LOVE Flutter" +}'''; + final response = await dio.Dio.post( + 'https://api.foss42.com/case/lower', + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelPost1, "https"), + expectedCode.format, + ); + }); + + test('POST 2', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; +import 'dart:convert' as convert; + +void main() async { + try { + final data = convert.json.decode(r'''{ +"text": "I LOVE Flutter" +}'''); + final response = await dio.Dio.post( + 'https://api.foss42.com/case/lower', + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelPost2, "https"), + expectedCode.format, + ); + }); + + test('POST 3', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; +import 'dart:convert' as convert; + +void main() async { + try { + final headers = {'User-Agent': 'Test Agent'}; + final data = convert.json.decode(r'''{ +"text": "I LOVE Flutter" +}'''); + final response = await dio.Dio.post( + 'https://api.foss42.com/case/lower', + options: Options(headers: headers), + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelPost3, "https"), + expectedCode.format, + ); + }); + }); + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; +import 'dart:convert' as convert; + +void main() async { + try { + final data = convert.json.decode(r'''{ +"name": "morpheus", +"job": "zion resident" +}'''); + final response = await dio.Dio.put( + 'https://reqres.in/api/users/2', + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelPut1, "https"), + expectedCode.format, + ); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; +import 'dart:convert' as convert; + +void main() async { + try { + final data = convert.json.decode(r'''{ +"name": "marfeus", +"job": "accountant" +}'''); + final response = await dio.Dio.patch( + 'https://reqres.in/api/users/2', + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelPatch1, "https"), + expectedCode.format, + ); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.delete('https://reqres.in/api/users/2'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelDelete1, "https"), + expectedCode.format, + ); + }); + + test('DELETE 2', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; +import 'dart:convert' as convert; + +void main() async { + try { + final data = convert.json.decode(r'''{ +"name": "marfeus", +"job": "accountant" +}'''); + final response = await dio.Dio.delete( + 'https://reqres.in/api/users/2', + data: data, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode(requestModelDelete2, "https"), + expectedCode.format, + ); + }); + }); +} From 06f8cd7f0267d1364d2fcbf78eef6bb5a23653cd Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:25:26 +0530 Subject: [PATCH 041/123] fix: review changes --- lib/codegen/dart/http.dart | 4 +- lib/codegen/kotlin/okhttp.dart | 7 +- lib/codegen/python/http_client.dart | 7 +- lib/codegen/python/requests.dart | 7 +- lib/models/request_model.dart | 69 +++++++++++-------- lib/providers/collection_providers.dart | 8 +-- .../request_pane/request_headers.dart | 35 ++++------ .../request_pane/request_params.dart | 31 ++++----- lib/services/http_service.dart | 5 +- lib/utils/convert_utils.dart | 6 +- lib/utils/har_utils.dart | 7 +- lib/utils/http_utils.dart | 7 +- test/models/request_model_test.dart | 4 +- test/utils/http_utils_test.dart | 17 +++-- 14 files changed, 104 insertions(+), 110 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 2c0e016c..9e3d6976 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -111,9 +111,9 @@ void main() async { } } - var headersList = requestModel.requestHeaders; + var headersList = requestModel.enabledRequestHeaders; if (headersList != null || hasBody) { - var headers = requestModel.headersMap; + var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index e28e7e7f..362e31a1 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -79,8 +79,7 @@ import okhttp3.MediaType.Companion.toMediaType"""; var rec = getValidRequestUri( url, - requestModel.requestParams, - requestModel.enabledParams, + requestModel.enabledRequestParams, ); Uri? uri = rec.$1; @@ -124,9 +123,9 @@ import okhttp3.MediaType.Companion.toMediaType"""; result = stringStart + result; result += kStringRequestStart; - var headersList = requestModel.requestHeaders; + var headersList = requestModel.enabledRequestHeaders; if (headersList != null) { - var headers = requestModel.headersMap; + var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty) { hasHeaders = true; result += getHeaders(headers); diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 169de25e..9ba66919 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -73,8 +73,7 @@ print(data.decode("utf-8")) result += kTemplateStart; var rec = getValidRequestUri( url, - requestModel.requestParams, - requestModel.enabledParams, + requestModel.enabledRequestParams, ); Uri? uri = rec.$1; @@ -101,9 +100,9 @@ print(data.decode("utf-8")) } } - var headersList = requestModel.requestHeaders; + var headersList = requestModel.enabledRequestHeaders; if (headersList != null || hasBody) { - var headers = requestModel.headersMap; + var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index e2e5f050..bb3c53c8 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -77,8 +77,7 @@ print('Response Body:', response.text) var rec = getValidRequestUri( url, - requestModel.requestParams, - requestModel.enabledParams, + requestModel.enabledRequestParams, ); Uri? uri = rec.$1; if (uri != null) { @@ -113,9 +112,9 @@ print('Response Body:', response.text) } } - var headersList = requestModel.requestHeaders; + var headersList = requestModel.enabledRequestHeaders; if (headersList != null || hasBody) { - var headers = requestModel.headersMap; + var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 78947792..df49ba1e 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,7 +1,7 @@ -import 'package:apidash/utils/convert_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' show mapToRows, rowsToMap; +import 'package:apidash/utils/utils.dart' + show mapToRows, rowsToMap, getEnabledRows; import 'name_value_model.dart'; import 'response_model.dart'; @@ -16,8 +16,8 @@ class RequestModel { this.requestTabIndex = 0, this.requestHeaders, this.requestParams, - this.enabledHeaders, - this.enabledParams, + this.isHeaderEnabledList, + this.isParamEnabledList, this.requestBodyContentType = ContentType.json, this.requestBody, this.responseStatus, @@ -33,18 +33,25 @@ class RequestModel { final int requestTabIndex; final List? requestHeaders; final List? requestParams; - final List? enabledHeaders; - final List? enabledParams; + final List? isHeaderEnabledList; + final List? isParamEnabledList; final ContentType requestBodyContentType; final String? requestBody; final int? responseStatus; final String? message; final ResponseModel? responseModel; - Map get headersMap => - rowsToMap(getEnabledRows(requestHeaders, enabledHeaders)) ?? {}; - Map get paramsMap => - rowsToMap(getEnabledRows(requestParams, enabledParams)) ?? {}; + List? get enabledRequestHeaders => + getEnabledRows(requestHeaders, isHeaderEnabledList); + List? get enabledRequestParams => + getEnabledRows(requestParams, isParamEnabledList); + + Map get enabledHeadersMap => + rowsToMap(enabledRequestHeaders) ?? {}; + Map get enabledParamsMap => + rowsToMap(enabledRequestParams) ?? {}; + Map get headersMap => rowsToMap(requestHeaders) ?? {}; + Map get paramsMap => rowsToMap(requestParams) ?? {}; RequestModel duplicate({ required String id, @@ -57,8 +64,10 @@ class RequestModel { description: description, requestHeaders: requestHeaders != null ? [...requestHeaders!] : null, requestParams: requestParams != null ? [...requestParams!] : null, - enabledHeaders: enabledHeaders != null ? [...enabledHeaders!] : null, - enabledParams: enabledParams != null ? [...enabledParams!] : null, + isHeaderEnabledList: + isHeaderEnabledList != null ? [...isHeaderEnabledList!] : null, + isParamEnabledList: + isParamEnabledList != null ? [...isParamEnabledList!] : null, requestBodyContentType: requestBodyContentType, requestBody: requestBody, ); @@ -73,8 +82,8 @@ class RequestModel { int? requestTabIndex, List? requestHeaders, List? requestParams, - List? enabledHeaders, - List? enabledParams, + List? isHeaderEnabledList, + List? isParamEnabledList, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, @@ -83,8 +92,8 @@ class RequestModel { }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; - var eHeaders = enabledHeaders ?? this.enabledHeaders; - var eParams = enabledParams ?? this.enabledParams; + var enabledHeaders = isHeaderEnabledList ?? this.isHeaderEnabledList; + var enabledParams = isParamEnabledList ?? this.isParamEnabledList; return RequestModel( id: id ?? this.id, method: method ?? this.method, @@ -94,8 +103,8 @@ class RequestModel { requestTabIndex: requestTabIndex ?? this.requestTabIndex, requestHeaders: headers != null ? [...headers] : null, requestParams: params != null ? [...params] : null, - enabledHeaders: eHeaders != null ? [...eHeaders] : null, - enabledParams: eParams != null ? [...eParams] : null, + isHeaderEnabledList: enabledHeaders != null ? [...enabledHeaders] : null, + isParamEnabledList: enabledParams != null ? [...enabledParams] : null, requestBodyContentType: requestBodyContentType ?? this.requestBodyContentType, requestBody: requestBody ?? this.requestBody, @@ -121,8 +130,8 @@ class RequestModel { final description = data["description"] as String?; final requestHeaders = data["requestHeaders"]; final requestParams = data["requestParams"]; - final enabledHeaders = data["enabledHeaders"] as List?; - final enabledParams = data["enabledParams"] as List?; + final isHeaderEnabledList = data["isHeaderEnabledList"] as List?; + final isParamEnabledList = data["isParamEnabledList"] as List?; try { requestBodyContentType = ContentType.values.byName(data["requestBodyContentType"] as String); @@ -153,8 +162,8 @@ class RequestModel { requestParams: requestParams != null ? mapToRows(Map.from(requestParams)) : null, - enabledHeaders: enabledHeaders, - enabledParams: enabledParams, + isHeaderEnabledList: isHeaderEnabledList, + isParamEnabledList: isParamEnabledList, requestBodyContentType: requestBodyContentType, requestBody: requestBody, responseStatus: responseStatus, @@ -172,8 +181,8 @@ class RequestModel { "description": description, "requestHeaders": rowsToMap(requestHeaders), "requestParams": rowsToMap(requestParams), - "enabledHeaders": enabledHeaders, - "enabledParams": enabledParams, + "isHeaderEnabledList": isHeaderEnabledList, + "isParamEnabledList": isParamEnabledList, "requestBodyContentType": requestBodyContentType.name, "requestBody": requestBody, "responseStatus": includeResponse ? responseStatus : null, @@ -192,9 +201,9 @@ class RequestModel { "Request Description: $description", "Request Tab Index: ${requestTabIndex.toString()}", "Request Headers: ${requestHeaders.toString()}", - "Enabled Headers: ${enabledHeaders.toString()}", + "Enabled Headers: ${isHeaderEnabledList.toString()}", "Request Params: ${requestParams.toString()}", - "Enabled Params: ${enabledParams.toString()}", + "Enabled Params: ${isParamEnabledList.toString()}", "Request Body Content Type: ${requestBodyContentType.toString()}", "Request Body: ${requestBody.toString()}", "Response Status: $responseStatus", @@ -215,8 +224,8 @@ class RequestModel { other.requestTabIndex == requestTabIndex && listEquals(other.requestHeaders, requestHeaders) && listEquals(other.requestParams, requestParams) && - listEquals(other.enabledHeaders, enabledHeaders) && - listEquals(other.enabledParams, enabledParams) && + listEquals(other.isHeaderEnabledList, isHeaderEnabledList) && + listEquals(other.isParamEnabledList, isParamEnabledList) && other.requestBodyContentType == requestBodyContentType && other.requestBody == requestBody && other.responseStatus == responseStatus && @@ -236,8 +245,8 @@ class RequestModel { requestTabIndex, requestHeaders, requestParams, - enabledHeaders, - enabledParams, + isHeaderEnabledList, + isParamEnabledList, requestBodyContentType, requestBody, responseStatus, diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 8bf8c97f..8e5b305a 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -123,8 +123,8 @@ class CollectionStateNotifier int? requestTabIndex, List? requestHeaders, List? requestParams, - List? enabledHeaders, - List? enabledParams, + List? isHeaderEnabledList, + List? isParamEnabledList, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, @@ -139,8 +139,8 @@ class CollectionStateNotifier requestTabIndex: requestTabIndex, requestHeaders: requestHeaders, requestParams: requestParams, - enabledHeaders: enabledHeaders, - enabledParams: enabledParams, + isHeaderEnabledList: isHeaderEnabledList, + isParamEnabledList: isParamEnabledList, requestBodyContentType: requestBodyContentType, requestBody: requestBody, responseStatus: responseStatus, diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 191655fc..4517d1d1 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -16,7 +16,7 @@ class EditRequestHeaders extends ConsumerStatefulWidget { class EditRequestHeadersState extends ConsumerState { late List rows; - late List enabledRows; + late List isRowEnabledList; final random = Random.secure(); late int seed; @@ -30,7 +30,7 @@ class EditRequestHeadersState extends ConsumerState { ref.read(collectionStateNotifierProvider.notifier).update( activeId, requestHeaders: rows, - enabledHeaders: enabledRows, + isHeaderEnabledList: isRowEnabledList, ); } @@ -45,8 +45,9 @@ class EditRequestHeadersState extends ConsumerState { kNameValueEmptyModel, ] : rH; - enabledRows = ref.read(activeRequestModelProvider)?.enabledHeaders ?? - List.filled(rows.length, true, growable: true); + isRowEnabledList = + ref.read(activeRequestModelProvider)?.isHeaderEnabledList ?? + List.filled(rows.length, true, growable: true); DaviModel model = DaviModel( rows: rows, @@ -58,10 +59,10 @@ class EditRequestHeadersState extends ConsumerState { int idx = row.index; return CheckBox( keyId: "$activeId-$idx-headers-c-$seed", - value: enabledRows[idx], + value: isRowEnabledList[idx], onChanged: (value) { setState(() { - enabledRows[idx] = value!; + isRowEnabledList[idx] = value!; }); _onFieldChange(activeId!); }, @@ -125,17 +126,13 @@ class EditRequestHeadersState extends ConsumerState { onTap: () { seed = random.nextInt(kRandMax); if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - enabledRows = [true]; - }); + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; } else { - setState(() { - enabledRows.removeAt(row.index); - rows.removeAt(row.index); - }); + isRowEnabledList.removeAt(row.index); + rows.removeAt(row.index); } _onFieldChange(activeId!); }, @@ -169,10 +166,8 @@ class EditRequestHeadersState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - setState(() { - rows.add(kNameValueEmptyModel); - enabledRows.add(true); - }); + rows.add(kNameValueEmptyModel); + isRowEnabledList.add(true); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 6bdf3cac..83603631 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -17,7 +17,7 @@ class EditRequestURLParams extends ConsumerStatefulWidget { class EditRequestURLParamsState extends ConsumerState { late List rows; - late List enabledRows; + late List isRowEnabledList; final random = Random.secure(); late int seed; @@ -31,7 +31,7 @@ class EditRequestURLParamsState extends ConsumerState { ref.read(collectionStateNotifierProvider.notifier).update( activeId, requestParams: rows, - enabledParams: enabledRows, + isParamEnabledList: isRowEnabledList, ); } @@ -46,8 +46,9 @@ class EditRequestURLParamsState extends ConsumerState { kNameValueEmptyModel, ] : rP; - enabledRows = ref.read(activeRequestModelProvider)?.enabledParams ?? - List.filled(rows.length, true, growable: true); + isRowEnabledList = + ref.read(activeRequestModelProvider)?.isParamEnabledList ?? + List.filled(rows.length, true, growable: true); DaviModel model = DaviModel( rows: rows, @@ -60,10 +61,10 @@ class EditRequestURLParamsState extends ConsumerState { return CheckBox( keyId: "$activeId-$idx-params-c-$seed", - value: enabledRows[idx], + value: isRowEnabledList[idx], onChanged: (value) { setState(() { - enabledRows[idx] = value!; + isRowEnabledList[idx] = value!; }); _onFieldChange(activeId!); }, @@ -127,17 +128,13 @@ class EditRequestURLParamsState extends ConsumerState { onTap: () { seed = random.nextInt(kRandMax); if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - enabledRows = [true]; - }); + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; } else { - setState(() { - enabledRows.removeAt(row.index); - rows.removeAt(row.index); - }); + isRowEnabledList.removeAt(row.index); + rows.removeAt(row.index); } _onFieldChange(activeId!); }, @@ -173,7 +170,7 @@ class EditRequestURLParamsState extends ConsumerState { onPressed: () { setState(() { rows.add(kNameValueEmptyModel); - enabledRows.add(true); + isRowEnabledList.add(true); }); _onFieldChange(activeId!); }, diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index c02af612..bac77ce6 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -12,13 +12,12 @@ Future<(http.Response?, Duration?, String?)> request( }) async { (Uri?, String?) uriRec = getValidRequestUri( requestModel.url, - requestModel.requestParams, - requestModel.enabledParams, + requestModel.enabledRequestParams, defaultUriScheme: defaultUriScheme, ); if (uriRec.$1 != null) { Uri requestUrl = uriRec.$1!; - Map headers = requestModel.headersMap; + Map headers = requestModel.enabledHeadersMap; http.Response response; String? body; try { diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index a7350257..94e6c878 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -111,11 +111,11 @@ Uint8List jsonMapToBytes(Map? map) { } List? getEnabledRows( - List? rows, List? enabledList) { - if (rows == null || enabledList == null) { + List? rows, List? isRowEnabledList) { + if (rows == null || isRowEnabledList == null) { return rows; } List finalRows = - rows.where((element) => enabledList[rows.indexOf(element)]).toList(); + rows.where((element) => isRowEnabledList[rows.indexOf(element)]).toList(); return finalRows == [] ? null : finalRows; } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index 15efa7f4..2bf30731 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -80,8 +80,7 @@ Map requestModelToHARJsonRequest( var rec = getValidRequestUri( requestModel.url, - requestModel.requestParams, - requestModel.enabledParams, + requestModel.enabledRequestParams, defaultUriScheme: defaultUriScheme, ); @@ -126,9 +125,9 @@ Map requestModelToHARJsonRequest( } } - var headersList = requestModel.requestHeaders; + var headersList = requestModel.enabledRequestHeaders; if (headersList != null || hasBody) { - var headers = requestModel.headersMap; + var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { if (hasBody) { var m = { diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 927cdc24..63aa6181 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -4,7 +4,7 @@ import 'package:collection/collection.dart' show mergeMaps; import 'package:http_parser/http_parser.dart'; import 'package:xml/xml.dart'; import '../models/models.dart'; -import 'convert_utils.dart' show getEnabledRows, rowsToMap; +import 'convert_utils.dart' show rowsToMap; import '../consts.dart'; String getRequestTitleFromUrl(String? url) { @@ -63,7 +63,7 @@ String stripUrlParams(String url) { } (Uri?, String?) getValidRequestUri( - String? url, List? requestParams, List? enabledParams, + String? url, List? requestParams, {String defaultUriScheme = kDefaultUriScheme}) { url = url?.trim(); if (url == null || url == "") { @@ -88,8 +88,7 @@ String stripUrlParams(String url) { uri = uri.removeFragment(); } - Map? queryParams = - rowsToMap(getEnabledRows(requestParams, enabledParams)); + Map? queryParams = rowsToMap(requestParams); if (queryParams != null) { if (uri.hasQuery) { Map urlQueryParams = uri.queryParameters; diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index 3c73b9d4..b1b56bfd 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -106,9 +106,9 @@ void main() { 'content-length': '18', 'content-type': 'application/json; charset=utf-8' }, - 'enabledHeaders': null, + 'isHeaderEnabledList': null, 'requestParams': null, - 'enabledParams': null, + 'isParamEnabledList': null, "requestBodyContentType": 'json', "requestBody": '''{ "text":"WORLD" diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 5b10cb63..55129bcc 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -182,16 +182,15 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url1, [kvRow1], null), (uri1Expected, null)); + expect(getValidRequestUri(url1, [kvRow1]), (uri1Expected, null)); }); test('Testing getValidRequestUri for null url value', () { const kvRow2 = NameValueModel(name: "code", value: "US"); - expect( - getValidRequestUri(null, [kvRow2], null), (null, "URL is missing!")); + expect(getValidRequestUri(null, [kvRow2]), (null, "URL is missing!")); }); test('Testing getValidRequestUri for empty url value', () { const kvRow3 = NameValueModel(name: "", value: ""); - expect(getValidRequestUri("", [kvRow3], null), (null, "URL is missing!")); + expect(getValidRequestUri("", [kvRow3]), (null, "URL is missing!")); }); test('Testing getValidRequestUri when https is not provided in url', () { String url4 = "api.foss42.com/country/data"; @@ -201,7 +200,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url4, [kvRow4], null), (uri4Expected, null)); + expect(getValidRequestUri(url4, [kvRow4]), (uri4Expected, null)); }); test('Testing getValidRequestUri when url has fragment', () { String url5 = "https://dart.dev/guides/libraries/library-tour#numbers"; @@ -209,11 +208,11 @@ void main() { scheme: 'https', host: 'dart.dev', path: '/guides/libraries/library-tour'); - expect(getValidRequestUri(url5, null, null), (uri5Expected, null)); + expect(getValidRequestUri(url5, null), (uri5Expected, null)); }); test('Testing getValidRequestUri when uri scheme is not supported', () { String url5 = "mailto:someone@example.com"; - expect(getValidRequestUri(url5, null, null), + expect(getValidRequestUri(url5, null), (null, "Unsupported URL Scheme (mailto)")); }); test('Testing getValidRequestUri when query params in both url and kvrow', @@ -225,7 +224,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url6, [kvRow6], null), (uri6Expected, null)); + expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null)); }); test('Testing getValidRequestUri when kvrow is null', () { String url7 = "api.foss42.com/country/data?code=US"; @@ -234,7 +233,7 @@ void main() { host: 'api.foss42.com', path: 'country/data', queryParameters: {'code': 'US'}); - expect(getValidRequestUri(url7, null, null), (uri7Expected, null)); + expect(getValidRequestUri(url7, null), (uri7Expected, null)); }); }); From 72bc6a6487709a1c82c0777da9f05309513dea2b Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:25:59 +0530 Subject: [PATCH 042/123] chore: add test for getEnabledRows --- test/utils/convert_utils_test.dart | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index 26be2c10..713d6242 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -127,4 +127,54 @@ Easily manipulate and play around with request inputs like headers, query parame expect(padMultilineString(text1, 10), text1FirstLineNotPaddedExpected); }); }); + + group("Test getEnabledRows", () { + test('Testing for null', () { + expect(getEnabledRows(null, null), null); + }); + test('Testing for empty list', () { + expect(getEnabledRows([], null), []); + }); + test('Testing for empty list', () { + expect(getEnabledRows([], []), []); + }); + test('Testing with isRowEnabledList null', () { + const kvRow1 = NameValueModel(name: "code", value: "IN"); + const kvRow2 = NameValueModel(name: "lang", value: "eng"); + const kvRow3 = NameValueModel(name: "version", value: 0.1); + const kvRow4 = NameValueModel(name: "month", value: 4); + expect(getEnabledRows([kvRow1, kvRow2, kvRow3, kvRow4], null), + [kvRow1, kvRow2, kvRow3, kvRow4]); + }); + test('Testing for list with all enabled', () { + const kvRow1 = NameValueModel(name: "code", value: "IN"); + const kvRow2 = NameValueModel(name: "lang", value: "eng"); + const kvRow3 = NameValueModel(name: "version", value: 0.1); + const kvRow4 = NameValueModel(name: "month", value: 4); + expect( + getEnabledRows( + [kvRow1, kvRow2, kvRow3, kvRow4], [true, true, true, true]), + [kvRow1, kvRow2, kvRow3, kvRow4]); + }); + test('Testing for list with all disabled', () { + const kvRow1 = NameValueModel(name: "code", value: "IN"); + const kvRow2 = NameValueModel(name: "lang", value: "eng"); + const kvRow3 = NameValueModel(name: "version", value: 0.1); + const kvRow4 = NameValueModel(name: "month", value: 4); + expect( + getEnabledRows( + [kvRow1, kvRow2, kvRow3, kvRow4], [false, false, false, false]), + []); + }); + test('Testing for list with some disabled', () { + const kvRow1 = NameValueModel(name: "code", value: "IN"); + const kvRow2 = NameValueModel(name: "lang", value: "eng"); + const kvRow3 = NameValueModel(name: "version", value: 0.1); + const kvRow4 = NameValueModel(name: "month", value: 4); + expect( + getEnabledRows( + [kvRow1, kvRow2, kvRow3, kvRow4], [true, false, true, false]), + [kvRow1, kvRow3]); + }); + }); } From ba007ad0ed85171857657b17468a4d70d9612015 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:45:59 +0530 Subject: [PATCH 043/123] fix: setState --- .../request_pane/request_headers.dart | 10 +++++----- .../request_pane/request_params.dart | 16 +++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 4517d1d1..312307ad 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -126,13 +126,13 @@ class EditRequestHeadersState extends ConsumerState { onTap: () { seed = random.nextInt(kRandMax); if (rows.length == 1) { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; + setState(() { + rows = [kNameValueEmptyModel]; + isRowEnabledList = [true]; + }); } else { - isRowEnabledList.removeAt(row.index); rows.removeAt(row.index); + isRowEnabledList.removeAt(row.index); } _onFieldChange(activeId!); }, diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 83603631..e4e0ebb4 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -128,13 +128,13 @@ class EditRequestURLParamsState extends ConsumerState { onTap: () { seed = random.nextInt(kRandMax); if (rows.length == 1) { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; + setState(() { + rows = [kNameValueEmptyModel]; + isRowEnabledList = [true]; + }); } else { - isRowEnabledList.removeAt(row.index); rows.removeAt(row.index); + isRowEnabledList.removeAt(row.index); } _onFieldChange(activeId!); }, @@ -168,10 +168,8 @@ class EditRequestURLParamsState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - setState(() { - rows.add(kNameValueEmptyModel); - isRowEnabledList.add(true); - }); + rows.add(kNameValueEmptyModel); + isRowEnabledList.add(true); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), From d912d5fcb58090f4fab117c91393426229d4b7c6 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Sat, 23 Dec 2023 02:10:08 +0530 Subject: [PATCH 044/123] Update convert_utils_test.dart --- test/utils/convert_utils_test.dart | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index 713d6242..53ec1c84 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -132,45 +132,30 @@ Easily manipulate and play around with request inputs like headers, query parame test('Testing for null', () { expect(getEnabledRows(null, null), null); }); - test('Testing for empty list', () { - expect(getEnabledRows([], null), []); - }); test('Testing for empty list', () { expect(getEnabledRows([], []), []); }); + const kvRow1 = NameValueModel(name: "code", value: "IN"); + const kvRow2 = NameValueModel(name: "lang", value: "eng"); + const kvRow3 = NameValueModel(name: "version", value: 0.1); + const kvRow4 = NameValueModel(name: "month", value: 4); test('Testing with isRowEnabledList null', () { - const kvRow1 = NameValueModel(name: "code", value: "IN"); - const kvRow2 = NameValueModel(name: "lang", value: "eng"); - const kvRow3 = NameValueModel(name: "version", value: 0.1); - const kvRow4 = NameValueModel(name: "month", value: 4); expect(getEnabledRows([kvRow1, kvRow2, kvRow3, kvRow4], null), [kvRow1, kvRow2, kvRow3, kvRow4]); }); test('Testing for list with all enabled', () { - const kvRow1 = NameValueModel(name: "code", value: "IN"); - const kvRow2 = NameValueModel(name: "lang", value: "eng"); - const kvRow3 = NameValueModel(name: "version", value: 0.1); - const kvRow4 = NameValueModel(name: "month", value: 4); expect( getEnabledRows( [kvRow1, kvRow2, kvRow3, kvRow4], [true, true, true, true]), [kvRow1, kvRow2, kvRow3, kvRow4]); }); test('Testing for list with all disabled', () { - const kvRow1 = NameValueModel(name: "code", value: "IN"); - const kvRow2 = NameValueModel(name: "lang", value: "eng"); - const kvRow3 = NameValueModel(name: "version", value: 0.1); - const kvRow4 = NameValueModel(name: "month", value: 4); expect( getEnabledRows( [kvRow1, kvRow2, kvRow3, kvRow4], [false, false, false, false]), []); }); test('Testing for list with some disabled', () { - const kvRow1 = NameValueModel(name: "code", value: "IN"); - const kvRow2 = NameValueModel(name: "lang", value: "eng"); - const kvRow3 = NameValueModel(name: "version", value: 0.1); - const kvRow4 = NameValueModel(name: "month", value: 4); expect( getEnabledRows( [kvRow1, kvRow2, kvRow3, kvRow4], [true, false, true, false]), From 20be6b1ba103d00fd389e9a4bac9fe62a33c0fec Mon Sep 17 00:00:00 2001 From: laiiihz Date: Sat, 23 Dec 2023 16:57:49 +0800 Subject: [PATCH 045/123] fix: fix dart code gen tests' matcher --- test/codegen/dart_dio_codegen_test.dart | 104 ++++------------ test/codegen/dart_http_codegen_test.dart | 146 ++++++----------------- 2 files changed, 62 insertions(+), 188 deletions(-) diff --git a/test/codegen/dart_dio_codegen_test.dart b/test/codegen/dart_dio_codegen_test.dart index 274511b4..6f1e3149 100644 --- a/test/codegen/dart_dio_codegen_test.dart +++ b/test/codegen/dart_dio_codegen_test.dart @@ -1,17 +1,8 @@ import 'package:apidash/codegen/dart/dio.dart'; -import 'package:dart_style/dart_style.dart'; import 'package:test/test.dart'; + import '../request_models.dart'; -final _formatter = DartFormatter(fixes: [ - StyleFix.singleCascadeStatements -]); - -extension on String { - // format code before compare - String get format => _formatter.format(this); -} - void main() { final dartDioCodeGen = DartDioCodeGen(); @@ -34,10 +25,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet1, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet1, "https"), expectedCode); }); test('GET 2', () { @@ -62,10 +50,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet2, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet2, "https"), expectedCode); }); test('GET 3', () { @@ -90,10 +75,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet3, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet3, "https"), expectedCode); }); test('GET 4', () { @@ -102,11 +84,11 @@ void main() async { void main() async { try { final queryParams = { - 'num': '8700000', - 'digits': '3', - 'system': 'SS', - 'add_space': 'true', - 'trailing_zeros': 'true', + 'num': '8700000', + 'digits': '3', + 'system': 'SS', + 'add_space': 'true', + 'trailing_zeros': 'true', }; final response = await dio.Dio.get( 'https://api.foss42.com/humanize/social', @@ -124,10 +106,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet4, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet4, "https"), expectedCode); }); test('GET 5', () { @@ -152,10 +131,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet5, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet5, "https"), expectedCode); }); test('GET 6', () { @@ -182,10 +158,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet6, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet6, "https"), expectedCode); }); test('GET 7', () { @@ -206,10 +179,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet7, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet7, "https"), expectedCode); }); test('GET 8', () { @@ -236,10 +206,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelGet8, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); }); @@ -262,10 +229,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelHead1, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelHead1, "https"), expectedCode); }); test('HEAD 2', () { @@ -286,8 +250,7 @@ void main() async { } } """; - expect(dartDioCodeGen.getCode(requestModelHead2, "http"), - expectedCode.format); + expect(dartDioCodeGen.getCode(requestModelHead2, "http"), expectedCode); }); }); @@ -297,7 +260,7 @@ void main() async { void main() async { try { - final data = r'''{ + final data = r'''{ "text": "I LOVE Flutter" }'''; final response = await dio.Dio.post( @@ -316,10 +279,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelPost1, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelPost1, "https"), expectedCode); }); test('POST 2', () { @@ -347,10 +307,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelPost2, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelPost2, "https"), expectedCode); }); test('POST 3', () { @@ -380,10 +337,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelPost3, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); group('PUT Request', () { @@ -413,10 +367,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelPut1, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelPut1, "https"), expectedCode); }); }); @@ -447,10 +398,7 @@ void main() async { } } """; - expect( - dartDioCodeGen.getCode(requestModelPatch1, "https"), - expectedCode.format, - ); + expect(dartDioCodeGen.getCode(requestModelPatch1, "https"), expectedCode); }); }); @@ -474,9 +422,7 @@ void main() async { } """; expect( - dartDioCodeGen.getCode(requestModelDelete1, "https"), - expectedCode.format, - ); + dartDioCodeGen.getCode(requestModelDelete1, "https"), expectedCode); }); test('DELETE 2', () { @@ -506,9 +452,7 @@ void main() async { } """; expect( - dartDioCodeGen.getCode(requestModelDelete2, "https"), - expectedCode.format, - ); + dartDioCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); } diff --git a/test/codegen/dart_http_codegen_test.dart b/test/codegen/dart_http_codegen_test.dart index 0bdc5f60..b28018c5 100644 --- a/test/codegen/dart_http_codegen_test.dart +++ b/test/codegen/dart_http_codegen_test.dart @@ -1,17 +1,8 @@ import 'package:apidash/codegen/dart/http.dart'; -import 'package:dart_style/dart_style.dart'; import 'package:test/test.dart'; + import '../request_models.dart'; -final _formatter = DartFormatter(fixes: [ - StyleFix.singleCascadeStatements -]); - -extension on String { - // format code before compare - String get format => _formatter.format(this); -} - void main() { final dartHttpCodeGen = DartHttpCodeGen(); @@ -28,17 +19,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet1, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet1, "https"), expectedCode); }); test('GET 2', () { @@ -56,26 +43,24 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet2, "https"), - expectedCode.format, - ); + + expect(dartHttpCodeGen.getCode(requestModelGet2, "https"), expectedCode); }); test('GET 3', () { const expectedCode = r"""import 'package:http/http.dart' as http; + void main() async { var uri = Uri.parse('https://api.foss42.com/country/data?code=US'); var queryParams = {'code': 'IND'}; - var urlQueryParams = Map.from(uri.queryParameters); + var urlQueryParams = Map.from(uri.queryParameters); urlQueryParams.addAll(queryParams); uri = uri.replace(queryParameters: urlQueryParams); @@ -85,17 +70,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet3, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet3, "https"), expectedCode); }); test('GET 4', () { @@ -119,17 +100,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet4, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet4, "https"), expectedCode); }); test('GET 5', () { @@ -149,17 +126,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet5, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet5, "https"), expectedCode); }); test('GET 6', () { @@ -182,17 +155,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet6, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet6, "https"), expectedCode); }); test('GET 7', () { @@ -207,17 +176,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet7, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet7, "https"), expectedCode); }); test('GET 8', () { @@ -240,17 +205,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelGet8, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); }); @@ -267,17 +228,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelHead1, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelHead1, "https"), expectedCode); }); test('HEAD 2', () { @@ -292,15 +249,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect(dartHttpCodeGen.getCode(requestModelHead2, "http"), - expectedCode.format); + expect(dartHttpCodeGen.getCode(requestModelHead2, "http"), expectedCode); }); }); @@ -327,17 +282,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelPost1, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelPost1, "https"), expectedCode); }); test('POST 2', () { @@ -362,17 +313,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelPost2, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelPost2, "https"), expectedCode); }); test('POST 3', () { @@ -400,17 +347,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelPost3, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); group('PUT Request', () { @@ -437,17 +380,13 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; - expect( - dartHttpCodeGen.getCode(requestModelPut1, "https"), - expectedCode.format, - ); + expect(dartHttpCodeGen.getCode(requestModelPut1, "https"), expectedCode); }); }); @@ -475,17 +414,14 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; expect( - dartHttpCodeGen.getCode(requestModelPatch1, "https"), - expectedCode.format, - ); + dartHttpCodeGen.getCode(requestModelPatch1, "https"), expectedCode); }); }); @@ -502,17 +438,14 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; expect( - dartHttpCodeGen.getCode(requestModelDelete1, "https"), - expectedCode.format, - ); + dartHttpCodeGen.getCode(requestModelDelete1, "https"), expectedCode); }); test('DELETE 2', () { @@ -538,17 +471,14 @@ void main() async { if (statusCode >= 200 && statusCode < 300) { print('Status Code: $statusCode'); print('Response Body: ${response.body}'); - } - else{ + } else { print('Error Status Code: $statusCode'); print('Error Response Body: ${response.body}'); } } """; expect( - dartHttpCodeGen.getCode(requestModelDelete2, "https"), - expectedCode.format, - ); + dartHttpCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); } From 1444317d914fd412609483b13650889f7fcbdea6 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:47:53 +0530 Subject: [PATCH 046/123] fix: PR fixes with few enhancements --- lib/consts.dart | 19 ++-- lib/models/form_data_model.dart | 2 +- lib/models/form_data_model.freezed.dart | 29 +++-- lib/models/form_data_model.g.dart | 2 +- lib/models/models.dart | 1 + .../request_pane/request_body.dart | 12 +- lib/utils/convert_utils.dart | 29 +++-- lib/widgets/dropdowns.dart | 1 + lib/widgets/form_data_field.dart | 52 ++++----- lib/widgets/form_data_widget.dart | 104 ++++++++++-------- 10 files changed, 122 insertions(+), 129 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index d5201956..967a20b7 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -1,10 +1,9 @@ -import 'dart:convert'; import 'dart:io'; - -import 'package:davi/davi.dart'; +import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:davi/davi.dart'; const kDiscordUrl = "https://bit.ly/heyfoss"; const kGitUrl = "https://github.com/foss42/apidash"; @@ -49,6 +48,10 @@ const kHintOpacity = 0.6; const kForegroundOpacity = 0.05; const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); +const kFormDataButton = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, +); const kBorderRadius8 = BorderRadius.all(Radius.circular(8)); final kBorderRadius10 = BorderRadius.circular(10); @@ -74,7 +77,7 @@ const kPh60 = EdgeInsets.symmetric(horizontal: 60); const kP24CollectionPane = EdgeInsets.only(top: 24, left: 8.0, bottom: 8.0); const kP8CollectionPane = EdgeInsets.only(top: 8.0, left: 8.0, bottom: 8.0); const kPr8CollectionPane = EdgeInsets.only(right: 8.0); - +const kpsV5 = EdgeInsets.symmetric(vertical: 2); const kHSpacer4 = SizedBox(width: 4); const kHSpacer5 = SizedBox(width: 5); const kHSpacer10 = SizedBox(width: 10); @@ -300,14 +303,6 @@ const kContentTypeMap = { ContentType.text: "$kTypeText/$kSubTypePlain", ContentType.formdata: "multipart/form-data", }; -const kFormDataTypeMap = { - FormDataType.file: "file", - FormDataType.text: "text", -}; -const kMapFormDataType = { - "file": FormDataType.file, - "text": FormDataType.text, -}; enum ResponseBodyView { preview, code, raw, none } diff --git a/lib/models/form_data_model.dart b/lib/models/form_data_model.dart index 90991419..add20833 100644 --- a/lib/models/form_data_model.dart +++ b/lib/models/form_data_model.dart @@ -8,7 +8,7 @@ part 'form_data_model.g.dart'; class FormDataModel with _$FormDataModel { const factory FormDataModel({ required String name, - required dynamic value, + required String value, required FormDataType type, }) = _FormDataModel; diff --git a/lib/models/form_data_model.freezed.dart b/lib/models/form_data_model.freezed.dart index e1babd78..0958bd4e 100644 --- a/lib/models/form_data_model.freezed.dart +++ b/lib/models/form_data_model.freezed.dart @@ -21,7 +21,7 @@ FormDataModel _$FormDataModelFromJson(Map json) { /// @nodoc mixin _$FormDataModel { String get name => throw _privateConstructorUsedError; - dynamic get value => throw _privateConstructorUsedError; + String get value => throw _privateConstructorUsedError; FormDataType get type => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @@ -36,7 +36,7 @@ abstract class $FormDataModelCopyWith<$Res> { FormDataModel value, $Res Function(FormDataModel) then) = _$FormDataModelCopyWithImpl<$Res, FormDataModel>; @useResult - $Res call({String name, dynamic value, FormDataType type}); + $Res call({String name, String value, FormDataType type}); } /// @nodoc @@ -53,7 +53,7 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel> @override $Res call({ Object? name = null, - Object? value = freezed, + Object? value = null, Object? type = null, }) { return _then(_value.copyWith( @@ -61,10 +61,10 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel> ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - value: freezed == value + value: null == value ? _value.value : value // ignore: cast_nullable_to_non_nullable - as dynamic, + as String, type: null == type ? _value.type : type // ignore: cast_nullable_to_non_nullable @@ -81,7 +81,7 @@ abstract class _$$FormDataModelImplCopyWith<$Res> __$$FormDataModelImplCopyWithImpl<$Res>; @override @useResult - $Res call({String name, dynamic value, FormDataType type}); + $Res call({String name, String value, FormDataType type}); } /// @nodoc @@ -96,7 +96,7 @@ class __$$FormDataModelImplCopyWithImpl<$Res> @override $Res call({ Object? name = null, - Object? value = freezed, + Object? value = null, Object? type = null, }) { return _then(_$FormDataModelImpl( @@ -104,10 +104,10 @@ class __$$FormDataModelImplCopyWithImpl<$Res> ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - value: freezed == value + value: null == value ? _value.value : value // ignore: cast_nullable_to_non_nullable - as dynamic, + as String, type: null == type ? _value.type : type // ignore: cast_nullable_to_non_nullable @@ -128,7 +128,7 @@ class _$FormDataModelImpl implements _FormDataModel { @override final String name; @override - final dynamic value; + final String value; @override final FormDataType type; @@ -143,14 +143,13 @@ class _$FormDataModelImpl implements _FormDataModel { (other.runtimeType == runtimeType && other is _$FormDataModelImpl && (identical(other.name, name) || other.name == name) && - const DeepCollectionEquality().equals(other.value, value) && + (identical(other.value, value) || other.value == value) && (identical(other.type, type) || other.type == type)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash( - runtimeType, name, const DeepCollectionEquality().hash(value), type); + int get hashCode => Object.hash(runtimeType, name, value, type); @JsonKey(ignore: true) @override @@ -169,7 +168,7 @@ class _$FormDataModelImpl implements _FormDataModel { abstract class _FormDataModel implements FormDataModel { const factory _FormDataModel( {required final String name, - required final dynamic value, + required final String value, required final FormDataType type}) = _$FormDataModelImpl; factory _FormDataModel.fromJson(Map json) = @@ -178,7 +177,7 @@ abstract class _FormDataModel implements FormDataModel { @override String get name; @override - dynamic get value; + String get value; @override FormDataType get type; @override diff --git a/lib/models/form_data_model.g.dart b/lib/models/form_data_model.g.dart index 7d9d353b..f539458f 100644 --- a/lib/models/form_data_model.g.dart +++ b/lib/models/form_data_model.g.dart @@ -9,7 +9,7 @@ part of 'form_data_model.dart'; _$FormDataModelImpl _$$FormDataModelImplFromJson(Map json) => _$FormDataModelImpl( name: json['name'] as String, - value: json['value'], + value: json['value'] as String, type: $enumDecode(_$FormDataTypeEnumMap, json['type']), ); diff --git a/lib/models/models.dart b/lib/models/models.dart index 3820e3c2..66d6f6ce 100644 --- a/lib/models/models.dart +++ b/lib/models/models.dart @@ -2,3 +2,4 @@ export 'name_value_model.dart'; export 'request_model.dart'; export 'response_model.dart'; export 'settings_model.dart'; +export 'form_data_model.dart'; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 21dd63c6..f6e06332 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:apidash/consts.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/form_data_widget.dart'; @@ -15,12 +13,9 @@ class EditRequestBody extends ConsumerStatefulWidget { } class _EditRequestBodyState extends ConsumerState { - final random = Random.secure(); - late int seed; @override void initState() { super.initState(); - seed = random.nextInt(kRandMax); } @override @@ -54,12 +49,7 @@ class _EditRequestBodyState extends ConsumerState { ), Expanded( child: requestBodyStateWatcher == ContentType.formdata - ? FormDataWidget( - seed: seed, - onFormDataRemove: () { - seed = random.nextInt(kRandMax); - }, - ) + ? const FormDataWidget() : TextFieldEditor( key: Key("$activeId-body"), fieldKey: "$activeId-body-editor", diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 63b1f3eb..72a88520 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -1,12 +1,9 @@ import 'dart:convert'; import 'dart:typed_data'; - -import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/consts.dart'; +import 'package:apidash/models/models.dart'; import 'package:http/http.dart' as http; -import '../consts.dart'; -import '../models/models.dart'; - String humanizeDuration(Duration? duration) { if (duration == null) { return ""; @@ -113,16 +110,24 @@ List? listToFormDataModel(List? kvMap) { if (kvMap == null) { return null; } - List finalRows = kvMap - .map((formData) => FormDataModel( - name: formData["name"], - value: formData["value"], - type: kMapFormDataType[formData["type"]] ?? FormDataType.text, - )) - .toList(); + List finalRows = kvMap.map( + (formData) { + return FormDataModel( + name: formData["name"], + value: formData["value"], + type: getFormDataType(formData["type"]), + ); + }, + ).toList(); return finalRows; } +FormDataType getFormDataType(String? type) { + List formData = FormDataType.values; + return formData.firstWhere((element) => element.name == type, + orElse: () => FormDataType.text); +} + Uint8List? stringToBytes(String? text) { if (text == null) { return null; diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index 98bd10d4..6ca7a698 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -129,6 +129,7 @@ class _DropdownButtonFormData extends State { Widget build(BuildContext context) { final surfaceColor = Theme.of(context).colorScheme.surface; return DropdownButton( + dropdownColor: surfaceColor, focusColor: surfaceColor, value: widget.formDataType, icon: const Icon( diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart index d00dd70b..0353d033 100644 --- a/lib/widgets/form_data_field.dart +++ b/lib/widgets/form_data_field.dart @@ -27,10 +27,8 @@ class FormDataField extends StatefulWidget { } class _FormDataFieldState extends State { - TextEditingController valueController = TextEditingController(); @override void initState() { - valueController.text = widget.initialValue ?? ""; super.initState(); } @@ -42,45 +40,41 @@ class _FormDataFieldState extends State { Expanded( flex: 1, child: TextFormField( - controller: valueController, + initialValue: widget.initialValue, key: Key(widget.keyId), style: kCodeStyle.copyWith( color: colorScheme.onSurface, ), decoration: InputDecoration( - hintStyle: kCodeStyle.copyWith( - color: colorScheme.outline.withOpacity( - kHintOpacity, - ), - ), - hintText: widget.hintText, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: colorScheme.primary.withOpacity( + hintStyle: kCodeStyle.copyWith( + color: colorScheme.outline.withOpacity( kHintOpacity, ), ), - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: colorScheme.surfaceVariant, + hintText: widget.hintText, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: colorScheme.primary.withOpacity( + kHintOpacity, + ), + ), ), - ), - ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: colorScheme.surfaceVariant, + ), + ), + suffixIcon: DropdownButtonFormData( + formDataType: widget.formDataType, + onChanged: (p0) { + if (widget.onFormDataTypeChanged != null) { + widget.onFormDataTypeChanged!(p0); + } + }, + )), onChanged: widget.onChanged, ), ), - Expanded( - child: DropdownButtonFormData( - formDataType: widget.formDataType, - onChanged: (p0) { - if (widget.onFormDataTypeChanged != null) { - widget.onFormDataTypeChanged!(p0); - valueController.clear(); - } - }, - ), - ) ], ); } diff --git a/lib/widgets/form_data_widget.dart b/lib/widgets/form_data_widget.dart index 85318d70..e28c2fc3 100644 --- a/lib/widgets/form_data_widget.dart +++ b/lib/widgets/form_data_widget.dart @@ -1,5 +1,7 @@ +import 'dart:math'; import 'package:apidash/consts.dart'; import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/models/models.dart'; import 'package:apidash/providers/collection_providers.dart'; import 'package:apidash/widgets/form_data_field.dart'; import 'package:apidash/widgets/textfields.dart'; @@ -9,43 +11,48 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class FormDataWidget extends ConsumerStatefulWidget { - const FormDataWidget({ - super.key, - required this.seed, - required this.onFormDataRemove, - }); - final int seed; - final Function onFormDataRemove; + const FormDataWidget({super.key}); @override ConsumerState createState() => _FormDataBodyState(); } class _FormDataBodyState extends ConsumerState { + late int seed; + final random = Random.secure(); + late List rows; + @override + void initState() { + super.initState(); + seed = random.nextInt(kRandMax); + } + @override Widget build(BuildContext context) { final activeId = ref.watch(activeIdStateProvider); - final requestModel = ref - .read(collectionStateNotifierProvider.notifier) - .getRequestModel(activeId!); - List rows = requestModel?.formDataList ?? []; - DaviModel model = DaviModel( + var formRows = ref.read(activeRequestModelProvider)?.formDataList; + rows = + formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows; + + DaviModel daviModelRows = DaviModel( rows: rows, columns: [ DaviColumn( + cellPadding: kpsV5, name: 'Key', grow: 1, cellBuilder: (_, row) { int idx = row.index; - return SizedBox( + return Theme( + data: Theme.of(context), child: FormDataField( - keyId: "$activeId-$idx-form-v-${widget.seed}", + keyId: "$activeId-$idx-form-v-$seed", initialValue: rows[idx].name, hintText: " Key", onChanged: (value) { rows[idx] = rows[idx].copyWith( name: value, ); - _onFieldChange(activeId); + _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, formDataType: rows[idx].type, @@ -54,7 +61,8 @@ class _FormDataBodyState extends ConsumerState { type: value ?? FormDataType.text, ); rows[idx] = rows[idx].copyWith(value: ""); - _onFieldChange(activeId); + setState(() {}); + _onFieldChange(activeId!); }, ), ); @@ -62,7 +70,9 @@ class _FormDataBodyState extends ConsumerState { sortable: false, ), DaviColumn( - width: 10, + width: 30, + cellPadding: kpsV5, + cellAlignment: Alignment.center, cellBuilder: (_, row) { return Text( "=", @@ -73,6 +83,7 @@ class _FormDataBodyState extends ConsumerState { DaviColumn( name: 'Value', grow: 4, + cellPadding: kpsV5, cellBuilder: (_, row) { int idx = row.index; return rows[idx].type == FormDataType.file @@ -83,36 +94,35 @@ class _FormDataBodyState extends ConsumerState { child: Row( children: [ Expanded( - child: ElevatedButtonTheme( - data: const ElevatedButtonThemeData(), + child: Theme( + data: Theme.of(context), child: ElevatedButton.icon( + icon: const Icon( + Icons.snippet_folder_rounded, + size: 20, + ), + style: const ButtonStyle(), onPressed: () async { FilePickerResult? pickedResult = await FilePicker.platform.pickFiles(); if (pickedResult != null && - pickedResult.files.isNotEmpty) { + pickedResult.files.isNotEmpty && + pickedResult.files.first.path != null) { rows[idx] = rows[idx].copyWith( - value: pickedResult.files.first.path, + value: pickedResult.files.first.path!, ); - _onFieldChange(activeId); + setState(() {}); + _onFieldChange(activeId!); } }, - icon: const Icon( - Icons.snippet_folder_rounded, - size: 18, - ), label: Text( - rows[idx].type == FormDataType.file - ? (rows[idx].value != null - ? rows[idx].value.toString() - : "Select File") + (rows[idx].type == FormDataType.file && + rows[idx].value.isNotEmpty) + ? rows[idx].value.toString() : "Select File", textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, - style: kTextStyleButton.copyWith( - fontSize: 12, - fontWeight: FontWeight.w500, - ), + style: kFormDataButton, ), ), ), @@ -122,12 +132,12 @@ class _FormDataBodyState extends ConsumerState { ), ) : CellField( - keyId: "$activeId-$idx-form-v-${widget.seed}", + keyId: "$activeId-$idx-form-v-$seed", initialValue: rows[idx].value, hintText: " Value", onChanged: (value) { rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(activeId); + _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, ); @@ -143,17 +153,16 @@ class _FormDataBodyState extends ConsumerState { ? kIconRemoveDark : kIconRemoveLight, onTap: () { - widget.onFormDataRemove(); + seed = random.nextInt(kRandMax); if (rows.length == 1) { setState(() { - rows = [ - kFormDataEmptyModel, - ]; + rows = [kFormDataEmptyModel]; }); } else { rows.removeAt(row.index); } - _onFieldChange(activeId); + _onFieldChange(activeId!); + setState(() {}); }, ); }, @@ -173,7 +182,7 @@ class _FormDataBodyState extends ConsumerState { Expanded( child: DaviTheme( data: kTableThemeData, - child: Davi(model), + child: Davi(daviModelRows), ), ), ], @@ -185,8 +194,10 @@ class _FormDataBodyState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - rows.add(kFormDataEmptyModel); - _onFieldChange(activeId); + setState(() { + rows.add(kFormDataEmptyModel); + }); + _onFieldChange(activeId!); }, icon: const Icon(Icons.add), label: const Text( @@ -201,12 +212,9 @@ class _FormDataBodyState extends ConsumerState { } void _onFieldChange(String activeId) { - List formDataList = - ref.read(collectionStateNotifierProvider)?[activeId]?.formDataList ?? - []; ref.read(collectionStateNotifierProvider.notifier).update( activeId, - formDataList: formDataList, + formDataList: rows, ); } } From 35c0ed32c66f198f300dc748ade7185544d8e51e Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:49:50 +0530 Subject: [PATCH 047/123] chore: reverted name view model --- lib/models/name_value_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/models/name_value_model.dart b/lib/models/name_value_model.dart index f99b7a60..3249fd6f 100644 --- a/lib/models/name_value_model.dart +++ b/lib/models/name_value_model.dart @@ -1,5 +1,5 @@ -import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:flutter/foundation.dart'; part 'name_value_model.freezed.dart'; part 'name_value_model.g.dart'; From 57aca1b9c4158c9c9346499edeba642324ef25bb Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:55:41 +0530 Subject: [PATCH 048/123] chore: imports reorder --- lib/models/request_model.dart | 5 +---- lib/providers/collection_providers.dart | 10 ++++------ lib/screens/home_page/collection_pane.dart | 8 ++++---- .../details_card/request_pane/request_body.dart | 8 ++++---- lib/services/http_service.dart | 8 +++----- lib/utils/convert_utils.dart | 6 +++--- lib/widgets/dropdowns.dart | 4 ++-- 7 files changed, 21 insertions(+), 28 deletions(-) diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 2e58015a..0203ea89 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,10 +1,7 @@ import 'package:apidash/consts.dart'; -import 'package:apidash/models/form_data_model.dart'; import 'package:apidash/utils/convert_utils.dart'; import 'package:flutter/foundation.dart'; - -import 'name_value_model.dart'; -import 'response_model.dart'; +import 'package:apidash/models/models.dart'; @immutable class RequestModel { diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index d5acd609..94735616 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,14 +1,12 @@ -import 'package:apidash/models/form_data_model.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:http/http.dart' as http; - -import '../consts.dart'; +import 'settings_providers.dart'; +import 'ui_providers.dart'; import '../models/models.dart'; import '../services/services.dart' show hiveHandler, HiveHandler, request, multiPartRequest; import '../utils/utils.dart' show uuid, collectionToHAR; -import 'settings_providers.dart'; -import 'ui_providers.dart'; +import '../consts.dart'; +import 'package:http/http.dart' as http; final activeIdStateProvider = StateProvider((ref) => null); diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 6f0b0bde..43e4713f 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,9 +1,9 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/providers/providers.dart'; -import 'package:apidash/widgets/widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:apidash/providers/providers.dart'; +import 'package:apidash/widgets/widgets.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/consts.dart'; class CollectionPane extends ConsumerWidget { const CollectionPane({ diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index f6e06332..91d2c97f 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -1,9 +1,9 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/providers/providers.dart'; -import 'package:apidash/widgets/form_data_widget.dart'; -import 'package:apidash/widgets/widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:apidash/providers/providers.dart'; +import 'package:apidash/widgets/widgets.dart'; +import 'package:apidash/consts.dart'; +import 'package:apidash/widgets/form_data_widget.dart'; class EditRequestBody extends ConsumerStatefulWidget { const EditRequestBody({super.key}); diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index d49656a0..2c63145b 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -1,12 +1,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; - -import 'package:apidash/consts.dart'; -import 'package:apidash/models/form_data_model.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/utils/utils.dart'; import 'package:http/http.dart' as http; +import 'package:apidash/utils/utils.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/consts.dart'; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 72a88520..b8829cfc 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -1,7 +1,7 @@ -import 'dart:convert'; import 'dart:typed_data'; -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; +import 'dart:convert'; +import '../models/models.dart'; +import '../consts.dart'; import 'package:http/http.dart' as http; String humanizeDuration(Duration? duration) { diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index 6ca7a698..0c897ea0 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -1,6 +1,6 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart'; import 'package:flutter/material.dart'; +import 'package:apidash/utils/utils.dart'; +import 'package:apidash/consts.dart'; class DropdownButtonHttpMethod extends StatefulWidget { const DropdownButtonHttpMethod({ From 22677d523f70bf1c52dd5dfd716614c0cc46dd92 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:57:31 +0530 Subject: [PATCH 049/123] chore: name value revert --- lib/models/name_value_model.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/models/name_value_model.dart b/lib/models/name_value_model.dart index 3249fd6f..886fbbe8 100644 --- a/lib/models/name_value_model.dart +++ b/lib/models/name_value_model.dart @@ -2,6 +2,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter/foundation.dart'; part 'name_value_model.freezed.dart'; + part 'name_value_model.g.dart'; @freezed From 784b8947aeb4e68df8fb20a62eea49567a40f650 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:00:22 +0530 Subject: [PATCH 050/123] req model imports --- lib/models/request_model.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 0203ea89..97a240f5 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,5 +1,6 @@ import 'package:apidash/consts.dart'; -import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/utils.dart' + show listToFormDataModel, mapToRows, rowsToFormDataMap, rowsToMap; import 'package:flutter/foundation.dart'; import 'package:apidash/models/models.dart'; From 7df09235c42c8ccb44586551e034219c1f56d37a Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:02:12 +0530 Subject: [PATCH 051/123] hive services revert --- lib/services/hive_services.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/services/hive_services.dart b/lib/services/hive_services.dart index 9d7b108c..3052024e 100644 --- a/lib/services/hive_services.dart +++ b/lib/services/hive_services.dart @@ -48,9 +48,8 @@ class HiveHandler { dynamic getRequestModel(String id) => dataBox.get(id); Future setRequestModel( - String id, Map? requestModelJson) { - return dataBox.put(id, requestModelJson); - } + String id, Map? requestModelJson) => + dataBox.put(id, requestModelJson); Future clear() => dataBox.clear(); From a4765e0a64b5f5bf02b5d8f1f4070716c2845690 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:03:44 +0530 Subject: [PATCH 052/123] file ext deleted --- lib/utils/extensions/file_extension.dart | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 lib/utils/extensions/file_extension.dart diff --git a/lib/utils/extensions/file_extension.dart b/lib/utils/extensions/file_extension.dart deleted file mode 100644 index 797a2ec9..00000000 --- a/lib/utils/extensions/file_extension.dart +++ /dev/null @@ -1,5 +0,0 @@ -extension FileExtension on String { - String get fileName { - return split(r'\').last; - } -} From 9f3b146f2783cd671674a646ce87f700d8685270 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 15:59:10 +0530 Subject: [PATCH 053/123] update widgets --- lib/app.dart | 25 +++++++++++++------------ lib/widgets/widgets.dart | 25 +++++++++++++------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index e6999c01..3f6b2a53 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,7 +1,7 @@ -import 'package:apidash/widgets/window_caption.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:window_manager/window_manager.dart' hide WindowCaption; +import 'widgets/widgets.dart' show WindowCaption; import 'providers/providers.dart'; import 'screens/screens.dart'; import 'consts.dart'; @@ -85,18 +85,19 @@ class _DashAppState extends ConsumerState { scaffoldBody: CollectionPane(), ) : Stack( - children: [ - kIsLinux ? const Dashboard() : const App(), - if (kIsWindows) - SizedBox( - height: 29, - child: WindowCaption( - backgroundColor: Colors.transparent, - brightness: isDarkMode ? Brightness.dark : Brightness.light, - ), + children: [ + kIsLinux ? const Dashboard() : const App(), + if (kIsWindows) + SizedBox( + height: 29, + child: WindowCaption( + backgroundColor: Colors.transparent, + brightness: + isDarkMode ? Brightness.dark : Brightness.light, + ), + ), + ], ), - ], - ), ); } } diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index 23929f62..a4921bdc 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -1,22 +1,23 @@ -export 'editor.dart'; export 'buttons.dart'; -export 'tables.dart'; -export 'previewer.dart'; +export 'cards.dart'; export 'code_previewer.dart'; export 'codegen_previewer.dart'; -export 'error_message.dart'; export 'dropdowns.dart'; -export 'splitviews.dart'; -export 'texts.dart'; -export 'textfields.dart'; +export 'editor.dart'; +export 'error_message.dart'; export 'headerfield.dart'; -export 'menus.dart'; -export 'cards.dart'; export 'intro_message.dart'; +export 'json_previewer.dart'; +export 'markdown.dart'; +export 'menus.dart'; +export 'previewer.dart'; export 'request_widgets.dart'; export 'response_widgets.dart'; export 'snackbars.dart'; -export 'markdown.dart'; -export 'uint8_audio_player.dart'; +export 'splitviews.dart'; +export 'tables.dart'; export 'tabs.dart'; -export 'json_previewer.dart'; +export 'textfields.dart'; +export 'texts.dart'; +export 'uint8_audio_player.dart'; +export 'window_caption.dart'; From 03479323f29323219c0d857cc0f9a2671ab28dd4 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 16:41:56 +0530 Subject: [PATCH 054/123] Update consts.dart --- lib/consts.dart | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index ff44e9f5..d881fb86 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -63,14 +63,27 @@ const kP10 = EdgeInsets.all(10); const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0); const kPt5o10 = EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0); +const kPh20 = EdgeInsets.symmetric( + horizontal: 20, +); const kPh20t40 = EdgeInsets.only( left: 20, right: 20, top: 40, ); const kPh60 = EdgeInsets.symmetric(horizontal: 60); -const kP24CollectionPane = EdgeInsets.only(top: 24, left: 8.0, bottom: 8.0); -const kP8CollectionPane = EdgeInsets.only(top: 8.0, left: 8.0, bottom: 8.0); +const kP24CollectionPane = EdgeInsets.only( + top: 24, + left: 4.0, + //right: 4.0, + // bottom: 8.0, +); +const kP8CollectionPane = EdgeInsets.only( + top: 8.0, + left: 4.0, + //right: 4.0, + // bottom: 8.0, +); const kPr8CollectionPane = EdgeInsets.only(right: 8.0); const kHSpacer4 = SizedBox(width: 4); From 22fc1d268d7047e367cf820363e7e993494c28e7 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 16:42:04 +0530 Subject: [PATCH 055/123] Update file_utils.dart --- lib/utils/file_utils.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/utils/file_utils.dart b/lib/utils/file_utils.dart index be18a209..e9594864 100644 --- a/lib/utils/file_utils.dart +++ b/lib/utils/file_utils.dart @@ -7,6 +7,10 @@ import 'package:path_provider/path_provider.dart'; const uuid = Uuid(); +String getNewUuid() { + return uuid.v1(); +} + String? getFileExtension(String? mimeType) { if (mimeType == null) { return null; From aceb3ada088000c3011227586749feacf3428d0d Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 16:42:18 +0530 Subject: [PATCH 056/123] Update box names --- lib/services/hive_services.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/hive_services.dart b/lib/services/hive_services.dart index 3052024e..43ed769c 100644 --- a/lib/services/hive_services.dart +++ b/lib/services/hive_services.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; -const String kDataBox = "data"; +const String kDataBox = "apidash-data"; const String kKeyDataBoxIds = "ids"; -const String kSettingsBox = "settings"; +const String kSettingsBox = "apidash-settings"; Future openBoxes() async { await Hive.initFlutter(); From f00384f7408055d09d7e0fcf73ea71a27a7a8e86 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 16:49:31 +0530 Subject: [PATCH 057/123] Widget refactoring --- lib/widgets/buttons.dart | 102 +++++++++++++---------------- lib/widgets/cards.dart | 8 +-- lib/widgets/codegen_previewer.dart | 21 +++--- lib/widgets/dropdowns.dart | 41 +++--------- lib/widgets/intro_message.dart | 7 +- lib/widgets/markdown.dart | 11 +--- lib/widgets/menus.dart | 9 +-- lib/widgets/response_widgets.dart | 60 +++++++---------- lib/widgets/tables.dart | 13 ++-- lib/widgets/textfields.dart | 43 ++++-------- lib/widgets/texts.dart | 6 +- 11 files changed, 117 insertions(+), 204 deletions(-) diff --git a/lib/widgets/buttons.dart b/lib/widgets/buttons.dart index 10d0c59c..348b81ca 100644 --- a/lib/widgets/buttons.dart +++ b/lib/widgets/buttons.dart @@ -5,7 +5,7 @@ import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; import "snackbars.dart"; -class CopyButton extends StatefulWidget { +class CopyButton extends StatelessWidget { const CopyButton({ super.key, required this.toCopy, @@ -15,21 +15,16 @@ class CopyButton extends StatefulWidget { final String toCopy; final bool showLabel; - @override - State createState() => _CopyButtonState(); -} - -class _CopyButtonState extends State { @override Widget build(BuildContext context) { var sm = ScaffoldMessenger.of(context); return Tooltip( - message: widget.showLabel ? '' : kLabelCopy, + message: showLabel ? '' : kLabelCopy, child: SizedBox( - width: widget.showLabel ? null : kTextButtonMinWidth, + width: showLabel ? null : kTextButtonMinWidth, child: TextButton( onPressed: () async { - await Clipboard.setData(ClipboardData(text: widget.toCopy)); + await Clipboard.setData(ClipboardData(text: toCopy)); sm.hideCurrentSnackBar(); sm.showSnackBar(getSnackBar("Copied")); }, @@ -40,7 +35,7 @@ class _CopyButtonState extends State { Icons.content_copy, size: 20, ), - if (widget.showLabel) const Text(kLabelCopy) + if (showLabel) const Text(kLabelCopy) ], ), ), @@ -49,7 +44,7 @@ class _CopyButtonState extends State { } } -class SendRequestButton extends StatefulWidget { +class SendRequestButton extends StatelessWidget { const SendRequestButton({ super.key, required this.activeId, @@ -61,29 +56,17 @@ class SendRequestButton extends StatefulWidget { final String? sentRequestId; final void Function() onTap; - @override - State createState() => _SendRequestButtonState(); -} - -class _SendRequestButtonState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { - bool disable = widget.sentRequestId != null; + bool disable = sentRequestId != null; return FilledButton( - onPressed: disable ? null : widget.onTap, + onPressed: disable ? null : onTap, child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( disable - ? (widget.activeId == widget.sentRequestId - ? kLabelSending - : kLabelBusy) + ? (activeId == sentRequestId ? kLabelSending : kLabelBusy) : kLabelSend, style: kTextStyleButton, ), @@ -99,7 +82,7 @@ class _SendRequestButtonState extends State { } } -class SaveInDownloadsButton extends StatefulWidget { +class SaveInDownloadsButton extends StatelessWidget { const SaveInDownloadsButton({ super.key, this.content, @@ -115,29 +98,24 @@ class SaveInDownloadsButton extends StatefulWidget { final String? name; final bool showLabel; - @override - State createState() => _SaveInDownloadsButtonState(); -} - -class _SaveInDownloadsButtonState extends State { @override Widget build(BuildContext context) { var sm = ScaffoldMessenger.of(context); return Tooltip( - message: widget.showLabel ? '' : kLabelDownload, + message: showLabel ? '' : kLabelDownload, child: SizedBox( - width: widget.showLabel ? null : kTextButtonMinWidth, + width: showLabel ? null : kTextButtonMinWidth, child: TextButton( - onPressed: (widget.content != null) + onPressed: (content != null) ? () async { var message = ""; var path = await getFileDownloadpath( - widget.name, - widget.ext ?? getFileExtension(widget.mimeType), + name, + ext ?? getFileExtension(mimeType), ); if (path != null) { try { - await saveFile(path, widget.content!); + await saveFile(path, content!); var sp = getShortPath(path); message = 'Saved to $sp'; } catch (e) { @@ -157,7 +135,7 @@ class _SaveInDownloadsButtonState extends State { Icons.download, size: 20, ), - if (widget.showLabel) const Text(kLabelDownload) + if (showLabel) const Text(kLabelDownload) ], ), ), @@ -166,7 +144,7 @@ class _SaveInDownloadsButtonState extends State { } } -class RepoButton extends StatefulWidget { +class RepoButton extends StatelessWidget { const RepoButton({ super.key, this.text, @@ -176,15 +154,10 @@ class RepoButton extends StatefulWidget { final String? text; final IconData? icon; - @override - State createState() => _RepoButtonState(); -} - -class _RepoButtonState extends State { @override Widget build(BuildContext context) { - var label = widget.text ?? "GitHub"; - if (widget.icon == null) { + var label = text ?? "GitHub"; + if (icon == null) { return FilledButton( onPressed: () { launchUrl(Uri.parse(kGitUrl)); @@ -200,7 +173,7 @@ class _RepoButtonState extends State { launchUrl(Uri.parse(kGitUrl)); }, icon: Icon( - widget.icon, + icon, size: 20.0, ), label: Text( @@ -211,7 +184,7 @@ class _RepoButtonState extends State { } } -class DiscordButton extends StatefulWidget { +class DiscordButton extends StatelessWidget { const DiscordButton({ super.key, this.text, @@ -219,14 +192,9 @@ class DiscordButton extends StatefulWidget { final String? text; - @override - State createState() => _DiscordButtonState(); -} - -class _DiscordButtonState extends State { @override Widget build(BuildContext context) { - var label = widget.text ?? 'Discord Server'; + var label = text ?? 'Discord Server'; return FilledButton.icon( onPressed: () { launchUrl(Uri.parse(kDiscordUrl)); @@ -242,3 +210,27 @@ class _DiscordButtonState extends State { ); } } + +class SaveButton extends StatelessWidget { + const SaveButton({ + super.key, + this.onPressed, + }); + + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return TextButton.icon( + onPressed: onPressed, + icon: const Icon( + Icons.save, + size: 20, + ), + label: const Text( + kLabelSave, + style: kTextStyleButton, + ), + ); + } +} diff --git a/lib/widgets/cards.dart b/lib/widgets/cards.dart index 43b3cb0c..e99a71f8 100644 --- a/lib/widgets/cards.dart +++ b/lib/widgets/cards.dart @@ -129,15 +129,11 @@ class SidebarRequestCard extends StatelessWidget { } } -class RequestDetailsCard extends StatefulWidget { +class RequestDetailsCard extends StatelessWidget { const RequestDetailsCard({super.key, this.child}); final Widget? child; @override - State createState() => _RequestDetailsCardState(); -} - -class _RequestDetailsCardState extends State { @override Widget build(BuildContext context) { return Card( @@ -148,7 +144,7 @@ class _RequestDetailsCardState extends State { borderRadius: kBorderRadius12, ), elevation: 0, - child: widget.child, + child: child, ); } } diff --git a/lib/widgets/codegen_previewer.dart b/lib/widgets/codegen_previewer.dart index 537458b7..298610c7 100644 --- a/lib/widgets/codegen_previewer.dart +++ b/lib/widgets/codegen_previewer.dart @@ -97,7 +97,7 @@ List generateSpans( return spans; } -class ViewCodePane extends StatefulWidget { +class ViewCodePane extends StatelessWidget { const ViewCodePane({ super.key, required this.code, @@ -109,11 +109,6 @@ class ViewCodePane extends StatefulWidget { final CodegenLanguage codegenLanguage; final Function(CodegenLanguage?) onChangedCodegenLanguage; - @override - State createState() => _ViewCodePaneState(); -} - -class _ViewCodePaneState extends State { @override Widget build(BuildContext context) { var codeTheme = Theme.of(context).brightness == Brightness.light @@ -145,17 +140,17 @@ class _ViewCodePaneState extends State { children: [ Expanded( child: DropdownButtonCodegenLanguage( - codegenLanguage: widget.codegenLanguage, - onChanged: widget.onChangedCodegenLanguage, + codegenLanguage: codegenLanguage, + onChanged: onChangedCodegenLanguage, ), ), CopyButton( - toCopy: widget.code, + toCopy: code, showLabel: showLabel, ), SaveInDownloadsButton( - content: stringToBytes(widget.code), - ext: widget.codegenLanguage.ext, + content: stringToBytes(code), + ext: codegenLanguage.ext, showLabel: showLabel, ) ], @@ -168,9 +163,9 @@ class _ViewCodePaneState extends State { padding: kP8, decoration: textContainerdecoration, child: CodeGenPreviewer( - code: widget.code, + code: code, theme: codeTheme, - language: widget.codegenLanguage.codeHighlightLang, + language: codegenLanguage.codeHighlightLang, textStyle: kCodeStyle, ), ), diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index e8290714..940ac34c 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; -class DropdownButtonHttpMethod extends StatefulWidget { +class DropdownButtonHttpMethod extends StatelessWidget { const DropdownButtonHttpMethod({ super.key, this.method, @@ -12,30 +12,19 @@ class DropdownButtonHttpMethod extends StatefulWidget { final HTTPVerb? method; final void Function(HTTPVerb? value)? onChanged; - @override - State createState() => - _DropdownButtonHttpMethodState(); -} - -class _DropdownButtonHttpMethodState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { final surfaceColor = Theme.of(context).colorScheme.surface; return DropdownButton( focusColor: surfaceColor, - value: widget.method, + value: method, icon: const Icon(Icons.unfold_more_rounded), elevation: 4, underline: Container( height: 0, ), borderRadius: kBorderRadius12, - onChanged: widget.onChanged, + onChanged: onChanged, items: HTTPVerb.values.map>((HTTPVerb value) { return DropdownMenuItem( value: value, @@ -58,7 +47,7 @@ class _DropdownButtonHttpMethodState extends State { } } -class DropdownButtonContentType extends StatefulWidget { +class DropdownButtonContentType extends StatelessWidget { const DropdownButtonContentType({ super.key, this.contentType, @@ -68,18 +57,12 @@ class DropdownButtonContentType extends StatefulWidget { final ContentType? contentType; final void Function(ContentType?)? onChanged; - @override - State createState() => - _DropdownButtonContentTypeState(); -} - -class _DropdownButtonContentTypeState extends State { @override Widget build(BuildContext context) { final surfaceColor = Theme.of(context).colorScheme.surface; return DropdownButton( focusColor: surfaceColor, - value: widget.contentType, + value: contentType, icon: const Icon( Icons.unfold_more_rounded, size: 16, @@ -91,7 +74,7 @@ class _DropdownButtonContentTypeState extends State { underline: Container( height: 0, ), - onChanged: widget.onChanged, + onChanged: onChanged, borderRadius: kBorderRadius12, items: ContentType.values .map>((ContentType value) { @@ -110,28 +93,22 @@ class _DropdownButtonContentTypeState extends State { } } -class DropdownButtonCodegenLanguage extends StatefulWidget { +class DropdownButtonCodegenLanguage extends StatelessWidget { const DropdownButtonCodegenLanguage({ super.key, this.codegenLanguage, this.onChanged, }); - @override - State createState() => - _DropdownButtonCodegenLanguageState(); final CodegenLanguage? codegenLanguage; final void Function(CodegenLanguage?)? onChanged; -} -class _DropdownButtonCodegenLanguageState - extends State { @override Widget build(BuildContext context) { final surfaceColor = Theme.of(context).colorScheme.surface; return DropdownButton( focusColor: surfaceColor, - value: widget.codegenLanguage, + value: codegenLanguage, icon: const Icon( Icons.unfold_more_rounded, size: 16, @@ -143,7 +120,7 @@ class _DropdownButtonCodegenLanguageState underline: Container( height: 0, ), - onChanged: widget.onChanged, + onChanged: onChanged, borderRadius: kBorderRadius12, items: CodegenLanguage.values .map>((CodegenLanguage value) { diff --git a/lib/widgets/intro_message.dart b/lib/widgets/intro_message.dart index 3feaf712..970596d3 100644 --- a/lib/widgets/intro_message.dart +++ b/lib/widgets/intro_message.dart @@ -5,16 +5,11 @@ import '../consts.dart'; import 'markdown.dart'; import 'error_message.dart'; -class IntroMessage extends StatefulWidget { +class IntroMessage extends StatelessWidget { const IntroMessage({ super.key, }); - @override - State createState() => _IntroMessageState(); -} - -class _IntroMessageState extends State { @override Widget build(BuildContext context) { late String text; diff --git a/lib/widgets/markdown.dart b/lib/widgets/markdown.dart index a9dde1dc..c1467fba 100644 --- a/lib/widgets/markdown.dart +++ b/lib/widgets/markdown.dart @@ -4,7 +4,7 @@ import 'package:markdown/markdown.dart' as md; import 'package:url_launcher/url_launcher.dart'; import 'buttons.dart'; -class CustomMarkdown extends StatefulWidget { +class CustomMarkdown extends StatelessWidget { const CustomMarkdown({ super.key, required this.data, @@ -13,11 +13,6 @@ class CustomMarkdown extends StatefulWidget { final String data; final EdgeInsets padding; - @override - State createState() => _CustomMarkdownState(); -} - -class _CustomMarkdownState extends State { @override Widget build(BuildContext context) { final mdStyleSheet = MarkdownStyleSheet( @@ -25,9 +20,9 @@ class _CustomMarkdownState extends State { p: Theme.of(context).textTheme.titleMedium, ); return Markdown( - padding: widget.padding, + padding: padding, styleSheet: mdStyleSheet, - data: widget.data, + data: data, selectable: true, extensionSet: md.ExtensionSet.gitHubFlavored, onTapLink: (text, href, title) { diff --git a/lib/widgets/menus.dart b/lib/widgets/menus.dart index 02a5a15c..81958a02 100644 --- a/lib/widgets/menus.dart +++ b/lib/widgets/menus.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; -class RequestCardMenu extends StatefulWidget { +class RequestCardMenu extends StatelessWidget { const RequestCardMenu({ super.key, this.onSelected, @@ -9,18 +9,13 @@ class RequestCardMenu extends StatefulWidget { final Function(RequestItemMenuOption)? onSelected; - @override - State createState() => _RequestCardMenuState(); -} - -class _RequestCardMenuState extends State { @override Widget build(BuildContext context) { return PopupMenuButton( padding: EdgeInsets.zero, splashRadius: 14, iconSize: 14, - onSelected: widget.onSelected, + onSelected: onSelected, itemBuilder: (BuildContext context) => >[ const PopupMenuItem( diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index da905749..960fc9dd 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -49,7 +49,7 @@ class SendingWidget extends StatelessWidget { } } -class ResponsePaneHeader extends StatefulWidget { +class ResponsePaneHeader extends StatelessWidget { const ResponsePaneHeader({ super.key, this.responseStatus, @@ -60,11 +60,7 @@ class ResponsePaneHeader extends StatefulWidget { final int? responseStatus; final String? message; final Duration? time; - @override - State createState() => _ResponsePaneHeaderState(); -} -class _ResponsePaneHeaderState extends State { @override Widget build(BuildContext context) { return Padding( @@ -81,10 +77,10 @@ class _ResponsePaneHeaderState extends State { text: "Response (", ), TextSpan( - text: "${widget.responseStatus}", + text: "$responseStatus", style: TextStyle( color: getResponseStatusCodeColor( - widget.responseStatus, + responseStatus, brightness: Theme.of(context).brightness, ), fontFamily: kCodeStyle.fontFamily, @@ -100,13 +96,13 @@ class _ResponsePaneHeaderState extends State { kHSpacer20, Expanded( child: Text( - widget.message ?? "", + message ?? "", softWrap: false, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.titleMedium!.copyWith( fontFamily: kCodeStyle.fontFamily, color: getResponseStatusCodeColor( - widget.responseStatus, + responseStatus, brightness: Theme.of(context).brightness, ), ), @@ -114,7 +110,7 @@ class _ResponsePaneHeaderState extends State { ), kHSpacer20, Text( - humanizeDuration(widget.time), + humanizeDuration(time), style: Theme.of(context).textTheme.titleMedium!.copyWith( fontFamily: kCodeStyle.fontFamily, color: Theme.of(context).colorScheme.secondary, @@ -207,7 +203,7 @@ class _ResponseTabViewState extends State } } -class ResponseHeadersHeader extends StatefulWidget { +class ResponseHeadersHeader extends StatelessWidget { const ResponseHeadersHeader({ super.key, required this.map, @@ -216,11 +212,7 @@ class ResponseHeadersHeader extends StatefulWidget { final Map map; final String name; - @override - State createState() => _ResponseHeadersHeaderState(); -} -class _ResponseHeadersHeaderState extends State { @override Widget build(BuildContext context) { return SizedBox( @@ -229,15 +221,15 @@ class _ResponseHeadersHeaderState extends State { children: [ Expanded( child: Text( - "${widget.name} (${widget.map.length} items)", + "$name (${map.length} items)", style: Theme.of(context).textTheme.labelLarge!.copyWith( fontWeight: FontWeight.bold, ), ), ), - if (widget.map.isNotEmpty) + if (map.isNotEmpty) CopyButton( - toCopy: kEncoder.convert(widget.map), + toCopy: kEncoder.convert(map), ), ], ), @@ -247,7 +239,7 @@ class _ResponseHeadersHeaderState extends State { const kHeaderRow = ["Header Name", "Header Value"]; -class ResponseHeaders extends StatefulWidget { +class ResponseHeaders extends StatelessWidget { const ResponseHeaders({ super.key, required this.responseHeaders, @@ -256,11 +248,7 @@ class ResponseHeaders extends StatefulWidget { final Map responseHeaders; final Map requestHeaders; - @override - State createState() => _ResponseHeadersState(); -} -class _ResponseHeadersState extends State { @override Widget build(BuildContext context) { return Padding( @@ -268,25 +256,25 @@ class _ResponseHeadersState extends State { child: ListView( children: [ ResponseHeadersHeader( - map: widget.responseHeaders, + map: responseHeaders, name: "Response Headers", ), - if (widget.responseHeaders.isNotEmpty) kVSpacer5, - if (widget.responseHeaders.isNotEmpty) + if (responseHeaders.isNotEmpty) kVSpacer5, + if (responseHeaders.isNotEmpty) MapTable( - map: widget.responseHeaders, + map: responseHeaders, colNames: kHeaderRow, firstColumnHeaderCase: true, ), kVSpacer10, ResponseHeadersHeader( - map: widget.requestHeaders, + map: requestHeaders, name: "Request Headers", ), - if (widget.requestHeaders.isNotEmpty) kVSpacer5, - if (widget.requestHeaders.isNotEmpty) + if (requestHeaders.isNotEmpty) kVSpacer5, + if (requestHeaders.isNotEmpty) MapTable( - map: widget.requestHeaders, + map: requestHeaders, colNames: kHeaderRow, firstColumnHeaderCase: true, ), @@ -296,21 +284,17 @@ class _ResponseHeadersState extends State { } } -class ResponseBody extends StatefulWidget { +class ResponseBody extends StatelessWidget { const ResponseBody({ super.key, this.activeRequestModel, }); final RequestModel? activeRequestModel; - @override - State createState() => _ResponseBodyState(); -} -class _ResponseBodyState extends State { @override Widget build(BuildContext context) { - final responseModel = widget.activeRequestModel?.responseModel; + final responseModel = activeRequestModel?.responseModel; if (responseModel == null) { return const ErrorMessage( message: @@ -348,7 +332,7 @@ class _ResponseBodyState extends State { } return BodySuccess( - key: Key("${widget.activeRequestModel!.id}-response"), + key: Key("${activeRequestModel!.id}-response"), mediaType: mediaType, options: options, bytes: responseModel.bodyBytes!, diff --git a/lib/widgets/tables.dart b/lib/widgets/tables.dart index 49d0021b..c238dae0 100644 --- a/lib/widgets/tables.dart +++ b/lib/widgets/tables.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:apidash/utils/utils.dart'; import 'package:apidash/consts.dart'; -class MapTable extends StatefulWidget { +class MapTable extends StatelessWidget { const MapTable( {super.key, required this.map, @@ -13,11 +13,6 @@ class MapTable extends StatefulWidget { final List colNames; final bool firstColumnHeaderCase; - @override - State createState() => _MapTableState(); -} - -class _MapTableState extends State { @override Widget build(BuildContext context) { return Table( @@ -33,7 +28,7 @@ class _MapTableState extends State { defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ TableRow( - children: widget.colNames + children: colNames .map( (e) => TableCell( verticalAlignment: TableCellVerticalAlignment.top, @@ -51,7 +46,7 @@ class _MapTableState extends State { ) .toList(), ), - ...widget.map.entries.map( + ...map.entries.map( (entry) => TableRow( children: [ TableCell( @@ -59,7 +54,7 @@ class _MapTableState extends State { child: Padding( padding: kP1, child: SelectableText( - widget.firstColumnHeaderCase + firstColumnHeaderCase ? formatHeaderCase(entry.key) : entry.key, style: kCodeStyle.copyWith( diff --git a/lib/widgets/textfields.dart b/lib/widgets/textfields.dart index ff7b7313..76d1a9dc 100644 --- a/lib/widgets/textfields.dart +++ b/lib/widgets/textfields.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; -class URLField extends StatefulWidget { +class URLField extends StatelessWidget { const URLField({ super.key, required this.activeId, @@ -13,21 +13,11 @@ class URLField extends StatefulWidget { final String? initialValue; final void Function(String)? onChanged; - @override - State createState() => _URLFieldState(); -} - -class _URLFieldState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return TextFormField( - key: Key("url-${widget.activeId}"), - initialValue: widget.initialValue, + key: Key("url-$activeId"), + initialValue: initialValue, style: kCodeStyle, decoration: InputDecoration( hintText: kHintTextUrlCard, @@ -38,12 +28,12 @@ class _URLFieldState extends State { ), border: InputBorder.none, ), - onChanged: widget.onChanged, + onChanged: onChanged, ); } } -class CellField extends StatefulWidget { +class CellField extends StatelessWidget { const CellField({ super.key, required this.keyId, @@ -59,41 +49,36 @@ class CellField extends StatefulWidget { final void Function(String)? onChanged; final ColorScheme? colorScheme; - @override - State createState() => _CellFieldState(); -} - -class _CellFieldState extends State { @override Widget build(BuildContext context) { - var colorScheme = widget.colorScheme ?? Theme.of(context).colorScheme; + var clrScheme = colorScheme ?? Theme.of(context).colorScheme; return TextFormField( - key: Key(widget.keyId), - initialValue: widget.initialValue, + key: Key(keyId), + initialValue: initialValue, style: kCodeStyle.copyWith( - color: colorScheme.onSurface, + color: clrScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( - color: colorScheme.outline.withOpacity( + color: clrScheme.outline.withOpacity( kHintOpacity, ), ), - hintText: widget.hintText, + hintText: hintText, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: colorScheme.primary.withOpacity( + color: clrScheme.primary.withOpacity( kHintOpacity, ), ), ), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( - color: colorScheme.surfaceVariant, + color: clrScheme.surfaceVariant, ), ), ), - onChanged: widget.onChanged, + onChanged: onChanged, ); } } diff --git a/lib/widgets/texts.dart b/lib/widgets/texts.dart index 861574d7..f2cf5c92 100644 --- a/lib/widgets/texts.dart +++ b/lib/widgets/texts.dart @@ -12,10 +12,14 @@ class MethodBox extends StatelessWidget { if (method == HTTPVerb.delete) { text = "DEL"; } + if (method == HTTPVerb.patch) { + text = "PAT"; + } return SizedBox( - width: 28, + width: 24, child: Text( text, + textAlign: TextAlign.center, style: TextStyle( fontSize: 8, fontWeight: FontWeight.bold, From 5b03a2641bab8e558851c6f28dfb8e08c52f960b Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 17:20:10 +0530 Subject: [PATCH 058/123] saveCollection Util --- lib/common/utils.dart | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 lib/common/utils.dart diff --git a/lib/common/utils.dart b/lib/common/utils.dart new file mode 100644 index 00000000..8eaf2b2c --- /dev/null +++ b/lib/common/utils.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:apidash/utils/utils.dart'; +import 'package:apidash/widgets/widgets.dart'; + +Future saveCollection( + Map data, ScaffoldMessengerState sm) async { + var message = ""; + try { + var pth = await getFileDownloadpath(null, "har"); + if (pth != null) { + await saveFile(pth, jsonMapToBytes(data)); + var sp = getShortPath(pth); + message = 'Saved to $sp'; + } + } catch (e) { + message = "An error occurred while exporting."; + } + sm.hideCurrentSnackBar(); + sm.showSnackBar(getSnackBar(message, small: false)); +} From 3423eb7d8ff44accb75ad633b1c2a2bc9eb83111 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 24 Dec 2023 17:21:42 +0530 Subject: [PATCH 059/123] Refactoring widgets --- lib/screens/dashboard.dart | 18 ++--- .../home_page/editor_pane/url_card.dart | 57 ++------------ lib/screens/home_page/home_page.dart | 7 +- lib/screens/intro_page.dart | 7 +- lib/screens/settings_page.dart | 76 +++++++++---------- 5 files changed, 54 insertions(+), 111 deletions(-) diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index 19d2ca28..35189fd0 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -6,16 +6,11 @@ import 'home_page/home_page.dart'; import 'intro_page.dart'; import 'settings_page.dart'; -class Dashboard extends ConsumerStatefulWidget { +class Dashboard extends ConsumerWidget { const Dashboard({super.key}); @override - ConsumerState createState() => _DashboardState(); -} - -class _DashboardState extends ConsumerState { - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final railIdx = ref.watch(navRailIndexStateProvider); return Scaffold( body: SafeArea( @@ -50,13 +45,13 @@ class _DashboardState extends ConsumerState { children: [ Padding( padding: const EdgeInsets.only(bottom: 16.0), - child: bottomButton(context, railIdx, 1, Icons.help, - Icons.help_outline), + child: bottomButton(context, ref, railIdx, 1, + Icons.help, Icons.help_outline), ), Padding( padding: const EdgeInsets.only(bottom: 16.0), - child: bottomButton(context, railIdx, 2, Icons.settings, - Icons.settings_outlined), + child: bottomButton(context, ref, railIdx, 2, + Icons.settings, Icons.settings_outlined), ), ], ), @@ -99,6 +94,7 @@ class _DashboardState extends ConsumerState { TextButton bottomButton( BuildContext context, + WidgetRef ref, int railIdx, int buttonIdx, IconData selectedIcon, diff --git a/lib/screens/home_page/editor_pane/url_card.dart b/lib/screens/home_page/editor_pane/url_card.dart index 753fb34a..b7df1d66 100644 --- a/lib/screens/home_page/editor_pane/url_card.dart +++ b/lib/screens/home_page/editor_pane/url_card.dart @@ -4,20 +4,9 @@ import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/consts.dart'; -class EditorPaneRequestURLCard extends StatefulWidget { +class EditorPaneRequestURLCard extends StatelessWidget { const EditorPaneRequestURLCard({super.key}); - @override - State createState() => - _EditorPaneRequestURLCardState(); -} - -class _EditorPaneRequestURLCardState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return Card( @@ -52,25 +41,13 @@ class _EditorPaneRequestURLCardState extends State { } } -class DropdownButtonHTTPMethod extends ConsumerStatefulWidget { +class DropdownButtonHTTPMethod extends ConsumerWidget { const DropdownButtonHTTPMethod({ super.key, }); @override - ConsumerState createState() => - _DropdownButtonHTTPMethodState(); -} - -class _DropdownButtonHTTPMethodState - extends ConsumerState { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final method = ref.watch(activeRequestModelProvider.select((value) => value?.method)); return DropdownButtonHttpMethod( @@ -85,23 +62,13 @@ class _DropdownButtonHTTPMethodState } } -class URLTextField extends ConsumerStatefulWidget { +class URLTextField extends ConsumerWidget { const URLTextField({ super.key, }); @override - ConsumerState createState() => _URLTextFieldState(); -} - -class _URLTextFieldState extends ConsumerState { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final activeId = ref.watch(activeIdStateProvider); return URLField( activeId: activeId!, @@ -118,23 +85,13 @@ class _URLTextFieldState extends ConsumerState { } } -class SendButton extends ConsumerStatefulWidget { +class SendButton extends ConsumerWidget { const SendButton({ super.key, }); @override - ConsumerState createState() => _SendButtonState(); -} - -class _SendButtonState extends ConsumerState { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final activeId = ref.watch(activeIdStateProvider); final sentRequestId = ref.watch(sentRequestIdStateProvider); return SendRequestButton( diff --git a/lib/screens/home_page/home_page.dart b/lib/screens/home_page/home_page.dart index d8843f0d..a7338a08 100644 --- a/lib/screens/home_page/home_page.dart +++ b/lib/screens/home_page/home_page.dart @@ -3,14 +3,9 @@ import 'package:apidash/widgets/widgets.dart'; import 'editor_pane/editor_pane.dart'; import 'collection_pane.dart'; -class HomePage extends StatefulWidget { +class HomePage extends StatelessWidget { const HomePage({super.key}); - @override - HomePageState createState() => HomePageState(); -} - -class HomePageState extends State { @override Widget build(BuildContext context) { return const Column( diff --git a/lib/screens/intro_page.dart b/lib/screens/intro_page.dart index f7ca937b..83d32253 100644 --- a/lib/screens/intro_page.dart +++ b/lib/screens/intro_page.dart @@ -1,14 +1,9 @@ import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; -class IntroPage extends StatefulWidget { +class IntroPage extends StatelessWidget { const IntroPage({super.key}); - @override - State createState() => _IntroPageState(); -} - -class _IntroPageState extends State { @override Widget build(BuildContext context) { return const IntroMessage(); diff --git a/lib/screens/settings_page.dart b/lib/screens/settings_page.dart index e1249812..c40c8dd2 100644 --- a/lib/screens/settings_page.dart +++ b/lib/screens/settings_page.dart @@ -2,36 +2,40 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/providers.dart'; import '../widgets/widgets.dart'; -import '../utils/utils.dart'; -import 'package:apidash/consts.dart'; +import '../common/utils.dart'; +import '../consts.dart'; -class SettingsPage extends ConsumerStatefulWidget { +class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override - ConsumerState createState() => _SettingsPageState(); -} - -class _SettingsPageState extends ConsumerState { - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final settings = ref.watch(settingsProvider); final clearingData = ref.watch(clearDataStateProvider); var sm = ScaffoldMessenger.of(context); return Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - constraints: const BoxConstraints(maxWidth: 800), + Padding( + padding: kPh20t40, + child: kIsDesktop + ? Text("Settings", + style: Theme.of(context).textTheme.headlineLarge) + : const SizedBox.shrink(), + ), + kIsDesktop + ? const Padding( + padding: kPh20, + child: Divider( + height: 1, + ), + ) + : const SizedBox.shrink(), + Expanded( child: ListView( - padding: kPh20t40, shrinkWrap: true, + padding: kPh20, children: [ - kIsDesktop - ? Text("Settings", - style: Theme.of(context).textTheme.headlineLarge) - : const SizedBox.shrink(), - kIsDesktop ? const Divider() : const SizedBox.shrink(), SwitchListTile( contentPadding: EdgeInsets.zero, hoverColor: kColorTransparent, @@ -114,26 +118,18 @@ class _SettingsPageState extends ConsumerState { title: const Text('Export Data'), subtitle: const Text( 'Export your collection to HAR (HTTP Archive format).\nVersion control this file or import in other API clients.'), - trailing: FilledButton( + trailing: FilledButton.icon( onPressed: () async { - var message = ""; - try { - var data = await ref - .read(collectionStateNotifierProvider.notifier) - .exportDataToHAR(); - var pth = await getFileDownloadpath(null, "har"); - if (pth != null) { - await saveFile(pth, jsonMapToBytes(data)); - var sp = getShortPath(pth); - message = 'Saved to $sp'; - } - } catch (e) { - message = "An error occurred while exporting."; - } - sm.hideCurrentSnackBar(); - sm.showSnackBar(getSnackBar(message, small: false)); + var data = await ref + .read(collectionStateNotifierProvider.notifier) + .exportDataToHAR(); + await saveCollection(data, sm); }, - child: const Text("Export Data"), + label: const Text("Export"), + icon: const Icon( + Icons.arrow_outward_rounded, + size: 20, + ), ), ), ListTile( @@ -141,7 +137,7 @@ class _SettingsPageState extends ConsumerState { hoverColor: kColorTransparent, title: const Text('Clear Data'), subtitle: const Text('Delete all requests data from the disk'), - trailing: FilledButton.tonal( + trailing: FilledButton.tonalIcon( style: FilledButton.styleFrom( backgroundColor: settings.isDark ? kColorDarkDanger @@ -185,7 +181,11 @@ class _SettingsPageState extends ConsumerState { ], ), ), - child: const Text("Clear Data"), + label: const Text("Clear"), + icon: const Icon( + Icons.delete_forever_rounded, + size: 20, + ), ), ), ], From 3fd0a1933c4fe42f166bb3148c5bd203351faf79 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:16:40 +0530 Subject: [PATCH 060/123] chore: add request_model tests --- lib/codegen/dart/dio.dart | 4 +- lib/codegen/js/axios.dart | 2 +- lib/codegen/js/fetch.dart | 2 +- lib/codegen/others/curl.dart | 2 +- lib/codegen/others/har.dart | 6 +- .../request_pane/request_headers.dart | 4 +- .../request_pane/request_params.dart | 4 +- lib/utils/har_utils.dart | 8 +- lib/utils/header_utils.dart | 1 + test/codegen/curl_codegen_test.dart | 37 ++++++ test/codegen/dart_dio_codegen_test.dart | 115 ++++++++++++++++ test/codegen/dart_http_codegen_test.dart | 117 ++++++++++++++++ test/codegen/har_codegen_test.dart | 83 ++++++++++++ test/codegen/js_axios_codegen_test.dart | 109 +++++++++++++++ test/codegen/js_fetch_codegen_test.dart | 121 +++++++++++++++++ test/codegen/kotlin_okhttp_codegen_test.dart | 113 ++++++++++++++++ test/codegen/nodejs_axios_codegen_test.dart | 117 ++++++++++++++++ test/codegen/nodejs_fetch_codegen_test.dart | 125 ++++++++++++++++++ .../python_http_client_codegen_test.dart | 92 +++++++++++++ .../codegen/python_requests_codegen_test.dart | 80 +++++++++++ test/request_models.dart | 88 ++++++++++++ 21 files changed, 1219 insertions(+), 11 deletions(-) diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index fcaa8314..1c6a42d3 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -18,8 +18,8 @@ class DartDioCodeGen { final next = generatedDartCode( url: url, method: requestModel.method, - queryParams: requestModel.paramsMap, - headers: requestModel.headersMap, + queryParams: requestModel.enabledParamsMap, + headers: requestModel.enabledHeadersMap, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, ); diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index 21c99c8b..bc338945 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -60,7 +60,7 @@ axios(config) } var rM = requestModel.copyWith(url: url); - var harJson = requestModelToHARJsonRequest(rM); + var harJson = requestModelToHARJsonRequest(rM, useEnabled: true); var templateStart = jj.Template(kTemplateStart); result += templateStart.render({ diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index 2d57d290..bc15b7dd 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -61,7 +61,7 @@ fetch(url, options) } var rM = requestModel.copyWith(url: url); - var harJson = requestModelToHARJsonRequest(rM); + var harJson = requestModelToHARJsonRequest(rM, useEnabled: true); var templateStart = jj.Template(kTemplateStart); result += templateStart.render({ diff --git a/lib/codegen/others/curl.dart b/lib/codegen/others/curl.dart index 5405ee1a..673014aa 100644 --- a/lib/codegen/others/curl.dart +++ b/lib/codegen/others/curl.dart @@ -28,7 +28,7 @@ class cURLCodeGen { } var rM = requestModel.copyWith(url: url); - var harJson = requestModelToHARJsonRequest(rM); + var harJson = requestModelToHARJsonRequest(rM, useEnabled: true); var templateStart = jj.Template(kTemplateStart); result += templateStart.render({ diff --git a/lib/codegen/others/har.dart b/lib/codegen/others/har.dart index f540cf76..77d78f58 100644 --- a/lib/codegen/others/har.dart +++ b/lib/codegen/others/har.dart @@ -9,8 +9,10 @@ class HARCodeGen { ) { try { var harString = kEncoder.convert(requestModelToHARJsonRequest( - requestModel, - defaultUriScheme: defaultUriScheme)); + requestModel, + defaultUriScheme: defaultUriScheme, + useEnabled: true, + )); return harString; } catch (e) { return null; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 312307ad..1637f265 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -127,7 +127,9 @@ class EditRequestHeadersState extends ConsumerState { seed = random.nextInt(kRandMax); if (rows.length == 1) { setState(() { - rows = [kNameValueEmptyModel]; + rows = [ + kNameValueEmptyModel, + ]; isRowEnabledList = [true]; }); } else { diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index e4e0ebb4..18b17e58 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -129,7 +129,9 @@ class EditRequestURLParamsState extends ConsumerState { seed = random.nextInt(kRandMax); if (rows.length == 1) { setState(() { - rows = [kNameValueEmptyModel]; + rows = [ + kNameValueEmptyModel, + ]; isRowEnabledList = [true]; }); } else { diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index 2bf30731..0ec7714d 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -74,6 +74,7 @@ Map requestModelToHARJsonRequest( RequestModel requestModel, { defaultUriScheme = kDefaultUriScheme, bool exportMode = false, + bool useEnabled = false, }) { Map json = {}; bool hasBody = false; @@ -125,9 +126,12 @@ Map requestModelToHARJsonRequest( } } - var headersList = requestModel.enabledRequestHeaders; + var headersList = useEnabled + ? requestModel.enabledRequestHeaders + : requestModel.requestHeaders; if (headersList != null || hasBody) { - var headers = requestModel.enabledHeadersMap; + var headers = + useEnabled ? requestModel.enabledHeadersMap : requestModel.headersMap; if (headers.isNotEmpty || hasBody) { if (hasBody) { var m = { diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..7d0728dd 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,6 +15,7 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": "Indicates the media type of the entity body.", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", diff --git a/test/codegen/curl_codegen_test.dart b/test/codegen/curl_codegen_test.dart index b67c8fa2..73bc8e85 100644 --- a/test/codegen/curl_codegen_test.dart +++ b/test/codegen/curl_codegen_test.dart @@ -100,6 +100,7 @@ void main() { expect(curlCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""curl --request PUT \ @@ -144,4 +145,40 @@ void main() { expect(curlCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'"""; + expect(curlCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social' \ + --header 'User-Agent: Test Agent'"""; + expect( + curlCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&digits=3' \ + --header 'User-Agent: Test Agent'"""; + expect( + curlCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social'"""; + expect( + curlCodeGen.getCode(requestModelDisabledRows, "https"), expectedCode); + }); + }); } diff --git a/test/codegen/dart_dio_codegen_test.dart b/test/codegen/dart_dio_codegen_test.dart index 6f1e3149..fba58e8c 100644 --- a/test/codegen/dart_dio_codegen_test.dart +++ b/test/codegen/dart_dio_codegen_test.dart @@ -340,6 +340,7 @@ void main() async { expect(dartDioCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import 'package:dio/dio.dart' as dio; @@ -455,4 +456,118 @@ void main() async { dartDioCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = { + 'num': '8700000', + 'add_space': 'true', + }; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + queryParameters: queryParams, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = { + 'num': '8700000', + 'digits': '3', + }; + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + queryParameters: queryParams, + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelEnabledRows, "https"), + expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.get('https://api.foss42.com/humanize/social'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/dart_http_codegen_test.dart b/test/codegen/dart_http_codegen_test.dart index b28018c5..faa1f6bf 100644 --- a/test/codegen/dart_http_codegen_test.dart +++ b/test/codegen/dart_http_codegen_test.dart @@ -356,6 +356,7 @@ void main() async { expect(dartHttpCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import 'package:http/http.dart' as http; @@ -481,4 +482,120 @@ void main() async { dartHttpCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var queryParams = { + 'num': '8700000', + 'add_space': 'true', + }; + uri = uri.replace(queryParameters: queryParams); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var headers = {'User-Agent': 'Test Agent'}; + + final response = await http.get( + uri, + headers: headers, + ); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + dartHttpCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var queryParams = { + 'num': '8700000', + 'digits': '3', + }; + uri = uri.replace(queryParameters: queryParams); + + var headers = {'User-Agent': 'Test Agent'}; + + final response = await http.get( + uri, + headers: headers, + ); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelEnabledRows, "https"), + expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/har_codegen_test.dart b/test/codegen/har_codegen_test.dart index cd9be868..e3c89961 100644 --- a/test/codegen/har_codegen_test.dart +++ b/test/codegen/har_codegen_test.dart @@ -240,6 +240,7 @@ void main() { expect(harCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""{ @@ -316,4 +317,86 @@ void main() { expect(harCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social?num=8700000&add_space=true", + "httpVersion": "HTTP/1.1", + "queryString": [ + { + "name": "num", + "value": "8700000" + }, + { + "name": "add_space", + "value": "true" + } + ], + "headers": [] +}"""; + expect( + harCodeGen.getCode(requestModelEnabledParams, "https"), expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social", + "httpVersion": "HTTP/1.1", + "queryString": [], + "headers": [ + { + "name": "User-Agent", + "value": "Test Agent" + } + ] +}"""; + expect( + harCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social?num=8700000&digits=3", + "httpVersion": "HTTP/1.1", + "queryString": [ + { + "name": "num", + "value": "8700000" + }, + { + "name": "digits", + "value": "3" + } + ], + "headers": [ + { + "name": "User-Agent", + "value": "Test Agent" + } + ] +}"""; + expect( + harCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social", + "httpVersion": "HTTP/1.1", + "queryString": [], + "headers": [] +}"""; + expect( + harCodeGen.getCode(requestModelDisabledRows, "https"), expectedCode); + }); + }); } diff --git a/test/codegen/js_axios_codegen_test.dart b/test/codegen/js_axios_codegen_test.dart index d809a122..49dce93b 100644 --- a/test/codegen/js_axios_codegen_test.dart +++ b/test/codegen/js_axios_codegen_test.dart @@ -324,6 +324,7 @@ axios(config) expect(axiosCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""let config = { @@ -425,4 +426,112 @@ axios(config) expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "add_space": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/js_fetch_codegen_test.dart b/test/codegen/js_fetch_codegen_test.dart index 589f59e7..9153c789 100644 --- a/test/codegen/js_fetch_codegen_test.dart +++ b/test/codegen/js_fetch_codegen_test.dart @@ -366,6 +366,7 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""let url = 'https://reqres.in/api/users/2'; @@ -486,4 +487,124 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/kotlin_okhttp_codegen_test.dart b/test/codegen/kotlin_okhttp_codegen_test.dart index f2205a1b..d20177f9 100644 --- a/test/codegen/kotlin_okhttp_codegen_test.dart +++ b/test/codegen/kotlin_okhttp_codegen_test.dart @@ -369,6 +369,7 @@ fun main() { expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r'''import okhttp3.OkHttpClient @@ -497,4 +498,116 @@ fun main() { expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.HttpUrl.Companion.toHttpUrl + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() + .addQueryParameter("num", "8700000") + .addQueryParameter("add_space", "true") + .build() + + val request = Request.Builder() + .url(url) + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect(kotlinOkHttpCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social" + + val request = Request.Builder() + .url(url) + .addHeader("User-Agent", "Test Agent") + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect( + kotlinOkHttpCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.HttpUrl.Companion.toHttpUrl + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() + .addQueryParameter("num", "8700000") + .addQueryParameter("digits", "3") + .build() + + val request = Request.Builder() + .url(url) + .addHeader("User-Agent", "Test Agent") + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect(kotlinOkHttpCodeGen.getCode(requestModelEnabledRows, "https"), + expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social" + + val request = Request.Builder() + .url(url) + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect(kotlinOkHttpCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/nodejs_axios_codegen_test.dart b/test/codegen/nodejs_axios_codegen_test.dart index 180edb8a..b39d571e 100644 --- a/test/codegen/nodejs_axios_codegen_test.dart +++ b/test/codegen/nodejs_axios_codegen_test.dart @@ -350,6 +350,7 @@ axios(config) expect(axiosCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import axios from 'axios'; @@ -459,4 +460,120 @@ axios(config) expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "add_space": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/nodejs_fetch_codegen_test.dart b/test/codegen/nodejs_fetch_codegen_test.dart index 1a82d8a1..d6bfbe29 100644 --- a/test/codegen/nodejs_fetch_codegen_test.dart +++ b/test/codegen/nodejs_fetch_codegen_test.dart @@ -386,6 +386,7 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelPost3, "https"), expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import fetch from 'node-fetch'; @@ -514,4 +515,128 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/python_http_client_codegen_test.dart b/test/codegen/python_http_client_codegen_test.dart index f95d265d..c97777c7 100644 --- a/test/codegen/python_http_client_codegen_test.dart +++ b/test/codegen/python_http_client_codegen_test.dart @@ -285,6 +285,7 @@ print(data.decode("utf-8")) expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import http.client @@ -383,4 +384,95 @@ print(data.decode("utf-8")) expectedCode); }); }); + + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import http.client +from urllib.parse import urlencode + +queryParams = { + "num": "8700000", + "add_space": "true" + } +queryParamsStr = '?' + urlencode(queryParams) + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social" + queryParamsStr) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect( + pythonHttpClientCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import http.client + +headers = { + "User-Agent": "Test Agent" + } + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social", + headers= headers) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect( + pythonHttpClientCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import http.client +from urllib.parse import urlencode + +queryParams = { + "num": "8700000", + "digits": "3" + } +queryParamsStr = '?' + urlencode(queryParams) + +headers = { + "User-Agent": "Test Agent" + } + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social" + queryParamsStr, + headers= headers) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect(pythonHttpClientCodeGen.getCode(requestModelEnabledRows, "https"), + expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import http.client + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social") + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect(pythonHttpClientCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/codegen/python_requests_codegen_test.dart b/test/codegen/python_requests_codegen_test.dart index 67e1f629..aaeb6c45 100644 --- a/test/codegen/python_requests_codegen_test.dart +++ b/test/codegen/python_requests_codegen_test.dart @@ -248,6 +248,7 @@ print('Response Body:', response.text) expectedCode); }); }); + group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import requests @@ -324,4 +325,83 @@ print('Response Body:', response.text) expectedCode); }); }); + group('Request with enabled Rows', () { + test('Enabled Params', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +params = { + "num": "8700000", + "add_space": "true" + } + +response = requests.get(url, params=params) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelEnabledParams, "https"), + expectedCode); + }); + + test('Enabled Headers', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +headers = { + "User-Agent": "Test Agent" + } + +response = requests.get(url, headers=headers) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect( + pythonRequestsCodeGen.getCode( + requestModelEnabledHeaders, + "https", + ), + expectedCode); + }); + + test('Enabled Headers and Params', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +params = { + "num": "8700000", + "digits": "3" + } + +headers = { + "User-Agent": "Test Agent" + } + +response = requests.get(url, params=params, headers=headers) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelEnabledRows, "https"), + expectedCode); + }); + + test('Disabled Headders and Params', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +response = requests.get(url) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelDisabledRows, "https"), + expectedCode); + }); + }); } diff --git a/test/request_models.dart b/test/request_models.dart index ede411bb..b51acaa3 100644 --- a/test/request_models.dart +++ b/test/request_models.dart @@ -180,3 +180,91 @@ const requestModelDelete2 = RequestModel( }""", requestBodyContentType: ContentType.json, ); + +/// Request model with enabled params +const requestModelEnabledParams = RequestModel( + id: 'enabledParams', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + isParamEnabledList: [ + true, + false, + false, + true, + ], +); + +/// Request model with enabled headers +const requestModelEnabledHeaders = RequestModel( + id: 'enabledParams', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isHeaderEnabledList: [ + true, + false, + ], +); + +/// Request model with enabled rows +const requestModelEnabledRows = RequestModel( + id: 'enabledRows', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isParamEnabledList: [ + true, + true, + false, + false, + ], + isHeaderEnabledList: [ + true, + false, + ], +); + +/// Request model with disabled rows +const requestModelDisabledRows = RequestModel( + id: 'disabledRows', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isParamEnabledList: [ + false, + false, + false, + false, + ], + isHeaderEnabledList: [ + false, + false, + ], +); From 880f445c31ae2cff769344147091da03d3e6fedb Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:25:58 +0530 Subject: [PATCH 061/123] fix: fixes for alignment issues and request handling methods --- lib/consts.dart | 2 +- lib/providers/collection_providers.dart | 22 +++---- lib/services/http_service.dart | 80 +++++++----------------- lib/widgets/dropdowns.dart | 4 +- lib/widgets/form_data_widget.dart | 83 +++++++++++++------------ 5 files changed, 76 insertions(+), 115 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 967a20b7..ea2c5325 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -48,7 +48,7 @@ const kHintOpacity = 0.6; const kForegroundOpacity = 0.05; const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); -const kFormDataButton = TextStyle( +const kFormDataButtonLabelTextStyle = TextStyle( fontSize: 12, fontWeight: FontWeight.w600, ); diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 94735616..10317b15 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -2,8 +2,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'settings_providers.dart'; import 'ui_providers.dart'; import '../models/models.dart'; -import '../services/services.dart' - show hiveHandler, HiveHandler, request, multiPartRequest; +import '../services/services.dart' show hiveHandler, HiveHandler, request; import '../utils/utils.dart' show uuid, collectionToHAR; import '../consts.dart'; import 'package:http/http.dart' as http; @@ -158,20 +157,13 @@ class CollectionStateNotifier ref.read(codePaneVisibleStateProvider.notifier).state = false; final defaultUriScheme = ref.read(settingsProvider.select((value) => value.defaultUriScheme)); - (http.Response?, Duration?, String?)? responseRec; RequestModel requestModel = state![id]!; - if (requestModel.formDataList != null && - requestModel.formDataList!.isNotEmpty) { - responseRec = await multiPartRequest( - requestModel, - defaultUriScheme: defaultUriScheme, - ); - } else { - responseRec = await request( - requestModel, - defaultUriScheme: defaultUriScheme, - ); - } + (http.Response?, Duration?, String?)? responseRec = await request( + requestModel, + defaultUriScheme: defaultUriScheme, + isMultiPartRequest: requestModel.formDataList != null && + requestModel.formDataList!.isNotEmpty, + ); late final RequestModel newRequestModel; if (responseRec.$1 == null) { newRequestModel = requestModel.copyWith( diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 2c63145b..8d6e70b9 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -9,6 +9,7 @@ import 'package:apidash/consts.dart'; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { String defaultUriScheme = kDefaultUriScheme, + bool isMultiPartRequest = false, }) async { (Uri?, String?) uriRec = getValidRequestUri( requestModel.url, @@ -33,6 +34,29 @@ Future<(http.Response?, Duration?, String?)> request( } } Stopwatch stopwatch = Stopwatch()..start(); + if (isMultiPartRequest) { + var multiPartRequest = http.MultipartRequest( + requestModel.method.name.toUpperCase(), + requestUrl, + ); + for (FormDataModel formData in (requestModel.formDataList ?? [])) { + if (formData.type == FormDataType.text) { + multiPartRequest.fields.addAll({formData.name: formData.value}); + } else { + multiPartRequest.files.add( + await http.MultipartFile.fromPath( + formData.name, + formData.value, + ), + ); + } + } + http.StreamedResponse multiPartResponse = await multiPartRequest.send(); + stopwatch.stop(); + http.Response convertedMultiPartResponse = + await convertStreamedResponse(multiPartResponse); + return (convertedMultiPartResponse, stopwatch.elapsed, null); + } switch (requestModel.method) { case HTTPVerb.get: response = await http.get(requestUrl, headers: headers); @@ -63,59 +87,3 @@ Future<(http.Response?, Duration?, String?)> request( return (null, null, uriRec.$2); } } - -Future<(http.Response?, Duration?, String?)> multiPartRequest( - RequestModel requestModel, { - String defaultUriScheme = kDefaultUriScheme, -}) async { - (Uri?, String?) uriRec = getValidRequestUri( - requestModel.url, - requestModel.requestParams, - defaultUriScheme: defaultUriScheme, - ); - if (uriRec.$1 != null) { - Uri requestUrl = uriRec.$1!; - Map headers = requestModel.headersMap; - try { - var requestBody = requestModel.requestBody; - if (kMethodsWithBody.contains(requestModel.method) && - requestBody != null) { - var contentLength = utf8.encode(requestBody).length; - if (contentLength > 0) { - headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; - } - } - Stopwatch stopwatch = Stopwatch()..start(); - - var request = http.MultipartRequest( - requestModel.method.name.toUpperCase(), - requestUrl, - ); - for (FormDataModel formData in (requestModel.formDataList ?? [])) { - if (formData.type == FormDataType.text) { - request.fields.addAll({formData.name: formData.value}); - } else { - request.files.add( - await http.MultipartFile.fromPath( - formData.name, - formData.value, - ), - ); - } - } - - http.StreamedResponse response = await request.send(); - - stopwatch.stop(); - http.Response convertedHttpResponse = - await convertStreamedResponse(response); - return (convertedHttpResponse, stopwatch.elapsed, null); - } catch (e) { - return (null, null, e.toString()); - } - } else { - return (null, null, uriRec.$2); - } -} diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index 0c897ea0..f88642c5 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -140,9 +140,7 @@ class _DropdownButtonFormData extends State { style: kCodeStyle.copyWith( color: Theme.of(context).colorScheme.primary, ), - underline: Container( - height: 0, - ), + underline: const IgnorePointer(), onChanged: widget.onChanged, borderRadius: kBorderRadius12, items: FormDataType.values diff --git a/lib/widgets/form_data_widget.dart b/lib/widgets/form_data_widget.dart index e28c2fc3..9a90262a 100644 --- a/lib/widgets/form_data_widget.dart +++ b/lib/widgets/form_data_widget.dart @@ -39,7 +39,7 @@ class _FormDataBodyState extends ConsumerState { DaviColumn( cellPadding: kpsV5, name: 'Key', - grow: 1, + grow: 4, cellBuilder: (_, row) { int idx = row.index; return Theme( @@ -47,7 +47,7 @@ class _FormDataBodyState extends ConsumerState { child: FormDataField( keyId: "$activeId-$idx-form-v-$seed", initialValue: rows[idx].name, - hintText: " Key", + hintText: " Add Key", onChanged: (value) { rows[idx] = rows[idx].copyWith( name: value, @@ -70,7 +70,7 @@ class _FormDataBodyState extends ConsumerState { sortable: false, ), DaviColumn( - width: 30, + width: 40, cellPadding: kpsV5, cellAlignment: Alignment.center, cellBuilder: (_, row) { @@ -89,52 +89,55 @@ class _FormDataBodyState extends ConsumerState { return rows[idx].type == FormDataType.file ? Align( alignment: Alignment.centerLeft, - child: Padding( - padding: kPs8, - child: Row( - children: [ - Expanded( - child: Theme( - data: Theme.of(context), - child: ElevatedButton.icon( - icon: const Icon( - Icons.snippet_folder_rounded, - size: 20, - ), - style: const ButtonStyle(), - onPressed: () async { - FilePickerResult? pickedResult = - await FilePicker.platform.pickFiles(); - if (pickedResult != null && - pickedResult.files.isNotEmpty && - pickedResult.files.first.path != null) { - rows[idx] = rows[idx].copyWith( - value: pickedResult.files.first.path!, - ); - setState(() {}); - _onFieldChange(activeId!); - } - }, - label: Text( - (rows[idx].type == FormDataType.file && - rows[idx].value.isNotEmpty) - ? rows[idx].value.toString() - : "Select File", - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: kFormDataButton, + child: Row( + children: [ + Expanded( + child: Theme( + data: Theme.of(context), + child: ElevatedButton.icon( + icon: const Icon( + Icons.snippet_folder_rounded, + size: 20, + ), + style: ButtonStyle( + shape: MaterialStatePropertyAll( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), ), ), + onPressed: () async { + FilePickerResult? pickedResult = + await FilePicker.platform.pickFiles(); + if (pickedResult != null && + pickedResult.files.isNotEmpty && + pickedResult.files.first.path != null) { + rows[idx] = rows[idx].copyWith( + value: pickedResult.files.first.path!, + ); + setState(() {}); + _onFieldChange(activeId!); + } + }, + label: Text( + (rows[idx].type == FormDataType.file && + rows[idx].value.isNotEmpty) + ? rows[idx].value.toString() + : "Select File", + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: kFormDataButtonLabelTextStyle, + ), ), ), - ], - ), + ), + ], ), ) : CellField( keyId: "$activeId-$idx-form-v-$seed", initialValue: rows[idx].value, - hintText: " Value", + hintText: " Add Value", onChanged: (value) { rows[idx] = rows[idx].copyWith(value: value); _onFieldChange(activeId!); From 80e13fc625622a7e5a37d18ceb9627f79d3da0ab Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:38:23 +0530 Subject: [PATCH 062/123] fix: fixed code gen issues in latest code --- lib/codegen/dart/dio.dart | 2 ++ lib/widgets/dropdowns.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index fcaa8314..1b4a8820 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -68,6 +68,8 @@ class DartDioCodeGen { case ContentType.text: dataExp = declareFinal('data').assign(strContent); // when add new type of [ContentType], need update [dataExp]. + case ContentType.formdata: + // TODO: Need to Handle this case. } } final responseExp = declareFinal('response').assign(InvokeExpression.newOf( diff --git a/lib/widgets/dropdowns.dart b/lib/widgets/dropdowns.dart index be25737d..69008a6b 100644 --- a/lib/widgets/dropdowns.dart +++ b/lib/widgets/dropdowns.dart @@ -143,7 +143,7 @@ class _DropdownButtonFormData extends State { } } -class DropdownButtonCodegenLanguage extends StatefulWidget { +class DropdownButtonCodegenLanguage extends StatelessWidget { const DropdownButtonCodegenLanguage({ super.key, this.codegenLanguage, From 2b41f54015eef432541c1bb5d50ae8e7e0016534 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:49:14 +0530 Subject: [PATCH 063/123] fix: pr fixes --- lib/providers/collection_providers.dart | 4 +- lib/screens/home_page/collection_pane.dart | 62 +++++++++---------- .../request_pane/request_body.dart | 6 -- lib/widgets/widgets.dart | 1 + 4 files changed, 32 insertions(+), 41 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 10317b15..9212ea35 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -161,8 +161,8 @@ class CollectionStateNotifier (http.Response?, Duration?, String?)? responseRec = await request( requestModel, defaultUriScheme: defaultUriScheme, - isMultiPartRequest: requestModel.formDataList != null && - requestModel.formDataList!.isNotEmpty, + isMultiPartRequest: + requestModel.requestBodyContentType == ContentType.formdata, ); late final RequestModel newRequestModel; if (responseRec.$1 == null) { diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 43e4713f..0ea875fb 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -108,40 +108,36 @@ class _RequestListState extends ConsumerState { controller: controller, thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), - child: requestSequence.isNotEmpty - ? ReorderableListView.builder( - padding: kPr8CollectionPane, - scrollController: controller, - buildDefaultDragHandles: false, - itemCount: requestSequence.length, - onReorder: (int oldIndex, int newIndex) { - if (oldIndex < newIndex) { - newIndex -= 1; - } - if (oldIndex != newIndex) { - ref - .read(collectionStateNotifierProvider.notifier) - .reorder(oldIndex, newIndex); - } - }, - itemBuilder: (context, index) { - var id = requestSequence[index]; - return ReorderableDragStartListener( - key: ValueKey(id), - index: index, - child: Padding( - padding: kP1, - child: RequestItem( - id: id, - requestModel: requestItems[id]!, - ), - ), - ); - }, - ) - : const Center( - child: Text("No Requests found"), + child: ReorderableListView.builder( + padding: kPr8CollectionPane, + scrollController: controller, + buildDefaultDragHandles: false, + itemCount: requestSequence.length, + onReorder: (int oldIndex, int newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + if (oldIndex != newIndex) { + ref + .read(collectionStateNotifierProvider.notifier) + .reorder(oldIndex, newIndex); + } + }, + itemBuilder: (context, index) { + var id = requestSequence[index]; + return ReorderableDragStartListener( + key: ValueKey(id), + index: index, + child: Padding( + padding: kP1, + child: RequestItem( + id: id, + requestModel: requestItems[id]!, + ), ), + ); + }, + ), ); } } diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 91d2c97f..94ff858c 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/consts.dart'; -import 'package:apidash/widgets/form_data_widget.dart'; class EditRequestBody extends ConsumerStatefulWidget { const EditRequestBody({super.key}); @@ -13,11 +12,6 @@ class EditRequestBody extends ConsumerStatefulWidget { } class _EditRequestBodyState extends ConsumerState { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { final activeId = ref.watch(activeIdStateProvider); diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index a4921bdc..69598ca8 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -21,3 +21,4 @@ export 'textfields.dart'; export 'texts.dart'; export 'uint8_audio_player.dart'; export 'window_caption.dart'; +export 'form_data_widget.dart'; From f74426f2d5fa1af3b6b56419a38b5ab4f5e5f6cf Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:57:26 +0530 Subject: [PATCH 064/123] fix: renamed and moved tests --- test/codegen/curl_codegen_test.dart | 67 +++-- test/codegen/dart_dio_codegen_test.dart | 223 ++++++++-------- test/codegen/dart_http_codegen_test.dart | 227 ++++++++-------- test/codegen/har_codegen_test.dart | 159 ++++++------ test/codegen/js_axios_codegen_test.dart | 211 ++++++++------- test/codegen/js_fetch_codegen_test.dart | 235 +++++++++-------- test/codegen/kotlin_okhttp_codegen_test.dart | 222 ++++++++-------- test/codegen/nodejs_axios_codegen_test.dart | 227 ++++++++-------- test/codegen/nodejs_fetch_codegen_test.dart | 243 +++++++++--------- .../python_http_client_codegen_test.dart | 179 +++++++------ .../codegen/python_requests_codegen_test.dart | 157 ++++++----- test/request_models.dart | 176 ++++++------- 12 files changed, 1140 insertions(+), 1186 deletions(-) diff --git a/test/codegen/curl_codegen_test.dart b/test/codegen/curl_codegen_test.dart index 73bc8e85..e9bb7f60 100644 --- a/test/codegen/curl_codegen_test.dart +++ b/test/codegen/curl_codegen_test.dart @@ -54,6 +54,37 @@ void main() { --header 'User-Agent: Test Agent'"""; expect(curlCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'"""; + expect(curlCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social' \ + --header 'User-Agent: Test Agent'"""; + expect( + curlCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&digits=3' \ + --header 'User-Agent: Test Agent'"""; + expect(curlCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = + r"""curl --url 'https://api.foss42.com/humanize/social'"""; + expect(curlCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -145,40 +176,4 @@ void main() { expect(curlCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = - r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'"""; - expect(curlCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = - r"""curl --url 'https://api.foss42.com/humanize/social' \ - --header 'User-Agent: Test Agent'"""; - expect( - curlCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = - r"""curl --url 'https://api.foss42.com/humanize/social?num=8700000&digits=3' \ - --header 'User-Agent: Test Agent'"""; - expect( - curlCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = - r"""curl --url 'https://api.foss42.com/humanize/social'"""; - expect( - curlCodeGen.getCode(requestModelDisabledRows, "https"), expectedCode); - }); - }); } diff --git a/test/codegen/dart_dio_codegen_test.dart b/test/codegen/dart_dio_codegen_test.dart index fba58e8c..30b371fd 100644 --- a/test/codegen/dart_dio_codegen_test.dart +++ b/test/codegen/dart_dio_codegen_test.dart @@ -208,6 +208,115 @@ void main() async { """; expect(dartDioCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = { + 'num': '8700000', + 'add_space': 'true', + }; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + queryParameters: queryParams, + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + dartDioCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final queryParams = { + 'num': '8700000', + 'digits': '3', + }; + final headers = {'User-Agent': 'Test Agent'}; + final response = await dio.Dio.get( + 'https://api.foss42.com/humanize/social', + queryParameters: queryParams, + options: Options(headers: headers), + ); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.get('https://api.foss42.com/humanize/social'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect(dartDioCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -456,118 +565,4 @@ void main() async { dartDioCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import 'package:dio/dio.dart' as dio; - -void main() async { - try { - final queryParams = { - 'num': '8700000', - 'add_space': 'true', - }; - final response = await dio.Dio.get( - 'https://api.foss42.com/humanize/social', - queryParameters: queryParams, - ); - print(response.statusCode); - print(response.data); - } on DioException catch (e, s) { - print(e.response?.statusCode); - print(e.response?.data); - print(s); - } catch (e, s) { - print(e); - print(s); - } -} -"""; - expect(dartDioCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import 'package:dio/dio.dart' as dio; - -void main() async { - try { - final headers = {'User-Agent': 'Test Agent'}; - final response = await dio.Dio.get( - 'https://api.foss42.com/humanize/social', - options: Options(headers: headers), - ); - print(response.statusCode); - print(response.data); - } on DioException catch (e, s) { - print(e.response?.statusCode); - print(e.response?.data); - print(s); - } catch (e, s) { - print(e); - print(s); - } -} -"""; - expect( - dartDioCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import 'package:dio/dio.dart' as dio; - -void main() async { - try { - final queryParams = { - 'num': '8700000', - 'digits': '3', - }; - final headers = {'User-Agent': 'Test Agent'}; - final response = await dio.Dio.get( - 'https://api.foss42.com/humanize/social', - queryParameters: queryParams, - options: Options(headers: headers), - ); - print(response.statusCode); - print(response.data); - } on DioException catch (e, s) { - print(e.response?.statusCode); - print(e.response?.data); - print(s); - } catch (e, s) { - print(e); - print(s); - } -} -"""; - expect(dartDioCodeGen.getCode(requestModelEnabledRows, "https"), - expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import 'package:dio/dio.dart' as dio; - -void main() async { - try { - final response = await dio.Dio.get('https://api.foss42.com/humanize/social'); - print(response.statusCode); - print(response.data); - } on DioException catch (e, s) { - print(e.response?.statusCode); - print(e.response?.data); - print(s); - } catch (e, s) { - print(e); - print(s); - } -} -"""; - expect(dartDioCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/dart_http_codegen_test.dart b/test/codegen/dart_http_codegen_test.dart index faa1f6bf..55ab070a 100644 --- a/test/codegen/dart_http_codegen_test.dart +++ b/test/codegen/dart_http_codegen_test.dart @@ -213,6 +213,117 @@ void main() async { """; expect(dartHttpCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var queryParams = { + 'num': '8700000', + 'add_space': 'true', + }; + uri = uri.replace(queryParameters: queryParams); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var headers = {'User-Agent': 'Test Agent'}; + + final response = await http.get( + uri, + headers: headers, + ); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + dartHttpCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var queryParams = { + 'num': '8700000', + 'digits': '3', + }; + uri = uri.replace(queryParameters: queryParams); + + var headers = {'User-Agent': 'Test Agent'}; + + final response = await http.get( + uri, + headers: headers, + ); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -482,120 +593,4 @@ void main() async { dartHttpCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import 'package:http/http.dart' as http; - -void main() async { - var uri = Uri.parse('https://api.foss42.com/humanize/social'); - - var queryParams = { - 'num': '8700000', - 'add_space': 'true', - }; - uri = uri.replace(queryParameters: queryParams); - - final response = await http.get(uri); - - int statusCode = response.statusCode; - if (statusCode >= 200 && statusCode < 300) { - print('Status Code: $statusCode'); - print('Response Body: ${response.body}'); - } else { - print('Error Status Code: $statusCode'); - print('Error Response Body: ${response.body}'); - } -} -"""; - expect(dartHttpCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import 'package:http/http.dart' as http; - -void main() async { - var uri = Uri.parse('https://api.foss42.com/humanize/social'); - - var headers = {'User-Agent': 'Test Agent'}; - - final response = await http.get( - uri, - headers: headers, - ); - - int statusCode = response.statusCode; - if (statusCode >= 200 && statusCode < 300) { - print('Status Code: $statusCode'); - print('Response Body: ${response.body}'); - } else { - print('Error Status Code: $statusCode'); - print('Error Response Body: ${response.body}'); - } -} -"""; - expect( - dartHttpCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import 'package:http/http.dart' as http; - -void main() async { - var uri = Uri.parse('https://api.foss42.com/humanize/social'); - - var queryParams = { - 'num': '8700000', - 'digits': '3', - }; - uri = uri.replace(queryParameters: queryParams); - - var headers = {'User-Agent': 'Test Agent'}; - - final response = await http.get( - uri, - headers: headers, - ); - - int statusCode = response.statusCode; - if (statusCode >= 200 && statusCode < 300) { - print('Status Code: $statusCode'); - print('Response Body: ${response.body}'); - } else { - print('Error Status Code: $statusCode'); - print('Error Response Body: ${response.body}'); - } -} -"""; - expect(dartHttpCodeGen.getCode(requestModelEnabledRows, "https"), - expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import 'package:http/http.dart' as http; - -void main() async { - var uri = Uri.parse('https://api.foss42.com/humanize/social'); - - final response = await http.get(uri); - - int statusCode = response.statusCode; - if (statusCode >= 200 && statusCode < 300) { - print('Status Code: $statusCode'); - print('Response Body: ${response.body}'); - } else { - print('Error Status Code: $statusCode'); - print('Error Response Body: ${response.body}'); - } -} -"""; - expect(dartHttpCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/har_codegen_test.dart b/test/codegen/har_codegen_test.dart index e3c89961..8e6b7bb0 100644 --- a/test/codegen/har_codegen_test.dart +++ b/test/codegen/har_codegen_test.dart @@ -149,6 +149,83 @@ void main() { }"""; expect(harCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social?num=8700000&add_space=true", + "httpVersion": "HTTP/1.1", + "queryString": [ + { + "name": "num", + "value": "8700000" + }, + { + "name": "add_space", + "value": "true" + } + ], + "headers": [] +}"""; + expect(harCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social", + "httpVersion": "HTTP/1.1", + "queryString": [], + "headers": [ + { + "name": "User-Agent", + "value": "Test Agent" + } + ] +}"""; + expect( + harCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social?num=8700000&digits=3", + "httpVersion": "HTTP/1.1", + "queryString": [ + { + "name": "num", + "value": "8700000" + }, + { + "name": "digits", + "value": "3" + } + ], + "headers": [ + { + "name": "User-Agent", + "value": "Test Agent" + } + ] +}"""; + expect(harCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com/humanize/social", + "httpVersion": "HTTP/1.1", + "queryString": [], + "headers": [] +}"""; + expect(harCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -317,86 +394,4 @@ void main() { expect(harCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""{ - "method": "GET", - "url": "https://api.foss42.com/humanize/social?num=8700000&add_space=true", - "httpVersion": "HTTP/1.1", - "queryString": [ - { - "name": "num", - "value": "8700000" - }, - { - "name": "add_space", - "value": "true" - } - ], - "headers": [] -}"""; - expect( - harCodeGen.getCode(requestModelEnabledParams, "https"), expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""{ - "method": "GET", - "url": "https://api.foss42.com/humanize/social", - "httpVersion": "HTTP/1.1", - "queryString": [], - "headers": [ - { - "name": "User-Agent", - "value": "Test Agent" - } - ] -}"""; - expect( - harCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""{ - "method": "GET", - "url": "https://api.foss42.com/humanize/social?num=8700000&digits=3", - "httpVersion": "HTTP/1.1", - "queryString": [ - { - "name": "num", - "value": "8700000" - }, - { - "name": "digits", - "value": "3" - } - ], - "headers": [ - { - "name": "User-Agent", - "value": "Test Agent" - } - ] -}"""; - expect( - harCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""{ - "method": "GET", - "url": "https://api.foss42.com/humanize/social", - "httpVersion": "HTTP/1.1", - "queryString": [], - "headers": [] -}"""; - expect( - harCodeGen.getCode(requestModelDisabledRows, "https"), expectedCode); - }); - }); } diff --git a/test/codegen/js_axios_codegen_test.dart b/test/codegen/js_axios_codegen_test.dart index 49dce93b..9498da1c 100644 --- a/test/codegen/js_axios_codegen_test.dart +++ b/test/codegen/js_axios_codegen_test.dart @@ -201,6 +201,109 @@ axios(config) """; expect(axiosCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "add_space": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -426,112 +529,4 @@ axios(config) expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - params: { - "num": "8700000", - "add_space": "true" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect(axiosCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - headers: { - "User-Agent": "Test Agent" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect( - axiosCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - params: { - "num": "8700000", - "digits": "3" - }, - headers: { - "User-Agent": "Test Agent" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect( - axiosCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get' -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect(axiosCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/js_fetch_codegen_test.dart b/test/codegen/js_fetch_codegen_test.dart index 9153c789..43d053f9 100644 --- a/test/codegen/js_fetch_codegen_test.dart +++ b/test/codegen/js_fetch_codegen_test.dart @@ -220,6 +220,121 @@ fetch(url, options) """; expect(fetchCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = + r"""let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -487,124 +602,4 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = - r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; - -let options = { - method: 'GET' -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect(fetchCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = - r"""let url = 'https://api.foss42.com/humanize/social'; - -let options = { - method: 'GET', - headers: { - "User-Agent": "Test Agent" - } -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect( - fetchCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = - r"""let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; - -let options = { - method: 'GET', - headers: { - "User-Agent": "Test Agent" - } -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect( - fetchCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = - r"""let url = 'https://api.foss42.com/humanize/social'; - -let options = { - method: 'GET' -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect(fetchCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/kotlin_okhttp_codegen_test.dart b/test/codegen/kotlin_okhttp_codegen_test.dart index d20177f9..4f3220fa 100644 --- a/test/codegen/kotlin_okhttp_codegen_test.dart +++ b/test/codegen/kotlin_okhttp_codegen_test.dart @@ -219,6 +219,116 @@ fun main() { expect( kotlinOkHttpCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.HttpUrl.Companion.toHttpUrl + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() + .addQueryParameter("num", "8700000") + .addQueryParameter("add_space", "true") + .build() + + val request = Request.Builder() + .url(url) + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect( + kotlinOkHttpCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social" + + val request = Request.Builder() + .url(url) + .addHeader("User-Agent", "Test Agent") + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect( + kotlinOkHttpCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.HttpUrl.Companion.toHttpUrl + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() + .addQueryParameter("num", "8700000") + .addQueryParameter("digits", "3") + .build() + + val request = Request.Builder() + .url(url) + .addHeader("User-Agent", "Test Agent") + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect(kotlinOkHttpCodeGen.getCode(requestModelGet11, "https"), + expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com/humanize/social" + + val request = Request.Builder() + .url(url) + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect(kotlinOkHttpCodeGen.getCode(requestModelGet12, "https"), + expectedCode); + }); }); group('HEAD Request', () { @@ -498,116 +608,4 @@ fun main() { expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.HttpUrl.Companion.toHttpUrl - -fun main() { - val client = OkHttpClient() - - val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() - .addQueryParameter("num", "8700000") - .addQueryParameter("add_space", "true") - .build() - - val request = Request.Builder() - .url(url) - .get() - .build() - - val response = client.newCall(request).execute() - - println(response.code) - println(response.body?.string()) -} -"""; - expect(kotlinOkHttpCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import okhttp3.OkHttpClient -import okhttp3.Request - -fun main() { - val client = OkHttpClient() - - val url = "https://api.foss42.com/humanize/social" - - val request = Request.Builder() - .url(url) - .addHeader("User-Agent", "Test Agent") - .get() - .build() - - val response = client.newCall(request).execute() - - println(response.code) - println(response.body?.string()) -} -"""; - expect( - kotlinOkHttpCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.HttpUrl.Companion.toHttpUrl - -fun main() { - val client = OkHttpClient() - - val url = "https://api.foss42.com/humanize/social".toHttpUrl().newBuilder() - .addQueryParameter("num", "8700000") - .addQueryParameter("digits", "3") - .build() - - val request = Request.Builder() - .url(url) - .addHeader("User-Agent", "Test Agent") - .get() - .build() - - val response = client.newCall(request).execute() - - println(response.code) - println(response.body?.string()) -} -"""; - expect(kotlinOkHttpCodeGen.getCode(requestModelEnabledRows, "https"), - expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import okhttp3.OkHttpClient -import okhttp3.Request - -fun main() { - val client = OkHttpClient() - - val url = "https://api.foss42.com/humanize/social" - - val request = Request.Builder() - .url(url) - .get() - .build() - - val response = client.newCall(request).execute() - - println(response.code) - println(response.body?.string()) -} -"""; - expect(kotlinOkHttpCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/nodejs_axios_codegen_test.dart b/test/codegen/nodejs_axios_codegen_test.dart index b39d571e..519f5ab5 100644 --- a/test/codegen/nodejs_axios_codegen_test.dart +++ b/test/codegen/nodejs_axios_codegen_test.dart @@ -217,6 +217,117 @@ axios(config) """; expect(axiosCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "add_space": "true" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + axiosCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get', + params: { + "num": "8700000", + "digits": "3" + }, + headers: { + "User-Agent": "Test Agent" + } +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com/humanize/social', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect(axiosCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -460,120 +571,4 @@ axios(config) expect(axiosCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import axios from 'axios'; - -let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - params: { - "num": "8700000", - "add_space": "true" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect(axiosCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import axios from 'axios'; - -let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - headers: { - "User-Agent": "Test Agent" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect( - axiosCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import axios from 'axios'; - -let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get', - params: { - "num": "8700000", - "digits": "3" - }, - headers: { - "User-Agent": "Test Agent" - } -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect( - axiosCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import axios from 'axios'; - -let config = { - url: 'https://api.foss42.com/humanize/social', - method: 'get' -}; - -axios(config) - .then(function (response) { - // handle success - console.log(response.status); - console.log(response.data); - }) - .catch(function (error) { - // handle error - console.log(error.response.status); - console.log(error); - }); -"""; - expect(axiosCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/nodejs_fetch_codegen_test.dart b/test/codegen/nodejs_fetch_codegen_test.dart index d6bfbe29..c06ceee5 100644 --- a/test/codegen/nodejs_fetch_codegen_test.dart +++ b/test/codegen/nodejs_fetch_codegen_test.dart @@ -230,6 +230,125 @@ fetch(url, options) """; expect(fetchCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + fetchCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; + +let options = { + method: 'GET', + headers: { + "User-Agent": "Test Agent" + } +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com/humanize/social'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect(fetchCodeGen.getCode(requestModelGet12, "https"), expectedCode); + }); }); group('HEAD Request', () { @@ -515,128 +634,4 @@ fetch(url, options) expect(fetchCodeGen.getCode(requestModelDelete2, "https"), expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import fetch from 'node-fetch'; - -let url = 'https://api.foss42.com/humanize/social?num=8700000&add_space=true'; - -let options = { - method: 'GET' -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect(fetchCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import fetch from 'node-fetch'; - -let url = 'https://api.foss42.com/humanize/social'; - -let options = { - method: 'GET', - headers: { - "User-Agent": "Test Agent" - } -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect( - fetchCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import fetch from 'node-fetch'; - -let url = 'https://api.foss42.com/humanize/social?num=8700000&digits=3'; - -let options = { - method: 'GET', - headers: { - "User-Agent": "Test Agent" - } -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect( - fetchCodeGen.getCode(requestModelEnabledRows, "https"), expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import fetch from 'node-fetch'; - -let url = 'https://api.foss42.com/humanize/social'; - -let options = { - method: 'GET' -}; - -let status; -fetch(url, options) - .then(res => { - status = res.status; - return res.json() - }) - .then(body => { - console.log(status); - console.log(body); - }) - .catch(err => { - console.log(status); - console.error('error:' + err); - }); -"""; - expect(fetchCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/python_http_client_codegen_test.dart b/test/codegen/python_http_client_codegen_test.dart index c97777c7..c617305c 100644 --- a/test/codegen/python_http_client_codegen_test.dart +++ b/test/codegen/python_http_client_codegen_test.dart @@ -174,6 +174,94 @@ print(data.decode("utf-8")) expect(pythonHttpClientCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import http.client +from urllib.parse import urlencode + +queryParams = { + "num": "8700000", + "add_space": "true" + } +queryParamsStr = '?' + urlencode(queryParams) + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social" + queryParamsStr) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect(pythonHttpClientCodeGen.getCode(requestModelGet9, "https"), + expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import http.client + +headers = { + "User-Agent": "Test Agent" + } + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social", + headers= headers) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect( + pythonHttpClientCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import http.client +from urllib.parse import urlencode + +queryParams = { + "num": "8700000", + "digits": "3" + } +queryParamsStr = '?' + urlencode(queryParams) + +headers = { + "User-Agent": "Test Agent" + } + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social" + queryParamsStr, + headers= headers) + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect(pythonHttpClientCodeGen.getCode(requestModelGet11, "https"), + expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import http.client + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "/humanize/social") + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect(pythonHttpClientCodeGen.getCode(requestModelGet12, "https"), + expectedCode); + }); }); group('HEAD Request', () { @@ -384,95 +472,4 @@ print(data.decode("utf-8")) expectedCode); }); }); - - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import http.client -from urllib.parse import urlencode - -queryParams = { - "num": "8700000", - "add_space": "true" - } -queryParamsStr = '?' + urlencode(queryParams) - -conn = http.client.HTTPSConnection("api.foss42.com") -conn.request("GET", "/humanize/social" + queryParamsStr) - -res = conn.getresponse() -data = res.read() - -print(data.decode("utf-8")) -"""; - expect( - pythonHttpClientCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import http.client - -headers = { - "User-Agent": "Test Agent" - } - -conn = http.client.HTTPSConnection("api.foss42.com") -conn.request("GET", "/humanize/social", - headers= headers) - -res = conn.getresponse() -data = res.read() - -print(data.decode("utf-8")) -"""; - expect( - pythonHttpClientCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import http.client -from urllib.parse import urlencode - -queryParams = { - "num": "8700000", - "digits": "3" - } -queryParamsStr = '?' + urlencode(queryParams) - -headers = { - "User-Agent": "Test Agent" - } - -conn = http.client.HTTPSConnection("api.foss42.com") -conn.request("GET", "/humanize/social" + queryParamsStr, - headers= headers) - -res = conn.getresponse() -data = res.read() - -print(data.decode("utf-8")) -"""; - expect(pythonHttpClientCodeGen.getCode(requestModelEnabledRows, "https"), - expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import http.client - -conn = http.client.HTTPSConnection("api.foss42.com") -conn.request("GET", "/humanize/social") - -res = conn.getresponse() -data = res.read() - -print(data.decode("utf-8")) -"""; - expect(pythonHttpClientCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/codegen/python_requests_codegen_test.dart b/test/codegen/python_requests_codegen_test.dart index aaeb6c45..1387accf 100644 --- a/test/codegen/python_requests_codegen_test.dart +++ b/test/codegen/python_requests_codegen_test.dart @@ -153,6 +153,84 @@ print('Response Body:', response.text) expect(pythonRequestsCodeGen.getCode(requestModelGet8, "https"), expectedCode); }); + + test('GET 9', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +params = { + "num": "8700000", + "add_space": "true" + } + +response = requests.get(url, params=params) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelGet9, "https"), + expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +headers = { + "User-Agent": "Test Agent" + } + +response = requests.get(url, headers=headers) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect( + pythonRequestsCodeGen.getCode( + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +params = { + "num": "8700000", + "digits": "3" + } + +headers = { + "User-Agent": "Test Agent" + } + +response = requests.get(url, params=params, headers=headers) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelGet11, "https"), + expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com/humanize/social' + +response = requests.get(url) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect(pythonRequestsCodeGen.getCode(requestModelGet12, "https"), + expectedCode); + }); }); group('HEAD Request', () { @@ -325,83 +403,4 @@ print('Response Body:', response.text) expectedCode); }); }); - group('Request with enabled Rows', () { - test('Enabled Params', () { - const expectedCode = r"""import requests - -url = 'https://api.foss42.com/humanize/social' - -params = { - "num": "8700000", - "add_space": "true" - } - -response = requests.get(url, params=params) - -print('Status Code:', response.status_code) -print('Response Body:', response.text) -"""; - expect(pythonRequestsCodeGen.getCode(requestModelEnabledParams, "https"), - expectedCode); - }); - - test('Enabled Headers', () { - const expectedCode = r"""import requests - -url = 'https://api.foss42.com/humanize/social' - -headers = { - "User-Agent": "Test Agent" - } - -response = requests.get(url, headers=headers) - -print('Status Code:', response.status_code) -print('Response Body:', response.text) -"""; - expect( - pythonRequestsCodeGen.getCode( - requestModelEnabledHeaders, - "https", - ), - expectedCode); - }); - - test('Enabled Headers and Params', () { - const expectedCode = r"""import requests - -url = 'https://api.foss42.com/humanize/social' - -params = { - "num": "8700000", - "digits": "3" - } - -headers = { - "User-Agent": "Test Agent" - } - -response = requests.get(url, params=params, headers=headers) - -print('Status Code:', response.status_code) -print('Response Body:', response.text) -"""; - expect(pythonRequestsCodeGen.getCode(requestModelEnabledRows, "https"), - expectedCode); - }); - - test('Disabled Headders and Params', () { - const expectedCode = r"""import requests - -url = 'https://api.foss42.com/humanize/social' - -response = requests.get(url) - -print('Status Code:', response.status_code) -print('Response Body:', response.text) -"""; - expect(pythonRequestsCodeGen.getCode(requestModelDisabledRows, "https"), - expectedCode); - }); - }); } diff --git a/test/request_models.dart b/test/request_models.dart index b51acaa3..adf7e0e8 100644 --- a/test/request_models.dart +++ b/test/request_models.dart @@ -90,6 +90,94 @@ const requestModelGet8 = RequestModel( ], ); +/// GET request model with some params enabled +const requestModelGet9 = RequestModel( + id: 'enabledParams', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + isParamEnabledList: [ + true, + false, + false, + true, + ], +); + +/// GET Request model with some headers enabled +const requestModelGet10 = RequestModel( + id: 'enabledParams', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isHeaderEnabledList: [ + true, + false, + ], +); + +/// GET Request model with some headers & URL parameters enabled +const requestModelGet11 = RequestModel( + id: 'enabledRows', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isParamEnabledList: [ + true, + true, + false, + false, + ], + isHeaderEnabledList: [ + true, + false, + ], +); + +/// Request model with all headers & URL parameters disabled +const requestModelGet12 = RequestModel( + id: 'disabledRows', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + ], + requestHeaders: [ + NameValueModel(name: 'User-Agent', value: 'Test Agent'), + NameValueModel(name: 'Content-Type', value: 'application/json'), + ], + isParamEnabledList: [ + false, + false, + false, + false, + ], + isHeaderEnabledList: [ + false, + false, + ], +); + /// Basic HEAD request model const requestModelHead1 = RequestModel( id: 'head1', @@ -180,91 +268,3 @@ const requestModelDelete2 = RequestModel( }""", requestBodyContentType: ContentType.json, ); - -/// Request model with enabled params -const requestModelEnabledParams = RequestModel( - id: 'enabledParams', - url: 'https://api.foss42.com/humanize/social', - method: HTTPVerb.get, - requestParams: [ - NameValueModel(name: 'num', value: '8700000'), - NameValueModel(name: 'digits', value: '3'), - NameValueModel(name: 'system', value: 'SS'), - NameValueModel(name: 'add_space', value: 'true'), - ], - isParamEnabledList: [ - true, - false, - false, - true, - ], -); - -/// Request model with enabled headers -const requestModelEnabledHeaders = RequestModel( - id: 'enabledParams', - url: 'https://api.foss42.com/humanize/social', - method: HTTPVerb.get, - requestHeaders: [ - NameValueModel(name: 'User-Agent', value: 'Test Agent'), - NameValueModel(name: 'Content-Type', value: 'application/json'), - ], - isHeaderEnabledList: [ - true, - false, - ], -); - -/// Request model with enabled rows -const requestModelEnabledRows = RequestModel( - id: 'enabledRows', - url: 'https://api.foss42.com/humanize/social', - method: HTTPVerb.get, - requestParams: [ - NameValueModel(name: 'num', value: '8700000'), - NameValueModel(name: 'digits', value: '3'), - NameValueModel(name: 'system', value: 'SS'), - NameValueModel(name: 'add_space', value: 'true'), - ], - requestHeaders: [ - NameValueModel(name: 'User-Agent', value: 'Test Agent'), - NameValueModel(name: 'Content-Type', value: 'application/json'), - ], - isParamEnabledList: [ - true, - true, - false, - false, - ], - isHeaderEnabledList: [ - true, - false, - ], -); - -/// Request model with disabled rows -const requestModelDisabledRows = RequestModel( - id: 'disabledRows', - url: 'https://api.foss42.com/humanize/social', - method: HTTPVerb.get, - requestParams: [ - NameValueModel(name: 'num', value: '8700000'), - NameValueModel(name: 'digits', value: '3'), - NameValueModel(name: 'system', value: 'SS'), - NameValueModel(name: 'add_space', value: 'true'), - ], - requestHeaders: [ - NameValueModel(name: 'User-Agent', value: 'Test Agent'), - NameValueModel(name: 'Content-Type', value: 'application/json'), - ], - isParamEnabledList: [ - false, - false, - false, - false, - ], - isHeaderEnabledList: [ - false, - false, - ], -); From 5fddefd21c3d1833036809f0ef2786505f088bd4 Mon Sep 17 00:00:00 2001 From: DenserMeerkat <95911940+DenserMeerkat@users.noreply.github.com> Date: Wed, 27 Dec 2023 22:06:09 +0530 Subject: [PATCH 065/123] Update pubspec.lock --- pubspec.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index ba941e23..1845e975 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: "direct main" description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -637,10 +637,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -994,10 +994,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" state_notifier: dependency: transitive description: @@ -1010,10 +1010,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1042,26 +1042,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" textwrap: dependency: transitive description: @@ -1210,10 +1210,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1280,5 +1280,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" From e0fe907d194440893c5a1c964d15600284bd209c Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Sat, 30 Dec 2023 12:35:10 +0530 Subject: [PATCH 066/123] feat: ability to override content type --- lib/consts.dart | 2 ++ .../request_pane/request_headers.dart | 18 ++++++++++++++++++ lib/utils/header_utils.dart | 11 +++++++++++ lib/widgets/headerfield.dart | 6 +++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/consts.dart b/lib/consts.dart index d881fb86..39cb0dbb 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -305,6 +305,8 @@ const kTypeVideo = 'video'; const kSubTypeDefaultViewOptions = 'all'; +const kContentType = 'Content-Type'; + const kContentTypeMap = { ContentType.json: "$kTypeApplication/$kSubTypeJson", ContentType.text: "$kTypeText/$kSubTypePlain", diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 82138db5..0f2cf728 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:davi/davi.dart'; @@ -78,6 +79,23 @@ class EditRequestHeadersState extends ConsumerState { grow: 1, cellBuilder: (_, row) { int idx = row.index; + + if (row.data.name == kContentType) { + return HeaderField( + keyId: "$activeId-$idx-headers-v-$seed", + initialValue: rows[idx].value, + hintText: " Add Header Value", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(value: value); + _onFieldChange(activeId!); + }, + headerSuggestionsCallback: (pattern) { + return getHeaderValueSuggestions(pattern); + }, + colorScheme: Theme.of(context).colorScheme, + ); + } + return CellField( keyId: "$activeId-$idx-headers-v-$seed", initialValue: rows[idx].value, diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..de13f8b4 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,6 +15,7 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", @@ -70,3 +71,13 @@ List getHeaderSuggestions(String pattern) { ) .toList(); } + +List headerValues = ['application/json', 'text/plain']; + +List getHeaderValueSuggestions(String pattern) { + return headerValues + .where( + (element) => element.contains(pattern.toLowerCase()), + ) + .toList(); +} diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 9c678ee3..4ff548e3 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; @@ -10,12 +12,14 @@ class HeaderField extends StatefulWidget { this.hintText, this.initialValue, this.onChanged, + this.headerSuggestionsCallback, this.colorScheme, }); final String keyId; final String? hintText; final String? initialValue; final void Function(String)? onChanged; + final FutureOr> Function(String)? headerSuggestionsCallback; final ColorScheme? colorScheme; @override @@ -67,7 +71,7 @@ class _HeaderFieldState extends State { title: Text(suggestion), ); }, - suggestionsCallback: headerSuggestionCallback, + suggestionsCallback: widget.headerSuggestionsCallback ?? headerSuggestionCallback, suggestionsBoxDecoration: suggestionBoxDecorations(context), textFieldConfiguration: TextFieldConfiguration( onChanged: widget.onChanged, From 68c69d37fe3465ed0d737cd2da313411dfbb2419 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 31 Dec 2023 18:38:06 +0530 Subject: [PATCH 067/123] wip: curl and python code gen tested and added --- lib/codegen/others/curl.dart | 20 +++++ lib/codegen/python/http_client.dart | 73 +++++++++++++++++-- lib/codegen/python/requests.dart | 72 ++++++++++++++++-- .../extensions/request_model_extension.dart | 8 ++ lib/utils/har_utils.dart | 8 +- 5 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 lib/utils/extensions/request_model_extension.dart diff --git a/lib/codegen/others/curl.dart b/lib/codegen/others/curl.dart index 5405ee1a..6c60193f 100644 --- a/lib/codegen/others/curl.dart +++ b/lib/codegen/others/curl.dart @@ -10,6 +10,9 @@ class cURLCodeGen { String kTemplateHeader = """ \\ --header '{{name}}: {{value}}' """; + String kTemplateFormData = """ \\ + --form '{{name}}: {{value}}' +"""; String kTemplateBody = """ \\ --data '{{body}}' @@ -48,6 +51,23 @@ class cURLCodeGen { .render({"name": item["name"], "value": item["value"]}); } } + if (harJson['formData'] != null) { + var formDataList = harJson['formData'] as List>; + for (var formData in formDataList) { + var templateFormData = jj.Template(kTemplateFormData); + if (formData['type'] != null && + formData['name'] != null && + formData['value'] != null && + formData['name']!.isNotEmpty && + formData['value']!.isNotEmpty) { + result += templateFormData.render({ + "name": formData["name"], + "value": + "${formData['type'] == 'file' ? '@' : ''}${formData["value"]}", + }); + } + } + } if (harJson["postData"]?["text"] != null) { var templateBody = jj.Template(kTemplateBody); diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 83d02676..a00038d5 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -1,13 +1,23 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri, padMultilineString; -import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonHttpClientCodeGen { final String kTemplateStart = """import http.client +{% if isFormDataRequest %} +import mimetypes +from codecs import encode +import uuid + +headers = {} +boundary = str(uuid.uuid4()) +{% endif %} """; String kTemplateParams = """ @@ -41,6 +51,10 @@ conn = http.client.HTTP{{isHttps}}Connection("{{authority}}")"""; conn.request("{{method}}", "{{path}}"{{queryParamsStr}}"""; + String kTemplateFormDataRequest = """ +conn.request("{{method}}", "{{path}}"{{queryParamsStr}},body=payload, headers=headers +"""; + String kStringRequestBody = """, body= body"""; @@ -55,10 +69,43 @@ data = res.read() print(data.decode("utf-8")) """; + final String kStringFormDataBody = r''' +def build_data_list(fields): + dataList = [] + for field in fields: + name = field.get('name', '') + value = field.get('value', '') + type_ = field.get('type', 'text') + + dataList.append(encode(f'--{boundary}')) + if type_ == 'text': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) + dataList.append(encode('Content-Type: text/plain')) + dataList.append(encode('')) + dataList.append(encode(value)) + elif type_ == 'file': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"; filename="{value}"')) + dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) + dataList.append(encode('')) + dataList.append(open(value, 'rb').read()) + + dataList.append(encode(f'--{boundary}--')) + dataList.append(encode('')) + return dataList +dataList = build_data_list({{fields_list}}) +body = b'\r\n'.join(dataList) +'''; + + String kFormDataHeaders = ''' +headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; +'''; + String? getCode( RequestModel requestModel, String defaultUriScheme, ) { + List formDataList = requestModel.formDataList ?? []; + try { String result = ""; bool hasHeaders = false; @@ -69,8 +116,12 @@ print(data.decode("utf-8")) if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; } - - result += kTemplateStart; + var templateStartUrl = jj.Template(kTemplateStart); + result += templateStartUrl.render( + { + "isFormDataRequest": requestModel.isFormDataRequest, + }, + ); var rec = getValidRequestUri(url, requestModel.requestParams); Uri? uri = rec.$1; @@ -112,13 +163,20 @@ print(data.decode("utf-8")) result += templateHeaders.render({"headers": headersString}); } } - + if (requestModel.isFormDataRequest) { + result += kFormDataHeaders; + var formDataBodyData = jj.Template(kStringFormDataBody); + result += formDataBodyData.render( + { + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }, + ); + } var templateConnection = jj.Template(kTemplateConnection); result += templateConnection.render({ "isHttps": uri.scheme == "https" ? "S" : "", "authority": uri.authority }); - var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": method.name.toUpperCase(), @@ -126,11 +184,11 @@ print(data.decode("utf-8")) "queryParamsStr": hasQuery ? " + queryParamsStr" : "", }); - if (hasBody) { + if (hasBody || requestModel.isFormDataRequest) { result += kStringRequestBody; } - if (hasHeaders) { + if (hasHeaders || requestModel.isFormDataRequest) { result += kStringRequestHeaders; } @@ -138,6 +196,7 @@ print(data.decode("utf-8")) } return result; } catch (e) { + print(e); return null; } } diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index af8b3fbe..821f45ed 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -1,16 +1,35 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri, padMultilineString, stripUriParams; -import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonRequestsCodeGen { final String kTemplateStart = """import requests +{% if isFormDataRequest %} +import mimetypes +from codecs import encode +import uuid +headers = {} +boundary = str(uuid.uuid4()) +{% endif %} url = '{{url}}' +"""; + + final String kTemplateFormDataImports = """ +import mimetypes +from codecs import encode +import uuid + +headers = {} +boundary = str(uuid.uuid4()) + """; String kTemplateParams = """ @@ -45,6 +64,32 @@ headers = {{headers}} response = requests.{{method}}(url """; + final String kStringFormDataBody = r''' +def build_data_list(fields): + dataList = [] + for field in fields: + name = field.get('name', '') + value = field.get('value', '') + type_ = field.get('type', 'text') + + dataList.append(encode(f'--{boundary}')) + if type_ == 'text': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) + dataList.append(encode('Content-Type: text/plain')) + dataList.append(encode('')) + dataList.append(encode(value)) + elif type_ == 'file': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"; filename="{value}"')) + dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) + dataList.append(encode('')) + dataList.append(open(value, 'rb').read()) + + dataList.append(encode(f'--{boundary}--')) + dataList.append(encode('')) + return dataList +dataList = build_data_list({{fields_list}}) +payload = b'\r\n'.join(dataList) +'''; String kStringRequestParams = """, params=params"""; String kStringRequestBody = """, data=payload"""; @@ -52,6 +97,9 @@ response = requests.{{method}}(url String kStringRequestJson = """, json=payload"""; String kStringRequestHeaders = """, headers=headers"""; + String kFormDataHeaders = ''' +headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; +'''; final String kStringRequestEnd = """) @@ -69,6 +117,7 @@ print('Response Body:', response.text) bool hasHeaders = false; bool hasBody = false; bool hasJsonBody = false; + List formDataList = requestModel.formDataList ?? []; String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { @@ -79,7 +128,10 @@ print('Response Body:', response.text) Uri? uri = rec.$1; if (uri != null) { var templateStartUrl = jj.Template(kTemplateStart); - result += templateStartUrl.render({"url": stripUriParams(uri)}); + result += templateStartUrl.render({ + "url": stripUriParams(uri), + 'isFormDataRequest': requestModel.isFormDataRequest + }); if (uri.hasQuery) { var params = uri.queryParameters; @@ -124,7 +176,15 @@ print('Response Body:', response.text) result += templateHeaders.render({"headers": headersString}); } } - + if (requestModel.isFormDataRequest) { + result += kFormDataHeaders; + var formDataBodyData = jj.Template(kStringFormDataBody); + result += formDataBodyData.render( + { + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }, + ); + } var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": method.name.toLowerCase(), @@ -134,15 +194,15 @@ print('Response Body:', response.text) result += kStringRequestParams; } - if (hasBody) { + if (hasBody || requestModel.isFormDataRequest) { result += kStringRequestBody; } - if (hasJsonBody) { + if (hasJsonBody || requestModel.isFormDataRequest) { result += kStringRequestJson; } - if (hasHeaders) { + if (hasHeaders || requestModel.isFormDataRequest) { result += kStringRequestHeaders; } diff --git a/lib/utils/extensions/request_model_extension.dart b/lib/utils/extensions/request_model_extension.dart new file mode 100644 index 00000000..95563a05 --- /dev/null +++ b/lib/utils/extensions/request_model_extension.dart @@ -0,0 +1,8 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/models/models.dart'; + +extension RequestModelExtension on RequestModel { + bool get isFormDataRequest { + return requestBodyContentType == ContentType.formdata; + } +} diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f0838807..c3581f86 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'package:apidash/consts.dart'; +import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri; import 'package:apidash/models/models.dart' show RequestModel; import 'package:package_info_plus/package_info_plus.dart'; @@ -148,7 +150,11 @@ Map requestModelToHARJsonRequest( } } } - + List formDataList = requestModel.formDataList ?? []; + if (requestModel.requestBodyContentType == ContentType.formdata) { + var formListMap = rowsToFormDataMap(formDataList); + json["formData"] = formListMap; + } if (exportMode) { json["comment"] = ""; json["cookies"] = []; From f0047aa087f6f1ca49ca9fa3e9568a08d0586395 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 31 Dec 2023 23:25:35 +0530 Subject: [PATCH 068/123] wip: updated http and requests header handle --- lib/codegen/python/http_client.dart | 38 ++++++++++++-------------- lib/codegen/python/requests.dart | 42 ++++++++++++++--------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index a00038d5..0225ff38 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -1,11 +1,10 @@ import 'dart:io'; import 'dart:convert'; -import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' - show getValidRequestUri, padMultilineString; + show getNewUuid, getValidRequestUri, padMultilineString, rowsToFormDataMap; import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonHttpClientCodeGen { @@ -13,11 +12,8 @@ class PythonHttpClientCodeGen { {% if isFormDataRequest %} import mimetypes from codecs import encode -import uuid - -headers = {} -boundary = str(uuid.uuid4()) {% endif %} + """; String kTemplateParams = """ @@ -40,6 +36,8 @@ body = r'''{{body}}''' headers = {{headers}} """; + String kTemplateFormHeaderContentType = ''' +multipart/form-data; boundary={{boundary}}'''; int kHeadersPadding = 10; @@ -51,10 +49,6 @@ conn = http.client.HTTP{{isHttps}}Connection("{{authority}}")"""; conn.request("{{method}}", "{{path}}"{{queryParamsStr}}"""; - String kTemplateFormDataRequest = """ -conn.request("{{method}}", "{{path}}"{{queryParamsStr}},body=payload, headers=headers -"""; - String kStringRequestBody = """, body= body"""; @@ -76,8 +70,7 @@ def build_data_list(fields): name = field.get('name', '') value = field.get('value', '') type_ = field.get('type', 'text') - - dataList.append(encode(f'--{boundary}')) + dataList.append(encode('--{{boundary}}')) if type_ == 'text': dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) dataList.append(encode('Content-Type: text/plain')) @@ -88,23 +81,18 @@ def build_data_list(fields): dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) dataList.append(encode('')) dataList.append(open(value, 'rb').read()) - - dataList.append(encode(f'--{boundary}--')) + dataList.append(encode(f'--{{boundary}}--')) dataList.append(encode('')) return dataList dataList = build_data_list({{fields_list}}) body = b'\r\n'.join(dataList) '''; - - String kFormDataHeaders = ''' -headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; -'''; - String? getCode( RequestModel requestModel, String defaultUriScheme, ) { List formDataList = requestModel.formDataList ?? []; + String uuid = getNewUuid(); try { String result = ""; @@ -116,6 +104,7 @@ headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; } + var templateStartUrl = jj.Template(kTemplateStart); result += templateStartUrl.render( { @@ -151,6 +140,13 @@ headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; var headersList = requestModel.requestHeaders; if (headersList != null || hasBody) { var headers = requestModel.headersMap; + if (requestModel.isFormDataRequest) { + var formHeaderTemplate = + jj.Template(kTemplateFormHeaderContentType); + headers[HttpHeaders.contentTypeHeader] = formHeaderTemplate.render({ + "boundary": uuid, + }); + } if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { @@ -164,11 +160,11 @@ headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; } } if (requestModel.isFormDataRequest) { - result += kFormDataHeaders; var formDataBodyData = jj.Template(kStringFormDataBody); result += formDataBodyData.render( { "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "boundary": uuid, }, ); } @@ -177,6 +173,7 @@ headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; "isHttps": uri.scheme == "https" ? "S" : "", "authority": uri.authority }); + var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": method.name.toUpperCase(), @@ -196,7 +193,6 @@ headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; } return result; } catch (e) { - print(e); return null; } } diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index 821f45ed..6f40fa2e 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -1,11 +1,15 @@ import 'dart:io'; import 'dart:convert'; -import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' - show getValidRequestUri, padMultilineString, stripUriParams; + show + getNewUuid, + getValidRequestUri, + padMultilineString, + rowsToFormDataMap, + stripUriParams; import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonRequestsCodeGen { @@ -13,23 +17,9 @@ class PythonRequestsCodeGen { {% if isFormDataRequest %} import mimetypes from codecs import encode -import uuid - -headers = {} -boundary = str(uuid.uuid4()) {% endif %} url = '{{url}}' -"""; - - final String kTemplateFormDataImports = """ -import mimetypes -from codecs import encode -import uuid - -headers = {} -boundary = str(uuid.uuid4()) - """; String kTemplateParams = """ @@ -56,6 +46,8 @@ payload = {{body}} headers = {{headers}} """; + String kTemplateFormHeaderContentType = ''' +multipart/form-data; boundary={{boundary}}'''; int kHeadersPadding = 10; @@ -72,7 +64,7 @@ def build_data_list(fields): value = field.get('value', '') type_ = field.get('type', 'text') - dataList.append(encode(f'--{boundary}')) + dataList.append(encode('--{{boundary}}')) if type_ == 'text': dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) dataList.append(encode('Content-Type: text/plain')) @@ -84,12 +76,13 @@ def build_data_list(fields): dataList.append(encode('')) dataList.append(open(value, 'rb').read()) - dataList.append(encode(f'--{boundary}--')) + dataList.append(encode('--{{boundary}}--')) dataList.append(encode('')) return dataList dataList = build_data_list({{fields_list}}) payload = b'\r\n'.join(dataList) '''; + String kStringRequestParams = """, params=params"""; String kStringRequestBody = """, data=payload"""; @@ -97,9 +90,6 @@ payload = b'\r\n'.join(dataList) String kStringRequestJson = """, json=payload"""; String kStringRequestHeaders = """, headers=headers"""; - String kFormDataHeaders = ''' -headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; -'''; final String kStringRequestEnd = """) @@ -118,6 +108,7 @@ print('Response Body:', response.text) bool hasBody = false; bool hasJsonBody = false; List formDataList = requestModel.formDataList ?? []; + String uuid = getNewUuid(); String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { @@ -164,6 +155,13 @@ print('Response Body:', response.text) var headersList = requestModel.requestHeaders; if (headersList != null || hasBody) { var headers = requestModel.headersMap; + if (requestModel.isFormDataRequest) { + var formHeaderTemplate = + jj.Template(kTemplateFormHeaderContentType); + headers[HttpHeaders.contentTypeHeader] = formHeaderTemplate.render({ + "boundary": uuid, + }); + } if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { @@ -177,11 +175,11 @@ print('Response Body:', response.text) } } if (requestModel.isFormDataRequest) { - result += kFormDataHeaders; var formDataBodyData = jj.Template(kStringFormDataBody); result += formDataBodyData.render( { "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "boundary": uuid, }, ); } From f39f30a085bb33217c47d9718a2c1ea755f5de1f Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 31 Dec 2023 23:25:55 +0530 Subject: [PATCH 069/123] wip: working on fetch api for js --- lib/codegen/js/fetch.dart | 104 ++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index 2d57d290..aeaa9c81 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -1,15 +1,22 @@ +import 'dart:convert'; + import 'package:apidash/consts.dart'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' - show requestModelToHARJsonRequest, padMultilineString; -import 'package:apidash/models/models.dart' show RequestModel; + show getNewUuid, padMultilineString, requestModelToHARJsonRequest; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class FetchCodeGen { FetchCodeGen({this.isNodeJs = false}); final bool isNodeJs; - String kStringImportNode = """import fetch from 'node-fetch'; + String kStringImportNode = """ +import fetch from 'node-fetch'; +{% if isFormDataRequest %}const fs = require('fs');{% endif %} + """; @@ -24,10 +31,55 @@ let options = { """; String kTemplateBody = """, - body: -{{body}} + body: {{body}} """; + String kMultiPartFileReader = ''' +function readFile(file) { + {% if isNodeJs %} return fs.readFile(file, 'binary'); {% else %} return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result); + reader.onerror = reject; + reader.readAsArrayBuffer(file); + }); +{% endif %} +} +'''; + String kMultiPartBodyTemplate = r''' +async function buildDataList(fields) { + const dataList = []; + for (const field of fields) { + const name = field.name || ''; + const value = field.value || ''; + const type = field.type || 'text'; + + dataList.push(`--{{boundary}}`); + if (type === 'text') { + dataList.push(`Content-Disposition: form-data; name="${name}"`); + dataList.push('Content-Type: text/plain'); + dataList.push(''); + dataList.push(value); + } else if (type === 'file') { + const fileContent = await readFile(value); + dataList.push(`Content-Disposition: form-data; name="$name"; filename="${value.name}"`); + dataList.push(`Content-Type: ${value.type}`); + dataList.push(''); + {% if isNodeJs %}dataList.push(fileContent); + {% else %} + dataList.push(fileContent.content);{% endif %}} + } + + dataList.push(`--{{boundary}}--`); + dataList.push(''); + return dataList.join('\r\n'); +} +var dataList = []; +buildDataList({{fields_list}}) + .then(data => dataList = data) + .catch(err => console.error(err)); +const payload = dataList.join('\r\n'); + +'''; String kStringRequest = """ }; @@ -53,8 +105,28 @@ fetch(url, options) String defaultUriScheme, ) { try { - String result = isNodeJs ? kStringImportNode : ""; + List formDataList = requestModel.formDataList ?? []; + String uuid = getNewUuid(); + jj.Template kNodejsImportTemplate = jj.Template(kStringImportNode); + String importsData = kNodejsImportTemplate.render({ + "isFormDataRequest": requestModel.isFormDataRequest, + }); + String result = isNodeJs ? importsData : ""; + if (requestModel.isFormDataRequest) { + jj.Template kMultiPartFileReaderTemplate = + jj.Template(kMultiPartFileReader); + result += kMultiPartFileReaderTemplate.render({ + "isNodeJs": isNodeJs, + }); + var boundary = uuid; + var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); + result += templateMultiPartBody.render({ + "boundary": boundary, + "isNodeJs": isNodeJs, + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }); + } String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; @@ -70,21 +142,33 @@ fetch(url, options) }); var headers = harJson["headers"]; + if (headers.isNotEmpty) { var templateHeader = jj.Template(kTemplateHeader); var m = {}; + if (requestModel.isFormDataRequest) { + m["Content-Type"] = "multipart/form-data; boundary=$uuid"; + } for (var i in headers) { m[i["name"]] = i["value"]; } - result += templateHeader - .render({"headers": padMultilineString(kEncoder.convert(m), 2)}); + result += templateHeader.render({ + "headers": padMultilineString(kEncoder.convert(m), 2), + }); } if (harJson["postData"]?["text"] != null) { var templateBody = jj.Template(kTemplateBody); - result += templateBody - .render({"body": kEncoder.convert(harJson["postData"]["text"])}); + result += templateBody.render({ + "body": kEncoder.convert(harJson["postData"]["text"]), + }); + } else if (requestModel.isFormDataRequest) { + var templateBody = jj.Template(kTemplateBody); + result += templateBody.render({ + "body": 'payload', + }); } + result += kStringRequest; return result; } catch (e) { From e08b40cfb6b09b3842723b83a0dcf0a4d428cb32 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 1 Jan 2024 09:32:35 +0530 Subject: [PATCH 070/123] Revert "feat: ability to override content type" This reverts commit e0fe907d194440893c5a1c964d15600284bd209c. --- lib/consts.dart | 2 -- .../request_pane/request_headers.dart | 18 ------------------ lib/utils/header_utils.dart | 11 ----------- lib/widgets/headerfield.dart | 6 +----- 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 39cb0dbb..d881fb86 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -305,8 +305,6 @@ const kTypeVideo = 'video'; const kSubTypeDefaultViewOptions = 'all'; -const kContentType = 'Content-Type'; - const kContentTypeMap = { ContentType.json: "$kTypeApplication/$kSubTypeJson", ContentType.text: "$kTypeText/$kSubTypePlain", diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 0f2cf728..82138db5 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,5 +1,4 @@ import 'dart:math'; -import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:davi/davi.dart'; @@ -79,23 +78,6 @@ class EditRequestHeadersState extends ConsumerState { grow: 1, cellBuilder: (_, row) { int idx = row.index; - - if (row.data.name == kContentType) { - return HeaderField( - keyId: "$activeId-$idx-headers-v-$seed", - initialValue: rows[idx].value, - hintText: " Add Header Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(activeId!); - }, - headerSuggestionsCallback: (pattern) { - return getHeaderValueSuggestions(pattern); - }, - colorScheme: Theme.of(context).colorScheme, - ); - } - return CellField( keyId: "$activeId-$idx-headers-v-$seed", initialValue: rows[idx].value, diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index de13f8b4..63a456ef 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,7 +15,6 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", - "Content-Type": "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", @@ -71,13 +70,3 @@ List getHeaderSuggestions(String pattern) { ) .toList(); } - -List headerValues = ['application/json', 'text/plain']; - -List getHeaderValueSuggestions(String pattern) { - return headerValues - .where( - (element) => element.contains(pattern.toLowerCase()), - ) - .toList(); -} diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 4ff548e3..9c678ee3 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; @@ -12,14 +10,12 @@ class HeaderField extends StatefulWidget { this.hintText, this.initialValue, this.onChanged, - this.headerSuggestionsCallback, this.colorScheme, }); final String keyId; final String? hintText; final String? initialValue; final void Function(String)? onChanged; - final FutureOr> Function(String)? headerSuggestionsCallback; final ColorScheme? colorScheme; @override @@ -71,7 +67,7 @@ class _HeaderFieldState extends State { title: Text(suggestion), ); }, - suggestionsCallback: widget.headerSuggestionsCallback ?? headerSuggestionCallback, + suggestionsCallback: headerSuggestionCallback, suggestionsBoxDecoration: suggestionBoxDecorations(context), textFieldConfiguration: TextFieldConfiguration( onChanged: widget.onChanged, From a4042e12d104d1e3c55d09e0d56144f25e77d972 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 1 Jan 2024 09:33:40 +0530 Subject: [PATCH 071/123] Update header_utils.dart --- lib/utils/header_utils.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..df97a08b 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,6 +15,8 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": + "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", From 5734b79b1fceb0c3510cb56b817c7e86853b8291 Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Mon, 1 Jan 2024 14:58:47 +0530 Subject: [PATCH 072/123] fix: set contenttype only if headers does not have one --- lib/services/http_service.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 8265a299..d4cfea2f 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,8 +28,10 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + if (!headers.containsKey(HttpHeaders.connectionHeader)) { + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + } } } Stopwatch stopwatch = Stopwatch()..start(); From 6efc5d56de06d2a94ee73758e568895e06ff270d Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Mon, 1 Jan 2024 15:03:42 +0530 Subject: [PATCH 073/123] fix: wrong header check while overriding content type --- lib/services/http_service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index d4cfea2f..0b6835a2 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,7 +28,7 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - if (!headers.containsKey(HttpHeaders.connectionHeader)) { + if (!headers.containsKey(HttpHeaders.contentTypeHeader)) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } From 5eb91fbaf708ac4f01b0bd9ba89aba17d37c800d Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Tue, 2 Jan 2024 09:22:11 +0530 Subject: [PATCH 074/123] fix: content type header presence check --- lib/services/http_service.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 0b6835a2..aad8b7f3 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,9 +28,10 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - if (!headers.containsKey(HttpHeaders.contentTypeHeader)) { - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + final hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (!hasContentTypeHeader) { + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } } } From c765cb378bf6a48d37d56cc44054f6a43cf10e91 Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Tue, 2 Jan 2024 09:23:04 +0530 Subject: [PATCH 075/123] refact: codegen to override content-type header --- lib/codegen/dart/http.dart | 5 ++++- lib/codegen/python/http_client.dart | 4 +++- lib/utils/har_utils.dart | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 67184c25..602b9a73 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -55,8 +55,11 @@ class DartHttpCodeGen { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); - composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, + final hasContentTypeHeader = composeHeaders.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (!hasContentTypeHeader) { + composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, () => kContentTypeMap[contentType] ?? ''); + } } Expression? queryParamExp; diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 83d02676..27f35380 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -102,7 +102,9 @@ print(data.decode("utf-8")) var headers = requestModel.headersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; - if (hasBody) { + bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + + if (hasBody && !hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f0838807..94cdda8b 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri; import 'package:apidash/models/models.dart' show RequestModel; @@ -129,7 +130,9 @@ Map requestModelToHARJsonRequest( if (headersList != null || hasBody) { var headers = requestModel.headersMap; if (headers.isNotEmpty || hasBody) { - if (hasBody) { + bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + + if (hasBody && !hasContentTypeHeader) { var m = { "name": "Content-Type", "value": kContentTypeMap[requestModel.requestBodyContentType] ?? "" From 5c9cffea047197805ac8977aa73a284e2d775a85 Mon Sep 17 00:00:00 2001 From: tanish goyal Date: Tue, 2 Jan 2024 19:14:40 +0530 Subject: [PATCH 076/123] added: more HTTP headers suggestions --- lib/utils/header_utils.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..a5135dd3 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -2,8 +2,18 @@ Map headers = { "Accept": "Specifies the media types that are acceptable for the response.", "Accept-Encoding": "Indicates the encoding methods the client can understand.", + "Access-Control-Allow-Headers": + "Specifies a list of HTTP headers that can be used in an actual request after a preflight request including the Access-Control-Request-Headers header is made.", + "Access-Control-Allow-Methods": + "Specifies a list of HTTP request methods allowed during CORS. ", + "Access-Control-Allow-Origin": + "Indicates whether the response can be shared with the requesting code from the given origin.", + "Access-Control-Max-Age": + "Indicates the maximum amount of time the results of a preflight request can be cached.", "Access-Control-Request-Headers": "Used in preflight requests during CORS to specify the headers that will be included in the actual request.", + "Access-Control-Request-Method": + "Used in preflight requests during CORS to indicate the HTTP method that will be used in the actual request.", "Authorization": "Contains credentials for authenticating the client with the server.", "Authorization Bearer Token": "Often used for token-based authentication.", @@ -15,6 +25,8 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": + "Indicates the original media type of the resource before any content-encoding applied for sending.", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", @@ -25,6 +37,8 @@ Map headers = { "DNT": "Informs websites whether the user's preference is to opt out of online tracking.", "Expect": "Indicates certain expectations that need to be met by the server.", + "Expires": + "Contains the date/time after which the response is considered expired", "Host": "Specifies the domain name of the server and the port number.", "If-Match": "Used for conditional requests, allows the server to respond based on certain conditions.", From 47d5bc327d81c90e1c44b5b8536a5260fe9492b3 Mon Sep 17 00:00:00 2001 From: tanish goyal Date: Tue, 2 Jan 2024 20:19:27 +0530 Subject: [PATCH 077/123] Tests (utils) : Introduces tests for header_utils --- test/utils/header_utils_test.dart | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/utils/header_utils_test.dart diff --git a/test/utils/header_utils_test.dart b/test/utils/header_utils_test.dart new file mode 100644 index 00000000..9f48ab18 --- /dev/null +++ b/test/utils/header_utils_test.dart @@ -0,0 +1,67 @@ +import 'package:apidash/utils/header_utils.dart'; +import 'package:test/test.dart'; + +void main() { + group("Testing getHeaderSuggestions function", () { + test("Testing using Allow-Headers", () { + String pattern = "Allow-Headers"; + List expected = ["Access-Control-Allow-Headers"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Allow-Methods", () { + String pattern = "Allow-Methods"; + List expected = ["Access-Control-Allow-Methods"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Allow-Origin", () { + String pattern = "Allow-Origin"; + List expected = ["Access-Control-Allow-Origin"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Request-Method", () { + String pattern = "Request-Method"; + List expected = ["Access-Control-Request-Method"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Max-Age", () { + String pattern = "Max-Age"; + List expected = ["Access-Control-Max-Age"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Access-Control-Allow-Headers", () { + String pattern = "Access-Control-Allow-Headers"; + List expected = ["Access-Control-Allow-Headers"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Access-Control-Allow-Methods", () { + String pattern = "Access-Control-Allow-Methods"; + List expected = ["Access-Control-Allow-Methods"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Access-Control-Allow-Origin", () { + String pattern = "Access-Control-Allow-Origin"; + List expected = ["Access-Control-Allow-Origin"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Access-Control-Request-Method", () { + String pattern = "Access-Control-Request-Method"; + List expected = ["Access-Control-Request-Method"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Access-Control-Max-Age", () { + String pattern = "Access-Control-Max-Age"; + List expected = ["Access-Control-Max-Age"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Content-Type", () { + String pattern = "Content-Type"; + List expected = ["Content-Type"]; + expect(getHeaderSuggestions(pattern), expected); + }); + test("Testing using Expires", () { + String pattern = "Expires"; + List expected = ["Expires"]; + expect(getHeaderSuggestions(pattern), expected); + }); + }); +} From f3e48324566eefe0c0d0de23ca848a229e65eeb3 Mon Sep 17 00:00:00 2001 From: tanish goyal Date: Wed, 3 Jan 2024 20:31:28 +0530 Subject: [PATCH 078/123] added: more common HTTP headers suggestions --- lib/utils/header_utils.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index a5135dd3..da76647d 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -14,15 +14,21 @@ Map headers = { "Used in preflight requests during CORS to specify the headers that will be included in the actual request.", "Access-Control-Request-Method": "Used in preflight requests during CORS to indicate the HTTP method that will be used in the actual request.", + "Accept-Language": + "Specifies the preferred natural language and locale for the response.", "Authorization": "Contains credentials for authenticating the client with the server.", "Authorization Bearer Token": "Often used for token-based authentication.", "Cache-Control": "Provides directives for caching mechanisms in both requests and responses.", + "Connection": + "Informs whether the connection stays open or close after the current transaction finishes.", "Content-Disposition": "Specifies the presentation style (inline or attachment) of the response.", "Content-Encoding": "Indicates the encoding transformations that have been applied to the entity body of the response.", + "Content-Length": + "Indicates the size of the message body sent to the recipient in bytes.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", "Content-Type": @@ -34,6 +40,7 @@ Map headers = { "Controls which documents are allowed to open a new window or access the current window.", "Cross-Origin-Resource-Policy": "Controls how cross-origin requests for resources are handled.", + "Date": "Indicates the date and time at which the message was sent.", "DNT": "Informs websites whether the user's preference is to opt out of online tracking.", "Expect": "Indicates certain expectations that need to be met by the server.", @@ -50,6 +57,8 @@ Map headers = { "Used in conjunction with the Range header to conditionally request a partial resource.", "If-Unmodified-Since": "Used for conditional requests, allows the server to respond based on certain conditions.", + "Location": + "Indicates the URL a client should redirect to for further interaction.", "Origin": "Specifies the origin of a cross-origin request.", "Range": "Used to request only part of a resource, typically in the context of downloading large files.", @@ -59,6 +68,7 @@ Map headers = { "Specifies how much information the browser should include in the Referer header when navigating to other pages.", "Retry-After": "Informs the client how long it should wait before making another request after a server has responded with a rate-limiting status code.", + "Server": "Indicates the software used by the origin server.", "Strict-Transport-Security": "Instructs the browser to always use HTTPS for the given domain.", "TE": "Specifies the transfer encodings that are acceptable to the client.", @@ -67,10 +77,14 @@ Map headers = { "Via": "Indicates intermediate proxies or gateways through which the request or response has passed.", "X-Api-Key": "Used to authenticate requests to an API with an API key.", + "X-Content-Type-Options": + "Used to prevent browsers from MIME-sniffing a response.", "X-CSRF-Token": "Used for protection against Cross-Site Request Forgery (CSRF) attacks.", "X-Forwarded-For": "Identifies the client's original IP address when behind a proxy or load balancer.", + "X-Frame-Options": + "Controls whether a webpage can be displayed within an iframe or other embedded frame elements.", "X-Requested-With": "Indicates whether the request was made with JavaScript using XMLHttpRequest.", "X-XSS-Protection": From 09916f2f52bf8f408f5877b246501646cdc38303 Mon Sep 17 00:00:00 2001 From: tanish goyal Date: Wed, 3 Jan 2024 20:34:17 +0530 Subject: [PATCH 079/123] Tests (utils) : Added more comprehensive tests --- test/utils/header_utils_test.dart | 76 ++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/test/utils/header_utils_test.dart b/test/utils/header_utils_test.dart index 9f48ab18..73c15721 100644 --- a/test/utils/header_utils_test.dart +++ b/test/utils/header_utils_test.dart @@ -8,60 +8,134 @@ void main() { List expected = ["Access-Control-Allow-Headers"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Allow-Methods", () { String pattern = "Allow-Methods"; List expected = ["Access-Control-Allow-Methods"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Allow-Origin", () { String pattern = "Allow-Origin"; List expected = ["Access-Control-Allow-Origin"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Request-Method", () { String pattern = "Request-Method"; List expected = ["Access-Control-Request-Method"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Max-Age", () { String pattern = "Max-Age"; List expected = ["Access-Control-Max-Age"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Access-Control-Allow-Headers", () { String pattern = "Access-Control-Allow-Headers"; List expected = ["Access-Control-Allow-Headers"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Access-Control-Allow-Methods", () { String pattern = "Access-Control-Allow-Methods"; List expected = ["Access-Control-Allow-Methods"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Access-Control-Allow-Origin", () { String pattern = "Access-Control-Allow-Origin"; List expected = ["Access-Control-Allow-Origin"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Access-Control-Request-Method", () { String pattern = "Access-Control-Request-Method"; List expected = ["Access-Control-Request-Method"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Access-Control-Max-Age", () { String pattern = "Access-Control-Max-Age"; List expected = ["Access-Control-Max-Age"]; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Content-Type", () { String pattern = "Content-Type"; - List expected = ["Content-Type"]; + List expected = ['Content-Type', 'X-Content-Type-Options']; expect(getHeaderSuggestions(pattern), expected); }); + test("Testing using Expires", () { String pattern = "Expires"; List expected = ["Expires"]; expect(getHeaderSuggestions(pattern), expected); }); + + test("Testing using 'Access-Control' pattern", () { + String pattern = "Access-Control"; + List expected = [ + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + "Access-Control-Max-Age", + "Access-Control-Request-Headers", + "Access-Control-Request-Method" + ]; + expect(getHeaderSuggestions(pattern), expected); + }); + + test("Testing using 'allow-' pattern", () { + String pattern = 'allow-'; + List expected = [ + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin" + ]; + expect(getHeaderSuggestions(pattern), expected); + }); + + test("Testing using 'content' pattern", () { + String pattern = "content"; + List expected = [ + 'Content-Disposition', + 'Content-Encoding', + 'Content-Length', + 'Content-Security-Policy', + 'Content-Type', + 'X-Content-Type-Options' + ]; + expect(getHeaderSuggestions(pattern), expected); + }); + + test("Testing using 'x-' pattern", () { + String pattern = "x-"; + List expected = [ + "Access-Control-Max-Age", + "X-Api-Key", + "X-Content-Type-Options", + "X-CSRF-Token", + "X-Forwarded-For", + "X-Frame-Options", + "X-Requested-With", + "X-XSS-Protection" + ]; + expect(getHeaderSuggestions(pattern), expected); + }); + + test("Testing for 'origin' pattern", () { + String pattern = "origin"; + List expected = [ + 'Access-Control-Allow-Origin', + 'Cross-Origin-Embedder-Policy', + 'Cross-Origin-Opener-Policy', + 'Cross-Origin-Resource-Policy', + 'Origin' + ]; + expect(getHeaderSuggestions(pattern), expected); + }); }); } From 8d7f745bd59d8e7c86efd26a4d0263d9f6556861 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 3 Jan 2024 21:02:32 +0530 Subject: [PATCH 080/123] feat: added js amd node-fetch code gen --- lib/codegen/js/fetch.dart | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index aeaa9c81..adbc2eec 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -47,37 +47,21 @@ function readFile(file) { '''; String kMultiPartBodyTemplate = r''' async function buildDataList(fields) { - const dataList = []; + var formdata = new FormData(); for (const field of fields) { const name = field.name || ''; const value = field.value || ''; const type = field.type || 'text'; - dataList.push(`--{{boundary}}`); if (type === 'text') { - dataList.push(`Content-Disposition: form-data; name="${name}"`); - dataList.push('Content-Type: text/plain'); - dataList.push(''); - dataList.push(value); + formdata.append(name, value); } else if (type === 'file') { - const fileContent = await readFile(value); - dataList.push(`Content-Disposition: form-data; name="$name"; filename="${value.name}"`); - dataList.push(`Content-Type: ${value.type}`); - dataList.push(''); - {% if isNodeJs %}dataList.push(fileContent); - {% else %} - dataList.push(fileContent.content);{% endif %}} + formdata.append(name,{% if isNodeJs %} fs.createReadStream(value){% else %} fileInput.files[0],value{% endif %}); } - dataList.push(`--{{boundary}}--`); - dataList.push(''); - return dataList.join('\r\n'); } -var dataList = []; -buildDataList({{fields_list}}) - .then(data => dataList = data) - .catch(err => console.error(err)); -const payload = dataList.join('\r\n'); + +const payload = buildDataList({{fields_list}}); '''; String kStringRequest = """ From e98ee3d2b1180e63d13246f3cafe47b368879c37 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 3 Jan 2024 21:27:17 +0530 Subject: [PATCH 081/123] fix: axios is added and fetch issues fixed --- lib/codegen/js/axios.dart | 62 +++++++++++++++++++++++++++++++++++---- lib/codegen/js/fetch.dart | 38 ++++++++---------------- 2 files changed, 69 insertions(+), 31 deletions(-) diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index 21c99c8b..4c67f4f7 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -1,8 +1,14 @@ +import 'dart:convert'; import 'package:apidash/consts.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' - show requestModelToHARJsonRequest, padMultilineString, stripUrlParams; -import 'package:apidash/models/models.dart' show RequestModel; + show + padMultilineString, + requestModelToHARJsonRequest, + rowsToFormDataMap, + stripUrlParams; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class AxiosCodeGen { AxiosCodeGen({this.isNodeJs = false}); @@ -10,6 +16,8 @@ class AxiosCodeGen { final bool isNodeJs; String kStringImportNode = """import axios from 'axios'; +{% if isFormDataRequest and isNodeJs %}const fs = require('fs'); +{% endif %} """; @@ -46,13 +54,45 @@ axios(config) console.log(error); }); """; + String kMultiPartBodyTemplate = r''' +async function buildFormData(fields) { + var formdata = new FormData(); + for (const field of fields) { + const name = field.name || ''; + const value = field.value || ''; + const type = field.type || 'text'; + if (type === 'text') { + formdata.append(name, value); + } else if (type === 'file') { + formdata.append(name,{% if isNodeJs %} fs.createReadStream(value){% else %} fileInput.files[0],value{% endif %}); + } + } + return formdata; +} + + +'''; + var kGetFormDataTemplate = '''buildFormData({{fields_list}}); +'''; String? getCode( RequestModel requestModel, String defaultUriScheme, ) { try { - String result = isNodeJs ? kStringImportNode : ""; + List formDataList = requestModel.formDataList ?? []; + jj.Template kNodejsImportTemplate = jj.Template(kStringImportNode); + String importsData = kNodejsImportTemplate.render({ + "isFormDataRequest": requestModel.isFormDataRequest, + "isNodeJs": isNodeJs, + }); + + String result = importsData; + var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); + var renderedMultiPartBody = templateMultiPartBody.render({ + "isNodeJs": isNodeJs, + }); + result += renderedMultiPartBody; String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { @@ -80,18 +120,30 @@ axios(config) } var headers = harJson["headers"]; - if (headers.isNotEmpty) { + if (headers.isNotEmpty || requestModel.isFormDataRequest) { var templateHeader = jj.Template(kTemplateHeader); var m = {}; for (var i in headers) { m[i["name"]] = i["value"]; } + if (requestModel.isFormDataRequest) { + m['Content-Type'] = 'multipart/form-data'; + } result += templateHeader .render({"headers": padMultilineString(kEncoder.convert(m), 2)}); } + var templateBody = jj.Template(kTemplateBody); + if (requestModel.isFormDataRequest) { + var getFieldDataTemplate = jj.Template(kGetFormDataTemplate); + + result += templateBody.render({ + "body": getFieldDataTemplate.render({ + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }) + }); + } if (harJson["postData"]?["text"] != null) { - var templateBody = jj.Template(kTemplateBody); result += templateBody .render({"body": kEncoder.convert(harJson["postData"]["text"])}); } diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index adbc2eec..715b5e6d 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -5,7 +5,7 @@ import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' - show getNewUuid, padMultilineString, requestModelToHARJsonRequest; + show padMultilineString, requestModelToHARJsonRequest; import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class FetchCodeGen { @@ -13,14 +13,16 @@ class FetchCodeGen { final bool isNodeJs; - String kStringImportNode = """ + String kStringImportNode = + """ import fetch from 'node-fetch'; {% if isFormDataRequest %}const fs = require('fs');{% endif %} """; - String kTemplateStart = """let url = '{{url}}'; + String kTemplateStart = + """let url = '{{url}}'; let options = { method: '{{method}}' @@ -33,19 +35,9 @@ let options = { String kTemplateBody = """, body: {{body}} """; - String kMultiPartFileReader = ''' -function readFile(file) { - {% if isNodeJs %} return fs.readFile(file, 'binary'); {% else %} return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = () => resolve(reader.result); - reader.onerror = reject; - reader.readAsArrayBuffer(file); - }); -{% endif %} -} -'''; - String kMultiPartBodyTemplate = r''' + String kMultiPartBodyTemplate = + r''' async function buildDataList(fields) { var formdata = new FormData(); for (const field of fields) { @@ -58,13 +50,15 @@ async function buildDataList(fields) { } else if (type === 'file') { formdata.append(name,{% if isNodeJs %} fs.createReadStream(value){% else %} fileInput.files[0],value{% endif %}); } - + } + return formdata; } const payload = buildDataList({{fields_list}}); '''; - String kStringRequest = """ + String kStringRequest = + """ }; @@ -90,7 +84,6 @@ fetch(url, options) ) { try { List formDataList = requestModel.formDataList ?? []; - String uuid = getNewUuid(); jj.Template kNodejsImportTemplate = jj.Template(kStringImportNode); String importsData = kNodejsImportTemplate.render({ "isFormDataRequest": requestModel.isFormDataRequest, @@ -98,15 +91,8 @@ fetch(url, options) String result = isNodeJs ? importsData : ""; if (requestModel.isFormDataRequest) { - jj.Template kMultiPartFileReaderTemplate = - jj.Template(kMultiPartFileReader); - result += kMultiPartFileReaderTemplate.render({ - "isNodeJs": isNodeJs, - }); - var boundary = uuid; var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); result += templateMultiPartBody.render({ - "boundary": boundary, "isNodeJs": isNodeJs, "fields_list": json.encode(rowsToFormDataMap(formDataList)), }); @@ -131,7 +117,7 @@ fetch(url, options) var templateHeader = jj.Template(kTemplateHeader); var m = {}; if (requestModel.isFormDataRequest) { - m["Content-Type"] = "multipart/form-data; boundary=$uuid"; + m["Content-Type"] = "multipart/form-data"; } for (var i in headers) { m[i["name"]] = i["value"]; From 9fa72af06bc171e752f3812fc67102e3b86df9bc Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Wed, 3 Jan 2024 23:10:51 +0530 Subject: [PATCH 082/123] feat: added http and dio code gen --- lib/codegen/dart/dio.dart | 30 ++++++++++-- lib/codegen/dart/http.dart | 83 +++++++++++++++++++++++++++++----- lib/services/http_service.dart | 1 + 3 files changed, 99 insertions(+), 15 deletions(-) diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index 1b4a8820..7453b8ca 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -1,5 +1,8 @@ +import 'dart:convert'; + import 'package:apidash/consts.dart'; import 'package:apidash/models/request_model.dart' show RequestModel; +import 'package:apidash/utils/convert_utils.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; @@ -22,6 +25,7 @@ class DartDioCodeGen { headers: requestModel.headersMap, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, + formData: rowsToFormDataMap(requestModel.formDataList) ?? [], ); return next; } catch (e) { @@ -36,6 +40,7 @@ class DartDioCodeGen { required Map headers, required String? body, required ContentType contentType, + required List> formData, }) { final sbf = StringBuffer(); final emitter = DartEmitter(); @@ -54,9 +59,22 @@ class DartDioCodeGen { literalMap(headers.map((key, value) => MapEntry(key, value))), ); } - + final multiPartList = Code(''' + final List> formDataList = ${json.encode(formData)}; + for (var formField in formDataList) { + if (formField['type'] == 'file') { + formData.files.add(MapEntry( + formField['name'], + await MultipartFile.fromFile(formField['value'], filename: formField['value']), + )); + } else { + formData.fields.add(MapEntry(formField['name'], formField['value'])); + } + } + '''); Expression? dataExp; - if (kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false)) { + if ((kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false) || + contentType == ContentType.formdata)) { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); switch (contentType) { // dio dosen't need pass `content-type` header when body is json or plain text @@ -69,7 +87,7 @@ class DartDioCodeGen { dataExp = declareFinal('data').assign(strContent); // when add new type of [ContentType], need update [dataExp]. case ContentType.formdata: - // TODO: Need to Handle this case. + dataExp = declareFinal('data').assign(refer('FormData()')); } } final responseExp = declareFinal('response').assign(InvokeExpression.newOf( @@ -95,6 +113,8 @@ class DartDioCodeGen { if (queryParamExp != null) queryParamExp, if (headerExp != null) headerExp, if (dataExp != null) dataExp, + if ((contentType == ContentType.formdata && formData.isNotEmpty)) + multiPartList, responseExp, refer('print').call([refer('response').property('statusCode')]), refer('print').call([refer('response').property('data')]), @@ -124,6 +144,8 @@ class DartDioCodeGen { sbf.writeln(mainFunction.accept(emitter)); - return DartFormatter(pageWidth: 160).format(sbf.toString()); + return DartFormatter( + pageWidth: contentType == ContentType.formdata ? 70 : 160) + .format(sbf.toString()); } } diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 67184c25..9f3ce219 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -1,7 +1,9 @@ +import 'dart:convert'; import 'dart:io'; import 'package:apidash/consts.dart'; import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/utils/convert_utils.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; @@ -24,6 +26,7 @@ class DartHttpCodeGen { headers: requestModel.headersMap, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, + formData: rowsToFormDataMap(requestModel.formDataList) ?? [], ); return next; } catch (e) { @@ -38,6 +41,7 @@ class DartHttpCodeGen { required Map headers, required String? body, required ContentType contentType, + required List> formData, }) { final uri = Uri.parse(url); @@ -99,7 +103,9 @@ class DartHttpCodeGen { ); } final responseExp = declareFinal('response').assign(InvokeExpression.newOf( - refer('http.${method.name}'), + refer( + 'http.${method.name}', + ), [refer('uri')], { if (headerExp != null) 'headers': refer('headers'), @@ -107,7 +113,36 @@ class DartHttpCodeGen { }, [], ).awaited); + final multiPartRequest = + declareFinal('request').assign(InvokeExpression.newOf( + refer( + 'http.MultipartRequest', + ), + [refer(jsonEncode(method.name.toUpperCase())), refer('uri')], + )); + final multiPartFiles = declareFinal('formDataList').assign(refer( + jsonEncode(formData), + )); + final addHeaders = refer('request.headers.addAll').call([refer('headers')]); + const multiPartList = Code(''' + for (Map formData in formDataList){ + if (formData['type'] == 'text') { + request.fields.addAll({formData['name']: formData['value']}); + } else { + request.files.add( + await http.MultipartFile.fromPath( + formData['name'], + formData['value'], + ), + ); + } + } +'''); + var multiPartRequestSend = + declareFinal('response').assign(refer('request.send()').awaited); + var multiPartResponseBody = declareFinal('responseBody') + .assign(refer('response.stream.bytesToString()').awaited); final mainFunction = Method((m) { final statusRef = refer('statusCode'); m @@ -132,25 +167,49 @@ class DartHttpCodeGen { b.statements.add(headerExp.statement); } b.statements.add(const Code('\n')); - b.statements.add(responseExp.statement); - b.statements.add(const Code('\n')); - b.statements.add(declareVar('statusCode', type: refer('int')) - .assign(refer('response').property('statusCode')) - .statement); + if (contentType == ContentType.formdata) { + if (formData.isNotEmpty) { + b.statements.add(multiPartFiles.statement); + } + b.statements.add(multiPartRequest.statement); + if (formData.isNotEmpty) { + b.statements.add(multiPartList); + } + if (headerExp != null) { + b.statements.add(addHeaders.statement); + } + b.statements.add(multiPartRequestSend.statement); + b.statements.add(multiPartResponseBody.statement); + b.statements.add(declareVar('statusCode', type: refer('int')) + .assign(refer('response').property('statusCode')) + .statement); + b.statements.add(const Code('\n')); + } else { + b.statements.add(responseExp.statement); + b.statements.add(const Code('\n')); + b.statements.add(declareVar('statusCode', type: refer('int')) + .assign(refer('response').property('statusCode')) + .statement); + } + b.statements.add(declareIfElse( condition: statusRef .greaterOrEqualTo(literalNum(200)) .and(statusRef.lessThan(literalNum(300))), body: [ refer('print').call([literalString(r'Status Code: $statusCode')]), - refer('print') - .call([literalString(r'Response Body: ${response.body}')]), + refer('print').call([ + literalString( + 'Response Body: ${contentType == ContentType.formdata ? ':\$responseBody' : '\${response.body}'}') + ]), ], elseBody: [ refer('print') .call([literalString(r'Error Status Code: $statusCode')]), - refer('print').call( - [literalString(r'Error Response Body: ${response.body}')]), + refer('print').call([ + literalString( + 'Error Response Body: ${contentType == ContentType.formdata ? ':\$responseBody' : '\${response.body}'}') + ]), ], )); }); @@ -158,6 +217,8 @@ class DartHttpCodeGen { sbf.writeln(mainFunction.accept(emitter)); - return DartFormatter(pageWidth: 160).format(sbf.toString()); + return DartFormatter( + pageWidth: contentType == ContentType.formdata ? 70 : 160) + .format(sbf.toString()); } } diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 8d6e70b9..a88f060d 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -39,6 +39,7 @@ Future<(http.Response?, Duration?, String?)> request( requestModel.method.name.toUpperCase(), requestUrl, ); + multiPartRequest.headers.addAll(headers); for (FormDataModel formData in (requestModel.formDataList ?? [])) { if (formData.type == FormDataType.text) { multiPartRequest.fields.addAll({formData.name: formData.value}); From 06b5eaff22e5dbff6d81793d5b024d7fec30db96 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:50:37 +0530 Subject: [PATCH 083/123] fix: fixed okhttp3 code gen --- lib/codegen/kotlin/okhttp.dart | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index 09cd2ce9..995dcaa4 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'package:apidash/consts.dart'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' show getValidRequestUri, stripUriParams; @@ -61,6 +63,13 @@ import okhttp3.MediaType.Companion.toMediaType"""; } """; +// Converting list of form data objects to kolin multi part data + String kFormDataBody = ''' + val body = MultipartBody.Builder().setType(MultipartBody.FORM){% for item in formDataList %}{% if item.type == 'file' %} + .addFormDataPart("{{item.name}}",null,File("{{item.value}}").asRequestBody("application/octet-stream".toMediaType())) + {% else %}.addFormDataPart("{{item.name}}","{{item.value}}") + {% endif %}{% endfor %}.build() +'''; String? getCode( RequestModel requestModel, @@ -68,7 +77,6 @@ import okhttp3.MediaType.Companion.toMediaType"""; ) { try { String result = ""; - bool hasHeaders = false; bool hasQuery = false; bool hasBody = false; @@ -99,7 +107,13 @@ import okhttp3.MediaType.Companion.toMediaType"""; var method = requestModel.method; var requestBody = requestModel.requestBody; - if (kMethodsWithBody.contains(method) && requestBody != null) { + if (requestModel.isFormDataRequest) { + var formDataTemplate = jj.Template(kFormDataBody); + + result += formDataTemplate.render({ + "formDataList": rowsToFormDataMap(requestModel.formDataList), + }); + } else if (kMethodsWithBody.contains(method) && requestBody != null) { var contentLength = utf8.encode(requestBody).length; if (contentLength > 0) { hasBody = true; @@ -124,7 +138,6 @@ import okhttp3.MediaType.Companion.toMediaType"""; if (headersList != null) { var headers = requestModel.headersMap; if (headers.isNotEmpty) { - hasHeaders = true; result += getHeaders(headers); } } @@ -132,7 +145,7 @@ import okhttp3.MediaType.Companion.toMediaType"""; var templateRequestEnd = jj.Template(kTemplateRequestEnd); result += templateRequestEnd.render({ "method": method.name.toLowerCase(), - "hasBody": hasBody ? "body" : "", + "hasBody": (hasBody || requestModel.isFormDataRequest) ? "body" : "", }); } return result; From 4cf36b645015194c33907e9f8c12499464e2152b Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 14:36:30 +0530 Subject: [PATCH 084/123] Update model & codegen --- lib/codegen/dart/dio.dart | 9 ++-- lib/codegen/dart/http.dart | 14 +++---- lib/codegen/js/axios.dart | 14 ++----- lib/codegen/js/fetch.dart | 22 ++++------ lib/codegen/kotlin/okhttp.dart | 6 +-- lib/codegen/python/http_client.dart | 13 +++--- lib/codegen/python/requests.dart | 13 ++---- lib/models/request_model.dart | 41 ++++++++++++------- lib/utils/convert_utils.dart | 29 +++++++------ .../extensions/request_model_extension.dart | 8 ---- 10 files changed, 71 insertions(+), 98 deletions(-) delete mode 100644 lib/utils/extensions/request_model_extension.dart diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index 72b62ac3..c4a7ed8e 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -1,11 +1,8 @@ import 'dart:convert'; - -import 'package:apidash/consts.dart'; -import 'package:apidash/models/request_model.dart' show RequestModel; -import 'package:apidash/utils/convert_utils.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; - +import 'package:apidash/models/request_model.dart' show RequestModel; +import 'package:apidash/consts.dart'; import 'shared.dart'; class DartDioCodeGen { @@ -25,7 +22,7 @@ class DartDioCodeGen { headers: requestModel.enabledHeadersMap, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, - formData: rowsToFormDataMap(requestModel.formDataList) ?? [], + formData: requestModel.formDataMapList, ); return next; } catch (e) { diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index b257c662..f301db19 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -1,12 +1,9 @@ import 'dart:convert'; import 'dart:io'; - -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart' show RequestModel; -import 'package:apidash/utils/convert_utils.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; - +import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/consts.dart'; import 'shared.dart'; class DartHttpCodeGen { @@ -26,7 +23,7 @@ class DartHttpCodeGen { headers: requestModel.enabledHeadersMap, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, - formData: rowsToFormDataMap(requestModel.formDataList) ?? [], + formData: requestModel.formDataMapList, ); return next; } catch (e) { @@ -59,10 +56,11 @@ class DartHttpCodeGen { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); - final hasContentTypeHeader = composeHeaders.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + final hasContentTypeHeader = composeHeaders.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (!hasContentTypeHeader) { composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, - () => kContentTypeMap[contentType] ?? ''); + () => kContentTypeMap[contentType] ?? ''); } } diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index cd9ee2a4..fc65905b 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -1,14 +1,9 @@ import 'dart:convert'; -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' - show - padMultilineString, - requestModelToHARJsonRequest, - rowsToFormDataMap, - stripUrlParams; -import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; + show padMultilineString, requestModelToHARJsonRequest, stripUrlParams; +import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/consts.dart'; class AxiosCodeGen { AxiosCodeGen({this.isNodeJs = false}); @@ -80,7 +75,6 @@ async function buildFormData(fields) { String defaultUriScheme, ) { try { - List formDataList = requestModel.formDataList ?? []; jj.Template kNodejsImportTemplate = jj.Template(kStringImportNode); String importsData = kNodejsImportTemplate.render({ "isFormDataRequest": requestModel.isFormDataRequest, @@ -139,7 +133,7 @@ async function buildFormData(fields) { result += templateBody.render({ "body": getFieldDataTemplate.render({ - "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "fields_list": json.encode(requestModel.formDataMapList), }) }); } diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index f959a33b..31f7a211 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -1,28 +1,23 @@ import 'dart:convert'; - -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/convert_utils.dart'; -import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' show padMultilineString, requestModelToHARJsonRequest; -import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; +import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/consts.dart'; class FetchCodeGen { FetchCodeGen({this.isNodeJs = false}); final bool isNodeJs; - String kStringImportNode = - """ + String kStringImportNode = """ import fetch from 'node-fetch'; {% if isFormDataRequest %}const fs = require('fs');{% endif %} """; - String kTemplateStart = - """let url = '{{url}}'; + String kTemplateStart = """let url = '{{url}}'; let options = { method: '{{method}}' @@ -36,8 +31,7 @@ let options = { body: {{body}} """; - String kMultiPartBodyTemplate = - r''' + String kMultiPartBodyTemplate = r''' async function buildDataList(fields) { var formdata = new FormData(); for (const field of fields) { @@ -57,8 +51,7 @@ async function buildDataList(fields) { const payload = buildDataList({{fields_list}}); '''; - String kStringRequest = - """ + String kStringRequest = """ }; @@ -83,7 +76,6 @@ fetch(url, options) String defaultUriScheme, ) { try { - List formDataList = requestModel.formDataList ?? []; jj.Template kNodejsImportTemplate = jj.Template(kStringImportNode); String importsData = kNodejsImportTemplate.render({ "isFormDataRequest": requestModel.isFormDataRequest, @@ -94,7 +86,7 @@ fetch(url, options) var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); result += templateMultiPartBody.render({ "isNodeJs": isNodeJs, - "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "fields_list": json.encode(requestModel.formDataMapList), }); } String url = requestModel.url; diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index df7774a9..becfdbe4 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -1,11 +1,9 @@ import 'dart:convert'; -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/convert_utils.dart'; -import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' show getValidRequestUri, stripUriParams; import '../../models/request_model.dart'; +import 'package:apidash/consts.dart'; class KotlinOkHttpCodeGen { final String kTemplateStart = """import okhttp3.OkHttpClient @@ -114,7 +112,7 @@ import okhttp3.MediaType.Companion.toMediaType"""; var formDataTemplate = jj.Template(kFormDataBody); result += formDataTemplate.render({ - "formDataList": rowsToFormDataMap(requestModel.formDataList), + "formDataList": requestModel.formDataMapList, }); } else if (kMethodsWithBody.contains(method) && requestBody != null) { var contentLength = utf8.encode(requestBody).length; diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 625c3937..cc34cb70 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -1,11 +1,10 @@ import 'dart:io'; import 'dart:convert'; -import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' - show getNewUuid, getValidRequestUri, padMultilineString, rowsToFormDataMap; -import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; + show getNewUuid, getValidRequestUri, padMultilineString; +import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/consts.dart'; class PythonHttpClientCodeGen { final String kTemplateStart = """import http.client @@ -91,7 +90,6 @@ body = b'\r\n'.join(dataList) RequestModel requestModel, String defaultUriScheme, ) { - List formDataList = requestModel.formDataList ?? []; String uuid = getNewUuid(); try { @@ -154,7 +152,8 @@ body = b'\r\n'.join(dataList) if (headers.isNotEmpty || hasBody) { hasHeaders = true; - bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + bool hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (hasBody && !hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = @@ -170,7 +169,7 @@ body = b'\r\n'.join(dataList) var formDataBodyData = jj.Template(kStringFormDataBody); result += formDataBodyData.render( { - "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "fields_list": json.encode(requestModel.formDataMapList), "boundary": uuid, }, ); diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index 5825584b..a2f359a1 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -1,16 +1,10 @@ import 'dart:io'; import 'dart:convert'; -import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' - show - getNewUuid, - getValidRequestUri, - padMultilineString, - rowsToFormDataMap, - stripUriParams; -import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; + show getNewUuid, getValidRequestUri, padMultilineString, stripUriParams; +import 'package:apidash/models/models.dart' show RequestModel; class PythonRequestsCodeGen { final String kTemplateStart = """import requests @@ -107,7 +101,6 @@ print('Response Body:', response.text) bool hasHeaders = false; bool hasBody = false; bool hasJsonBody = false; - List formDataList = requestModel.formDataList ?? []; String uuid = getNewUuid(); String url = requestModel.url; @@ -181,7 +174,7 @@ print('Response Body:', response.text) var formDataBodyData = jj.Template(kStringFormDataBody); result += formDataBodyData.render( { - "fields_list": json.encode(rowsToFormDataMap(formDataList)), + "fields_list": json.encode(requestModel.formDataMapList), "boundary": uuid, }, ); diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index f1dfb492..49277d1f 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,6 +1,11 @@ import 'package:flutter/foundation.dart'; -import '../utils/utils.dart'; - show listToFormDataModel, rowsToFormDataMap, mapToRows, rowsToMap, getEnabledRows; +import '../utils/utils.dart' + show + mapListToFormDataModelRows, + rowsToFormDataMapList, + mapToRows, + rowsToMap, + getEnabledRows; import '../consts.dart'; import 'models.dart'; @@ -19,10 +24,10 @@ class RequestModel { this.isParamEnabledList, this.requestBodyContentType = ContentType.json, this.requestBody, + this.requestFormDataList, this.responseStatus, this.message, this.responseModel, - this.formDataList, }); final String id; @@ -35,9 +40,9 @@ class RequestModel { final List? requestParams; final List? isHeaderEnabledList; final List? isParamEnabledList; - final List? requestFormDataList; final ContentType requestBodyContentType; final String? requestBody; + final List? requestFormDataList; final int? responseStatus; final String? message; final ResponseModel? responseModel; @@ -54,6 +59,10 @@ class RequestModel { Map get headersMap => rowsToMap(requestHeaders) ?? {}; Map get paramsMap => rowsToMap(requestParams) ?? {}; + List> get formDataMapList => + rowsToFormDataMapList(requestFormDataList) ?? []; + bool get isFormDataRequest => requestBodyContentType == ContentType.formdata; + RequestModel duplicate({ required String id, }) { @@ -71,7 +80,8 @@ class RequestModel { isParamEnabledList != null ? [...isParamEnabledList!] : null, requestBodyContentType: requestBodyContentType, requestBody: requestBody, - formDataList: formDataList != null ? [...formDataList!] : null, + requestFormDataList: + requestFormDataList != null ? [...requestFormDataList!] : null, ); } @@ -88,10 +98,10 @@ class RequestModel { List? isParamEnabledList, ContentType? requestBodyContentType, String? requestBody, + List? requestFormDataList, int? responseStatus, String? message, ResponseModel? responseModel, - List? formDataList, }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; @@ -111,10 +121,10 @@ class RequestModel { requestBodyContentType: requestBodyContentType ?? this.requestBodyContentType, requestBody: requestBody ?? this.requestBody, + requestFormDataList: requestFormDataList ?? this.requestFormDataList, responseStatus: responseStatus ?? this.responseStatus, message: message ?? this.message, responseModel: responseModel ?? this.responseModel, - formDataList: formDataList ?? this.formDataList, ); } @@ -143,10 +153,10 @@ class RequestModel { requestBodyContentType = kDefaultContentType; } final requestBody = data["requestBody"] as String?; + final requestFormDataList = data["requestFormDataList"]; final responseStatus = data["responseStatus"] as int?; final message = data["message"] as String?; final responseModelJson = data["responseModel"]; - final formDataList = data["formDataList"]; if (responseModelJson != null) { responseModel = @@ -172,11 +182,12 @@ class RequestModel { isParamEnabledList: isParamEnabledList, requestBodyContentType: requestBodyContentType, requestBody: requestBody, + requestFormDataList: requestFormDataList != null + ? mapListToFormDataModelRows(List.from(requestFormDataList)) + : null, responseStatus: responseStatus, message: message, responseModel: responseModel, - formDataList: - formDataList != null ? listToFormDataModel(formDataList) : null, ); } @@ -193,10 +204,10 @@ class RequestModel { "isParamEnabledList": isParamEnabledList, "requestBodyContentType": requestBodyContentType.name, "requestBody": requestBody, + "requestFormDataList": rowsToFormDataMapList(requestFormDataList), "responseStatus": includeResponse ? responseStatus : null, "message": includeResponse ? message : null, "responseModel": includeResponse ? responseModel?.toJson() : null, - "formDataList": rowsToFormDataMap(formDataList) }; } @@ -215,10 +226,10 @@ class RequestModel { "Enabled Params: ${isParamEnabledList.toString()}", "Request Body Content Type: ${requestBodyContentType.toString()}", "Request Body: ${requestBody.toString()}", + "Request FormData: ${requestFormDataList.toString()}", "Response Status: $responseStatus", "Response Message: $message", "Response: ${responseModel.toString()}" - "FormData: ${formDataList.toString()}" ].join("\n"); } @@ -238,10 +249,10 @@ class RequestModel { listEquals(other.isParamEnabledList, isParamEnabledList) && other.requestBodyContentType == requestBodyContentType && other.requestBody == requestBody && + other.requestFormDataList == requestFormDataList && other.responseStatus == responseStatus && other.message == message && - other.responseModel == responseModel && - other.formDataList == formDataList; + other.responseModel == responseModel; } @override @@ -260,10 +271,10 @@ class RequestModel { isParamEnabledList, requestBodyContentType, requestBody, + requestFormDataList, responseStatus, message, responseModel, - formDataList, ); } } diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 10aec7a0..bc704af9 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -79,7 +79,18 @@ Map? rowsToMap(List? kvRows, return finalMap; } -List>? rowsToFormDataMap( +List? mapToRows(Map? kvMap) { + if (kvMap == null) { + return null; + } + List finalRows = []; + for (var k in kvMap.keys) { + finalRows.add(NameValueModel(name: k, value: kvMap[k])); + } + return finalRows; +} + +List>? rowsToFormDataMapList( List? kvRows, ) { if (kvRows == null) { @@ -95,18 +106,7 @@ List>? rowsToFormDataMap( return finalMap; } -List? mapToRows(Map? kvMap) { - if (kvMap == null) { - return null; - } - List finalRows = []; - for (var k in kvMap.keys) { - finalRows.add(NameValueModel(name: k, value: kvMap[k])); - } - return finalRows; -} - -List? listToFormDataModel(List? kvMap) { +List? mapListToFormDataModelRows(List? kvMap) { if (kvMap == null) { return null; } @@ -123,8 +123,7 @@ List? listToFormDataModel(List? kvMap) { } FormDataType getFormDataType(String? type) { - List formData = FormDataType.values; - return formData.firstWhere((element) => element.name == type, + return FormDataType.values.firstWhere((element) => element.name == type, orElse: () => FormDataType.text); } diff --git a/lib/utils/extensions/request_model_extension.dart b/lib/utils/extensions/request_model_extension.dart deleted file mode 100644 index 95563a05..00000000 --- a/lib/utils/extensions/request_model_extension.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; - -extension RequestModelExtension on RequestModel { - bool get isFormDataRequest { - return requestBodyContentType == ContentType.formdata; - } -} From 462519610a9834794417ff2a85be1f2118f84a1e Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 14:45:18 +0530 Subject: [PATCH 085/123] fixes --- lib/providers/collection_providers.dart | 1 - lib/services/http_service.dart | 10 ++++++---- lib/utils/har_utils.dart | 11 +++++------ lib/widgets/form_data_widget.dart | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 6aee2c2e..415c9715 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -149,7 +149,6 @@ class CollectionStateNotifier responseStatus: responseStatus, message: message, responseModel: responseModel); - ); //print(newModel); var map = {...state!}; map[id] = newModel; diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index aa46f010..1b8b8395 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -29,10 +29,11 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - final hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + final hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (!hasContentTypeHeader) { - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } } } @@ -43,7 +44,8 @@ Future<(http.Response?, Duration?, String?)> request( requestUrl, ); multiPartRequest.headers.addAll(headers); - for (FormDataModel formData in (requestModel.formDataList ?? [])) { + for (FormDataModel formData + in (requestModel.requestFormDataList ?? [])) { if (formData.type == FormDataType.text) { multiPartRequest.fields.addAll({formData.name: formData.value}); } else { diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index 1d7c5073..da338a52 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -136,8 +136,9 @@ Map requestModelToHARJsonRequest( var headers = useEnabled ? requestModel.enabledHeadersMap : requestModel.headersMap; if (headers.isNotEmpty || hasBody) { - bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); - + bool hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (hasBody && !hasContentTypeHeader) { var m = { "name": "Content-Type", @@ -157,10 +158,8 @@ Map requestModelToHARJsonRequest( } } } - List formDataList = requestModel.formDataList ?? []; - if (requestModel.requestBodyContentType == ContentType.formdata) { - var formListMap = rowsToFormDataMap(formDataList); - json["formData"] = formListMap; + if (requestModel.isFormDataRequest) { + json["formData"] = requestModel.formDataMapList; } if (exportMode) { json["comment"] = ""; diff --git a/lib/widgets/form_data_widget.dart b/lib/widgets/form_data_widget.dart index 9a90262a..bb4782d2 100644 --- a/lib/widgets/form_data_widget.dart +++ b/lib/widgets/form_data_widget.dart @@ -29,7 +29,7 @@ class _FormDataBodyState extends ConsumerState { @override Widget build(BuildContext context) { final activeId = ref.watch(activeIdStateProvider); - var formRows = ref.read(activeRequestModelProvider)?.formDataList; + var formRows = ref.read(activeRequestModelProvider)?.requestFormDataList; rows = formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows; @@ -217,7 +217,7 @@ class _FormDataBodyState extends ConsumerState { void _onFieldChange(String activeId) { ref.read(collectionStateNotifierProvider.notifier).update( activeId, - formDataList: rows, + requestFormDataList: rows, ); } } From fead5e6a20500abe99b8bc3ef345a097266f51e5 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 15:07:40 +0530 Subject: [PATCH 086/123] format --- lib/codegen/dart/http.dart | 5 +++-- lib/codegen/python/http_client.dart | 3 ++- lib/services/http_service.dart | 7 ++++--- lib/utils/har_utils.dart | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 563361d8..708ae859 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -55,10 +55,11 @@ class DartHttpCodeGen { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); - final hasContentTypeHeader = composeHeaders.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + final hasContentTypeHeader = composeHeaders.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (!hasContentTypeHeader) { composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, - () => kContentTypeMap[contentType] ?? ''); + () => kContentTypeMap[contentType] ?? ''); } } diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 0179fdae..35f97b9f 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -105,7 +105,8 @@ print(data.decode("utf-8")) var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; - bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + bool hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (hasBody && !hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 54d9c387..17708c53 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,10 +28,11 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - final hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + final hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (!hasContentTypeHeader) { - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } } } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index b35c02a9..c74a1750 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -134,8 +134,9 @@ Map requestModelToHARJsonRequest( var headers = useEnabled ? requestModel.enabledHeadersMap : requestModel.headersMap; if (headers.isNotEmpty || hasBody) { - bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); - + bool hasContentTypeHeader = headers.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (hasBody && !hasContentTypeHeader) { var m = { "name": "Content-Type", From 5153841a9796a62e7f070e477ec17d1185dcaedf Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:12:46 +0530 Subject: [PATCH 087/123] fix: curl gen issue fixes --- lib/codegen/others/curl.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen/others/curl.dart b/lib/codegen/others/curl.dart index 50dfb503..4ae610de 100644 --- a/lib/codegen/others/curl.dart +++ b/lib/codegen/others/curl.dart @@ -52,7 +52,7 @@ class cURLCodeGen { } } if (harJson['formData'] != null) { - var formDataList = harJson['formData'] as List>; + var formDataList = harJson['formData'] as List>; for (var formData in formDataList) { var templateFormData = jj.Template(kTemplateFormData); if (formData['type'] != null && From 805f82a6775d5a7e02e421556a2105da972c861f Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 15:44:19 +0530 Subject: [PATCH 088/123] hasContentTypeHeader getter added to RequestModel --- lib/codegen/dart/http.dart | 9 ++++----- lib/codegen/python/http_client.dart | 5 +---- lib/models/request_model.dart | 4 ++++ lib/services/http_service.dart | 4 +--- lib/utils/har_utils.dart | 5 +---- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 708ae859..3b70db65 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -21,9 +21,10 @@ class DartHttpCodeGen { url: url, method: requestModel.method, queryParams: requestModel.enabledParamsMap, - headers: requestModel.enabledHeadersMap, + headers: {...requestModel.enabledHeadersMap}, body: requestModel.requestBody, contentType: requestModel.requestBodyContentType, + hasContentTypeHeader: requestModel.hasContentTypeHeader, ); return next; } catch (e) { @@ -38,6 +39,7 @@ class DartHttpCodeGen { required Map headers, required String? body, required ContentType contentType, + required bool hasContentTypeHeader, }) { final uri = Uri.parse(url); @@ -49,16 +51,13 @@ class DartHttpCodeGen { final uriExp = declareVar('uri').assign(refer('Uri.parse').call([literalString(url)])); - final composeHeaders = headers; Expression? dataExp; if (kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false)) { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); - final hasContentTypeHeader = composeHeaders.keys - .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); if (!hasContentTypeHeader) { - composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, + headers.putIfAbsent(HttpHeaders.contentTypeHeader, () => kContentTypeMap[contentType] ?? ''); } } diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 35f97b9f..1c72f138 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -105,10 +105,7 @@ print(data.decode("utf-8")) var headers = requestModel.enabledHeadersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; - bool hasContentTypeHeader = headers.keys - .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); - - if (hasBody && !hasContentTypeHeader) { + if (hasBody && !requestModel.hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index df49ba1e..265d2c3f 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' @@ -53,6 +54,9 @@ class RequestModel { Map get headersMap => rowsToMap(requestHeaders) ?? {}; Map get paramsMap => rowsToMap(requestParams) ?? {}; + bool get hasContentTypeHeader => enabledHeadersMap.keys + .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + RequestModel duplicate({ required String id, }) { diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 17708c53..485ad862 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,9 +28,7 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - final hasContentTypeHeader = headers.keys - .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); - if (!hasContentTypeHeader) { + if (!requestModel.hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index c74a1750..87f9a3fb 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -134,10 +134,7 @@ Map requestModelToHARJsonRequest( var headers = useEnabled ? requestModel.enabledHeadersMap : requestModel.headersMap; if (headers.isNotEmpty || hasBody) { - bool hasContentTypeHeader = headers.keys - .any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); - - if (hasBody && !hasContentTypeHeader) { + if (hasBody && !requestModel.hasContentTypeHeader) { var m = { "name": "Content-Type", "value": kContentTypeMap[requestModel.requestBodyContentType] ?? "" From 30791df102e5c7504f071f6b9a2153848337176b Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 16:13:53 +0530 Subject: [PATCH 089/123] Fix tests --- lib/codegen/js/fetch.dart | 3 ++- lib/codegen/python/http_client.dart | 1 - test/models/request_model_test.dart | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index 31f7a211..ccebf616 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -28,7 +28,8 @@ let options = { """; String kTemplateBody = """, - body: {{body}} + body: +{{body}} """; String kMultiPartBodyTemplate = r''' diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index b95ebf4c..39c39864 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -12,7 +12,6 @@ class PythonHttpClientCodeGen { import mimetypes from codecs import encode {% endif %} - """; String kTemplateParams = """ diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index b1b56bfd..66064d31 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -113,6 +113,7 @@ void main() { "requestBody": '''{ "text":"WORLD" }''', + 'requestFormDataList': null, 'responseStatus': null, 'message': null, 'responseModel': null @@ -147,6 +148,7 @@ void main() { "Enabled Params: null", "Request Body Content Type: ContentType.json", 'Request Body: {\n"text":"WORLD"\n}', + 'Request FormData: null', "Response Status: null", "Response Message: null", "Response: null" From b532044981d12397522f1e42a7d062df7bddab38 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 7 Jan 2024 19:32:09 +0530 Subject: [PATCH 090/123] chore: fixed code generation test cases --- lib/codegen/js/axios.dart | 22 ++++++++++++--------- lib/codegen/js/fetch.dart | 1 - lib/codegen/python/http_client.dart | 3 +-- test/codegen/js_fetch_codegen_test.dart | 18 ++++++----------- test/codegen/nodejs_fetch_codegen_test.dart | 18 ++++++----------- test/models/request_model_test.dart | 2 ++ 6 files changed, 28 insertions(+), 36 deletions(-) diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index fc65905b..ef73f646 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -10,10 +10,10 @@ class AxiosCodeGen { final bool isNodeJs; - String kStringImportNode = """import axios from 'axios'; -{% if isFormDataRequest and isNodeJs %}const fs = require('fs'); -{% endif %} + String kStringImportNode = """{% if isNodeJs %}import axios from 'axios'; +{% endif %}{% if isFormDataRequest and isNodeJs %} +const fs = require('fs');{% endif %} """; String kTemplateStart = """let config = { @@ -82,11 +82,14 @@ async function buildFormData(fields) { }); String result = importsData; - var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); - var renderedMultiPartBody = templateMultiPartBody.render({ - "isNodeJs": isNodeJs, - }); - result += renderedMultiPartBody; + if (requestModel.isFormDataRequest && + requestModel.formDataMapList.isNotEmpty) { + var templateMultiPartBody = jj.Template(kMultiPartBodyTemplate); + var renderedMultiPartBody = templateMultiPartBody.render({ + "isNodeJs": isNodeJs, + }); + result += renderedMultiPartBody; + } String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { @@ -128,7 +131,8 @@ async function buildFormData(fields) { } var templateBody = jj.Template(kTemplateBody); - if (requestModel.isFormDataRequest) { + if (requestModel.isFormDataRequest && + requestModel.formDataMapList.isNotEmpty) { var getFieldDataTemplate = jj.Template(kGetFormDataTemplate); result += templateBody.render({ diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index 31f7a211..fb2b4e36 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -14,7 +14,6 @@ class FetchCodeGen { import fetch from 'node-fetch'; {% if isFormDataRequest %}const fs = require('fs');{% endif %} - """; String kTemplateStart = """let url = '{{url}}'; diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index cc34cb70..8efb368a 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -7,8 +7,7 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class PythonHttpClientCodeGen { - final String kTemplateStart = """import http.client -{% if isFormDataRequest %} + final String kTemplateStart = """import http.client{% if isFormDataRequest %} import mimetypes from codecs import encode {% endif %} diff --git a/test/codegen/js_fetch_codegen_test.dart b/test/codegen/js_fetch_codegen_test.dart index 43d053f9..e7426bf1 100644 --- a/test/codegen/js_fetch_codegen_test.dart +++ b/test/codegen/js_fetch_codegen_test.dart @@ -398,8 +398,7 @@ let options = { headers: { "Content-Type": "text/plain" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -428,8 +427,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -459,8 +457,7 @@ let options = { "Content-Type": "application/json", "User-Agent": "Test Agent" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -491,8 +488,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" + body: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" }; let status; @@ -523,8 +519,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; @@ -580,8 +575,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; diff --git a/test/codegen/nodejs_fetch_codegen_test.dart b/test/codegen/nodejs_fetch_codegen_test.dart index c06ceee5..feca786d 100644 --- a/test/codegen/nodejs_fetch_codegen_test.dart +++ b/test/codegen/nodejs_fetch_codegen_test.dart @@ -418,8 +418,7 @@ let options = { headers: { "Content-Type": "text/plain" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -450,8 +449,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -483,8 +481,7 @@ let options = { "Content-Type": "application/json", "User-Agent": "Test Agent" }, - body: -"{\n\"text\": \"I LOVE Flutter\"\n}" + body: "{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -517,8 +514,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" + body: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" }; let status; @@ -551,8 +547,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; @@ -612,8 +607,7 @@ let options = { headers: { "Content-Type": "application/json" }, - body: -"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index b1b56bfd..66064d31 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -113,6 +113,7 @@ void main() { "requestBody": '''{ "text":"WORLD" }''', + 'requestFormDataList': null, 'responseStatus': null, 'message': null, 'responseModel': null @@ -147,6 +148,7 @@ void main() { "Enabled Params: null", "Request Body Content Type: ContentType.json", 'Request Body: {\n"text":"WORLD"\n}', + 'Request FormData: null', "Response Status: null", "Response Message: null", "Response: null" From 9d8379e9ac5cced7a03d6e67f419558548f836c5 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 7 Jan 2024 19:50:25 +0530 Subject: [PATCH 091/123] chore: fixed spacing issues in nodejs axios codegen --- lib/codegen/js/axios.dart | 6 +++--- test/codegen/nodejs_axios_codegen_test.dart | 21 --------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index ef73f646..ee826e32 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -11,9 +11,7 @@ class AxiosCodeGen { final bool isNodeJs; String kStringImportNode = """{% if isNodeJs %}import axios from 'axios'; - -{% endif %}{% if isFormDataRequest and isNodeJs %} -const fs = require('fs');{% endif %} +{% endif %}{% if isFormDataRequest and isNodeJs %}const fs = require('fs');{% endif %} """; String kTemplateStart = """let config = { @@ -50,6 +48,8 @@ axios(config) }); """; String kMultiPartBodyTemplate = r''' + + async function buildFormData(fields) { var formdata = new FormData(); for (const field of fields) { diff --git a/test/codegen/nodejs_axios_codegen_test.dart b/test/codegen/nodejs_axios_codegen_test.dart index 519f5ab5..974b410e 100644 --- a/test/codegen/nodejs_axios_codegen_test.dart +++ b/test/codegen/nodejs_axios_codegen_test.dart @@ -8,7 +8,6 @@ void main() { group('GET Request', () { test('GET 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com', method: 'get' @@ -31,7 +30,6 @@ axios(config) test('GET 2', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/country/data', method: 'get', @@ -57,7 +55,6 @@ axios(config) test('GET 3', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/country/data', method: 'get', @@ -83,7 +80,6 @@ axios(config) test('GET 4', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -113,7 +109,6 @@ axios(config) test('GET 5', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -139,7 +134,6 @@ axios(config) test('GET 6', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -168,7 +162,6 @@ axios(config) test('GET 7', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com', method: 'get' @@ -191,7 +184,6 @@ axios(config) test('GET 8', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -220,7 +212,6 @@ axios(config) test('GET 9', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -247,7 +238,6 @@ axios(config) test('GET 10', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -278,7 +268,6 @@ axios(config) test('GET 11', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -308,7 +297,6 @@ axios(config) test('GET 12', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/humanize/social', method: 'get' @@ -333,7 +321,6 @@ axios(config) group('HEAD Request', () { test('HEAD 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com', method: 'head' @@ -356,7 +343,6 @@ axios(config) test('HEAD 2', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'http://api.foss42.com', method: 'head' @@ -381,7 +367,6 @@ axios(config) group('POST Request', () { test('POST 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -408,7 +393,6 @@ axios(config) test('POST 2', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -435,7 +419,6 @@ axios(config) test('POST 3', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -465,7 +448,6 @@ axios(config) group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://reqres.in/api/users/2', method: 'put', @@ -494,7 +476,6 @@ axios(config) group('PATCH Request', () { test('PATCH 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://reqres.in/api/users/2', method: 'patch', @@ -523,7 +504,6 @@ axios(config) group('DELETE Request', () { test('DELETE 1', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://reqres.in/api/users/2', method: 'delete' @@ -546,7 +526,6 @@ axios(config) test('DELETE 2', () { const expectedCode = r"""import axios from 'axios'; - let config = { url: 'https://reqres.in/api/users/2', method: 'delete', From fe3bea31bd2dd25250a3703dc0d3ec7841ae70b2 Mon Sep 17 00:00:00 2001 From: Vidya Sagar <59490902+vidya-hub@users.noreply.github.com> Date: Sun, 7 Jan 2024 20:21:37 +0530 Subject: [PATCH 092/123] rev: reverted changes in js code gen --- lib/codegen/js/axios.dart | 1 + lib/codegen/js/fetch.dart | 3 ++- test/codegen/js_fetch_codegen_test.dart | 18 ++++++++++++------ test/codegen/nodejs_axios_codegen_test.dart | 21 +++++++++++++++++++++ test/codegen/nodejs_fetch_codegen_test.dart | 18 ++++++++++++------ 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index ee826e32..1aeee285 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -11,6 +11,7 @@ class AxiosCodeGen { final bool isNodeJs; String kStringImportNode = """{% if isNodeJs %}import axios from 'axios'; + {% endif %}{% if isFormDataRequest and isNodeJs %}const fs = require('fs');{% endif %} """; diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index fb2b4e36..4ef2e551 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -27,7 +27,8 @@ let options = { """; String kTemplateBody = """, - body: {{body}} + body: +{{body}} """; String kMultiPartBodyTemplate = r''' diff --git a/test/codegen/js_fetch_codegen_test.dart b/test/codegen/js_fetch_codegen_test.dart index e7426bf1..43d053f9 100644 --- a/test/codegen/js_fetch_codegen_test.dart +++ b/test/codegen/js_fetch_codegen_test.dart @@ -398,7 +398,8 @@ let options = { headers: { "Content-Type": "text/plain" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -427,7 +428,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -457,7 +459,8 @@ let options = { "Content-Type": "application/json", "User-Agent": "Test Agent" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -488,7 +491,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" + body: +"{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" }; let status; @@ -519,7 +523,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: +"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; @@ -575,7 +580,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: +"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; diff --git a/test/codegen/nodejs_axios_codegen_test.dart b/test/codegen/nodejs_axios_codegen_test.dart index 974b410e..519f5ab5 100644 --- a/test/codegen/nodejs_axios_codegen_test.dart +++ b/test/codegen/nodejs_axios_codegen_test.dart @@ -8,6 +8,7 @@ void main() { group('GET Request', () { test('GET 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com', method: 'get' @@ -30,6 +31,7 @@ axios(config) test('GET 2', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/country/data', method: 'get', @@ -55,6 +57,7 @@ axios(config) test('GET 3', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/country/data', method: 'get', @@ -80,6 +83,7 @@ axios(config) test('GET 4', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -109,6 +113,7 @@ axios(config) test('GET 5', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -134,6 +139,7 @@ axios(config) test('GET 6', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -162,6 +168,7 @@ axios(config) test('GET 7', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com', method: 'get' @@ -184,6 +191,7 @@ axios(config) test('GET 8', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.github.com/repos/foss42/apidash', method: 'get', @@ -212,6 +220,7 @@ axios(config) test('GET 9', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -238,6 +247,7 @@ axios(config) test('GET 10', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -268,6 +278,7 @@ axios(config) test('GET 11', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/humanize/social', method: 'get', @@ -297,6 +308,7 @@ axios(config) test('GET 12', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/humanize/social', method: 'get' @@ -321,6 +333,7 @@ axios(config) group('HEAD Request', () { test('HEAD 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com', method: 'head' @@ -343,6 +356,7 @@ axios(config) test('HEAD 2', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'http://api.foss42.com', method: 'head' @@ -367,6 +381,7 @@ axios(config) group('POST Request', () { test('POST 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -393,6 +408,7 @@ axios(config) test('POST 2', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -419,6 +435,7 @@ axios(config) test('POST 3', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://api.foss42.com/case/lower', method: 'post', @@ -448,6 +465,7 @@ axios(config) group('PUT Request', () { test('PUT 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://reqres.in/api/users/2', method: 'put', @@ -476,6 +494,7 @@ axios(config) group('PATCH Request', () { test('PATCH 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://reqres.in/api/users/2', method: 'patch', @@ -504,6 +523,7 @@ axios(config) group('DELETE Request', () { test('DELETE 1', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://reqres.in/api/users/2', method: 'delete' @@ -526,6 +546,7 @@ axios(config) test('DELETE 2', () { const expectedCode = r"""import axios from 'axios'; + let config = { url: 'https://reqres.in/api/users/2', method: 'delete', diff --git a/test/codegen/nodejs_fetch_codegen_test.dart b/test/codegen/nodejs_fetch_codegen_test.dart index feca786d..c06ceee5 100644 --- a/test/codegen/nodejs_fetch_codegen_test.dart +++ b/test/codegen/nodejs_fetch_codegen_test.dart @@ -418,7 +418,8 @@ let options = { headers: { "Content-Type": "text/plain" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -449,7 +450,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -481,7 +483,8 @@ let options = { "Content-Type": "application/json", "User-Agent": "Test Agent" }, - body: "{\n\"text\": \"I LOVE Flutter\"\n}" + body: +"{\n\"text\": \"I LOVE Flutter\"\n}" }; let status; @@ -514,7 +517,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" + body: +"{\n\"name\": \"morpheus\",\n\"job\": \"zion resident\"\n}" }; let status; @@ -547,7 +551,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: +"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; @@ -607,7 +612,8 @@ let options = { headers: { "Content-Type": "application/json" }, - body: "{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" + body: +"{\n\"name\": \"marfeus\",\n\"job\": \"accountant\"\n}" }; let status; From b92ac78424374cd53b56107294de20b6f74d9b63 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 20:42:23 +0530 Subject: [PATCH 093/123] Fix python codegens --- lib/codegen/python/http_client.dart | 6 ++++-- lib/codegen/python/requests.dart | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 086151bb..2d002ca7 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -7,8 +7,8 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class PythonHttpClientCodeGen { - final String kTemplateStart = """import http.client{% if isFormDataRequest %} -import mimetypes + final String kTemplateStart = """import http.client +{% if isFormDataRequest %}import mimetypes from codecs import encode {% endif %} """; @@ -61,6 +61,7 @@ print(data.decode("utf-8")) """; final String kStringFormDataBody = r''' + def build_data_list(fields): dataList = [] for field in fields: @@ -81,6 +82,7 @@ def build_data_list(fields): dataList.append(encode(f'--{{boundary}}--')) dataList.append(encode('')) return dataList + dataList = build_data_list({{fields_list}}) body = b'\r\n'.join(dataList) '''; diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index a2f359a1..4d9523e4 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -8,8 +8,7 @@ import 'package:apidash/models/models.dart' show RequestModel; class PythonRequestsCodeGen { final String kTemplateStart = """import requests -{% if isFormDataRequest %} -import mimetypes +{% if isFormDataRequest %}import mimetypes from codecs import encode {% endif %} url = '{{url}}' @@ -51,6 +50,7 @@ response = requests.{{method}}(url """; final String kStringFormDataBody = r''' + def build_data_list(fields): dataList = [] for field in fields: @@ -69,10 +69,10 @@ def build_data_list(fields): dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) dataList.append(encode('')) dataList.append(open(value, 'rb').read()) - dataList.append(encode('--{{boundary}}--')) dataList.append(encode('')) return dataList + dataList = build_data_list({{fields_list}}) payload = b'\r\n'.join(dataList) '''; From 678c61296c4212af34468bdf9b11401d85be669c Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 7 Jan 2024 23:05:15 +0530 Subject: [PATCH 094/123] Include all files in coverage --- test/widget_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/widget_test.dart b/test/widget_test.dart index ab73b3a2..156d97e1 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1 +1,4 @@ +import 'package:apidash/common/utils.dart'; +import 'package:apidash/screens/screens.dart'; + void main() {} From 05b173e3151513975b83bf0838f20a9366a94223 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:17:28 +0530 Subject: [PATCH 095/123] Cover all lines in tests --- test/widget_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/widget_test.dart b/test/widget_test.dart index 156d97e1..48eb1d93 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,3 +1,5 @@ +import 'package:apidash/main.dart'; +import 'package:apidash/app.dart'; import 'package:apidash/common/utils.dart'; import 'package:apidash/screens/screens.dart'; From 61ea8ff2778761e903e8518e46a2bbb5b26a6b32 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:17:35 +0530 Subject: [PATCH 096/123] Create settings_model_test.dart --- test/models/settings_model_test.dart | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 test/models/settings_model_test.dart diff --git a/test/models/settings_model_test.dart b/test/models/settings_model_test.dart new file mode 100644 index 00000000..62745e62 --- /dev/null +++ b/test/models/settings_model_test.dart @@ -0,0 +1,74 @@ +import 'package:test/test.dart'; +import 'package:flutter/material.dart'; +import 'package:apidash/models/settings_model.dart'; +import 'package:apidash/consts.dart'; + +void main() { + const sm = SettingsModel( + isDark: false, + alwaysShowCollectionPaneScrollbar: true, + size: Size(300, 200), + offset: Offset(100, 150), + defaultUriScheme: "http", + defaultCodeGenLang: CodegenLanguage.curl, + saveResponses: true, + ); + + test('Testing toJson()', () { + const expectedResult = { + "isDark": false, + "alwaysShowCollectionPaneScrollbar": true, + "width": 300.0, + "height": 200.0, + "dx": 100.0, + "dy": 150.0, + "defaultUriScheme": "http", + "defaultCodeGenLang": "curl", + "saveResponses": true, + }; + expect(sm.toJson(), expectedResult); + }); + + test('Testing fromJson()', () { + const input = { + "isDark": false, + "alwaysShowCollectionPaneScrollbar": true, + "width": 300.0, + "height": 200.0, + "dx": 100.0, + "dy": 150.0, + "defaultUriScheme": "http", + "defaultCodeGenLang": "curl", + "saveResponses": true, + }; + expect(SettingsModel.fromJson(input), sm); + }); + + test('Testing copyWith()', () { + const expectedResult = SettingsModel( + isDark: true, + alwaysShowCollectionPaneScrollbar: true, + size: Size(300, 200), + offset: Offset(100, 150), + defaultUriScheme: "http", + defaultCodeGenLang: CodegenLanguage.curl, + saveResponses: false, + ); + expect( + sm.copyWith( + isDark: true, + saveResponses: false, + ), + expectedResult); + }); + + test('Testing toString()', () { + const expectedResult = + "{isDark: false, alwaysShowCollectionPaneScrollbar: true, width: 300.0, height: 200.0, dx: 100.0, dy: 150.0, defaultUriScheme: http, defaultCodeGenLang: curl, saveResponses: true}"; + expect(sm.toString(), expectedResult); + }); + + test('Testing hashcode', () { + expect(sm.hashCode, greaterThan(0)); + }); +} From 472f296d325887b63f3c1658021eb02c94e47cb6 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:17:42 +0530 Subject: [PATCH 097/123] Update request_model_test.dart --- test/models/request_model_test.dart | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index 66064d31..626727de 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -156,6 +156,29 @@ void main() { test('Testing toString', () { expect(requestModelDup.toString(), requestModeDupString); }); + + test('Testing getters', () { + expect(requestModel.enabledRequestHeaders, const [ + NameValueModel(name: 'content-length', value: '18'), + NameValueModel( + name: 'content-type', value: 'application/json; charset=utf-8') + ]); + expect(requestModel.enabledRequestParams, null); + expect(requestModel.enabledHeadersMap, { + 'content-length': '18', + 'content-type': 'application/json; charset=utf-8' + }); + expect(requestModel.enabledParamsMap, {}); + expect(requestModel.headersMap, { + 'content-length': '18', + 'content-type': 'application/json; charset=utf-8' + }); + expect(requestModel.paramsMap, {}); + expect(requestModel.formDataMapList, []); + expect(requestModel.isFormDataRequest, false); + expect(requestModel.hasContentTypeHeader, true); + }); + test('Testing hashcode', () { expect(requestModel.hashCode, greaterThan(0)); }); From ec3e4922dfeafa0289e8d0164ffa8cf8df7495a1 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:17:48 +0530 Subject: [PATCH 098/123] Update name_value_model_test.dart --- test/models/name_value_model_test.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/models/name_value_model_test.dart b/test/models/name_value_model_test.dart index f451cea9..c1fd9f57 100644 --- a/test/models/name_value_model_test.dart +++ b/test/models/name_value_model_test.dart @@ -13,6 +13,11 @@ void main() { const resultExpected = {"name": "harry", "value": 23}; expect(nmRow1.toJson(), resultExpected); }); + test('Testing fromJson()', () { + const resultExpected = nmRow1; + expect(NameValueModel.fromJson({"name": "harry", "value": 23}), + resultExpected); + }); test('Testing copyWith()', () { const resultExpected = NameValueModel(name: "winter", value: "26"); From 0278eaaee15da973a0dc4134e4f9548d2d87b8a9 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:17:51 +0530 Subject: [PATCH 099/123] Create form_data_model_test.dart --- test/models/form_data_model_test.dart | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/models/form_data_model_test.dart diff --git a/test/models/form_data_model_test.dart b/test/models/form_data_model_test.dart new file mode 100644 index 00000000..c8569a57 --- /dev/null +++ b/test/models/form_data_model_test.dart @@ -0,0 +1,44 @@ +import 'package:apidash/consts.dart'; +import 'package:test/test.dart'; +import 'package:apidash/models/form_data_model.dart'; + +void main() { + const fdmRow1 = FormDataModel( + name: "harry", + value: "23", + type: FormDataType.text, + ); + + test('Testing toString()', () { + const resultExpected = + 'FormDataModel(name: harry, value: 23, type: FormDataType.text)'; + expect(fdmRow1.toString(), resultExpected); + }); + + test('Testing toJson()', () { + const resultExpected = {"name": "harry", "value": "23", "type": "text"}; + expect(fdmRow1.toJson(), resultExpected); + }); + test('Testing fromJson()', () { + const resultExpected = fdmRow1; + expect( + FormDataModel.fromJson( + {"name": "harry", "value": "23", "type": "text"}), + resultExpected); + }); + + test('Testing copyWith()', () { + const resultExpected = FormDataModel( + name: "winter", + value: "26", + type: FormDataType.file, + ); + expect( + fdmRow1.copyWith(name: "winter", value: "26", type: FormDataType.file), + resultExpected); + }); + + test('Testing hashcode', () { + expect(fdmRow1.hashCode, greaterThan(0)); + }); +} From b6691af932cb78cdfad079d202ecb43266ec0ecf Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:18:11 +0530 Subject: [PATCH 100/123] Remove default in codegen switch --- lib/codegen/codegen.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 45b72014..1aec7144 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -42,8 +42,6 @@ class Codegen { .getCode(requestModel, defaultUriScheme); case CodegenLanguage.pythonRequests: return PythonRequestsCodeGen().getCode(requestModel, defaultUriScheme); - default: - throw ArgumentError('Invalid codegenLanguage'); } } } From 26bed23c4df65f69f6a9188eb266203ff474e17d Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:18:15 +0530 Subject: [PATCH 101/123] Update settings_model.dart --- lib/models/settings_model.dart | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/models/settings_model.dart b/lib/models/settings_model.dart index eaeb4fa7..8ee87ee7 100644 --- a/lib/models/settings_model.dart +++ b/lib/models/settings_model.dart @@ -101,4 +101,32 @@ class SettingsModel { String toString() { return toJson().toString(); } + + @override + bool operator ==(Object other) { + return other is SettingsModel && + other.runtimeType == runtimeType && + other.isDark == isDark && + other.alwaysShowCollectionPaneScrollbar == + alwaysShowCollectionPaneScrollbar && + other.size == size && + other.offset == offset && + other.defaultUriScheme == defaultUriScheme && + other.defaultCodeGenLang == defaultCodeGenLang && + other.saveResponses == saveResponses; + } + + @override + int get hashCode { + return Object.hash( + runtimeType, + isDark, + alwaysShowCollectionPaneScrollbar, + size, + offset, + defaultUriScheme, + defaultCodeGenLang, + saveResponses, + ); + } } From fdd749d4a0a3e0be845562f698fbcdcf7cbea574 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:18:37 +0530 Subject: [PATCH 102/123] Create codegen_test.dart --- test/codegen/codegen_test.dart | 239 +++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 test/codegen/codegen_test.dart diff --git a/test/codegen/codegen_test.dart b/test/codegen/codegen_test.dart new file mode 100644 index 00000000..63102e0a --- /dev/null +++ b/test/codegen/codegen_test.dart @@ -0,0 +1,239 @@ +import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/consts.dart'; +import '../request_models.dart'; +import 'package:test/test.dart'; + +void main() { + final codeGen = Codegen(); + + group('Test various Code generators', () { + test('cURL', () { + const expectedCode = r"""curl --url 'https://api.foss42.com'"""; + expect(codeGen.getCode(CodegenLanguage.curl, requestModelGet1, "https"), + expectedCode); + }); + + test('Dart Dio', () { + const expectedCode = r"""import 'package:dio/dio.dart' as dio; + +void main() async { + try { + final response = await dio.Dio.get('https://api.foss42.com'); + print(response.statusCode); + print(response.data); + } on DioException catch (e, s) { + print(e.response?.statusCode); + print(e.response?.data); + print(s); + } catch (e, s) { + print(e); + print(s); + } +} +"""; + expect( + codeGen.getCode(CodegenLanguage.dartDio, requestModelGet1, "https"), + expectedCode); + }); + + test('Dart HTTP', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com'); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } else { + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + codeGen.getCode(CodegenLanguage.dartHttp, requestModelGet1, "https"), + expectedCode); + }); + + test('HAR', () { + const expectedCode = r"""{ + "method": "GET", + "url": "https://api.foss42.com", + "httpVersion": "HTTP/1.1", + "queryString": [], + "headers": [] +}"""; + expect(codeGen.getCode(CodegenLanguage.har, requestModelGet1, "https"), + expectedCode); + }); + + test('JS Axios', () { + const expectedCode = r"""let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + codeGen.getCode(CodegenLanguage.jsAxios, requestModelGet1, "https"), + expectedCode); + }); + + test('JS Fetch', () { + const expectedCode = r"""let url = 'https://api.foss42.com'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + codeGen.getCode(CodegenLanguage.jsFetch, requestModelGet1, "https"), + expectedCode); + }); + + test('Kotlin OkHttp', () { + const expectedCode = r"""import okhttp3.OkHttpClient +import okhttp3.Request + +fun main() { + val client = OkHttpClient() + + val url = "https://api.foss42.com" + + val request = Request.Builder() + .url(url) + .get() + .build() + + val response = client.newCall(request).execute() + + println(response.code) + println(response.body?.string()) +} +"""; + expect( + codeGen.getCode( + CodegenLanguage.kotlinOkHttp, requestModelGet1, "https"), + expectedCode); + }); + + test('NodeJs Axios', () { + const expectedCode = r"""import axios from 'axios'; + +let config = { + url: 'https://api.foss42.com', + method: 'get' +}; + +axios(config) + .then(function (response) { + // handle success + console.log(response.status); + console.log(response.data); + }) + .catch(function (error) { + // handle error + console.log(error.response.status); + console.log(error); + }); +"""; + expect( + codeGen.getCode( + CodegenLanguage.nodejsAxios, requestModelGet1, "https"), + expectedCode); + }); + + test('Nodejs Fetch', () { + const expectedCode = r"""import fetch from 'node-fetch'; + +let url = 'https://api.foss42.com'; + +let options = { + method: 'GET' +}; + +let status; +fetch(url, options) + .then(res => { + status = res.status; + return res.json() + }) + .then(body => { + console.log(status); + console.log(body); + }) + .catch(err => { + console.log(status); + console.error('error:' + err); + }); +"""; + expect( + codeGen.getCode( + CodegenLanguage.nodejsFetch, requestModelGet1, "https"), + expectedCode); + }); + + test('Python http.client', () { + const expectedCode = r"""import http.client + +conn = http.client.HTTPSConnection("api.foss42.com") +conn.request("GET", "") + +res = conn.getresponse() +data = res.read() + +print(data.decode("utf-8")) +"""; + expect( + codeGen.getCode( + CodegenLanguage.pythonHttpClient, requestModelGet1, "https"), + expectedCode); + }); + + test('Python requests', () { + const expectedCode = r"""import requests + +url = 'https://api.foss42.com' + +response = requests.get(url) + +print('Status Code:', response.status_code) +print('Response Body:', response.text) +"""; + expect( + codeGen.getCode( + CodegenLanguage.pythonRequests, requestModelGet1, "https"), + expectedCode); + }); + }); +} From d46dd0071feffcd491e95f5da189bdb0db6f0a26 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 00:32:49 +0530 Subject: [PATCH 103/123] Update ContentType & ResponseBodyView enums --- lib/codegen/dart/http.dart | 6 ++--- lib/codegen/kotlin/okhttp.dart | 3 +-- lib/codegen/python/http_client.dart | 2 +- lib/codegen/python/requests.dart | 2 +- lib/consts.dart | 36 ++++++++++++++--------------- lib/services/http_service.dart | 2 +- lib/utils/har_utils.dart | 4 ++-- lib/widgets/response_widgets.dart | 9 +++----- 8 files changed, 29 insertions(+), 35 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 8c1f3c8f..3e423743 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -22,7 +22,7 @@ class DartHttpCodeGen { queryParams: requestModel.enabledParamsMap, headers: {...requestModel.enabledHeadersMap}, contentType: requestModel.requestBodyContentType, - hasContentTypeHeader: requestModel.hasContentTypeHeader, + hasContentTypeHeader: requestModel.hasContentTypeHeader, body: requestModel.requestBody, formData: requestModel.formDataMapList, ); @@ -57,8 +57,8 @@ class DartHttpCodeGen { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); if (!hasContentTypeHeader) { - headers.putIfAbsent(HttpHeaders.contentTypeHeader, - () => kContentTypeMap[contentType] ?? ''); + headers.putIfAbsent( + HttpHeaders.contentTypeHeader, () => contentType.header); } } diff --git a/lib/codegen/kotlin/okhttp.dart b/lib/codegen/kotlin/okhttp.dart index becfdbe4..07e5a92b 100644 --- a/lib/codegen/kotlin/okhttp.dart +++ b/lib/codegen/kotlin/okhttp.dart @@ -118,8 +118,7 @@ import okhttp3.MediaType.Companion.toMediaType"""; var contentLength = utf8.encode(requestBody).length; if (contentLength > 0) { hasBody = true; - String contentType = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + String contentType = requestModel.requestBodyContentType.header; var templateBody = jj.Template(kTemplateRequestBody); result += templateBody .render({"contentType": contentType, "body": requestBody}); diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 2d002ca7..4406effb 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -154,7 +154,7 @@ body = b'\r\n'.join(dataList) hasHeaders = true; if (hasBody && !requestModel.hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + requestModel.requestBodyContentType.header; } var headersString = kEncoder.convert(headers); headersString = padMultilineString(headersString, kHeadersPadding); diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index 4d9523e4..3a5beeb6 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -162,7 +162,7 @@ print('Response Body:', response.text) hasHeaders = true; if (hasBody) { headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + requestModel.requestBodyContentType.header; } var headersString = kEncoder.convert(headers); headersString = padMultilineString(headersString, kHeadersPadding); diff --git a/lib/consts.dart b/lib/consts.dart index cc1ae394..e598db62 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -242,8 +242,6 @@ enum RequestItemMenuOption { edit, delete, duplicate } enum HTTPVerb { get, head, post, put, patch, delete } -enum ContentType { json, text, formdata } - enum FormDataType { text, file } const kSupportedUriSchemes = ["https", "http"]; @@ -312,25 +310,25 @@ const kTypeVideo = 'video'; const kSubTypeDefaultViewOptions = 'all'; -const kContentTypeMap = { - ContentType.json: "$kTypeApplication/$kSubTypeJson", - ContentType.text: "$kTypeText/$kSubTypePlain", - ContentType.formdata: "multipart/form-data", -}; +enum ContentType { + json("$kTypeApplication/$kSubTypeJson"), + text("$kTypeText/$kSubTypePlain"), + formdata("multipart/form-data"); -enum ResponseBodyView { preview, code, raw, none } + const ContentType(this.header); + final String header; +} -const kKeyIcon = "icon"; -const kKeyName = "name"; -const Map kResponseBodyViewIcons = { - ResponseBodyView.none: {kKeyName: "Preview", kKeyIcon: Icons.warning}, - ResponseBodyView.preview: { - kKeyName: "Preview", - kKeyIcon: Icons.visibility_rounded - }, - ResponseBodyView.code: {kKeyName: "Preview", kKeyIcon: Icons.code_rounded}, - ResponseBodyView.raw: {kKeyName: "Raw", kKeyIcon: Icons.text_snippet_rounded} -}; +enum ResponseBodyView { + preview("Preview", Icons.visibility_rounded), + code("Preview", Icons.code_rounded), + raw("Raw", Icons.text_snippet_rounded), + none("Preview", Icons.warning); + + const ResponseBodyView(this.label, this.icon); + final String label; + final IconData icon; +} const kNoBodyViewOptions = [ResponseBodyView.none]; const kNoRawBodyViewOptions = [ResponseBodyView.none, ResponseBodyView.raw]; diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 46a66a91..c5a7b4ce 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -31,7 +31,7 @@ Future<(http.Response?, Duration?, String?)> request( headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); if (!requestModel.hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + requestModel.requestBodyContentType.header; } } } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f7491bc1..4ca2dd05 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -121,7 +121,7 @@ Map requestModelToHARJsonRequest( hasBody = true; json["postData"] = {}; json["postData"]["mimeType"] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + requestModel.requestBodyContentType.header; json["postData"]["text"] = requestBody; if (exportMode) { json["postData"]["comment"] = ""; @@ -139,7 +139,7 @@ Map requestModelToHARJsonRequest( if (hasBody && !requestModel.hasContentTypeHeader) { var m = { "name": "Content-Type", - "value": kContentTypeMap[requestModel.requestBodyContentType] ?? "" + "value": requestModel.requestBodyContentType.header }; if (exportMode) { m["comment"] = ""; diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 960fc9dd..680041c0 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -397,16 +397,13 @@ class _BodySuccessState extends State { (widget.options == kRawBodyViewOptions) ? const SizedBox() : SegmentedButton( - selectedIcon: Icon( - kResponseBodyViewIcons[currentSeg]![kKeyIcon]), + selectedIcon: Icon(currentSeg.icon), segments: widget.options .map>( (e) => ButtonSegment( value: e, - label: Text( - kResponseBodyViewIcons[e]![kKeyName]), - icon: Icon( - kResponseBodyViewIcons[e]![kKeyIcon]), + label: Text(e.label), + icon: Icon(e.icon), ), ) .toList(), From 3f31549d3786724d3249ac000a50b04239ef1bc1 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 09:22:46 +0530 Subject: [PATCH 104/123] Fix params for useEnabled in requestModelToHARJsonRequest --- lib/utils/har_utils.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index 4ca2dd05..38913c6e 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -1,8 +1,5 @@ import 'dart:convert'; -import 'dart:io'; import 'package:apidash/consts.dart'; -import 'package:apidash/models/form_data_model.dart'; -import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri; import 'package:apidash/models/models.dart' show RequestModel; import 'package:package_info_plus/package_info_plus.dart'; @@ -84,7 +81,7 @@ Map requestModelToHARJsonRequest( var rec = getValidRequestUri( requestModel.url, - requestModel.enabledRequestParams, + useEnabled ? requestModel.enabledRequestParams : requestModel.requestParams, defaultUriScheme: defaultUriScheme, ); From 2cad2c182cefb27a24b6dada177d38fbb0f8ef62 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 8 Jan 2024 09:22:56 +0530 Subject: [PATCH 105/123] Update file_utils_test.dart --- test/utils/file_utils_test.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/utils/file_utils_test.dart b/test/utils/file_utils_test.dart index fef80ace..18e2816a 100644 --- a/test/utils/file_utils_test.dart +++ b/test/utils/file_utils_test.dart @@ -3,15 +3,21 @@ import 'package:apidash/utils/file_utils.dart'; void main() { group( - "Testing x function", + "Testing File Utils", () { - /*test('Test case 2', () { - expect(showButtonLabelsInViewCodePane(350), false); + test('Test getFileExtension', () { + String mimetype = "text/csv"; + expect(getFileExtension(mimetype), "csv"); }); - test('Test case 3', () { - expect(showButtonLabelsInViewCodePane(450), true); - });*/ + test('Test getShortPath', () { + String path = "A/B/C/D.csv"; + expect(getShortPath(path), ".../C/D.csv"); + }); + + test('Test getTempFileName', () { + expect(getTempFileName().length, greaterThan(0)); + }); }, ); } From 1d57a9ab7d58c12ddfd3ed83f15e860e04c77342 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 08:00:55 +0530 Subject: [PATCH 106/123] Create har_utils_test.dart --- test/utils/har_utils_test.dart | 323 +++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 test/utils/har_utils_test.dart diff --git a/test/utils/har_utils_test.dart b/test/utils/har_utils_test.dart new file mode 100644 index 00000000..0dd16d62 --- /dev/null +++ b/test/utils/har_utils_test.dart @@ -0,0 +1,323 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/utils/har_utils.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import '../request_models.dart'; + +void main() { + group( + "Testing HAR Utils", + () { + test('Test collectionToHAR', () async { + Map expectedResult = { + 'log': { + 'creator': { + 'comment': + 'For support, check out API Dash repo - https://github.com/foss42/apidash', + 'version': '1.0', + 'name': 'API Dash' + }, + 'entries': [ + { + 'startedDateTime': 'ABC', + 'comment': 'id:get6', + 'serverIPAddress': '', + 'time': 0, + 'timings': { + 'connect': -1, + 'comment': '', + 'blocked': -1, + 'dns': -1, + 'receive': 0, + 'send': 0, + 'wait': 0, + 'ssl': -1 + }, + 'response': { + 'status': 200, + 'statusText': 'OK', + 'httpVersion': 'HTTP/1.1', + 'cookies': [], + 'headers': [], + 'content': { + 'size': 0, + 'mimeType': '', + 'comment': '', + 'text': '' + }, + 'redirectURL': '', + 'headersSize': 0, + 'bodySize': 0, + 'comment': '' + }, + 'request': { + 'method': 'GET', + 'url': 'https://api.github.com/repos/foss42/apidash?raw=true', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'raw', 'value': 'true', 'comment': ''} + ], + 'headers': [ + {'name': 'User-Agent', 'value': 'Test Agent', 'comment': ''} + ], + 'comment': '', + 'cookies': [], + 'headersSize': -1, + 'bodySize': 0 + }, + 'cache': {} + }, + { + 'startedDateTime': 'ABC', + 'comment': 'id:enabledRows', + 'serverIPAddress': '', + 'time': 0, + 'timings': { + 'connect': -1, + 'comment': '', + 'blocked': -1, + 'dns': -1, + 'receive': 0, + 'send': 0, + 'wait': 0, + 'ssl': -1 + }, + 'response': { + 'status': 200, + 'statusText': 'OK', + 'httpVersion': 'HTTP/1.1', + 'cookies': [], + 'headers': [], + 'content': { + 'size': 0, + 'mimeType': '', + 'comment': '', + 'text': '' + }, + 'redirectURL': '', + 'headersSize': 0, + 'bodySize': 0, + 'comment': '' + }, + 'request': { + 'method': 'GET', + 'url': + 'https://api.foss42.com/humanize/social?num=8700000&digits=3&system=SS&add_space=true', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'num', 'value': '8700000', 'comment': ''}, + {'name': 'digits', 'value': '3', 'comment': ''}, + {'name': 'system', 'value': 'SS', 'comment': ''}, + {'name': 'add_space', 'value': 'true', 'comment': ''} + ], + 'headers': [ + { + 'name': 'User-Agent', + 'value': 'Test Agent', + 'comment': '' + }, + { + 'name': 'Content-Type', + 'value': 'application/json', + 'comment': '' + } + ], + 'comment': '', + 'cookies': [], + 'headersSize': -1, + 'bodySize': 0 + }, + 'cache': {} + }, + { + 'startedDateTime': 'ABC', + 'comment': 'id:post3', + 'serverIPAddress': '', + 'time': 0, + 'timings': { + 'connect': -1, + 'comment': '', + 'blocked': -1, + 'dns': -1, + 'receive': 0, + 'send': 0, + 'wait': 0, + 'ssl': -1 + }, + 'response': { + 'status': 200, + 'statusText': 'OK', + 'httpVersion': 'HTTP/1.1', + 'cookies': [], + 'headers': [], + 'content': { + 'size': 0, + 'mimeType': '', + 'comment': '', + 'text': '' + }, + 'redirectURL': '', + 'headersSize': 0, + 'bodySize': 0, + 'comment': '' + }, + 'request': { + 'method': 'POST', + 'url': 'https://api.foss42.com/case/lower', + 'httpVersion': 'HTTP/1.1', + 'queryString': [], + 'headers': [ + { + 'name': 'Content-Type', + 'value': 'application/json', + 'comment': '' + }, + {'name': 'User-Agent', 'value': 'Test Agent', 'comment': ''} + ], + 'postData': { + 'mimeType': 'application/json', + 'text': '{\n' + '"text": "I LOVE Flutter"\n' + '}', + 'comment': '' + }, + 'comment': '', + 'cookies': [], + 'headersSize': -1, + 'bodySize': 28 + }, + 'cache': {} + } + ], + 'comment': '', + 'browser': {'version': '1.0', 'comment': '', 'name': 'API Dash'}, + 'version': '1.2' + } + }; + PackageInfo.setMockInitialValues( + appName: "apidash", + packageName: "dev.apidash.apidash", + version: "1.0", + buildNumber: "3", + buildSignature: "XYZ"); + var result = await collectionToHAR([ + requestModelGet6, + requestModelGet11, + requestModelPost3, + ]); + result['log']['entries'][0]['startedDateTime'] = 'ABC'; + result['log']['entries'][1]['startedDateTime'] = 'ABC'; + result['log']['entries'][2]['startedDateTime'] = 'ABC'; + expect(result, expectedResult); + }); + + test('Test requestModelToHARJsonRequest', () { + Map expectedResult = { + 'method': 'GET', + 'url': 'https://api.github.com/repos/foss42/apidash?raw=true', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'raw', 'value': 'true'} + ], + 'headers': [ + {'name': 'User-Agent', 'value': 'Test Agent'} + ] + }; + expect(requestModelToHARJsonRequest(requestModelGet6), expectedResult); + }); + + test('Test requestModelToHARJsonRequest exportMode=true', () { + Map expectedResult = { + 'method': 'GET', + 'url': 'https://api.github.com/repos/foss42/apidash?raw=true', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'raw', 'value': 'true', 'comment': ''} + ], + 'headers': [ + {'name': 'User-Agent', 'value': 'Test Agent', 'comment': ''} + ], + 'comment': '', + 'cookies': [], + 'headersSize': -1, + 'bodySize': 0 + }; + expect( + requestModelToHARJsonRequest( + requestModelGet6, + exportMode: true, + ), + expectedResult); + }); + + test('Test requestModelToHARJsonRequest exportMode=true', () { + Map expectedResult = { + 'method': 'POST', + 'url': 'https://api.foss42.com/case/lower', + 'httpVersion': 'HTTP/1.1', + 'queryString': [], + 'headers': [ + {'name': 'Content-Type', 'value': 'application/json', 'comment': ''} + ], + 'postData': { + 'mimeType': 'application/json', + 'text': '{\n' + '"text": "I LOVE Flutter"\n' + '}', + 'comment': '' + }, + 'comment': '', + 'cookies': [], + 'headersSize': -1, + 'bodySize': 28 + }; + expect( + requestModelToHARJsonRequest( + requestModelPost2, + exportMode: true, + ), + expectedResult); + }); + + test('Test requestModelToHARJsonRequest useEnabled=false', () { + Map expectedResult = { + 'method': 'GET', + 'url': + 'https://api.foss42.com/humanize/social?num=8700000&digits=3&system=SS&add_space=true', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'num', 'value': '8700000'}, + {'name': 'digits', 'value': '3'}, + {'name': 'system', 'value': 'SS'}, + {'name': 'add_space', 'value': 'true'} + ], + 'headers': [ + {'name': 'User-Agent', 'value': 'Test Agent'}, + {'name': 'Content-Type', 'value': 'application/json'} + ] + }; + expect(requestModelToHARJsonRequest(requestModelGet11), expectedResult); + }); + + test('Test requestModelToHARJsonRequest useEnabled=true', () { + Map expectedResult = { + 'method': 'GET', + 'url': 'https://api.foss42.com/humanize/social?num=8700000&digits=3', + 'httpVersion': 'HTTP/1.1', + 'queryString': [ + {'name': 'num', 'value': '8700000'}, + {'name': 'digits', 'value': '3'} + ], + 'headers': [ + {'name': 'User-Agent', 'value': 'Test Agent'} + ] + }; + expect( + requestModelToHARJsonRequest( + requestModelGet11, + useEnabled: true, + ), + expectedResult); + }); + }, + ); +} From 064b8980190efd6a9d0af52da39b5f29f3a83e25 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 08:00:57 +0530 Subject: [PATCH 107/123] Update convert_utils_test.dart --- test/utils/convert_utils_test.dart | 88 ++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index 53ec1c84..e632bd3a 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -1,6 +1,8 @@ +import 'package:apidash/consts.dart'; import 'package:test/test.dart'; import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/models/name_value_model.dart'; +import 'package:apidash/models/form_data_model.dart'; void main() { group("Testing humanizeDuration function", () { @@ -106,6 +108,92 @@ void main() { }); }); + group("Testing rowsToFormDataMapList", () { + test('Testing for null', () { + expect(rowsToFormDataMapList(null), null); + }); + test('Testing with a map value', () { + const input = [ + FormDataModel(name: "text", value: "abc", type: FormDataType.file), + FormDataModel(name: "lang", value: "eng", type: FormDataType.file), + FormDataModel(name: "code", value: "1", type: FormDataType.text) + ]; + const expectedResult = [ + {"name": "text", "value": "abc", "type": "file"}, + {"name": "lang", "value": "eng", "type": "file"}, + {"name": "code", "value": "1", "type": "text"} + ]; + expect(rowsToFormDataMapList(input), expectedResult); + }); + }); + + group("Testing mapListToFormDataModelRows", () { + test('Testing for null', () { + expect(mapListToFormDataModelRows(null), null); + }); + test('Testing with a map value', () { + const input = [ + {"name": "text", "value": "abc", "type": "file"}, + {"name": "lang", "value": "eng", "type": "file"}, + {"name": "code", "value": "1", "type": "text"} + ]; + const expectedResult = [ + FormDataModel(name: "text", value: "abc", type: FormDataType.file), + FormDataModel(name: "lang", value: "eng", type: FormDataType.file), + FormDataModel(name: "code", value: "1", type: FormDataType.text) + ]; + expect(mapListToFormDataModelRows(input), expectedResult); + }); + }); + + group("Testing getFormDataType", () { + test('Testing for null', () { + expect(getFormDataType(null), FormDataType.text); + }); + test('Testing with a map value', () { + const input = "file"; + const expectedResult = FormDataType.file; + expect(getFormDataType(input), expectedResult); + }); + }); + + group("Testing jsonMapToBytes", () { + test('Testing for null', () { + expect(jsonMapToBytes(null), []); + }); + test('Testing with a map value', () { + Map value1 = {"a": "1"}; + const result1Expected = [ + 123, + 10, + 32, + 32, + 34, + 97, + 34, + 58, + 32, + 34, + 49, + 34, + 10, + 125 + ]; + expect(jsonMapToBytes(value1), result1Expected); + }); + }); + + group("Testing stringToBytes", () { + test('Testing for null', () { + expect(stringToBytes(null), null); + }); + test('Testing with a stringToBytes value', () { + String value1 = "ab"; + const result1Expected = [97, 98]; + expect(stringToBytes(value1), result1Expected); + }); + }); + group("Testing padMultilineString", () { String text1 = '''Using API Dash, you can draft API requests via an easy to use GUI which allows you to: From bea80e9661368d3a99c88e456a1db6cb079a0515 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 08:00:59 +0530 Subject: [PATCH 108/123] Update buttons_test.dart --- test/widgets/buttons_test.dart | 114 ++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/test/widgets/buttons_test.dart b/test/widgets/buttons_test.dart index 55eaa096..91677be8 100644 --- a/test/widgets/buttons_test.dart +++ b/test/widgets/buttons_test.dart @@ -1,7 +1,8 @@ -import 'package:apidash/consts.dart'; +import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:apidash/widgets/buttons.dart'; +import 'package:apidash/consts.dart'; import '../test_consts.dart'; void main() { @@ -53,6 +54,7 @@ void main() { await tester.tap(button1); expect(changedValue, 'Send'); }); + testWidgets('Testing for Send Request button when sentRequestId is not null', (tester) async { await tester.pumpWidget( @@ -76,6 +78,7 @@ void main() { expect(tester.widget(button1).enabled, isFalse); }); + testWidgets('Testing for Send Request button when sentRequestId = activeId', (tester) async { await tester.pumpWidget( @@ -99,4 +102,113 @@ void main() { expect(tester.widget(button1).enabled, isFalse); }); + + testWidgets('Testing for Save in Downloads button', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Save in Downloads button', + theme: kThemeDataLight, + home: const Scaffold( + body: SaveInDownloadsButton(), + ), + ), + ); + + expect(find.byIcon(Icons.download), findsOneWidget); + expect(find.text("Download"), findsOneWidget); + + final button1 = find.byType(TextButton); + expect(button1, findsOneWidget); + + expect(tester.widget(button1).enabled, isFalse); + }); + + testWidgets('Testing for Save in Downloads button 2', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Save in Downloads button', + theme: kThemeDataLight, + home: Scaffold( + body: SaveInDownloadsButton( + content: Uint8List.fromList([1]), + ), + ), + ), + ); + + expect(find.byIcon(Icons.download), findsOneWidget); + expect(find.text("Download"), findsOneWidget); + + final button1 = find.byType(TextButton); + expect(button1, findsOneWidget); + + expect(tester.widget(button1).enabled, isTrue); + }); + + testWidgets('Testing for Repo button', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Repo button', + theme: kThemeDataLight, + home: const Scaffold( + body: RepoButton( + icon: Icons.code, + ), + ), + ), + ); + + expect(find.byIcon(Icons.code), findsOneWidget); + expect(find.text("GitHub"), findsOneWidget); + }); + + testWidgets('Testing for Repo button icon = null', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Repo button', + theme: kThemeDataLight, + home: const Scaffold( + body: RepoButton(), + ), + ), + ); + + expect(find.byIcon(Icons.code), findsNothing); + expect(find.text("GitHub"), findsOneWidget); + + final button1 = find.byType(FilledButton); + expect(button1, findsOneWidget); + + expect(tester.widget(button1).enabled, isTrue); + }); + + testWidgets('Testing for Discord button', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Discord button', + theme: kThemeDataLight, + home: const Scaffold( + body: DiscordButton(), + ), + ), + ); + + expect(find.byIcon(Icons.discord), findsOneWidget); + expect(find.text("Discord Server"), findsOneWidget); + }); + + testWidgets('Testing for Save button', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Save button', + theme: kThemeDataLight, + home: const Scaffold( + body: SaveButton(), + ), + ), + ); + + expect(find.byIcon(Icons.save), findsOneWidget); + expect(find.text("Save"), findsOneWidget); + }); } From 082002e478eb989ca617563efdbc7cba97d267b1 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 08:18:22 +0530 Subject: [PATCH 109/123] Update dropdowns_test.dart --- test/widgets/dropdowns_test.dart | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/widgets/dropdowns_test.dart b/test/widgets/dropdowns_test.dart index d6922bfa..7d304ce8 100644 --- a/test/widgets/dropdowns_test.dart +++ b/test/widgets/dropdowns_test.dart @@ -87,4 +87,88 @@ void main() { expect(changedValue, ContentType.text); }); + + testWidgets('Testing Dropdown for FormData', (tester) async { + dynamic changedValue; + await tester.pumpWidget( + MaterialApp( + title: 'Dropdown FormData Type testing', + theme: kThemeDataLight, + home: Scaffold( + body: Center( + child: Column( + children: [ + DropdownButtonFormData( + formDataType: FormDataType.file, + onChanged: (value) { + changedValue = value!; + }, + ), + ], + ), + ), + ), + ), + ); + + expect(find.byIcon(Icons.unfold_more_rounded), findsOneWidget); + expect(find.byType(DropdownButton), findsOneWidget); + expect( + (tester.widget(find.byType(DropdownButton)) + as DropdownButton) + .value, + equals(FormDataType.file)); + + await tester.tap(find.text('file')); + await tester.pump(); + await tester.pump(const Duration(seconds: 1)); + + await tester.tap(find.text('text').last); + await tester.pump(); + await tester.pump(const Duration(seconds: 1)); + + expect(changedValue, FormDataType.text); + }); + + testWidgets('Testing Dropdown for Codegen', (tester) async { + dynamic changedValue; + await tester.pumpWidget( + MaterialApp( + title: 'Dropdown Codegen Type testing', + theme: kThemeDataLight, + home: Scaffold( + body: Center( + child: Column( + children: [ + DropdownButtonCodegenLanguage( + codegenLanguage: CodegenLanguage.curl, + onChanged: (value) { + changedValue = value!; + }, + ), + ], + ), + ), + ), + ), + ); + + expect(find.byIcon(Icons.unfold_more_rounded), findsOneWidget); + expect(find.byType(DropdownButton), findsOneWidget); + expect( + (tester.widget(find.byType(DropdownButton)) + as DropdownButton) + .value, + equals(CodegenLanguage.curl)); + + await tester.tap(find.text('cURL')); + await tester.pump(); + await tester.pump(const Duration(seconds: 1)); + + await tester.tap(find.text('Dart (dio)').last); + await tester.pump(); + await tester.pump(const Duration(seconds: 1)); + + expect(changedValue, CodegenLanguage.dartDio); + }); } From 8b4de31948a425c07adc22757858652d97108952 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 08:25:22 +0530 Subject: [PATCH 110/123] Create window_caption_test.dart --- test/widgets/window_caption_test.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/widgets/window_caption_test.dart diff --git a/test/widgets/window_caption_test.dart b/test/widgets/window_caption_test.dart new file mode 100644 index 00000000..ab48cea9 --- /dev/null +++ b/test/widgets/window_caption_test.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/widgets/window_caption.dart'; + +void main() { + testWidgets('Testing for Window caption', (tester) async { + await tester.pumpWidget( + const MaterialApp( + title: 'Window caption', + home: Scaffold( + body: WindowCaption(), + ), + ), + ); + + final wd = find.byType(GestureDetector); + expect(wd, findsAny); + }); +} From eea3a7399b9948ad9d04225ef8a9178efbaab46e Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 22:09:36 +0530 Subject: [PATCH 111/123] Move form_data_widget --- .../editor_pane/details_card/request_pane/request_body.dart | 1 + .../details_card/request_pane/request_form_data.dart} | 0 lib/widgets/widgets.dart | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename lib/{widgets/form_data_widget.dart => screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart} (100%) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index 94ff858c..3c8b74cb 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.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/consts.dart'; +import 'request_form_data.dart'; class EditRequestBody extends ConsumerStatefulWidget { const EditRequestBody({super.key}); diff --git a/lib/widgets/form_data_widget.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart similarity index 100% rename from lib/widgets/form_data_widget.dart rename to lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index c627f82a..8c288953 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -22,4 +22,3 @@ export 'textfields.dart'; export 'texts.dart'; export 'uint8_audio_player.dart'; export 'window_caption.dart'; -export 'form_data_widget.dart'; From 3e2132808c0c83def834e2da53ad992794524d6d Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 22:09:40 +0530 Subject: [PATCH 112/123] Create checkbox_test.dart --- test/widgets/checkbox_test.dart | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/widgets/checkbox_test.dart diff --git a/test/widgets/checkbox_test.dart b/test/widgets/checkbox_test.dart new file mode 100644 index 00000000..fc6167a0 --- /dev/null +++ b/test/widgets/checkbox_test.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/widgets/checkbox.dart'; + +void main() { + testWidgets('Testing for Checkbox', (tester) async { + dynamic changedValue; + await tester.pumpWidget( + MaterialApp( + title: 'Checkbox Widget', + home: Scaffold( + body: CheckBox( + keyId: "1", + value: false, + onChanged: (value) { + changedValue = value; + }, + ), + ), + ), + ); + + expect(find.byKey(const Key("1")), findsOneWidget); + var box = find.byKey(const Key("1")); + await tester.tap(box); + await tester.pump(); + await tester.pumpAndSettle(); + expect(changedValue, true); + }); +} From 5a66f03585c7855ae95d4d6757832662a9f3b72e Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 22:09:42 +0530 Subject: [PATCH 113/123] Create form_data_field_test.dart --- test/widgets/form_data_field_test.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/widgets/form_data_field_test.dart diff --git a/test/widgets/form_data_field_test.dart b/test/widgets/form_data_field_test.dart new file mode 100644 index 00000000..b5748370 --- /dev/null +++ b/test/widgets/form_data_field_test.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/widgets/form_data_field.dart'; + +void main() { + testWidgets('Testing for Form Data Widget', (tester) async { + await tester.pumpWidget( + const MaterialApp( + title: 'Form Data Field Widget', + home: Scaffold( + body: FormDataField( + keyId: "1", + initialValue: "Test Field", + ), + ), + ), + ); + + expect(find.text("Test Field"), findsOneWidget); + }); +} From 1eaef02abad7211abdb3728c2d32fab645ede46a Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 22:39:33 +0530 Subject: [PATCH 114/123] Create headerfield_test.dart --- test/widgets/headerfield_test.dart | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/widgets/headerfield_test.dart diff --git a/test/widgets/headerfield_test.dart b/test/widgets/headerfield_test.dart new file mode 100644 index 00000000..63a179f2 --- /dev/null +++ b/test/widgets/headerfield_test.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/widgets/headerfield.dart'; + +void main() { + testWidgets('Testing Header Field', (tester) async { + await tester.pumpWidget( + const MaterialApp( + title: 'Header Field', + home: Scaffold( + body: Column(children: [ + HeaderField( + keyId: "1", + initialValue: "X", + ) + ]), + ), + ), + ); + + expect(find.byKey(const Key("1")), findsOneWidget); + expect(find.text('X'), findsOneWidget); + }); +} From e074b738ad326c70107c4e3969b606983bffa2e8 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Tue, 9 Jan 2024 22:39:55 +0530 Subject: [PATCH 115/123] Create markdown_test.dart --- test/widgets/markdown_test.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/widgets/markdown_test.dart diff --git a/test/widgets/markdown_test.dart b/test/widgets/markdown_test.dart new file mode 100644 index 00000000..79cb579a --- /dev/null +++ b/test/widgets/markdown_test.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:apidash/widgets/markdown.dart'; + +void main() { + testWidgets('Testing CustomMarkdown', (tester) async { + const markdown = CustomMarkdown(data: """Is a markdown ~`star on github`~ + + #br + #br + + ~`github repo`~ ~`Discord Server`~"""); + await tester.pumpWidget(markdown); + //expectTextStrings(tester.allWidgets, ['Data1']); + }, skip: true); +} From 05fb363f14190846b2ecbf05881fc1c0723b9482 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 14 Jan 2024 22:57:03 +0530 Subject: [PATCH 116/123] bump json_data_explorer version --- devtools_options.yaml | 1 + pubspec.lock | 22 +++++++++++++++++++--- pubspec.yaml | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 devtools_options.yaml diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 00000000..7e7e7f67 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1 @@ +extensions: diff --git a/pubspec.lock b/pubspec.lock index 1845e975..c42c9d37 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -265,6 +265,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6" + url: "https://pub.dev" + source: hosted + version: "6.1.1" fixnum: dependency: transitive description: @@ -350,6 +358,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.18+2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" flutter_riverpod: dependency: "direct main" description: @@ -533,10 +549,10 @@ packages: description: path: "." ref: HEAD - resolved-ref: "9e279ee9862c4fc4050dbcb5074529b22e67a7c3" + resolved-ref: "320c9fc7d4b8366daa1d70ba28523977ab101d9f" url: "https://github.com/foss42/json_data_explorer.git" source: git - version: "0.1.1" + version: "0.1.2" json_serializable: dependency: "direct dev" description: @@ -1280,5 +1296,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.2.3 <4.0.0" flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 33a4ad9f..f91513e3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,7 +46,7 @@ dependencies: json_data_explorer: git: url: https://github.com/foss42/json_data_explorer.git - version: ^0.1.1 + version: ^0.1.2 scrollable_positioned_list: ^0.2.3 file_picker: ^6.1.1 flutter_svg: ^2.0.9 From 9ab777e5c6bd19f6fce20dd5090b29a5897ce8e5 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 14 Jan 2024 23:11:08 +0530 Subject: [PATCH 117/123] Update json_data_explorer ref --- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c42c9d37..5e8d5462 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -548,8 +548,8 @@ packages: dependency: "direct main" description: path: "." - ref: HEAD - resolved-ref: "320c9fc7d4b8366daa1d70ba28523977ab101d9f" + ref: "9fa58d7b51e65174ab11cbcae17bba88a4194dde" + resolved-ref: "9fa58d7b51e65174ab11cbcae17bba88a4194dde" url: "https://github.com/foss42/json_data_explorer.git" source: git version: "0.1.2" diff --git a/pubspec.yaml b/pubspec.yaml index f91513e3..bdb8665a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,7 +46,7 @@ dependencies: json_data_explorer: git: url: https://github.com/foss42/json_data_explorer.git - version: ^0.1.2 + ref: 9fa58d7b51e65174ab11cbcae17bba88a4194dde scrollable_positioned_list: ^0.2.3 file_picker: ^6.1.1 flutter_svg: ^2.0.9 From 88ba5361677a1e62c319d53dee3f2203599ca464 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Sun, 14 Jan 2024 23:21:08 +0530 Subject: [PATCH 118/123] Rebuild JSON preview for cases where the response is in a few ms. --- lib/widgets/json_previewer.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/widgets/json_previewer.dart b/lib/widgets/json_previewer.dart index 49b1eb10..28fff99b 100644 --- a/lib/widgets/json_previewer.dart +++ b/lib/widgets/json_previewer.dart @@ -151,6 +151,14 @@ class _JsonPreviewerState extends State { store.expandAll(); } + @override + void didUpdateWidget(JsonPreviewer oldWidget) { + if (oldWidget.code != widget.code) { + store.buildNodes(widget.code, areAllCollapsed: true); + store.expandAll(); + } + } + @override Widget build(BuildContext context) { var sm = ScaffoldMessenger.of(context); From 14dfa720e0e8a9c9373a7b3b916cd84c004ba870 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 15 Jan 2024 00:44:26 +0530 Subject: [PATCH 119/123] Add maxRootNodeWidth to JSON Previewer Fixes #106 --- lib/utils/ui_utils.dart | 10 ++ lib/widgets/json_previewer.dart | 217 +++++++++++++++++--------------- 2 files changed, 126 insertions(+), 101 deletions(-) diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index aeaf1b1a..a0a05c0b 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -59,3 +59,13 @@ Color getDarkModeColor(Color col) { kColorWhite, ); } + +double? getJsonPreviewerMaxRootNodeWidth(double w) { + if (w < 300) { + return 150; + } + if (w < 400) { + return 200; + } + return null; +} diff --git a/lib/widgets/json_previewer.dart b/lib/widgets/json_previewer.dart index 28fff99b..3056b23c 100644 --- a/lib/widgets/json_previewer.dart +++ b/lib/widgets/json_previewer.dart @@ -5,6 +5,7 @@ import 'package:provider/provider.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:url_launcher/url_launcher_string.dart'; import '../consts.dart'; +import '../utils/ui_utils.dart'; import "snackbars.dart"; import 'textfields.dart'; @@ -165,114 +166,128 @@ class _JsonPreviewerState extends State { return ChangeNotifierProvider.value( value: store, child: Consumer( - builder: (context, state, child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () async { - await _copy(kEncoder.convert(widget.code), sm); - }, - child: const Text('Copy'), - ), - TextButton( - onPressed: state.areAllExpanded() ? null : state.expandAll, - child: const Text('Expand All'), - ), - TextButton( - onPressed: state.areAllCollapsed() ? null : state.collapseAll, - child: const Text('Collapse All'), - ), - ], - ), - Expanded( - child: JsonDataExplorer( - nodes: state.displayNodes, - itemScrollController: itemScrollController, - itemSpacing: 4, - rootInformationBuilder: (context, node) => - rootInfoBox(context, node), - collapsableToggleBuilder: (context, node) => AnimatedRotation( - turns: node.isCollapsed ? -0.25 : 0, - duration: const Duration(milliseconds: 300), - child: const Icon(Icons.arrow_drop_down), - ), - trailingBuilder: (context, node) => node.isFocused - ? Padding( - padding: const EdgeInsets.only(right: 12), - child: IconButton( - padding: EdgeInsets.zero, - constraints: const BoxConstraints(maxHeight: 18), - icon: const Icon( - Icons.copy, - size: 18, - ), - onPressed: () async { - await _copy(kEncoder.convert(toJson(node)), sm); - }, - ), - ) - : const SizedBox(), - valueStyleBuilder: (value, style) => - valueStyleOverride(context, value, style), - theme: (Theme.of(context).brightness == Brightness.light) - ? dataExplorerThemeLight - : dataExplorerThemeDark, - ), - ), - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - border: Border.all( - color: Theme.of(context).colorScheme.surfaceVariant), - borderRadius: kBorderRadius8, - ), - child: Row( + builder: (context, state, child) { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + var maxRootNodeWidth = + getJsonPreviewerMaxRootNodeWidth(constraints.maxWidth); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 8.0), - child: Icon( - Icons.search, - size: 18, - ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () async { + await _copy(kEncoder.convert(widget.code), sm); + }, + child: const Text('Copy'), + ), + TextButton( + onPressed: + state.areAllExpanded() ? null : state.expandAll, + child: const Text('Expand All'), + ), + TextButton( + onPressed: + state.areAllCollapsed() ? null : state.collapseAll, + child: const Text('Collapse All'), + ), + ], ), Expanded( - child: JsonSearchField( - controller: searchController, - onChanged: (term) => state.search(term), + child: JsonDataExplorer( + nodes: state.displayNodes, + itemScrollController: itemScrollController, + itemSpacing: 4, + rootInformationBuilder: (context, node) => + rootInfoBox(context, node), + collapsableToggleBuilder: (context, node) => + AnimatedRotation( + turns: node.isCollapsed ? -0.25 : 0, + duration: const Duration(milliseconds: 300), + child: const Icon(Icons.arrow_drop_down), + ), + trailingBuilder: (context, node) => node.isFocused + ? Padding( + padding: const EdgeInsets.only(right: 12), + child: IconButton( + padding: EdgeInsets.zero, + constraints: + const BoxConstraints(maxHeight: 18), + icon: const Icon( + Icons.copy, + size: 18, + ), + onPressed: () async { + await _copy( + kEncoder.convert(toJson(node)), sm); + }, + ), + ) + : const SizedBox(), + valueStyleBuilder: (value, style) => + valueStyleOverride(context, value, style), + theme: (Theme.of(context).brightness == Brightness.light) + ? dataExplorerThemeLight + : dataExplorerThemeDark, + maxRootNodeWidth: maxRootNodeWidth, ), ), - const SizedBox( - width: 8, + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + border: Border.all( + color: Theme.of(context).colorScheme.surfaceVariant), + borderRadius: kBorderRadius8, + ), + child: Row( + children: [ + const Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: Icon( + Icons.search, + size: 18, + ), + ), + Expanded( + child: JsonSearchField( + controller: searchController, + onChanged: (term) => state.search(term), + ), + ), + const SizedBox( + width: 8, + ), + if (state.searchResults.isNotEmpty) + Text(_searchFocusText(), + style: Theme.of(context).textTheme.bodySmall), + if (state.searchResults.isNotEmpty) + IconButton( + visualDensity: VisualDensity.compact, + onPressed: () { + store.focusPreviousSearchResult(); + _scrollToSearchMatch(); + }, + icon: const Icon(Icons.arrow_drop_up), + ), + if (state.searchResults.isNotEmpty) + IconButton( + visualDensity: VisualDensity.compact, + onPressed: () { + store.focusNextSearchResult(); + _scrollToSearchMatch(); + }, + icon: const Icon(Icons.arrow_drop_down), + ), + ], + ), ), - if (state.searchResults.isNotEmpty) - Text(_searchFocusText(), - style: Theme.of(context).textTheme.bodySmall), - if (state.searchResults.isNotEmpty) - IconButton( - visualDensity: VisualDensity.compact, - onPressed: () { - store.focusPreviousSearchResult(); - _scrollToSearchMatch(); - }, - icon: const Icon(Icons.arrow_drop_up), - ), - if (state.searchResults.isNotEmpty) - IconButton( - visualDensity: VisualDensity.compact, - onPressed: () { - store.focusNextSearchResult(); - _scrollToSearchMatch(); - }, - icon: const Icon(Icons.arrow_drop_down), - ), ], - ), - ), - ], - ), + ); + }, + ); + }, ), ); } From 1c50591db1d2ac5cc6f315c6364ec62a7bfaca19 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 15 Jan 2024 00:51:17 +0530 Subject: [PATCH 120/123] Small button styles --- lib/consts.dart | 1 + lib/widgets/json_previewer.dart | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index e598db62..f8f9f97c 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -48,6 +48,7 @@ const kHintOpacity = 0.6; const kForegroundOpacity = 0.05; const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); +const kTextStyleButtonSmall = TextStyle(fontSize: 12); const kFormDataButtonLabelTextStyle = TextStyle( fontSize: 12, fontWeight: FontWeight.w600, diff --git a/lib/widgets/json_previewer.dart b/lib/widgets/json_previewer.dart index 3056b23c..078a9721 100644 --- a/lib/widgets/json_previewer.dart +++ b/lib/widgets/json_previewer.dart @@ -181,17 +181,26 @@ class _JsonPreviewerState extends State { onPressed: () async { await _copy(kEncoder.convert(widget.code), sm); }, - child: const Text('Copy'), + child: const Text( + 'Copy', + style: kTextStyleButtonSmall, + ), ), TextButton( onPressed: state.areAllExpanded() ? null : state.expandAll, - child: const Text('Expand All'), + child: const Text( + 'Expand All', + style: kTextStyleButtonSmall, + ), ), TextButton( onPressed: state.areAllCollapsed() ? null : state.collapseAll, - child: const Text('Collapse All'), + child: const Text( + 'Collapse All', + style: kTextStyleButtonSmall, + ), ), ], ), From 46b320501f2b5b69156b31342cebd85e0a2f9520 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 15 Jan 2024 00:51:21 +0530 Subject: [PATCH 121/123] Update ui_utils.dart --- lib/utils/ui_utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index a0a05c0b..3bf1fb98 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -67,5 +67,5 @@ double? getJsonPreviewerMaxRootNodeWidth(double w) { if (w < 400) { return 200; } - return null; + return w - 150; } From 8720317eb634a6711d6604b530bee4907cb41501 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 15 Jan 2024 01:01:29 +0530 Subject: [PATCH 122/123] UI fixes params & headers --- .../editor_pane/details_card/request_pane/request_headers.dart | 3 ++- .../editor_pane/details_card/request_pane/request_params.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 1637f265..76866ab9 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -54,7 +54,7 @@ class EditRequestHeadersState extends ConsumerState { columns: [ DaviColumn( name: 'Checkbox', - width: 36, + width: 30, cellBuilder: (_, row) { int idx = row.index; return CheckBox( @@ -72,6 +72,7 @@ class EditRequestHeadersState extends ConsumerState { ), DaviColumn( name: 'Header Name', + width: 70, grow: 1, cellBuilder: (_, row) { int idx = row.index; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 18b17e58..736bf619 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -55,7 +55,7 @@ class EditRequestURLParamsState extends ConsumerState { columns: [ DaviColumn( name: 'Checkbox', - width: 36, + width: 30, cellBuilder: (_, row) { int idx = row.index; @@ -74,6 +74,7 @@ class EditRequestURLParamsState extends ConsumerState { ), DaviColumn( name: 'URL Parameter', + width: 70, grow: 1, cellBuilder: (_, row) { int idx = row.index; From 13f230c2ddb0024284bd677a40125128e73d3e30 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 15 Jan 2024 01:18:31 +0530 Subject: [PATCH 123/123] Fix SegmentedButton padding --- lib/widgets/response_widgets.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 680041c0..6d8960e2 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -397,6 +397,13 @@ class _BodySuccessState extends State { (widget.options == kRawBodyViewOptions) ? const SizedBox() : SegmentedButton( + style: const ButtonStyle( + padding: MaterialStatePropertyAll( + EdgeInsets.symmetric( + horizontal: 8, + ), + ), + ), selectedIcon: Icon(currentSeg.icon), segments: widget.options .map>(