mirror of
https://github.com/foss42/apidash.git
synced 2025-06-02 16:02:12 +08:00
Merge branch 'foss42:main' into feat/URLSession-codegen
This commit is contained in:
15
.github/ISSUE_TEMPLATE/bug_report.md
vendored
15
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -7,16 +7,23 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug/problem**
|
#### Describe the bug/problem
|
||||||
_Please describe the bug/problem here_
|
_Please describe the bug/problem here_
|
||||||
|
|
||||||
**Steps to Reproduce the bug/problem**
|
#### Steps to Reproduce the bug/problem
|
||||||
_Please provide the steps to reproduce the behaviour. Screenshot(s)/image(s) are preferred to help explain it better_
|
_Please provide the steps to reproduce the behaviour. Screenshot(s)/image(s) are preferred to help explain it better_
|
||||||
|
|
||||||
**Expected behavior**
|
#### Expected behavior
|
||||||
_Description of what you expected to happen_
|
_Description of what you expected to happen_
|
||||||
|
|
||||||
**Device Info (The device where you encountered this issue):**
|
#### Device Info (The device where you encountered this issue)
|
||||||
- OS: [e.g. Windows, MacOS]
|
- OS: [e.g. Windows, MacOS]
|
||||||
- Version: [e.g. Catalina 10.15.7, Monterey 12.3.1, Windows 11 22H2]
|
- Version: [e.g. Catalina 10.15.7, Monterey 12.3.1, Windows 11 22H2]
|
||||||
- Browser (only if you encountered the issue while running the web app): [e.g. chrome, safari]
|
- Browser (only if you encountered the issue while running the web app): [e.g. chrome, safari]
|
||||||
|
|
||||||
|
#### Flutter Doctor
|
||||||
|
Please run the `flutter doctor -v` command and provide the details below:
|
||||||
|
|
||||||
|
```
|
||||||
|
<insert flutter doctor output here>
|
||||||
|
```
|
||||||
|
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
6
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -7,11 +7,11 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Tell us about the task you want to perform and are unable to do so because the feature is not available**
|
#### Tell us about the task you want to perform and are unable to do so because the feature is not available
|
||||||
_Your response here_
|
_Your response here_
|
||||||
|
|
||||||
**Describe the solution/feature you'd like us to add**
|
#### Describe the solution/feature you'd like us to add
|
||||||
_Your response here_
|
_Your response here_
|
||||||
|
|
||||||
**Any other feedback you would like to provide regarding the site**
|
#### Any other feedback you would like to provide regarding the site
|
||||||
_Your response here_
|
_Your response here_
|
||||||
|
2
.github/ISSUE_TEMPLATE/feedback.md
vendored
2
.github/ISSUE_TEMPLATE/feedback.md
vendored
@ -8,5 +8,5 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Feedback**
|
#### Feedback
|
||||||
_Please feel free to share anything. The stage is all yours._
|
_Please feel free to share anything. The stage is all yours._
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -57,3 +57,6 @@ coverage/*
|
|||||||
installers/*
|
installers/*
|
||||||
.metadata
|
.metadata
|
||||||
.fvm/
|
.fvm/
|
||||||
|
|
||||||
|
# Testing Files & Folders
|
||||||
|
test-hive-storage
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## API Dash Roadmap
|
## API Dash Roadmap
|
||||||
|
|
||||||
- [ ] Environment Variables (https://github.com/foss42/apidash/issues/25)
|
- [x] Environment Variables (https://github.com/foss42/apidash/issues/25)
|
||||||
- [ ] WebSocket support (https://github.com/foss42/apidash/issues/15)
|
- [ ] WebSocket support (https://github.com/foss42/apidash/issues/15)
|
||||||
- [ ] SSE support (https://github.com/foss42/apidash/issues/116)
|
- [ ] SSE support (https://github.com/foss42/apidash/issues/116)
|
||||||
- [ ] MQTT support (https://github.com/foss42/apidash/issues/115)
|
- [ ] MQTT support (https://github.com/foss42/apidash/issues/115)
|
||||||
@ -8,7 +8,7 @@
|
|||||||
- [ ] gRPC support (https://github.com/foss42/apidash/issues/14)
|
- [ ] gRPC support (https://github.com/foss42/apidash/issues/14)
|
||||||
- [ ] API Testing Suite (https://github.com/foss42/apidash/discussions/96, https://github.com/foss42/apidash/issues/100)
|
- [ ] API Testing Suite (https://github.com/foss42/apidash/discussions/96, https://github.com/foss42/apidash/issues/100)
|
||||||
- [ ] API Workflow Builder (https://github.com/foss42/apidash/issues/120)
|
- [ ] API Workflow Builder (https://github.com/foss42/apidash/issues/120)
|
||||||
- [ ] Integration Testing (https://github.com/foss42/apidash/issues/119)
|
- [x] Integration Testing (https://github.com/foss42/apidash/issues/119)
|
||||||
- [ ] Remaining Code Generators (https://github.com/foss42/apidash/discussions/80)
|
- [ ] Remaining Code Generators (https://github.com/foss42/apidash/discussions/80)
|
||||||
- [ ] Embedded WebView in Response Previewer
|
- [ ] Embedded WebView in Response Previewer
|
||||||
- [ ] Figuring out how to build for various Linux packaging formats (https://github.com/foss42/apidash/discussions/240)
|
- [ ] Figuring out how to build for various Linux packaging formats (https://github.com/foss42/apidash/discussions/240)
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
flutter_icons:
|
flutter_launcher_icons:
|
||||||
image_path: "icons/logo.png"
|
image_path: "icons/logo.png"
|
||||||
android: false #"ic_launcher"
|
android: true
|
||||||
ios: false
|
ios: false
|
||||||
image_path_ios: "icons/logo_ios.png"
|
image_path_ios: "icons/logo_ios.png"
|
||||||
min_sdk_android: 21
|
min_sdk_android: 21
|
||||||
web:
|
web:
|
||||||
generate: true
|
generate: false
|
||||||
windows:
|
windows:
|
||||||
generate: true
|
generate: false
|
||||||
icon_size: 256
|
icon_size: 256
|
||||||
macos:
|
macos:
|
||||||
generate: true
|
generate: false
|
||||||
image_path: "icons/logo_macos.png"
|
image_path: "icons/logo_macos.png"
|
||||||
|
10
flutter_native_splash.yaml
Normal file
10
flutter_native_splash.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
flutter_native_splash:
|
||||||
|
color: "#f8f9ff"
|
||||||
|
image: icons/logo.png
|
||||||
|
android_12:
|
||||||
|
color: "#f8f9ff"
|
||||||
|
image: icons/logo_android12.png
|
||||||
|
|
||||||
|
android: true
|
||||||
|
ios: false
|
||||||
|
web: false
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'package:apidash/models/settings_model.dart';
|
||||||
|
import 'package:apidash/providers/providers.dart';
|
||||||
|
import 'package:apidash/services/services.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
@ -34,17 +37,24 @@ class ApidashTestHelper {
|
|||||||
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
|
||||||
await app.initApp();
|
await app.initApp(false);
|
||||||
await app.initWindow(sz: size);
|
await app.initWindow(sz: size);
|
||||||
|
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> loadApp(WidgetTester tester) async {
|
static Future<void> loadApp(WidgetTester tester) async {
|
||||||
await app.initApp();
|
await app.initApp(false);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const ProviderScope(
|
ProviderScope(
|
||||||
child: DashApp(),
|
overrides: [
|
||||||
|
settingsProvider.overrideWith(
|
||||||
|
(ref) => ThemeStateNotifier(
|
||||||
|
settingsModel: const SettingsModel()
|
||||||
|
.copyWithPath(workspaceFolderPath: "test")),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: const DashApp(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -123,6 +133,7 @@ void apidashWidgetTest(
|
|||||||
size: width != null ? Size(width, kMinWindowSize.height) : null);
|
size: width != null ? Size(width, kMinWindowSize.height) : null);
|
||||||
await ApidashTestHelper.loadApp(widgetTester);
|
await ApidashTestHelper.loadApp(widgetTester);
|
||||||
await test(widgetTester, ApidashTestHelper(widgetTester));
|
await test(widgetTester, ApidashTestHelper(widgetTester));
|
||||||
|
await clearSharedPrefs();
|
||||||
},
|
},
|
||||||
semanticsEnabled: false,
|
semanticsEnabled: false,
|
||||||
);
|
);
|
||||||
|
55
lib/app.dart
55
lib/app.dart
@ -4,8 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_portal/flutter_portal.dart';
|
import 'package:flutter_portal/flutter_portal.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:window_manager/window_manager.dart' hide WindowCaption;
|
import 'package:window_manager/window_manager.dart' hide WindowCaption;
|
||||||
import 'widgets/widgets.dart' show WindowCaption;
|
import 'widgets/widgets.dart' show WindowCaption, WorkspaceSelector;
|
||||||
import 'providers/providers.dart';
|
import 'providers/providers.dart';
|
||||||
|
import 'services/services.dart';
|
||||||
import 'extensions/extensions.dart';
|
import 'extensions/extensions.dart';
|
||||||
import 'screens/screens.dart';
|
import 'screens/screens.dart';
|
||||||
import 'consts.dart';
|
import 'consts.dart';
|
||||||
@ -107,29 +108,49 @@ class DashApp extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isDarkMode =
|
final isDarkMode =
|
||||||
ref.watch(settingsProvider.select((value) => value.isDark));
|
ref.watch(settingsProvider.select((value) => value.isDark));
|
||||||
|
final workspaceFolderPath = ref
|
||||||
|
.watch(settingsProvider.select((value) => value.workspaceFolderPath));
|
||||||
|
final showWorkspaceSelector = kIsDesktop && (workspaceFolderPath == null);
|
||||||
return Portal(
|
return Portal(
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: kLightMaterialAppTheme,
|
theme: kLightMaterialAppTheme,
|
||||||
darkTheme: kDarkMaterialAppTheme,
|
darkTheme: kDarkMaterialAppTheme,
|
||||||
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
|
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
|
||||||
home: Stack(
|
home: showWorkspaceSelector
|
||||||
children: [
|
? WorkspaceSelector(
|
||||||
!kIsLinux && !kIsMobile
|
onContinue: (val) async {
|
||||||
? const App()
|
await initHiveBoxes(kIsDesktop, val);
|
||||||
: context.isMediumWindow
|
ref
|
||||||
? const MobileDashboard()
|
.read(settingsProvider.notifier)
|
||||||
: const Dashboard(),
|
.update(workspaceFolderPath: val);
|
||||||
if (kIsWindows)
|
},
|
||||||
SizedBox(
|
onCancel: () async {
|
||||||
height: 29,
|
try {
|
||||||
child: WindowCaption(
|
await windowManager.destroy();
|
||||||
backgroundColor: Colors.transparent,
|
} catch (e) {
|
||||||
brightness: isDarkMode ? Brightness.dark : Brightness.light,
|
debugPrint(e.toString());
|
||||||
),
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Stack(
|
||||||
|
children: [
|
||||||
|
!kIsLinux && !kIsMobile
|
||||||
|
? const App()
|
||||||
|
: context.isMediumWindow
|
||||||
|
? const MobileDashboard()
|
||||||
|
: const Dashboard(),
|
||||||
|
if (kIsWindows)
|
||||||
|
SizedBox(
|
||||||
|
height: 29,
|
||||||
|
child: WindowCaption(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
brightness:
|
||||||
|
isDarkMode ? Brightness.dark : Brightness.light,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ import okhttp3.MultipartBody;""";
|
|||||||
var templateBody = jj.Template(kTemplateRequestBody);
|
var templateBody = jj.Template(kTemplateRequestBody);
|
||||||
result += templateBody.render({
|
result += templateBody.render({
|
||||||
"contentType": contentType,
|
"contentType": contentType,
|
||||||
"body": kEncoder.convert(requestBody)
|
"body": kJsonEncoder.convert(requestBody)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ axios(config)
|
|||||||
m[i["name"]] = i["value"];
|
m[i["name"]] = i["value"];
|
||||||
}
|
}
|
||||||
result += templateParams
|
result += templateParams
|
||||||
.render({"params": padMultilineString(kEncoder.convert(m), 2)});
|
.render({"params": padMultilineString(kJsonEncoder.convert(m), 2)});
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers = harJson["headers"];
|
var headers = harJson["headers"];
|
||||||
@ -92,8 +92,8 @@ axios(config)
|
|||||||
if (requestModel.hasFormData) {
|
if (requestModel.hasFormData) {
|
||||||
m[kHeaderContentType] = ContentType.formdata.header;
|
m[kHeaderContentType] = ContentType.formdata.header;
|
||||||
}
|
}
|
||||||
result += templateHeader
|
result += templateHeader.render(
|
||||||
.render({"headers": padMultilineString(kEncoder.convert(m), 2)});
|
{"headers": padMultilineString(kJsonEncoder.convert(m), 2)});
|
||||||
}
|
}
|
||||||
var templateBody = jj.Template(kTemplateBody);
|
var templateBody = jj.Template(kTemplateBody);
|
||||||
if (requestModel.hasFormData && requestModel.formDataMapList.isNotEmpty) {
|
if (requestModel.hasFormData && requestModel.formDataMapList.isNotEmpty) {
|
||||||
@ -108,12 +108,13 @@ axios(config)
|
|||||||
: "fileInput$formFileCounter.files[0]";
|
: "fileInput$formFileCounter.files[0]";
|
||||||
if (element["type"] == "file") formFileCounter++;
|
if (element["type"] == "file") formFileCounter++;
|
||||||
}
|
}
|
||||||
var sanitizedJSObject = sanitzeJSObject(kEncoder.convert(formParams));
|
var sanitizedJSObject =
|
||||||
|
sanitzeJSObject(kJsonEncoder.convert(formParams));
|
||||||
result += templateBody
|
result += templateBody
|
||||||
.render({"body": padMultilineString(sanitizedJSObject, 2)});
|
.render({"body": padMultilineString(sanitizedJSObject, 2)});
|
||||||
} else if (harJson["postData"]?["text"] != null) {
|
} else if (harJson["postData"]?["text"] != null) {
|
||||||
result += templateBody
|
result += templateBody.render(
|
||||||
.render({"body": kEncoder.convert(harJson["postData"]["text"])});
|
{"body": kJsonEncoder.convert(harJson["postData"]["text"])});
|
||||||
}
|
}
|
||||||
result += kStringRequest;
|
result += kStringRequest;
|
||||||
return result;
|
return result;
|
||||||
|
@ -106,7 +106,7 @@ fetch(url, options)
|
|||||||
}
|
}
|
||||||
if (m.isNotEmpty) {
|
if (m.isNotEmpty) {
|
||||||
result += templateHeader.render({
|
result += templateHeader.render({
|
||||||
"headers": padMultilineString(kEncoder.convert(m), 2),
|
"headers": padMultilineString(kJsonEncoder.convert(m), 2),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ fetch(url, options)
|
|||||||
if (harJson["postData"]?["text"] != null) {
|
if (harJson["postData"]?["text"] != null) {
|
||||||
var templateBody = jj.Template(kTemplateBody);
|
var templateBody = jj.Template(kTemplateBody);
|
||||||
result += templateBody.render({
|
result += templateBody.render({
|
||||||
"body": kEncoder.convert(harJson["postData"]["text"]),
|
"body": kJsonEncoder.convert(harJson["postData"]["text"]),
|
||||||
});
|
});
|
||||||
} else if (requestModel.hasFormData) {
|
} else if (requestModel.hasFormData) {
|
||||||
var templateBody = jj.Template(kTemplateBody);
|
var templateBody = jj.Template(kTemplateBody);
|
||||||
|
@ -9,7 +9,7 @@ class HARCodeGen {
|
|||||||
String? boundary,
|
String? boundary,
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
var harString = kEncoder.convert(requestModelToHARJsonRequest(
|
var harString = kJsonEncoder.convert(requestModelToHARJsonRequest(
|
||||||
requestModel,
|
requestModel,
|
||||||
defaultUriScheme: defaultUriScheme,
|
defaultUriScheme: defaultUriScheme,
|
||||||
useEnabled: true,
|
useEnabled: true,
|
||||||
|
@ -111,7 +111,7 @@ body = b'\r\n'.join(dataList)
|
|||||||
if (params.isNotEmpty) {
|
if (params.isNotEmpty) {
|
||||||
hasQuery = true;
|
hasQuery = true;
|
||||||
var templateParams = jj.Template(kTemplateParams);
|
var templateParams = jj.Template(kTemplateParams);
|
||||||
var paramsString = kEncoder.convert(params);
|
var paramsString = kJsonEncoder.convert(params);
|
||||||
result += templateParams.render({"params": paramsString});
|
result += templateParams.render({"params": paramsString});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ body = b'\r\n'.join(dataList)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var headersString = kEncoder.convert(headers);
|
var headersString = kJsonEncoder.convert(headers);
|
||||||
var templateHeaders = jj.Template(kTemplateHeaders);
|
var templateHeaders = jj.Template(kTemplateHeaders);
|
||||||
result += templateHeaders.render({"headers": headersString});
|
result += templateHeaders.render({"headers": headersString});
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ print('Response Body:', response.text)
|
|||||||
if (params.isNotEmpty) {
|
if (params.isNotEmpty) {
|
||||||
hasQuery = true;
|
hasQuery = true;
|
||||||
var templateParams = jj.Template(kTemplateParams);
|
var templateParams = jj.Template(kTemplateParams);
|
||||||
var paramsString = kEncoder.convert(params);
|
var paramsString = kJsonEncoder.convert(params);
|
||||||
result += templateParams.render({"params": paramsString});
|
result += templateParams.render({"params": paramsString});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ print('Response Body:', response.text)
|
|||||||
}
|
}
|
||||||
if (headers.isNotEmpty) {
|
if (headers.isNotEmpty) {
|
||||||
hasHeaders = true;
|
hasHeaders = true;
|
||||||
var headersString = kEncoder.convert(headers);
|
var headersString = kJsonEncoder.convert(headers);
|
||||||
headersString = refactorHeaderString(headersString);
|
headersString = refactorHeaderString(headersString);
|
||||||
var templateHeaders = jj.Template(kTemplateHeaders);
|
var templateHeaders = jj.Template(kTemplateHeaders);
|
||||||
result += templateHeaders.render({"headers": headersString});
|
result += templateHeaders.render({"headers": headersString});
|
||||||
|
@ -415,7 +415,8 @@ enum ImportFormat {
|
|||||||
final String label;
|
final String label;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonEncoder kEncoder = JsonEncoder.withIndent(' ');
|
const JsonEncoder kJsonEncoder = JsonEncoder.withIndent(' ');
|
||||||
|
const JsonDecoder kJsonDecoder = JsonDecoder();
|
||||||
const LineSplitter kSplitter = LineSplitter();
|
const LineSplitter kSplitter = LineSplitter();
|
||||||
|
|
||||||
const String kGlobalEnvironmentId = "global";
|
const String kGlobalEnvironmentId = "global";
|
||||||
@ -745,6 +746,9 @@ const kLabelSaving = "Saving";
|
|||||||
const kLabelSaved = "Saved";
|
const kLabelSaved = "Saved";
|
||||||
const kLabelCode = "Code";
|
const kLabelCode = "Code";
|
||||||
const kLabelDuplicate = "Duplicate";
|
const kLabelDuplicate = "Duplicate";
|
||||||
|
const kLabelSelect = "Select";
|
||||||
|
const kLabelContinue = "Continue";
|
||||||
|
const kLabelCancel = "Cancel";
|
||||||
// Request Pane
|
// Request Pane
|
||||||
const kLabelRequest = "Request";
|
const kLabelRequest = "Request";
|
||||||
const kLabelHideCode = "Hide Code";
|
const kLabelHideCode = "Hide Code";
|
||||||
@ -779,3 +783,5 @@ const kNullResponseModelError = "Error: Response data does not exist.";
|
|||||||
const kMsgNullBody = "Response body is missing (null).";
|
const kMsgNullBody = "Response body is missing (null).";
|
||||||
const kMsgNoContent = "No content";
|
const kMsgNoContent = "No content";
|
||||||
const kMsgUnknowContentType = "Unknown Response Content-Type";
|
const kMsgUnknowContentType = "Unknown Response Content-Type";
|
||||||
|
// Workspace Selector
|
||||||
|
const kMsgSelectWorkspace = "Create your workspace";
|
||||||
|
@ -10,8 +10,6 @@ class Importer {
|
|||||||
switch (fileType) {
|
switch (fileType) {
|
||||||
case ImportFormat.curl:
|
case ImportFormat.curl:
|
||||||
return CurlFileImport().getHttpRequestModel(content);
|
return CurlFileImport().getHttpRequestModel(content);
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,82 @@
|
|||||||
|
import 'package:apidash/providers/settings_providers.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'models/models.dart';
|
||||||
|
import 'providers/providers.dart';
|
||||||
import 'services/services.dart';
|
import 'services/services.dart';
|
||||||
import 'consts.dart' show kIsLinux, kIsMacOS, kIsWindows;
|
import 'consts.dart';
|
||||||
import 'app.dart';
|
import 'app.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
var settingsModel = await getSettingsFromSharedPrefs();
|
||||||
await initApp();
|
final initStatus = await initApp(
|
||||||
await initWindow();
|
kIsDesktop,
|
||||||
|
settingsModel: settingsModel,
|
||||||
|
);
|
||||||
|
if (kIsDesktop) {
|
||||||
|
await initWindow(settingsModel: settingsModel);
|
||||||
|
}
|
||||||
|
if (!initStatus) {
|
||||||
|
settingsModel = settingsModel?.copyWithPath(workspaceFolderPath: null);
|
||||||
|
}
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
const ProviderScope(
|
ProviderScope(
|
||||||
child: DashApp(),
|
overrides: [
|
||||||
|
settingsProvider.overrideWith(
|
||||||
|
(ref) => ThemeStateNotifier(settingsModel: settingsModel),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: const DashApp(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initApp() async {
|
Future<bool> initApp(
|
||||||
|
bool initializeUsingPath, {
|
||||||
|
SettingsModel? settingsModel,
|
||||||
|
}) async {
|
||||||
GoogleFonts.config.allowRuntimeFetching = false;
|
GoogleFonts.config.allowRuntimeFetching = false;
|
||||||
await openBoxes();
|
try {
|
||||||
await autoClearHistory();
|
debugPrint("initializeUsingPath: $initializeUsingPath");
|
||||||
|
debugPrint("workspaceFolderPath: ${settingsModel?.workspaceFolderPath}");
|
||||||
|
final openBoxesStatus = await initHiveBoxes(
|
||||||
|
initializeUsingPath,
|
||||||
|
settingsModel?.workspaceFolderPath,
|
||||||
|
);
|
||||||
|
debugPrint("openBoxesStatus: $openBoxesStatus");
|
||||||
|
if (openBoxesStatus) {
|
||||||
|
await autoClearHistory(settingsModel: settingsModel);
|
||||||
|
}
|
||||||
|
return openBoxesStatus;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("initApp failed due to $e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initWindow({Size? sz}) async {
|
Future<void> initWindow({
|
||||||
|
Size? sz,
|
||||||
|
SettingsModel? settingsModel,
|
||||||
|
}) async {
|
||||||
if (kIsLinux) {
|
if (kIsLinux) {
|
||||||
await setupInitialWindow(sz: sz);
|
await setupInitialWindow(
|
||||||
|
sz: sz ?? settingsModel?.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (kIsMacOS || kIsWindows) {
|
if (kIsMacOS || kIsWindows) {
|
||||||
var win = sz != null ? (sz, const Offset(100, 100)) : getInitialSize();
|
if (sz != null) {
|
||||||
await setupWindow(sz: win.$1, off: win.$2);
|
await setupWindow(
|
||||||
|
sz: sz,
|
||||||
|
off: const Offset(100, 100),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await setupWindow(
|
||||||
|
sz: settingsModel?.size,
|
||||||
|
off: settingsModel?.offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ class SettingsModel {
|
|||||||
this.promptBeforeClosing = true,
|
this.promptBeforeClosing = true,
|
||||||
this.activeEnvironmentId,
|
this.activeEnvironmentId,
|
||||||
this.historyRetentionPeriod = HistoryRetentionPeriod.oneWeek,
|
this.historyRetentionPeriod = HistoryRetentionPeriod.oneWeek,
|
||||||
|
this.workspaceFolderPath,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool isDark;
|
final bool isDark;
|
||||||
@ -26,6 +27,7 @@ class SettingsModel {
|
|||||||
final bool promptBeforeClosing;
|
final bool promptBeforeClosing;
|
||||||
final String? activeEnvironmentId;
|
final String? activeEnvironmentId;
|
||||||
final HistoryRetentionPeriod historyRetentionPeriod;
|
final HistoryRetentionPeriod historyRetentionPeriod;
|
||||||
|
final String? workspaceFolderPath;
|
||||||
|
|
||||||
SettingsModel copyWith({
|
SettingsModel copyWith({
|
||||||
bool? isDark,
|
bool? isDark,
|
||||||
@ -38,6 +40,7 @@ class SettingsModel {
|
|||||||
bool? promptBeforeClosing,
|
bool? promptBeforeClosing,
|
||||||
String? activeEnvironmentId,
|
String? activeEnvironmentId,
|
||||||
HistoryRetentionPeriod? historyRetentionPeriod,
|
HistoryRetentionPeriod? historyRetentionPeriod,
|
||||||
|
String? workspaceFolderPath,
|
||||||
}) {
|
}) {
|
||||||
return SettingsModel(
|
return SettingsModel(
|
||||||
isDark: isDark ?? this.isDark,
|
isDark: isDark ?? this.isDark,
|
||||||
@ -52,6 +55,25 @@ class SettingsModel {
|
|||||||
activeEnvironmentId: activeEnvironmentId ?? this.activeEnvironmentId,
|
activeEnvironmentId: activeEnvironmentId ?? this.activeEnvironmentId,
|
||||||
historyRetentionPeriod:
|
historyRetentionPeriod:
|
||||||
historyRetentionPeriod ?? this.historyRetentionPeriod,
|
historyRetentionPeriod ?? this.historyRetentionPeriod,
|
||||||
|
workspaceFolderPath: workspaceFolderPath ?? this.workspaceFolderPath,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsModel copyWithPath({
|
||||||
|
String? workspaceFolderPath,
|
||||||
|
}) {
|
||||||
|
return SettingsModel(
|
||||||
|
isDark: isDark,
|
||||||
|
alwaysShowCollectionPaneScrollbar: alwaysShowCollectionPaneScrollbar,
|
||||||
|
size: size,
|
||||||
|
defaultUriScheme: defaultUriScheme,
|
||||||
|
defaultCodeGenLang: defaultCodeGenLang,
|
||||||
|
offset: offset,
|
||||||
|
saveResponses: saveResponses,
|
||||||
|
promptBeforeClosing: promptBeforeClosing,
|
||||||
|
activeEnvironmentId: activeEnvironmentId,
|
||||||
|
historyRetentionPeriod: historyRetentionPeriod,
|
||||||
|
workspaceFolderPath: workspaceFolderPath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +108,7 @@ class SettingsModel {
|
|||||||
final promptBeforeClosing = data["promptBeforeClosing"] as bool?;
|
final promptBeforeClosing = data["promptBeforeClosing"] as bool?;
|
||||||
final activeEnvironmentId = data["activeEnvironmentId"] as String?;
|
final activeEnvironmentId = data["activeEnvironmentId"] as String?;
|
||||||
final historyRetentionPeriodStr = data["historyRetentionPeriod"] as String?;
|
final historyRetentionPeriodStr = data["historyRetentionPeriod"] as String?;
|
||||||
HistoryRetentionPeriod historyRetentionPeriod =
|
HistoryRetentionPeriod? historyRetentionPeriod;
|
||||||
HistoryRetentionPeriod.oneWeek;
|
|
||||||
if (historyRetentionPeriodStr != null) {
|
if (historyRetentionPeriodStr != null) {
|
||||||
try {
|
try {
|
||||||
historyRetentionPeriod =
|
historyRetentionPeriod =
|
||||||
@ -96,6 +117,7 @@ class SettingsModel {
|
|||||||
// pass
|
// pass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final workspaceFolderPath = data["workspaceFolderPath"] as String?;
|
||||||
|
|
||||||
const sm = SettingsModel();
|
const sm = SettingsModel();
|
||||||
|
|
||||||
@ -109,7 +131,9 @@ class SettingsModel {
|
|||||||
saveResponses: saveResponses,
|
saveResponses: saveResponses,
|
||||||
promptBeforeClosing: promptBeforeClosing,
|
promptBeforeClosing: promptBeforeClosing,
|
||||||
activeEnvironmentId: activeEnvironmentId,
|
activeEnvironmentId: activeEnvironmentId,
|
||||||
historyRetentionPeriod: historyRetentionPeriod,
|
historyRetentionPeriod:
|
||||||
|
historyRetentionPeriod ?? HistoryRetentionPeriod.oneWeek,
|
||||||
|
workspaceFolderPath: workspaceFolderPath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,12 +151,13 @@ class SettingsModel {
|
|||||||
"promptBeforeClosing": promptBeforeClosing,
|
"promptBeforeClosing": promptBeforeClosing,
|
||||||
"activeEnvironmentId": activeEnvironmentId,
|
"activeEnvironmentId": activeEnvironmentId,
|
||||||
"historyRetentionPeriod": historyRetentionPeriod.name,
|
"historyRetentionPeriod": historyRetentionPeriod.name,
|
||||||
|
"workspaceFolderPath": workspaceFolderPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return toJson().toString();
|
return kJsonEncoder.convert(toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -149,7 +174,8 @@ class SettingsModel {
|
|||||||
other.saveResponses == saveResponses &&
|
other.saveResponses == saveResponses &&
|
||||||
other.promptBeforeClosing == promptBeforeClosing &&
|
other.promptBeforeClosing == promptBeforeClosing &&
|
||||||
other.activeEnvironmentId == activeEnvironmentId &&
|
other.activeEnvironmentId == activeEnvironmentId &&
|
||||||
other.historyRetentionPeriod == historyRetentionPeriod;
|
other.historyRetentionPeriod == historyRetentionPeriod &&
|
||||||
|
other.workspaceFolderPath == workspaceFolderPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -166,6 +192,7 @@ class SettingsModel {
|
|||||||
promptBeforeClosing,
|
promptBeforeClosing,
|
||||||
activeEnvironmentId,
|
activeEnvironmentId,
|
||||||
historyRetentionPeriod,
|
historyRetentionPeriod,
|
||||||
|
workspaceFolderPath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import '../models/models.dart';
|
import '../models/models.dart';
|
||||||
import '../services/services.dart' show hiveHandler, HiveHandler;
|
import '../services/services.dart';
|
||||||
import '../consts.dart';
|
import '../consts.dart';
|
||||||
|
|
||||||
final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) =>
|
final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) =>
|
||||||
@ -11,14 +11,13 @@ final activeEnvironmentIdStateProvider = StateProvider<String?>((ref) =>
|
|||||||
ref.watch(settingsProvider.select((value) => value.activeEnvironmentId)));
|
ref.watch(settingsProvider.select((value) => value.activeEnvironmentId)));
|
||||||
|
|
||||||
final StateNotifierProvider<ThemeStateNotifier, SettingsModel>
|
final StateNotifierProvider<ThemeStateNotifier, SettingsModel>
|
||||||
settingsProvider =
|
settingsProvider = StateNotifierProvider((ref) => ThemeStateNotifier());
|
||||||
StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler));
|
|
||||||
|
|
||||||
class ThemeStateNotifier extends StateNotifier<SettingsModel> {
|
class ThemeStateNotifier extends StateNotifier<SettingsModel> {
|
||||||
ThemeStateNotifier(this.hiveHandler) : super(const SettingsModel()) {
|
ThemeStateNotifier({this.settingsModel}) : super(const SettingsModel()) {
|
||||||
state = SettingsModel.fromJson(hiveHandler.settings);
|
state = settingsModel ?? const SettingsModel();
|
||||||
}
|
}
|
||||||
final HiveHandler hiveHandler;
|
final SettingsModel? settingsModel;
|
||||||
|
|
||||||
Future<void> update({
|
Future<void> update({
|
||||||
bool? isDark,
|
bool? isDark,
|
||||||
@ -31,6 +30,7 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
|
|||||||
bool? promptBeforeClosing,
|
bool? promptBeforeClosing,
|
||||||
String? activeEnvironmentId,
|
String? activeEnvironmentId,
|
||||||
HistoryRetentionPeriod? historyRetentionPeriod,
|
HistoryRetentionPeriod? historyRetentionPeriod,
|
||||||
|
String? workspaceFolderPath,
|
||||||
}) async {
|
}) async {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
isDark: isDark,
|
isDark: isDark,
|
||||||
@ -43,7 +43,8 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
|
|||||||
promptBeforeClosing: promptBeforeClosing,
|
promptBeforeClosing: promptBeforeClosing,
|
||||||
activeEnvironmentId: activeEnvironmentId,
|
activeEnvironmentId: activeEnvironmentId,
|
||||||
historyRetentionPeriod: historyRetentionPeriod,
|
historyRetentionPeriod: historyRetentionPeriod,
|
||||||
|
workspaceFolderPath: workspaceFolderPath,
|
||||||
);
|
);
|
||||||
await hiveHandler.saveSettings(state.toJson());
|
await setSettingsToSharedPrefs(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,21 @@ class EditRequestBody extends ConsumerWidget {
|
|||||||
final contentType = ref.watch(selectedRequestModelProvider
|
final contentType = ref.watch(selectedRequestModelProvider
|
||||||
.select((value) => value?.httpRequestModel?.bodyContentType));
|
.select((value) => value?.httpRequestModel?.bodyContentType));
|
||||||
|
|
||||||
|
// TODO: #178 GET->POST Currently switches to POST everytime user edits body even if the user intentionally chooses GET
|
||||||
|
// final sm = ScaffoldMessenger.of(context);
|
||||||
|
// void changeToPostMethod() {
|
||||||
|
// if (requestModel?.httpRequestModel!.method == HTTPVerb.get) {
|
||||||
|
// ref
|
||||||
|
// .read(collectionStateNotifierProvider.notifier)
|
||||||
|
// .update(selectedId, method: HTTPVerb.post);
|
||||||
|
// sm.hideCurrentSnackBar();
|
||||||
|
// sm.showSnackBar(getSnackBar(
|
||||||
|
// "Switched to POST method",
|
||||||
|
// small: false,
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -33,8 +48,12 @@ class EditRequestBody extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: switch (contentType) {
|
child: switch (contentType) {
|
||||||
ContentType.formdata =>
|
ContentType.formdata => const Padding(
|
||||||
const Padding(padding: kPh4, child: FormDataWidget()),
|
padding: kPh4,
|
||||||
|
child: FormDataWidget(
|
||||||
|
// TODO: See changeToPostMethod above
|
||||||
|
// changeMethodToPost: changeToPostMethod,
|
||||||
|
)),
|
||||||
// TODO: Fix JsonTextFieldEditor & plug it here
|
// TODO: Fix JsonTextFieldEditor & plug it here
|
||||||
ContentType.json => Padding(
|
ContentType.json => Padding(
|
||||||
padding: kPt5o10,
|
padding: kPt5o10,
|
||||||
@ -43,6 +62,7 @@ class EditRequestBody extends ConsumerWidget {
|
|||||||
fieldKey: "$selectedId-json-body-editor",
|
fieldKey: "$selectedId-json-body-editor",
|
||||||
initialValue: requestModel?.httpRequestModel?.body,
|
initialValue: requestModel?.httpRequestModel?.body,
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
|
// changeToPostMethod();
|
||||||
ref
|
ref
|
||||||
.read(collectionStateNotifierProvider.notifier)
|
.read(collectionStateNotifierProvider.notifier)
|
||||||
.update(selectedId, body: value);
|
.update(selectedId, body: value);
|
||||||
@ -56,6 +76,7 @@ class EditRequestBody extends ConsumerWidget {
|
|||||||
fieldKey: "$selectedId-body-editor",
|
fieldKey: "$selectedId-body-editor",
|
||||||
initialValue: requestModel?.httpRequestModel?.body,
|
initialValue: requestModel?.httpRequestModel?.body,
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
|
// changeToPostMethod();
|
||||||
ref
|
ref
|
||||||
.read(collectionStateNotifierProvider.notifier)
|
.read(collectionStateNotifierProvider.notifier)
|
||||||
.update(selectedId, body: value);
|
.update(selectedId, body: value);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import '../providers/providers.dart';
|
import '../providers/providers.dart';
|
||||||
|
import '../services/services.dart';
|
||||||
import '../widgets/widgets.dart';
|
import '../widgets/widgets.dart';
|
||||||
import '../common/utils.dart';
|
import '../common/utils.dart';
|
||||||
import '../consts.dart';
|
import '../consts.dart';
|
||||||
@ -206,6 +207,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.pop(context, 'Yes');
|
Navigator.pop(context, 'Yes');
|
||||||
|
await clearSharedPrefs();
|
||||||
await ref
|
await ref
|
||||||
.read(collectionStateNotifierProvider
|
.read(collectionStateNotifierProvider
|
||||||
.notifier)
|
.notifier)
|
||||||
|
@ -1,18 +1,9 @@
|
|||||||
import 'package:apidash/models/models.dart';
|
import 'package:apidash/models/models.dart';
|
||||||
import 'package:apidash/utils/utils.dart';
|
import 'package:apidash/utils/utils.dart';
|
||||||
import 'package:apidash/consts.dart';
|
|
||||||
import 'hive_services.dart';
|
import 'hive_services.dart';
|
||||||
|
|
||||||
Future<void> autoClearHistory() async {
|
Future<void> autoClearHistory({SettingsModel? settingsModel}) async {
|
||||||
final settingsMap = hiveHandler.settings;
|
final historyRetentionPeriod = settingsModel?.historyRetentionPeriod;
|
||||||
final retentionPeriod = settingsMap['historyRetentionPeriod'];
|
|
||||||
|
|
||||||
HistoryRetentionPeriod historyRetentionPeriod =
|
|
||||||
HistoryRetentionPeriod.oneWeek;
|
|
||||||
if (retentionPeriod != null) {
|
|
||||||
historyRetentionPeriod =
|
|
||||||
HistoryRetentionPeriod.values.byName(retentionPeriod);
|
|
||||||
}
|
|
||||||
DateTime? retentionDate = getRetentionDate(historyRetentionPeriod);
|
DateTime? retentionDate = getRetentionDate(historyRetentionPeriod);
|
||||||
|
|
||||||
if (retentionDate == null) {
|
if (retentionDate == null) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
|
||||||
const String kDataBox = "apidash-data";
|
const String kDataBox = "apidash-data";
|
||||||
@ -11,54 +11,95 @@ const String kHistoryMetaBox = "apidash-history-meta";
|
|||||||
const String kHistoryBoxIds = "historyIds";
|
const String kHistoryBoxIds = "historyIds";
|
||||||
const String kHistoryLazyBox = "apidash-history-lazy";
|
const String kHistoryLazyBox = "apidash-history-lazy";
|
||||||
|
|
||||||
const String kSettingsBox = "apidash-settings";
|
Future<bool> initHiveBoxes(
|
||||||
|
bool initializeUsingPath,
|
||||||
Future<void> openBoxes() async {
|
String? workspaceFolderPath,
|
||||||
await Hive.initFlutter();
|
) async {
|
||||||
await Hive.openBox(kDataBox);
|
try {
|
||||||
await Hive.openBox(kSettingsBox);
|
if (initializeUsingPath) {
|
||||||
await Hive.openBox(kEnvironmentBox);
|
if (workspaceFolderPath != null) {
|
||||||
await Hive.openBox(kHistoryMetaBox);
|
Hive.init(workspaceFolderPath);
|
||||||
await Hive.openLazyBox(kHistoryLazyBox);
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Hive.initFlutter();
|
||||||
|
}
|
||||||
|
final openHiveBoxesStatus = await openHiveBoxes();
|
||||||
|
return openHiveBoxesStatus;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Size?, Offset?) getInitialSize() {
|
Future<bool> openHiveBoxes() async {
|
||||||
Size? sz;
|
try {
|
||||||
Offset? off;
|
await Hive.openBox(kDataBox);
|
||||||
var settingsBox = Hive.box(kSettingsBox);
|
await Hive.openBox(kEnvironmentBox);
|
||||||
double? w = settingsBox.get("width") as double?;
|
await Hive.openBox(kHistoryMetaBox);
|
||||||
double? h = settingsBox.get("height") as double?;
|
await Hive.openLazyBox(kHistoryLazyBox);
|
||||||
if (w != null && h != null) {
|
return true;
|
||||||
sz = Size(w, h);
|
} catch (e) {
|
||||||
|
debugPrint("ERROR OPEN HIVE BOXES: $e");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
double? dx = settingsBox.get("dx") as double?;
|
}
|
||||||
double? dy = settingsBox.get("dy") as double?;
|
|
||||||
if (dx != null && dy != null) {
|
Future<void> clearHiveBoxes() async {
|
||||||
off = Offset(dx, dy);
|
try {
|
||||||
|
if (Hive.isBoxOpen(kDataBox)) {
|
||||||
|
await Hive.box(kDataBox).clear();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kEnvironmentBox)) {
|
||||||
|
await Hive.box(kEnvironmentBox).clear();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kHistoryMetaBox)) {
|
||||||
|
await Hive.box(kHistoryMetaBox).clear();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kHistoryLazyBox)) {
|
||||||
|
await Hive.lazyBox(kHistoryLazyBox).clear();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("ERROR CLEAR HIVE BOXES: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteHiveBoxes() async {
|
||||||
|
try {
|
||||||
|
if (Hive.isBoxOpen(kDataBox)) {
|
||||||
|
await Hive.box(kDataBox).deleteFromDisk();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kEnvironmentBox)) {
|
||||||
|
await Hive.box(kEnvironmentBox).deleteFromDisk();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kHistoryMetaBox)) {
|
||||||
|
await Hive.box(kHistoryMetaBox).deleteFromDisk();
|
||||||
|
}
|
||||||
|
if (Hive.isBoxOpen(kHistoryLazyBox)) {
|
||||||
|
await Hive.lazyBox(kHistoryLazyBox).deleteFromDisk();
|
||||||
|
}
|
||||||
|
await Hive.close();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("ERROR DELETE HIVE BOXES: $e");
|
||||||
}
|
}
|
||||||
return (sz, off);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final hiveHandler = HiveHandler();
|
final hiveHandler = HiveHandler();
|
||||||
|
|
||||||
class HiveHandler {
|
class HiveHandler {
|
||||||
late final Box dataBox;
|
late final Box dataBox;
|
||||||
late final Box settingsBox;
|
|
||||||
late final Box environmentBox;
|
late final Box environmentBox;
|
||||||
late final Box historyMetaBox;
|
late final Box historyMetaBox;
|
||||||
late final LazyBox historyLazyBox;
|
late final LazyBox historyLazyBox;
|
||||||
|
|
||||||
HiveHandler() {
|
HiveHandler() {
|
||||||
|
debugPrint("Trying to open Hive boxes");
|
||||||
dataBox = Hive.box(kDataBox);
|
dataBox = Hive.box(kDataBox);
|
||||||
settingsBox = Hive.box(kSettingsBox);
|
|
||||||
environmentBox = Hive.box(kEnvironmentBox);
|
environmentBox = Hive.box(kEnvironmentBox);
|
||||||
historyMetaBox = Hive.box(kHistoryMetaBox);
|
historyMetaBox = Hive.box(kHistoryMetaBox);
|
||||||
historyLazyBox = Hive.lazyBox(kHistoryLazyBox);
|
historyLazyBox = Hive.lazyBox(kHistoryLazyBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map get settings => settingsBox.toMap();
|
|
||||||
Future<void> saveSettings(Map data) => settingsBox.putAll(data);
|
|
||||||
|
|
||||||
dynamic getIds() => dataBox.get(kKeyDataBoxIds);
|
dynamic getIds() => dataBox.get(kKeyDataBoxIds);
|
||||||
Future<void> setIds(List<String>? ids) => dataBox.put(kKeyDataBoxIds, ids);
|
Future<void> setIds(List<String>? ids) => dataBox.put(kKeyDataBoxIds, ids);
|
||||||
|
|
||||||
@ -102,6 +143,8 @@ class HiveHandler {
|
|||||||
Future clear() async {
|
Future clear() async {
|
||||||
await dataBox.clear();
|
await dataBox.clear();
|
||||||
await environmentBox.clear();
|
await environmentBox.clear();
|
||||||
|
await historyMetaBox.clear();
|
||||||
|
await historyLazyBox.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeUnused() async {
|
Future<void> removeUnused() async {
|
||||||
|
@ -2,3 +2,4 @@ export 'http_service.dart';
|
|||||||
export 'hive_services.dart';
|
export 'hive_services.dart';
|
||||||
export 'history_service.dart';
|
export 'history_service.dart';
|
||||||
export 'window_services.dart';
|
export 'window_services.dart';
|
||||||
|
export 'shared_preferences_services.dart';
|
||||||
|
28
lib/services/shared_preferences_services.dart
Normal file
28
lib/services/shared_preferences_services.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:apidash/consts.dart';
|
||||||
|
import 'package:apidash/models/models.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
const String kSharedPrefSettingsKey = 'apidash-settings';
|
||||||
|
|
||||||
|
Future<SettingsModel?> getSettingsFromSharedPrefs() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
var settingsStr = prefs.getString(kSharedPrefSettingsKey);
|
||||||
|
if (settingsStr != null) {
|
||||||
|
var jsonSettings = kJsonDecoder.convert(settingsStr);
|
||||||
|
var jsonMap = Map<String, Object?>.from(jsonSettings);
|
||||||
|
var settingsModel = SettingsModel.fromJson(jsonMap);
|
||||||
|
return settingsModel;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setSettingsToSharedPrefs(SettingsModel settingsModel) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString(kSharedPrefSettingsKey, settingsModel.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> clearSharedPrefs() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.remove(kSharedPrefSettingsKey);
|
||||||
|
}
|
@ -150,7 +150,7 @@ Uint8List jsonMapToBytes(Map<String, dynamic>? map) {
|
|||||||
if (map == null) {
|
if (map == null) {
|
||||||
return Uint8List.fromList([]);
|
return Uint8List.fromList([]);
|
||||||
} else {
|
} else {
|
||||||
String text = kEncoder.convert(map);
|
String text = kJsonEncoder.convert(map);
|
||||||
var l = utf8.encode(text);
|
var l = utf8.encode(text);
|
||||||
var bytes = Uint8List.fromList(l);
|
var bytes = Uint8List.fromList(l);
|
||||||
return bytes;
|
return bytes;
|
||||||
|
@ -114,7 +114,7 @@ List<HistoryMetaModel> getRequestGroup(
|
|||||||
return requestGroup;
|
return requestGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime? getRetentionDate(HistoryRetentionPeriod retentionPeriod) {
|
DateTime? getRetentionDate(HistoryRetentionPeriod? retentionPeriod) {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
DateTime today = stripTime(now);
|
DateTime today = stripTime(now);
|
||||||
|
|
||||||
|
@ -101,33 +101,34 @@ String stripUrlParams(String url) {
|
|||||||
|
|
||||||
(List<ResponseBodyView>, String?) getResponseBodyViewOptions(
|
(List<ResponseBodyView>, String?) getResponseBodyViewOptions(
|
||||||
MediaType? mediaType) {
|
MediaType? mediaType) {
|
||||||
if (mediaType != null) {
|
if (mediaType == null) {
|
||||||
var type = mediaType.type;
|
return (kRawBodyViewOptions, null);
|
||||||
var subtype = mediaType.subtype;
|
}
|
||||||
if (kResponseBodyViewOptions.containsKey(type)) {
|
var type = mediaType.type;
|
||||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)) {
|
var subtype = mediaType.subtype;
|
||||||
return (
|
if (kResponseBodyViewOptions.containsKey(type)) {
|
||||||
kResponseBodyViewOptions[type]![subtype]!,
|
if (kResponseBodyViewOptions[type]!.containsKey(subtype)) {
|
||||||
kCodeHighlighterMap[subtype] ?? subtype
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (subtype.contains(kSubTypeJson)) {
|
|
||||||
subtype = kSubTypeJson;
|
|
||||||
}
|
|
||||||
if (subtype.contains(kSubTypeXml)) {
|
|
||||||
subtype = kSubTypeXml;
|
|
||||||
}
|
|
||||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)) {
|
|
||||||
return (
|
|
||||||
kResponseBodyViewOptions[type]![subtype]!,
|
|
||||||
kCodeHighlighterMap[subtype] ?? subtype
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!,
|
kResponseBodyViewOptions[type]![subtype]!,
|
||||||
subtype
|
kCodeHighlighterMap[subtype] ?? subtype
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (subtype.contains(kSubTypeJson)) {
|
||||||
|
subtype = kSubTypeJson;
|
||||||
|
}
|
||||||
|
if (subtype.contains(kSubTypeXml)) {
|
||||||
|
subtype = kSubTypeXml;
|
||||||
|
}
|
||||||
|
if (kResponseBodyViewOptions[type]!.containsKey(subtype)) {
|
||||||
|
return (
|
||||||
|
kResponseBodyViewOptions[type]![subtype]!,
|
||||||
|
kCodeHighlighterMap[subtype] ?? subtype
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!,
|
||||||
|
subtype
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (kNoBodyViewOptions, null);
|
return (kNoBodyViewOptions, null);
|
||||||
}
|
}
|
||||||
@ -138,7 +139,7 @@ String? formatBody(String? body, MediaType? mediaType) {
|
|||||||
try {
|
try {
|
||||||
if (subtype.contains(kSubTypeJson)) {
|
if (subtype.contains(kSubTypeJson)) {
|
||||||
final tmp = jsonDecode(body);
|
final tmp = jsonDecode(body);
|
||||||
String result = kEncoder.convert(tmp);
|
String result = kJsonEncoder.convert(tmp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (subtype.contains(kSubTypeXml)) {
|
if (subtype.contains(kSubTypeXml)) {
|
||||||
|
54
lib/widgets/field_outlined.dart
Normal file
54
lib/widgets/field_outlined.dart
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:apidash/consts.dart';
|
||||||
|
|
||||||
|
class OutlinedField extends StatelessWidget {
|
||||||
|
const OutlinedField({
|
||||||
|
super.key,
|
||||||
|
this.keyId,
|
||||||
|
this.initialValue,
|
||||||
|
this.hintText,
|
||||||
|
this.onChanged,
|
||||||
|
this.colorScheme,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? keyId;
|
||||||
|
final String? initialValue;
|
||||||
|
final String? hintText;
|
||||||
|
final void Function(String)? onChanged;
|
||||||
|
final ColorScheme? colorScheme;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var clrScheme = colorScheme ?? Theme.of(context).colorScheme;
|
||||||
|
return TextFormField(
|
||||||
|
key: keyId != null ? Key(keyId!) : null,
|
||||||
|
initialValue: initialValue,
|
||||||
|
style: kCodeStyle.copyWith(
|
||||||
|
color: clrScheme.onSurface,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintStyle: kCodeStyle.copyWith(
|
||||||
|
color: clrScheme.outline.withOpacity(
|
||||||
|
kHintOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
hintText: hintText,
|
||||||
|
contentPadding: kP10,
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: clrScheme.primary.withOpacity(
|
||||||
|
kHintOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: clrScheme.surfaceContainerHighest,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -182,7 +182,7 @@ class _JsonPreviewerState extends State<JsonPreviewer> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _copy(
|
await _copy(
|
||||||
kEncoder.convert(widget.code), sm);
|
kJsonEncoder.convert(widget.code), sm);
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Copy',
|
'Copy',
|
||||||
@ -215,7 +215,7 @@ class _JsonPreviewerState extends State<JsonPreviewer> {
|
|||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _copy(
|
await _copy(
|
||||||
kEncoder.convert(widget.code), sm);
|
kJsonEncoder.convert(widget.code), sm);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.copy,
|
Icons.copy,
|
||||||
@ -273,7 +273,7 @@ class _JsonPreviewerState extends State<JsonPreviewer> {
|
|||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _copy(
|
await _copy(
|
||||||
kEncoder.convert(toJson(node)), sm);
|
kJsonEncoder.convert(toJson(node)), sm);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -262,7 +262,7 @@ class ResponseHeadersHeader extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
if (map.isNotEmpty)
|
if (map.isNotEmpty)
|
||||||
CopyButton(
|
CopyButton(
|
||||||
toCopy: kEncoder.convert(map),
|
toCopy: kJsonEncoder.convert(map),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -345,12 +345,14 @@ class ResponseBody extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mediaType = responseModel.mediaType;
|
final mediaType =
|
||||||
if (mediaType == null) {
|
responseModel.mediaType ?? MediaType(kTypeText, kSubTypePlain);
|
||||||
return ErrorMessage(
|
// Fix #415: Treat null Content-type as plain text instead of Error message
|
||||||
message:
|
// if (mediaType == null) {
|
||||||
'$kMsgUnknowContentType - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
// return ErrorMessage(
|
||||||
}
|
// message:
|
||||||
|
// '$kMsgUnknowContentType - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
||||||
|
// }
|
||||||
|
|
||||||
var responseBodyView = getResponseBodyViewOptions(mediaType);
|
var responseBodyView = getResponseBodyViewOptions(mediaType);
|
||||||
var options = responseBodyView.$1;
|
var options = responseBodyView.$1;
|
||||||
|
@ -31,6 +31,7 @@ export 'field_cell_obscurable.dart';
|
|||||||
export 'field_cell.dart';
|
export 'field_cell.dart';
|
||||||
export 'field_header.dart';
|
export 'field_header.dart';
|
||||||
export 'field_json_search.dart';
|
export 'field_json_search.dart';
|
||||||
|
export 'field_outlined.dart';
|
||||||
export 'field_raw.dart';
|
export 'field_raw.dart';
|
||||||
export 'field_read_only.dart';
|
export 'field_read_only.dart';
|
||||||
export 'field_url.dart';
|
export 'field_url.dart';
|
||||||
@ -60,3 +61,4 @@ export 'tabs.dart';
|
|||||||
export 'texts.dart';
|
export 'texts.dart';
|
||||||
export 'uint8_audio_player.dart';
|
export 'uint8_audio_player.dart';
|
||||||
export 'window_caption.dart';
|
export 'window_caption.dart';
|
||||||
|
export 'workspace_selector.dart';
|
||||||
|
133
lib/widgets/workspace_selector.dart
Normal file
133
lib/widgets/workspace_selector.dart
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import 'package:apidash/consts.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:file_selector/file_selector.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'field_outlined.dart';
|
||||||
|
|
||||||
|
class WorkspaceSelector extends HookWidget {
|
||||||
|
const WorkspaceSelector({
|
||||||
|
super.key,
|
||||||
|
required this.onContinue,
|
||||||
|
this.onCancel,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Future<void> Function(String)? onContinue;
|
||||||
|
final Future<void> Function()? onCancel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var selectedDirectory = useState<String?>(null);
|
||||||
|
var workspaceName = useState<String?>(null);
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 400,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
kMsgSelectWorkspace,
|
||||||
|
style: kTextStyleButton,
|
||||||
|
),
|
||||||
|
kVSpacer20,
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"CHOOSE DIRECTORY",
|
||||||
|
style: kCodeStyle.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
kVSpacer5,
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
width: 1,
|
||||||
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
),
|
||||||
|
borderRadius: kBorderRadius6,
|
||||||
|
),
|
||||||
|
padding: kP4,
|
||||||
|
child: Text(
|
||||||
|
style: kTextStyleButtonSmall,
|
||||||
|
selectedDirectory.value ?? "",
|
||||||
|
maxLines: 4,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
kHSpacer10,
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
onPressed: () async {
|
||||||
|
selectedDirectory.value = await getDirectoryPath();
|
||||||
|
},
|
||||||
|
label: const Text(kLabelSelect),
|
||||||
|
icon: const Icon(Icons.folder_rounded),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
kVSpacer10,
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"WORKSPACE NAME [OPTIONAL]\n(FOLDER WILL BE CREATED IN THE SELECTED DIRECTORY)",
|
||||||
|
style: kCodeStyle.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
kVSpacer5,
|
||||||
|
OutlinedField(
|
||||||
|
keyId: "workspace-name",
|
||||||
|
onChanged: (value) {
|
||||||
|
workspaceName.value = value.trim();
|
||||||
|
},
|
||||||
|
colorScheme: Theme.of(context).colorScheme,
|
||||||
|
),
|
||||||
|
kVSpacer40,
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
FilledButton(
|
||||||
|
onPressed: selectedDirectory.value == null
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
String finalPath = selectedDirectory.value!;
|
||||||
|
if (workspaceName.value != null &&
|
||||||
|
workspaceName.value!.trim().isNotEmpty) {
|
||||||
|
finalPath =
|
||||||
|
p.join(finalPath, workspaceName.value);
|
||||||
|
}
|
||||||
|
await onContinue?.call(finalPath);
|
||||||
|
},
|
||||||
|
child: const Text(kLabelContinue),
|
||||||
|
),
|
||||||
|
kHSpacer10,
|
||||||
|
FilledButton(
|
||||||
|
onPressed: onCancel,
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).brightness == Brightness.dark
|
||||||
|
? kColorDarkDanger
|
||||||
|
: kColorLightDanger,
|
||||||
|
surfaceTintColor: kColorRed,
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).colorScheme.onPrimary),
|
||||||
|
child: const Text(kLabelCancel),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
98
pubspec.lock
98
pubspec.lock
@ -22,6 +22,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.7.0"
|
version: "6.7.0"
|
||||||
|
ansicolor:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ansicolor
|
||||||
|
sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -259,10 +267,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.6"
|
version: "2.3.7"
|
||||||
dartx:
|
dartx:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -521,6 +529,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.3+1"
|
version: "0.7.3+1"
|
||||||
|
flutter_native_splash:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_native_splash
|
||||||
|
sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
flutter_portal:
|
flutter_portal:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -596,10 +612,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: fvp
|
name: fvp
|
||||||
sha256: "6462fd078de4478a0990d437463897036cff98aff3f0ac9efbbf817c99654c87"
|
sha256: "040aa12beccd5bc60631259f27a481c4abc11a389aa4f57a47b643f58fe0b060"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.24.1"
|
version: "0.26.1"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -778,10 +794,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: just_audio
|
name: just_audio
|
||||||
sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a
|
sha256: d8e8aaf417d33e345299c17f6457f72bd4ba0c549dc34607abb5183a354edc4d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.39"
|
version: "0.9.40"
|
||||||
just_audio_mpv:
|
just_audio_mpv:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1215,6 +1231,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.8"
|
version: "0.3.8"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.2"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1428,6 +1500,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.2"
|
||||||
|
universal_io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: universal_io
|
||||||
|
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
url_launcher:
|
url_launcher:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1496,10 +1576,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90"
|
sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.4.2"
|
version: "4.5.0"
|
||||||
vector_graphics:
|
vector_graphics:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1671,4 +1751,4 @@ packages:
|
|||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.5.0-259.0.dev <3.999.0"
|
dart: ">=3.5.0-259.0.dev <3.999.0"
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.24.2"
|
||||||
|
12
pubspec.yaml
12
pubspec.yaml
@ -5,7 +5,7 @@ version: 0.4.0+4
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
flutter: ">=3.19.0"
|
flutter: ">=3.24.2"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
@ -18,7 +18,7 @@ dependencies:
|
|||||||
url: https://github.com/foss42/curl_converter.git
|
url: https://github.com/foss42/curl_converter.git
|
||||||
ref: 726e8cd04aeb326211af27f75920be5b21c90bb4
|
ref: 726e8cd04aeb326211af27f75920be5b21c90bb4
|
||||||
data_table_2: ^2.5.15
|
data_table_2: ^2.5.15
|
||||||
dart_style: ^2.3.6
|
dart_style: ^2.3.7
|
||||||
desktop_drop: ^0.4.4
|
desktop_drop: ^0.4.4
|
||||||
extended_text_field: ^16.0.0
|
extended_text_field: ^16.0.0
|
||||||
file_selector: ^1.0.3
|
file_selector: ^1.0.3
|
||||||
@ -30,7 +30,7 @@ dependencies:
|
|||||||
flutter_svg: ^2.0.10+1
|
flutter_svg: ^2.0.10+1
|
||||||
flutter_typeahead: ^5.2.0
|
flutter_typeahead: ^5.2.0
|
||||||
freezed_annotation: ^2.4.1
|
freezed_annotation: ^2.4.1
|
||||||
fvp: ^0.24.1
|
fvp: ^0.26.1
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
highlighter: ^0.1.1
|
highlighter: ^0.1.1
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
@ -45,7 +45,7 @@ dependencies:
|
|||||||
url: https://github.com/foss42/json_data_explorer.git
|
url: https://github.com/foss42/json_data_explorer.git
|
||||||
ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a
|
ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a
|
||||||
json_text_field: ^1.2.0
|
json_text_field: ^1.2.0
|
||||||
just_audio: ^0.9.34
|
just_audio: ^0.9.40
|
||||||
just_audio_mpv: ^0.1.7
|
just_audio_mpv: ^0.1.7
|
||||||
just_audio_windows: ^0.2.0
|
just_audio_windows: ^0.2.0
|
||||||
lottie: ^3.1.0
|
lottie: ^3.1.0
|
||||||
@ -63,8 +63,9 @@ dependencies:
|
|||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
riverpod: ^2.5.1
|
riverpod: ^2.5.1
|
||||||
scrollable_positioned_list: ^0.3.8
|
scrollable_positioned_list: ^0.3.8
|
||||||
|
shared_preferences: ^2.3.2
|
||||||
url_launcher: ^6.2.5
|
url_launcher: ^6.2.5
|
||||||
uuid: ^4.3.3
|
uuid: ^4.5.0
|
||||||
vector_graphics_compiler: ^1.1.9+1
|
vector_graphics_compiler: ^1.1.9+1
|
||||||
video_player: ^2.8.7
|
video_player: ^2.8.7
|
||||||
video_player_platform_interface: ^6.2.2
|
video_player_platform_interface: ^6.2.2
|
||||||
@ -86,6 +87,7 @@ dev_dependencies:
|
|||||||
build_runner: ^2.4.12
|
build_runner: ^2.4.12
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.13.1
|
||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^4.0.0
|
||||||
|
flutter_native_splash: ^2.4.1
|
||||||
freezed: ^2.5.7
|
freezed: ^2.5.7
|
||||||
json_serializable: ^6.7.1
|
json_serializable: ^6.7.1
|
||||||
integration_test:
|
integration_test:
|
||||||
|
@ -15,6 +15,7 @@ void main() {
|
|||||||
promptBeforeClosing: true,
|
promptBeforeClosing: true,
|
||||||
activeEnvironmentId: null,
|
activeEnvironmentId: null,
|
||||||
historyRetentionPeriod: HistoryRetentionPeriod.oneWeek,
|
historyRetentionPeriod: HistoryRetentionPeriod.oneWeek,
|
||||||
|
workspaceFolderPath: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
test('Testing toJson()', () {
|
test('Testing toJson()', () {
|
||||||
@ -31,6 +32,7 @@ void main() {
|
|||||||
"promptBeforeClosing": true,
|
"promptBeforeClosing": true,
|
||||||
"activeEnvironmentId": null,
|
"activeEnvironmentId": null,
|
||||||
"historyRetentionPeriod": "oneWeek",
|
"historyRetentionPeriod": "oneWeek",
|
||||||
|
"workspaceFolderPath": null,
|
||||||
};
|
};
|
||||||
expect(sm.toJson(), expectedResult);
|
expect(sm.toJson(), expectedResult);
|
||||||
});
|
});
|
||||||
@ -49,6 +51,7 @@ void main() {
|
|||||||
"promptBeforeClosing": true,
|
"promptBeforeClosing": true,
|
||||||
"activeEnvironmentId": null,
|
"activeEnvironmentId": null,
|
||||||
"historyRetentionPeriod": "oneWeek",
|
"historyRetentionPeriod": "oneWeek",
|
||||||
|
"workspaceFolderPath": null,
|
||||||
};
|
};
|
||||||
expect(SettingsModel.fromJson(input), sm);
|
expect(SettingsModel.fromJson(input), sm);
|
||||||
});
|
});
|
||||||
@ -75,8 +78,21 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Testing toString()', () {
|
test('Testing toString()', () {
|
||||||
const expectedResult =
|
const expectedResult = '''{
|
||||||
"{isDark: false, alwaysShowCollectionPaneScrollbar: true, width: 300.0, height: 200.0, dx: 100.0, dy: 150.0, defaultUriScheme: http, defaultCodeGenLang: curl, saveResponses: true, promptBeforeClosing: true, activeEnvironmentId: null, historyRetentionPeriod: oneWeek}";
|
"isDark": false,
|
||||||
|
"alwaysShowCollectionPaneScrollbar": true,
|
||||||
|
"width": 300.0,
|
||||||
|
"height": 200.0,
|
||||||
|
"dx": 100.0,
|
||||||
|
"dy": 150.0,
|
||||||
|
"defaultUriScheme": "http",
|
||||||
|
"defaultCodeGenLang": "curl",
|
||||||
|
"saveResponses": true,
|
||||||
|
"promptBeforeClosing": true,
|
||||||
|
"activeEnvironmentId": null,
|
||||||
|
"historyRetentionPeriod": "oneWeek",
|
||||||
|
"workspaceFolderPath": null
|
||||||
|
}''';
|
||||||
expect(sm.toString(), expectedResult);
|
expect(sm.toString(), expectedResult);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
54
test/providers/collection_providers_test.dart
Normal file
54
test/providers/collection_providers_test.dart
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import 'package:apidash/consts.dart';
|
||||||
|
import 'package:apidash/screens/home_page/editor_pane/details_card/request_pane/request_body.dart';
|
||||||
|
import 'package:apidash/widgets/editor.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:apidash/providers/providers.dart';
|
||||||
|
import 'helpers.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
await testSetUpTempDirForHive();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Request method changes from GET to POST when body is added and Snackbar is shown',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
// Set up the test environment
|
||||||
|
final container = createContainer();
|
||||||
|
final notifier = container.read(collectionStateNotifierProvider.notifier);
|
||||||
|
|
||||||
|
// Ensure the initial request is a GET request with no body
|
||||||
|
final id = notifier.state!.entries.first.key;
|
||||||
|
expect(
|
||||||
|
notifier.getRequestModel(id)!.httpRequestModel!.method, HTTPVerb.get);
|
||||||
|
expect(notifier.getRequestModel(id)!.httpRequestModel!.body, isNull);
|
||||||
|
|
||||||
|
// Build the EditRequestBody widget
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ProviderScope(
|
||||||
|
// ignore: deprecated_member_use
|
||||||
|
parent: container,
|
||||||
|
child: const MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: EditRequestBody(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add a body to the request, which should trigger the method change
|
||||||
|
await tester.enterText(find.byType(TextFieldEditor), 'new body added');
|
||||||
|
await tester.pump(); // Process the state change
|
||||||
|
|
||||||
|
// Verify that the request method changed to POST
|
||||||
|
expect(
|
||||||
|
notifier.getRequestModel(id)!.httpRequestModel!.method, HTTPVerb.post);
|
||||||
|
|
||||||
|
// Verify that the Snackbar is shown
|
||||||
|
expect(find.text('Switched to POST method'), findsOneWidget);
|
||||||
|
}, skip: true);
|
||||||
|
}
|
57
test/providers/helpers.dart
Normal file
57
test/providers/helpers.dart
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:apidash/services/hive_services.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
/// A testing utility which creates a [ProviderContainer] and automatically
|
||||||
|
/// disposes it at the end of the test.
|
||||||
|
ProviderContainer createContainer({
|
||||||
|
ProviderContainer? parent,
|
||||||
|
List<Override> overrides = const [],
|
||||||
|
List<ProviderObserver>? observers,
|
||||||
|
}) {
|
||||||
|
// Create a ProviderContainer, and optionally allow specifying parameters.
|
||||||
|
final container = ProviderContainer(
|
||||||
|
parent: parent,
|
||||||
|
overrides: overrides,
|
||||||
|
observers: observers,
|
||||||
|
);
|
||||||
|
|
||||||
|
// When the test ends, dispose the container.
|
||||||
|
addTearDown(container.dispose);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> testSetUpForHive() async {
|
||||||
|
// override path_provider methodCall to point
|
||||||
|
// path to temporary location for all unit tests
|
||||||
|
const MethodChannel channel =
|
||||||
|
MethodChannel('plugins.flutter.io/path_provider');
|
||||||
|
|
||||||
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||||
|
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
|
||||||
|
return './test-hive-storage/';
|
||||||
|
});
|
||||||
|
|
||||||
|
await initHiveBoxes(false, null);
|
||||||
|
// await deleteHiveBoxes();
|
||||||
|
// await openHiveBoxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> testSetUpTempDirForHive() async {
|
||||||
|
const MethodChannel channel =
|
||||||
|
MethodChannel('plugins.flutter.io/path_provider');
|
||||||
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||||
|
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
|
||||||
|
if (methodCall.method == 'getApplicationDocumentsDirectory') {
|
||||||
|
// Create a mock app doc directory for testing
|
||||||
|
Directory tempDir =
|
||||||
|
await Directory.systemTemp.createTemp('mock_app_doc_dir');
|
||||||
|
return tempDir.path; // Return the path to the mock directory
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
await initHiveBoxes(false, null);
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
import 'dart:io';
|
|
||||||
//import 'package:spot/spot.dart';
|
//import 'package:spot/spot.dart';
|
||||||
import 'package:apidash/providers/providers.dart';
|
import 'package:apidash/providers/providers.dart';
|
||||||
import 'package:apidash/screens/common_widgets/common_widgets.dart';
|
import 'package:apidash/screens/common_widgets/common_widgets.dart';
|
||||||
@ -12,7 +11,6 @@ import 'package:apidash/screens/home_page/editor_pane/url_card.dart';
|
|||||||
import 'package:apidash/screens/home_page/home_page.dart';
|
import 'package:apidash/screens/home_page/home_page.dart';
|
||||||
import 'package:apidash/screens/settings_page.dart';
|
import 'package:apidash/screens/settings_page.dart';
|
||||||
import 'package:apidash/screens/history/history_page.dart';
|
import 'package:apidash/screens/history/history_page.dart';
|
||||||
import 'package:apidash/services/hive_services.dart';
|
|
||||||
import 'package:apidash/widgets/widgets.dart';
|
import 'package:apidash/widgets/widgets.dart';
|
||||||
import 'package:extended_text_field/extended_text_field.dart';
|
import 'package:extended_text_field/extended_text_field.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -22,24 +20,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import '../extensions/widget_tester_extensions.dart';
|
import '../extensions/widget_tester_extensions.dart';
|
||||||
import '../test_consts.dart';
|
import '../test_consts.dart';
|
||||||
|
import 'helpers.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
const MethodChannel channel =
|
await testSetUpTempDirForHive();
|
||||||
MethodChannel('plugins.flutter.io/path_provider');
|
|
||||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
||||||
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
|
|
||||||
if (methodCall.method == 'getApplicationDocumentsDirectory') {
|
|
||||||
// Create a mock app doc directory for testing
|
|
||||||
Directory tempDir =
|
|
||||||
await Directory.systemTemp.createTemp('mock_app_doc_dir');
|
|
||||||
return tempDir.path; // Return the path to the mock directory
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
await openBoxes();
|
|
||||||
final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf');
|
final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf');
|
||||||
final fontLoader = FontLoader('OpenSans')..addFont(flamante);
|
final fontLoader = FontLoader('OpenSans')..addFont(flamante);
|
||||||
await fontLoader.load();
|
await fontLoader.load();
|
||||||
|
@ -214,8 +214,13 @@ void main() {
|
|||||||
findsOneWidget);
|
findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Testing Response Body, no mediaType', (tester) async {
|
testWidgets(
|
||||||
var responseModelNoHeaders = responseModel.copyWith(headers: null);
|
'Testing Response Body, no mediaType; shoud be default plaintext preview',
|
||||||
|
(tester) async {
|
||||||
|
var responseModelNoHeaders = responseModel.copyWith(
|
||||||
|
headers: null,
|
||||||
|
formattedBody: null,
|
||||||
|
);
|
||||||
var requestModelNoResponseHeaders =
|
var requestModelNoResponseHeaders =
|
||||||
testRequestModel.copyWith(httpResponseModel: responseModelNoHeaders);
|
testRequestModel.copyWith(httpResponseModel: responseModelNoHeaders);
|
||||||
|
|
||||||
@ -230,10 +235,8 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(find.text("Raw"), findsOneWidget);
|
||||||
find.text(
|
expect(find.text('{"data":"world"}'), findsOneWidget);
|
||||||
'Unknown Response Content-Type - ${responseModelNoHeaders.contentType}. $kUnexpectedRaiseIssue'),
|
|
||||||
findsOneWidget);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Testing Response Body for No body view', (tester) async {
|
testWidgets('Testing Response Body for No body view', (tester) async {
|
||||||
|
@ -6,6 +6,7 @@ import 'package:apidash/models/models.dart';
|
|||||||
import 'package:apidash/consts.dart';
|
import 'package:apidash/consts.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
dataTableShowLogs = false;
|
||||||
testWidgets('Testing RequestFormDataTable', (WidgetTester tester) async {
|
testWidgets('Testing RequestFormDataTable', (WidgetTester tester) async {
|
||||||
const List<FormDataModel> sampleData = [
|
const List<FormDataModel> sampleData = [
|
||||||
FormDataModel(name: 'Key1', value: 'Value1', type: FormDataType.file),
|
FormDataModel(name: 'Key1', value: 'Value1', type: FormDataType.file),
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
dataTableShowLogs = false;
|
||||||
testWidgets('Testing RequestDataTable', (WidgetTester tester) async {
|
testWidgets('Testing RequestDataTable', (WidgetTester tester) async {
|
||||||
final Map<String, String> sampleData = {
|
final Map<String, String> sampleData = {
|
||||||
'Key1': 'Value1',
|
'Key1': 'Value1',
|
||||||
|
Reference in New Issue
Block a user