mirror of
https://github.com/foss42/apidash.git
synced 2025-07-02 05:57:55 +08:00
wip: history request groups
This commit is contained in:
@ -68,6 +68,7 @@ const kFormDataButtonLabelTextStyle = TextStyle(
|
||||
const kTextStylePopupMenuItem = TextStyle(fontSize: 16);
|
||||
|
||||
const kBorderRadius4 = BorderRadius.all(Radius.circular(4));
|
||||
const kBorderRadius6 = BorderRadius.all(Radius.circular(6));
|
||||
const kBorderRadius8 = BorderRadius.all(Radius.circular(8));
|
||||
final kBorderRadius10 = BorderRadius.circular(10);
|
||||
const kBorderRadius12 = BorderRadius.all(Radius.circular(12));
|
||||
@ -88,7 +89,7 @@ const kPv8 = EdgeInsets.symmetric(vertical: 8);
|
||||
const kPv6 = EdgeInsets.symmetric(vertical: 6);
|
||||
const kPv2 = EdgeInsets.symmetric(vertical: 2);
|
||||
const kPh2 = EdgeInsets.symmetric(horizontal: 2);
|
||||
const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0);
|
||||
const kPt28o8 = EdgeInsets.only(top: 28, 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 kPh4 = EdgeInsets.symmetric(horizontal: 4);
|
||||
|
21
lib/models/history_meta_model.dart
Normal file
21
lib/models/history_meta_model.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'history_meta_model.freezed.dart';
|
||||
|
||||
part 'history_meta_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class HistoryMetaModel with _$HistoryMetaModel {
|
||||
const factory HistoryMetaModel({
|
||||
required String historyId,
|
||||
@Default("") String name,
|
||||
required String url,
|
||||
required HTTPVerb method,
|
||||
required int responseStatus,
|
||||
required DateTime timeStamp,
|
||||
}) = _HistoryMetaModel;
|
||||
|
||||
factory HistoryMetaModel.fromJson(Map<String, Object?> json) =>
|
||||
_$HistoryMetaModelFromJson(json);
|
||||
}
|
261
lib/models/history_meta_model.freezed.dart
Normal file
261
lib/models/history_meta_model.freezed.dart
Normal file
@ -0,0 +1,261 @@
|
||||
// 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 'history_meta_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(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#adding-getters-and-methods-to-our-models');
|
||||
|
||||
HistoryMetaModel _$HistoryMetaModelFromJson(Map<String, dynamic> json) {
|
||||
return _HistoryMetaModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HistoryMetaModel {
|
||||
String get historyId => throw _privateConstructorUsedError;
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
String get url => throw _privateConstructorUsedError;
|
||||
HTTPVerb get method => throw _privateConstructorUsedError;
|
||||
int get responseStatus => throw _privateConstructorUsedError;
|
||||
DateTime get timeStamp => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$HistoryMetaModelCopyWith<HistoryMetaModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HistoryMetaModelCopyWith<$Res> {
|
||||
factory $HistoryMetaModelCopyWith(
|
||||
HistoryMetaModel value, $Res Function(HistoryMetaModel) then) =
|
||||
_$HistoryMetaModelCopyWithImpl<$Res, HistoryMetaModel>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String historyId,
|
||||
String name,
|
||||
String url,
|
||||
HTTPVerb method,
|
||||
int responseStatus,
|
||||
DateTime timeStamp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HistoryMetaModelCopyWithImpl<$Res, $Val extends HistoryMetaModel>
|
||||
implements $HistoryMetaModelCopyWith<$Res> {
|
||||
_$HistoryMetaModelCopyWithImpl(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? historyId = null,
|
||||
Object? name = null,
|
||||
Object? url = null,
|
||||
Object? method = null,
|
||||
Object? responseStatus = null,
|
||||
Object? timeStamp = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
historyId: null == historyId
|
||||
? _value.historyId
|
||||
: historyId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
url: null == url
|
||||
? _value.url
|
||||
: url // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
method: null == method
|
||||
? _value.method
|
||||
: method // ignore: cast_nullable_to_non_nullable
|
||||
as HTTPVerb,
|
||||
responseStatus: null == responseStatus
|
||||
? _value.responseStatus
|
||||
: responseStatus // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
timeStamp: null == timeStamp
|
||||
? _value.timeStamp
|
||||
: timeStamp // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$HistoryMetaModelImplCopyWith<$Res>
|
||||
implements $HistoryMetaModelCopyWith<$Res> {
|
||||
factory _$$HistoryMetaModelImplCopyWith(_$HistoryMetaModelImpl value,
|
||||
$Res Function(_$HistoryMetaModelImpl) then) =
|
||||
__$$HistoryMetaModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String historyId,
|
||||
String name,
|
||||
String url,
|
||||
HTTPVerb method,
|
||||
int responseStatus,
|
||||
DateTime timeStamp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$HistoryMetaModelImplCopyWithImpl<$Res>
|
||||
extends _$HistoryMetaModelCopyWithImpl<$Res, _$HistoryMetaModelImpl>
|
||||
implements _$$HistoryMetaModelImplCopyWith<$Res> {
|
||||
__$$HistoryMetaModelImplCopyWithImpl(_$HistoryMetaModelImpl _value,
|
||||
$Res Function(_$HistoryMetaModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? historyId = null,
|
||||
Object? name = null,
|
||||
Object? url = null,
|
||||
Object? method = null,
|
||||
Object? responseStatus = null,
|
||||
Object? timeStamp = null,
|
||||
}) {
|
||||
return _then(_$HistoryMetaModelImpl(
|
||||
historyId: null == historyId
|
||||
? _value.historyId
|
||||
: historyId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
url: null == url
|
||||
? _value.url
|
||||
: url // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
method: null == method
|
||||
? _value.method
|
||||
: method // ignore: cast_nullable_to_non_nullable
|
||||
as HTTPVerb,
|
||||
responseStatus: null == responseStatus
|
||||
? _value.responseStatus
|
||||
: responseStatus // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
timeStamp: null == timeStamp
|
||||
? _value.timeStamp
|
||||
: timeStamp // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$HistoryMetaModelImpl implements _HistoryMetaModel {
|
||||
const _$HistoryMetaModelImpl(
|
||||
{required this.historyId,
|
||||
this.name = "",
|
||||
required this.url,
|
||||
required this.method,
|
||||
required this.responseStatus,
|
||||
required this.timeStamp});
|
||||
|
||||
factory _$HistoryMetaModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$HistoryMetaModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String historyId;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String name;
|
||||
@override
|
||||
final String url;
|
||||
@override
|
||||
final HTTPVerb method;
|
||||
@override
|
||||
final int responseStatus;
|
||||
@override
|
||||
final DateTime timeStamp;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HistoryMetaModel(historyId: $historyId, name: $name, url: $url, method: $method, responseStatus: $responseStatus, timeStamp: $timeStamp)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$HistoryMetaModelImpl &&
|
||||
(identical(other.historyId, historyId) ||
|
||||
other.historyId == historyId) &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.url, url) || other.url == url) &&
|
||||
(identical(other.method, method) || other.method == method) &&
|
||||
(identical(other.responseStatus, responseStatus) ||
|
||||
other.responseStatus == responseStatus) &&
|
||||
(identical(other.timeStamp, timeStamp) ||
|
||||
other.timeStamp == timeStamp));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, historyId, name, url, method, responseStatus, timeStamp);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$HistoryMetaModelImplCopyWith<_$HistoryMetaModelImpl> get copyWith =>
|
||||
__$$HistoryMetaModelImplCopyWithImpl<_$HistoryMetaModelImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$HistoryMetaModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _HistoryMetaModel implements HistoryMetaModel {
|
||||
const factory _HistoryMetaModel(
|
||||
{required final String historyId,
|
||||
final String name,
|
||||
required final String url,
|
||||
required final HTTPVerb method,
|
||||
required final int responseStatus,
|
||||
required final DateTime timeStamp}) = _$HistoryMetaModelImpl;
|
||||
|
||||
factory _HistoryMetaModel.fromJson(Map<String, dynamic> json) =
|
||||
_$HistoryMetaModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get historyId;
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
String get url;
|
||||
@override
|
||||
HTTPVerb get method;
|
||||
@override
|
||||
int get responseStatus;
|
||||
@override
|
||||
DateTime get timeStamp;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$HistoryMetaModelImplCopyWith<_$HistoryMetaModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
38
lib/models/history_meta_model.g.dart
Normal file
38
lib/models/history_meta_model.g.dart
Normal file
@ -0,0 +1,38 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'history_meta_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$HistoryMetaModelImpl _$$HistoryMetaModelImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$HistoryMetaModelImpl(
|
||||
historyId: json['historyId'] as String,
|
||||
name: json['name'] as String? ?? "",
|
||||
url: json['url'] as String,
|
||||
method: $enumDecode(_$HTTPVerbEnumMap, json['method']),
|
||||
responseStatus: (json['responseStatus'] as num).toInt(),
|
||||
timeStamp: DateTime.parse(json['timeStamp'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$HistoryMetaModelImplToJson(
|
||||
_$HistoryMetaModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'historyId': instance.historyId,
|
||||
'name': instance.name,
|
||||
'url': instance.url,
|
||||
'method': _$HTTPVerbEnumMap[instance.method]!,
|
||||
'responseStatus': instance.responseStatus,
|
||||
'timeStamp': instance.timeStamp.toIso8601String(),
|
||||
};
|
||||
|
||||
const _$HTTPVerbEnumMap = {
|
||||
HTTPVerb.get: 'get',
|
||||
HTTPVerb.head: 'head',
|
||||
HTTPVerb.post: 'post',
|
||||
HTTPVerb.put: 'put',
|
||||
HTTPVerb.patch: 'patch',
|
||||
HTTPVerb.delete: 'delete',
|
||||
};
|
23
lib/models/history_request_model.dart
Normal file
23
lib/models/history_request_model.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'models.dart';
|
||||
|
||||
part 'history_request_model.freezed.dart';
|
||||
|
||||
part 'history_request_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class HistoryRequestModel with _$HistoryRequestModel {
|
||||
@JsonSerializable(
|
||||
explicitToJson: true,
|
||||
anyMap: true,
|
||||
)
|
||||
const factory HistoryRequestModel({
|
||||
required String historyId,
|
||||
required HistoryMetaModel metaData,
|
||||
required HttpRequestModel httpRequestModel,
|
||||
required HttpResponseModel httpResponseModel,
|
||||
}) = _HistoryRequestModel;
|
||||
|
||||
factory HistoryRequestModel.fromJson(Map<String, Object?> json) =>
|
||||
_$HistoryRequestModelFromJson(json);
|
||||
}
|
258
lib/models/history_request_model.freezed.dart
Normal file
258
lib/models/history_request_model.freezed.dart
Normal file
@ -0,0 +1,258 @@
|
||||
// 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 'history_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(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#adding-getters-and-methods-to-our-models');
|
||||
|
||||
HistoryRequestModel _$HistoryRequestModelFromJson(Map<String, dynamic> json) {
|
||||
return _HistoryRequestModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HistoryRequestModel {
|
||||
String get historyId => throw _privateConstructorUsedError;
|
||||
HistoryMetaModel get metaData => throw _privateConstructorUsedError;
|
||||
HttpRequestModel get httpRequestModel => throw _privateConstructorUsedError;
|
||||
HttpResponseModel get httpResponseModel => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$HistoryRequestModelCopyWith<HistoryRequestModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HistoryRequestModelCopyWith<$Res> {
|
||||
factory $HistoryRequestModelCopyWith(
|
||||
HistoryRequestModel value, $Res Function(HistoryRequestModel) then) =
|
||||
_$HistoryRequestModelCopyWithImpl<$Res, HistoryRequestModel>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String historyId,
|
||||
HistoryMetaModel metaData,
|
||||
HttpRequestModel httpRequestModel,
|
||||
HttpResponseModel httpResponseModel});
|
||||
|
||||
$HistoryMetaModelCopyWith<$Res> get metaData;
|
||||
$HttpRequestModelCopyWith<$Res> get httpRequestModel;
|
||||
$HttpResponseModelCopyWith<$Res> get httpResponseModel;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HistoryRequestModelCopyWithImpl<$Res, $Val extends HistoryRequestModel>
|
||||
implements $HistoryRequestModelCopyWith<$Res> {
|
||||
_$HistoryRequestModelCopyWithImpl(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? historyId = null,
|
||||
Object? metaData = null,
|
||||
Object? httpRequestModel = null,
|
||||
Object? httpResponseModel = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
historyId: null == historyId
|
||||
? _value.historyId
|
||||
: historyId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
metaData: null == metaData
|
||||
? _value.metaData
|
||||
: metaData // ignore: cast_nullable_to_non_nullable
|
||||
as HistoryMetaModel,
|
||||
httpRequestModel: null == httpRequestModel
|
||||
? _value.httpRequestModel
|
||||
: httpRequestModel // ignore: cast_nullable_to_non_nullable
|
||||
as HttpRequestModel,
|
||||
httpResponseModel: null == httpResponseModel
|
||||
? _value.httpResponseModel
|
||||
: httpResponseModel // ignore: cast_nullable_to_non_nullable
|
||||
as HttpResponseModel,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$HistoryMetaModelCopyWith<$Res> get metaData {
|
||||
return $HistoryMetaModelCopyWith<$Res>(_value.metaData, (value) {
|
||||
return _then(_value.copyWith(metaData: value) as $Val);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$HttpRequestModelCopyWith<$Res> get httpRequestModel {
|
||||
return $HttpRequestModelCopyWith<$Res>(_value.httpRequestModel, (value) {
|
||||
return _then(_value.copyWith(httpRequestModel: value) as $Val);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$HttpResponseModelCopyWith<$Res> get httpResponseModel {
|
||||
return $HttpResponseModelCopyWith<$Res>(_value.httpResponseModel, (value) {
|
||||
return _then(_value.copyWith(httpResponseModel: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$HistoryRequestModelImplCopyWith<$Res>
|
||||
implements $HistoryRequestModelCopyWith<$Res> {
|
||||
factory _$$HistoryRequestModelImplCopyWith(_$HistoryRequestModelImpl value,
|
||||
$Res Function(_$HistoryRequestModelImpl) then) =
|
||||
__$$HistoryRequestModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String historyId,
|
||||
HistoryMetaModel metaData,
|
||||
HttpRequestModel httpRequestModel,
|
||||
HttpResponseModel httpResponseModel});
|
||||
|
||||
@override
|
||||
$HistoryMetaModelCopyWith<$Res> get metaData;
|
||||
@override
|
||||
$HttpRequestModelCopyWith<$Res> get httpRequestModel;
|
||||
@override
|
||||
$HttpResponseModelCopyWith<$Res> get httpResponseModel;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$HistoryRequestModelImplCopyWithImpl<$Res>
|
||||
extends _$HistoryRequestModelCopyWithImpl<$Res, _$HistoryRequestModelImpl>
|
||||
implements _$$HistoryRequestModelImplCopyWith<$Res> {
|
||||
__$$HistoryRequestModelImplCopyWithImpl(_$HistoryRequestModelImpl _value,
|
||||
$Res Function(_$HistoryRequestModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? historyId = null,
|
||||
Object? metaData = null,
|
||||
Object? httpRequestModel = null,
|
||||
Object? httpResponseModel = null,
|
||||
}) {
|
||||
return _then(_$HistoryRequestModelImpl(
|
||||
historyId: null == historyId
|
||||
? _value.historyId
|
||||
: historyId // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
metaData: null == metaData
|
||||
? _value.metaData
|
||||
: metaData // ignore: cast_nullable_to_non_nullable
|
||||
as HistoryMetaModel,
|
||||
httpRequestModel: null == httpRequestModel
|
||||
? _value.httpRequestModel
|
||||
: httpRequestModel // ignore: cast_nullable_to_non_nullable
|
||||
as HttpRequestModel,
|
||||
httpResponseModel: null == httpResponseModel
|
||||
? _value.httpResponseModel
|
||||
: httpResponseModel // ignore: cast_nullable_to_non_nullable
|
||||
as HttpResponseModel,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
@JsonSerializable(explicitToJson: true, anyMap: true)
|
||||
class _$HistoryRequestModelImpl implements _HistoryRequestModel {
|
||||
const _$HistoryRequestModelImpl(
|
||||
{required this.historyId,
|
||||
required this.metaData,
|
||||
required this.httpRequestModel,
|
||||
required this.httpResponseModel});
|
||||
|
||||
factory _$HistoryRequestModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$HistoryRequestModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String historyId;
|
||||
@override
|
||||
final HistoryMetaModel metaData;
|
||||
@override
|
||||
final HttpRequestModel httpRequestModel;
|
||||
@override
|
||||
final HttpResponseModel httpResponseModel;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HistoryRequestModel(historyId: $historyId, metaData: $metaData, httpRequestModel: $httpRequestModel, httpResponseModel: $httpResponseModel)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$HistoryRequestModelImpl &&
|
||||
(identical(other.historyId, historyId) ||
|
||||
other.historyId == historyId) &&
|
||||
(identical(other.metaData, metaData) ||
|
||||
other.metaData == metaData) &&
|
||||
(identical(other.httpRequestModel, httpRequestModel) ||
|
||||
other.httpRequestModel == httpRequestModel) &&
|
||||
(identical(other.httpResponseModel, httpResponseModel) ||
|
||||
other.httpResponseModel == httpResponseModel));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, historyId, metaData, httpRequestModel, httpResponseModel);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$HistoryRequestModelImplCopyWith<_$HistoryRequestModelImpl> get copyWith =>
|
||||
__$$HistoryRequestModelImplCopyWithImpl<_$HistoryRequestModelImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$HistoryRequestModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _HistoryRequestModel implements HistoryRequestModel {
|
||||
const factory _HistoryRequestModel(
|
||||
{required final String historyId,
|
||||
required final HistoryMetaModel metaData,
|
||||
required final HttpRequestModel httpRequestModel,
|
||||
required final HttpResponseModel httpResponseModel}) =
|
||||
_$HistoryRequestModelImpl;
|
||||
|
||||
factory _HistoryRequestModel.fromJson(Map<String, dynamic> json) =
|
||||
_$HistoryRequestModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get historyId;
|
||||
@override
|
||||
HistoryMetaModel get metaData;
|
||||
@override
|
||||
HttpRequestModel get httpRequestModel;
|
||||
@override
|
||||
HttpResponseModel get httpResponseModel;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$HistoryRequestModelImplCopyWith<_$HistoryRequestModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
27
lib/models/history_request_model.g.dart
Normal file
27
lib/models/history_request_model.g.dart
Normal file
@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'history_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$HistoryRequestModelImpl _$$HistoryRequestModelImplFromJson(Map json) =>
|
||||
_$HistoryRequestModelImpl(
|
||||
historyId: json['historyId'] as String,
|
||||
metaData: HistoryMetaModel.fromJson(
|
||||
Map<String, Object?>.from(json['metaData'] as Map)),
|
||||
httpRequestModel: HttpRequestModel.fromJson(
|
||||
Map<String, Object?>.from(json['httpRequestModel'] as Map)),
|
||||
httpResponseModel: HttpResponseModel.fromJson(
|
||||
Map<String, Object?>.from(json['httpResponseModel'] as Map)),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$HistoryRequestModelImplToJson(
|
||||
_$HistoryRequestModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'historyId': instance.historyId,
|
||||
'metaData': instance.metaData.toJson(),
|
||||
'httpRequestModel': instance.httpRequestModel.toJson(),
|
||||
'httpResponseModel': instance.httpResponseModel.toJson(),
|
||||
};
|
@ -1,5 +1,7 @@
|
||||
export 'environment_model.dart';
|
||||
export 'form_data_model.dart';
|
||||
export 'history_meta_model.dart';
|
||||
export 'history_request_model.dart';
|
||||
export 'http_request_model.dart';
|
||||
export 'http_response_model.dart';
|
||||
export 'name_value_model.dart';
|
||||
|
@ -240,12 +240,28 @@ class CollectionStateNotifier
|
||||
httpResponseModel: responseModel,
|
||||
isWorking: false,
|
||||
);
|
||||
String newHistoryId = getNewUuid();
|
||||
HistoryRequestModel model = HistoryRequestModel(
|
||||
historyId: newHistoryId,
|
||||
metaData: HistoryMetaModel(
|
||||
historyId: newHistoryId,
|
||||
name: requestModel.name,
|
||||
url: substitutedHttpRequestModel.url,
|
||||
method: substitutedHttpRequestModel.method,
|
||||
responseStatus: statusCode,
|
||||
timeStamp: DateTime.now(),
|
||||
),
|
||||
httpRequestModel: substitutedHttpRequestModel,
|
||||
httpResponseModel: responseModel,
|
||||
);
|
||||
ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
|
||||
}
|
||||
|
||||
// update state with response data
|
||||
map = {...state!};
|
||||
map[id] = newRequestModel;
|
||||
state = map;
|
||||
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
|
91
lib/providers/history_providers.dart
Normal file
91
lib/providers/history_providers.dart
Normal file
@ -0,0 +1,91 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
import '../services/services.dart' show hiveHandler, HiveHandler;
|
||||
import '../utils/history_utils.dart';
|
||||
|
||||
final selectedHistoryIdStateProvider = StateProvider<String?>((ref) => null);
|
||||
|
||||
final selectedRequestGroupStateProvider = StateProvider<String?>((ref) {
|
||||
final selectedHistoryId = ref.watch(selectedHistoryIdStateProvider);
|
||||
if (selectedHistoryId == null) {
|
||||
return null;
|
||||
}
|
||||
final historyMetaState = ref.read(historyMetaStateNotifier);
|
||||
return getHistoryRequestKey(historyMetaState![selectedHistoryId]!);
|
||||
});
|
||||
|
||||
final selectedHistoryRequestModelProvider =
|
||||
StateProvider<HistoryRequestModel?>((ref) => null);
|
||||
|
||||
final historySequenceProvider =
|
||||
StateProvider<Map<DateTime, List<HistoryMetaModel>>?>((ref) {
|
||||
final historyMetas = ref.watch(historyMetaStateNotifier);
|
||||
return getTemporalGroups(historyMetas?.values.toList());
|
||||
});
|
||||
|
||||
final StateNotifierProvider<HistoryMetaStateNotifier,
|
||||
Map<String, HistoryMetaModel>?> historyMetaStateNotifier =
|
||||
StateNotifierProvider((ref) => HistoryMetaStateNotifier(ref, hiveHandler));
|
||||
|
||||
class HistoryMetaStateNotifier
|
||||
extends StateNotifier<Map<String, HistoryMetaModel>?> {
|
||||
HistoryMetaStateNotifier(this.ref, this.hiveHandler) : super(null) {
|
||||
var status = loadHistoryMetas();
|
||||
Future.microtask(() {
|
||||
if (status) {
|
||||
final temporalGroups = getTemporalGroups(state?.values.toList());
|
||||
final latestRequestId = getLatestRequestId(temporalGroups);
|
||||
if (latestRequestId != null) {
|
||||
loadHistoryRequest(latestRequestId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final Ref ref;
|
||||
final HiveHandler hiveHandler;
|
||||
|
||||
bool loadHistoryMetas() {
|
||||
List<String>? historyIds = hiveHandler.getHistoryIds();
|
||||
if (historyIds == null || historyIds.isEmpty) {
|
||||
state = null;
|
||||
return false;
|
||||
} else {
|
||||
Map<String, HistoryMetaModel> historyMetaMap = {};
|
||||
for (var historyId in historyIds) {
|
||||
var jsonModel = hiveHandler.getHistoryMeta(historyId);
|
||||
if (jsonModel != null) {
|
||||
var jsonMap = Map<String, Object?>.from(jsonModel);
|
||||
var historyMetaModelFromJson = HistoryMetaModel.fromJson(jsonMap);
|
||||
historyMetaMap[historyId] = historyMetaModelFromJson;
|
||||
}
|
||||
}
|
||||
state = historyMetaMap;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> loadHistoryRequest(String id) async {
|
||||
var jsonModel = await hiveHandler.getHistoryRequest(id);
|
||||
if (jsonModel != null) {
|
||||
var jsonMap = Map<String, Object?>.from(jsonModel);
|
||||
var historyRequestModelFromJson = HistoryRequestModel.fromJson(jsonMap);
|
||||
ref.read(selectedHistoryRequestModelProvider.notifier).state =
|
||||
historyRequestModelFromJson;
|
||||
ref.read(selectedHistoryIdStateProvider.notifier).state = id;
|
||||
}
|
||||
}
|
||||
|
||||
void addHistoryRequest(HistoryRequestModel model) async {
|
||||
final id = model.historyId;
|
||||
state = {
|
||||
...state ?? {},
|
||||
id: model.metaData,
|
||||
};
|
||||
final List<String> updatedHistoryKeys =
|
||||
state == null ? [id] : [...state!.keys, id];
|
||||
hiveHandler.setHistoryIds(updatedHistoryKeys);
|
||||
hiveHandler.setHistoryMeta(id, model.metaData.toJson());
|
||||
await hiveHandler.setHistoryRequest(id, model.toJson());
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
export 'collection_providers.dart';
|
||||
export 'environment_providers.dart';
|
||||
export 'history_providers.dart';
|
||||
export 'settings_providers.dart';
|
||||
export 'ui_providers.dart';
|
||||
|
@ -1,29 +0,0 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
|
||||
showAboutAppDialog(
|
||||
BuildContext context,
|
||||
) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
contentPadding: kPt20 + kPh20,
|
||||
content: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
constraints: const BoxConstraints(maxWidth: 540, maxHeight: 544),
|
||||
child: const IntroMessage(),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text("Close"),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import 'package:apidash/screens/about_dialog.dart';
|
||||
import 'package:apidash/screens/history/history_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
@ -118,7 +118,9 @@ class Dashboard extends ConsumerWidget {
|
||||
EnvironmentPage(
|
||||
scaffoldKey: mobileScaffoldKey,
|
||||
),
|
||||
const SizedBox(),
|
||||
HistoryPage(
|
||||
scaffoldKey: mobileScaffoldKey,
|
||||
),
|
||||
const SettingsPage(),
|
||||
],
|
||||
),
|
||||
|
@ -19,7 +19,7 @@ class EnvironmentEditor extends ConsumerWidget {
|
||||
padding: context.isMediumWindow
|
||||
? kPb10
|
||||
: (kIsMacOS || kIsWindows)
|
||||
? kPt24o8
|
||||
? kPt28o8
|
||||
: kP8,
|
||||
child: Column(
|
||||
children: [
|
||||
@ -65,34 +65,40 @@ class EnvironmentEditor extends ConsumerWidget {
|
||||
kVSpacer5,
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: context.isMediumWindow ? null : kPv6,
|
||||
margin: context.isMediumWindow ? null : kP4,
|
||||
decoration: context.isMediumWindow
|
||||
? null
|
||||
: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.outlineVariant,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: kBorderRadius12,
|
||||
),
|
||||
child: const Column(
|
||||
children: [
|
||||
kHSpacer40,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
child: Card(
|
||||
margin: EdgeInsets.zero,
|
||||
color: kColorTransparent,
|
||||
surfaceTintColor: kColorTransparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color:
|
||||
Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
),
|
||||
borderRadius: kBorderRadius12,
|
||||
),
|
||||
elevation: 0,
|
||||
child: const Padding(
|
||||
padding: kPv6,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(width: 30),
|
||||
Text("Variable"),
|
||||
SizedBox(width: 30),
|
||||
Text("Value"),
|
||||
SizedBox(width: 40),
|
||||
kHSpacer40,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(width: 30),
|
||||
Text("Variable"),
|
||||
SizedBox(width: 30),
|
||||
Text("Value"),
|
||||
SizedBox(width: 40),
|
||||
],
|
||||
),
|
||||
kHSpacer40,
|
||||
Divider(),
|
||||
Expanded(child: EditEnvironmentVariables())
|
||||
],
|
||||
),
|
||||
kHSpacer40,
|
||||
Divider(),
|
||||
Expanded(child: EditEnvironmentVariables())
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
10
lib/screens/history/history_details.dart
Normal file
10
lib/screens/history/history_details.dart
Normal file
@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HistoryDetails extends StatelessWidget {
|
||||
const HistoryDetails({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
41
lib/screens/history/history_page.dart
Normal file
41
lib/screens/history/history_page.dart
Normal file
@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/extensions/extensions.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'history_pane.dart';
|
||||
import 'history_viewer.dart';
|
||||
|
||||
class HistoryPage extends ConsumerWidget {
|
||||
const HistoryPage({
|
||||
super.key,
|
||||
required this.scaffoldKey,
|
||||
});
|
||||
|
||||
final GlobalKey<ScaffoldState> scaffoldKey;
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final historyModel = ref.watch(selectedHistoryRequestModelProvider);
|
||||
if (context.isMediumWindow) {
|
||||
return DrawerSplitView(
|
||||
scaffoldKey: scaffoldKey,
|
||||
mainContent: const HistoryViewer(),
|
||||
title: Text(historyModel?.historyId ?? 'History'),
|
||||
leftDrawerContent: const HistoryPane(),
|
||||
actions: const [SizedBox(width: 16)],
|
||||
onDrawerChanged: (value) =>
|
||||
ref.read(leftDrawerStateProvider.notifier).state = value,
|
||||
);
|
||||
}
|
||||
return const Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DashboardSplitView(
|
||||
sidebarWidget: HistoryPane(),
|
||||
mainWidget: HistoryViewer(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
96
lib/screens/history/history_pane.dart
Normal file
96
lib/screens/history/history_pane.dart
Normal file
@ -0,0 +1,96 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:apidash/extensions/extensions.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/utils/utils.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class HistoryPane extends ConsumerWidget {
|
||||
const HistoryPane({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Padding(
|
||||
padding: (!context.isMediumWindow && kIsMacOS
|
||||
? kP24CollectionPane
|
||||
: kP8CollectionPane) +
|
||||
(context.isMediumWindow ? kPb70 : EdgeInsets.zero),
|
||||
child: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [kVSpacer10, Expanded(child: HistoryList()), kVSpacer5],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryList extends HookConsumerWidget {
|
||||
const HistoryList({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final historySequence = ref.watch(historySequenceProvider);
|
||||
final alwaysShowHistoryPaneScrollbar = ref.watch(settingsProvider
|
||||
.select((value) => value.alwaysShowCollectionPaneScrollbar));
|
||||
final List<DateTime>? sortedHistoryKeys = historySequence?.keys.toList();
|
||||
sortedHistoryKeys?.sort((a, b) => b.compareTo(a));
|
||||
ScrollController scrollController = useScrollController();
|
||||
return Scrollbar(
|
||||
controller: scrollController,
|
||||
thumbVisibility: alwaysShowHistoryPaneScrollbar,
|
||||
radius: const Radius.circular(12),
|
||||
child: ListView(
|
||||
padding: context.isMediumWindow
|
||||
? EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom,
|
||||
right: 8,
|
||||
)
|
||||
: kPe8,
|
||||
controller: scrollController,
|
||||
children: sortedHistoryKeys != null
|
||||
? sortedHistoryKeys.map((date) {
|
||||
var items = historySequence![date]!;
|
||||
final requestGroups = getRequestGroups(items);
|
||||
return Column(
|
||||
children: [
|
||||
ExpansionTile(
|
||||
title: Text(
|
||||
humanizeDate(date),
|
||||
),
|
||||
children: requestGroups.values.map((item) {
|
||||
return Padding(
|
||||
padding: kPv2 + kPh4,
|
||||
child: SidebarHistoryCard(
|
||||
id: item.first.historyId,
|
||||
models: item,
|
||||
method: item.first.method,
|
||||
selectedId:
|
||||
ref.watch(selectedRequestGroupStateProvider),
|
||||
requestGroupSize: item.length,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(historyMetaStateNotifier.notifier)
|
||||
.loadHistoryRequest(item.first.historyId);
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList()
|
||||
: [
|
||||
const Text(
|
||||
'No history',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
10
lib/screens/history/history_requests.dart
Normal file
10
lib/screens/history/history_requests.dart
Normal file
@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HistoryRequests extends StatelessWidget {
|
||||
const HistoryRequests({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
35
lib/screens/history/history_viewer.dart
Normal file
35
lib/screens/history/history_viewer.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:apidash/extensions/extensions.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'history_details.dart';
|
||||
import 'history_requests.dart';
|
||||
|
||||
class HistoryViewer extends StatelessWidget {
|
||||
const HistoryViewer({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (context.isMediumWindow) {
|
||||
return const HistoryDetails();
|
||||
}
|
||||
return Padding(
|
||||
padding: kIsMacOS || kIsWindows ? kPt28o8 : kP8,
|
||||
child: Card(
|
||||
color: kColorTransparent,
|
||||
surfaceTintColor: kColorTransparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
),
|
||||
borderRadius: kBorderRadius12,
|
||||
),
|
||||
elevation: 0,
|
||||
child: const HistorySplitView(
|
||||
sidebarWidget: HistoryRequests(),
|
||||
mainWidget: HistoryDetails(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ class RequestEditor extends StatelessWidget {
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: kIsMacOS || kIsWindows ? kPt24o8 : kP8,
|
||||
padding: kIsMacOS || kIsWindows ? kPt28o8 : kP8,
|
||||
child: const Column(
|
||||
children: [
|
||||
RequestEditorTopBar(),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:apidash/screens/history/history_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@ -39,7 +40,7 @@ class _MobileDashboardState extends ConsumerState<MobileDashboard> {
|
||||
),
|
||||
if (context.isMediumWindow)
|
||||
AnimatedPositioned(
|
||||
bottom: railIdx > 1
|
||||
bottom: railIdx > 2
|
||||
? 0
|
||||
: isLeftDrawerOpen
|
||||
? 0
|
||||
@ -72,17 +73,9 @@ class PageBranch extends ConsumerWidget {
|
||||
return EnvironmentPage(
|
||||
scaffoldKey: scaffoldKey,
|
||||
);
|
||||
// case 2:
|
||||
// // TODO: Implement history page
|
||||
// return const PageBase(
|
||||
// title: 'History',
|
||||
// scaffoldBody: SizedBox(),
|
||||
// );
|
||||
case 2:
|
||||
// TODO: Implement history page
|
||||
return const PageBase(
|
||||
title: 'History',
|
||||
scaffoldBody: SizedBox(),
|
||||
return HistoryPage(
|
||||
scaffoldKey: scaffoldKey,
|
||||
);
|
||||
case 3:
|
||||
return const PageBase(
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:apidash/screens/about_dialog.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../providers/providers.dart';
|
||||
|
@ -3,9 +3,14 @@ import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
const String kDataBox = "apidash-data";
|
||||
const String kKeyDataBoxIds = "ids";
|
||||
|
||||
const String kEnvironmentBox = "apidash-environments";
|
||||
const String kKeyEnvironmentBoxIds = "environmentIds";
|
||||
|
||||
const String kHistoryMetaBox = "apidash-history-meta";
|
||||
const String kHistoryBoxIds = "historyIds";
|
||||
const String kHistoryLazyBox = "apidash-history-lazy";
|
||||
|
||||
const String kSettingsBox = "apidash-settings";
|
||||
|
||||
Future<void> openBoxes() async {
|
||||
@ -13,6 +18,8 @@ Future<void> openBoxes() async {
|
||||
await Hive.openBox(kDataBox);
|
||||
await Hive.openBox(kSettingsBox);
|
||||
await Hive.openBox(kEnvironmentBox);
|
||||
await Hive.openBox(kHistoryMetaBox);
|
||||
await Hive.openLazyBox(kHistoryLazyBox);
|
||||
}
|
||||
|
||||
(Size?, Offset?) getInitialSize() {
|
||||
@ -38,11 +45,15 @@ class HiveHandler {
|
||||
late final Box dataBox;
|
||||
late final Box settingsBox;
|
||||
late final Box environmentBox;
|
||||
late final Box historyMetaBox;
|
||||
late final LazyBox historyLazyBox;
|
||||
|
||||
HiveHandler() {
|
||||
dataBox = Hive.box(kDataBox);
|
||||
settingsBox = Hive.box(kSettingsBox);
|
||||
environmentBox = Hive.box(kEnvironmentBox);
|
||||
historyMetaBox = Hive.box(kHistoryMetaBox);
|
||||
historyLazyBox = Hive.lazyBox(kHistoryLazyBox);
|
||||
}
|
||||
|
||||
Map get settings => settingsBox.toMap();
|
||||
@ -69,6 +80,25 @@ class HiveHandler {
|
||||
|
||||
Future<void> deleteEnvironment(String id) => environmentBox.delete(id);
|
||||
|
||||
dynamic getHistoryIds() => historyMetaBox.get(kHistoryBoxIds);
|
||||
Future<void> setHistoryIds(List<String>? ids) =>
|
||||
historyMetaBox.put(kHistoryBoxIds, ids);
|
||||
|
||||
dynamic getHistoryMeta(String id) => historyMetaBox.get(id);
|
||||
Future<void> setHistoryMeta(
|
||||
String id, Map<String, dynamic>? historyMetaJson) =>
|
||||
historyMetaBox.put(id, historyMetaJson);
|
||||
|
||||
Future<void> deleteHistoryMeta(String id) => historyMetaBox.delete(id);
|
||||
|
||||
Future<dynamic> getHistoryRequest(String id) async =>
|
||||
await historyLazyBox.get(id);
|
||||
Future<void> setHistoryRequest(
|
||||
String id, Map<String, dynamic>? historyRequestJsoon) =>
|
||||
historyLazyBox.put(id, historyRequestJsoon);
|
||||
|
||||
Future<void> deleteHistoryReqyest(String id) => historyLazyBox.delete(id);
|
||||
|
||||
Future clear() async {
|
||||
await dataBox.clear();
|
||||
await environmentBox.clear();
|
||||
|
@ -1,10 +1,18 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../models/models.dart';
|
||||
import '../consts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
String humanizeDate(DateTime? date) {
|
||||
if (date == null) {
|
||||
return "";
|
||||
}
|
||||
return DateFormat('MMMM d, yyyy').format(date);
|
||||
}
|
||||
|
||||
String humanizeDuration(Duration? duration) {
|
||||
if (duration == null) {
|
||||
return "";
|
||||
|
86
lib/utils/history_utils.dart
Normal file
86
lib/utils/history_utils.dart
Normal file
@ -0,0 +1,86 @@
|
||||
import 'package:apidash/models/models.dart';
|
||||
import 'package:apidash/utils/convert_utils.dart';
|
||||
|
||||
DateTime stripTime(DateTime dateTime) {
|
||||
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||
}
|
||||
|
||||
String getHistoryRequestName(HistoryMetaModel model) {
|
||||
if (model.name.isNotEmpty) {
|
||||
return model.name;
|
||||
} else {
|
||||
return model.url;
|
||||
}
|
||||
}
|
||||
|
||||
String getHistoryRequestKey(HistoryMetaModel model) {
|
||||
String timeStamp = humanizeDate(model.timeStamp);
|
||||
if (model.name.isNotEmpty) {
|
||||
return model.name + model.method.name + timeStamp;
|
||||
} else {
|
||||
return model.url + model.method.name + timeStamp;
|
||||
}
|
||||
}
|
||||
|
||||
String? getLatestRequestId(
|
||||
Map<DateTime, List<HistoryMetaModel>> temporalGroups) {
|
||||
if (temporalGroups.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
List<DateTime> keys = temporalGroups.keys.toList();
|
||||
keys.sort((a, b) => b.compareTo(a));
|
||||
return temporalGroups[keys.first]!.first.historyId;
|
||||
}
|
||||
|
||||
DateTime getDateTimeKey(List<DateTime> keys, DateTime currentKey) {
|
||||
if (keys.isEmpty) return currentKey;
|
||||
for (DateTime key in keys) {
|
||||
if (key.year == currentKey.year &&
|
||||
key.month == currentKey.month &&
|
||||
key.day == currentKey.day) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return stripTime(currentKey);
|
||||
}
|
||||
|
||||
Map<DateTime, List<HistoryMetaModel>> getTemporalGroups(
|
||||
List<HistoryMetaModel>? models) {
|
||||
Map<DateTime, List<HistoryMetaModel>> temporalGroups = {};
|
||||
if (models?.isEmpty ?? true) {
|
||||
return temporalGroups;
|
||||
}
|
||||
for (HistoryMetaModel model in models!) {
|
||||
List<DateTime> existingKeys = temporalGroups.keys.toList();
|
||||
DateTime key = getDateTimeKey(existingKeys, model.timeStamp);
|
||||
if (existingKeys.contains(key)) {
|
||||
temporalGroups[key]!.add(model);
|
||||
} else {
|
||||
temporalGroups[stripTime(key)] = [model];
|
||||
}
|
||||
}
|
||||
temporalGroups.forEach((key, value) {
|
||||
value.sort((a, b) => b.timeStamp.compareTo(a.timeStamp));
|
||||
});
|
||||
return temporalGroups;
|
||||
}
|
||||
|
||||
Map<String, List<HistoryMetaModel>> getRequestGroups(
|
||||
List<HistoryMetaModel>? models) {
|
||||
Map<String, List<HistoryMetaModel>> historyGroups = {};
|
||||
if (models?.isEmpty ?? true) {
|
||||
return historyGroups;
|
||||
}
|
||||
for (HistoryMetaModel model in models!) {
|
||||
String key = getHistoryRequestKey(model);
|
||||
if (historyGroups.containsKey(key)) {
|
||||
historyGroups[key]!.add(model);
|
||||
} else {
|
||||
historyGroups[key] = [model];
|
||||
}
|
||||
}
|
||||
historyGroups.forEach((key, value) {
|
||||
value.sort((a, b) => b.timeStamp.compareTo(a.timeStamp));
|
||||
});
|
||||
return historyGroups;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
export 'ui_utils.dart';
|
||||
export 'convert_utils.dart';
|
||||
export 'header_utils.dart';
|
||||
export 'history_utils.dart';
|
||||
export 'http_utils.dart';
|
||||
export 'file_utils.dart';
|
||||
export 'window_utils.dart';
|
||||
|
110
lib/widgets/card_sidebar_history.dart
Normal file
110
lib/widgets/card_sidebar_history.dart
Normal file
@ -0,0 +1,110 @@
|
||||
import 'package:apidash/models/history_meta_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/utils/utils.dart';
|
||||
import 'texts.dart' show MethodBox;
|
||||
|
||||
class SidebarHistoryCard extends StatelessWidget {
|
||||
const SidebarHistoryCard({
|
||||
super.key,
|
||||
required this.id,
|
||||
required this.models,
|
||||
required this.method,
|
||||
this.selectedId,
|
||||
this.requestGroupSize = 1,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final List<HistoryMetaModel> models;
|
||||
final HTTPVerb method;
|
||||
final String? selectedId;
|
||||
final int requestGroupSize;
|
||||
final Function()? onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Color color = Theme.of(context).colorScheme.surface;
|
||||
final Color colorVariant =
|
||||
Theme.of(context).colorScheme.surfaceContainerHighest.withOpacity(0.5);
|
||||
final model = models.first;
|
||||
final Color surfaceTint = Theme.of(context).colorScheme.primary;
|
||||
bool isSelected = selectedId == getHistoryRequestKey(model);
|
||||
final String name = getHistoryRequestName(model);
|
||||
return Tooltip(
|
||||
message: name,
|
||||
triggerMode: TooltipTriggerMode.manual,
|
||||
waitDuration: const Duration(seconds: 1),
|
||||
child: Card(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: kBorderRadius8,
|
||||
),
|
||||
elevation: isSelected ? 1 : 0,
|
||||
surfaceTintColor: isSelected ? surfaceTint : null,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.brightness == Brightness.dark
|
||||
? colorVariant
|
||||
: color
|
||||
: color,
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: kBorderRadius8,
|
||||
hoverColor: colorVariant,
|
||||
focusColor: colorVariant.withOpacity(0.5),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 6,
|
||||
right: 6,
|
||||
top: 5,
|
||||
bottom: 5,
|
||||
),
|
||||
child: SizedBox(
|
||||
height: 20,
|
||||
child: Row(
|
||||
children: [
|
||||
MethodBox(method: method),
|
||||
kHSpacer4,
|
||||
Expanded(
|
||||
child: Text(
|
||||
name,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
),
|
||||
),
|
||||
requestGroupSize > 1 ? kHSpacer4 : const SizedBox.shrink(),
|
||||
Visibility(
|
||||
visible: requestGroupSize > 1,
|
||||
child: Container(
|
||||
padding: kPh4,
|
||||
constraints: const BoxConstraints(minWidth: 24),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
borderRadius: kBorderRadius6,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
requestGroupSize == 2
|
||||
? requestGroupSize.toString()
|
||||
: "9+",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall
|
||||
?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onPrimaryContainer,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
65
lib/widgets/splitview_history.dart
Normal file
65
lib/widgets/splitview_history.dart
Normal file
@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:multi_split_view/multi_split_view.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class HistorySplitView extends StatefulWidget {
|
||||
const HistorySplitView({
|
||||
super.key,
|
||||
required this.sidebarWidget,
|
||||
required this.mainWidget,
|
||||
});
|
||||
|
||||
final Widget sidebarWidget;
|
||||
final Widget mainWidget;
|
||||
|
||||
@override
|
||||
HistorySplitViewState createState() => HistorySplitViewState();
|
||||
}
|
||||
|
||||
class HistorySplitViewState extends State<HistorySplitView> {
|
||||
final MultiSplitViewController _controller = MultiSplitViewController(
|
||||
areas: [
|
||||
Area(id: "sidebar", min: 200, size: 220, max: 300),
|
||||
Area(id: "main"),
|
||||
],
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiSplitViewTheme(
|
||||
data: MultiSplitViewThemeData(
|
||||
dividerThickness: 3,
|
||||
dividerPainter: DividerPainters.background(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
highlightedColor: Theme.of(context).colorScheme.outline.withOpacity(
|
||||
kHintOpacity,
|
||||
),
|
||||
animationEnabled: false,
|
||||
),
|
||||
),
|
||||
child: MultiSplitView(
|
||||
controller: _controller,
|
||||
sizeOverflowPolicy: SizeOverflowPolicy.shrinkFirst,
|
||||
sizeUnderflowPolicy: SizeUnderflowPolicy.stretchLast,
|
||||
builder: (context, area) {
|
||||
return switch (area.id) {
|
||||
"sidebar" => widget.sidebarWidget,
|
||||
"main" => widget.mainWidget,
|
||||
_ => Container(),
|
||||
};
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ export 'button_save_download.dart';
|
||||
export 'button_send.dart';
|
||||
export 'card_request_details.dart';
|
||||
export 'card_sidebar_environment.dart';
|
||||
export 'card_sidebar_history.dart';
|
||||
export 'card_sidebar_request.dart';
|
||||
export 'checkbox.dart';
|
||||
export 'code_previewer.dart';
|
||||
@ -42,6 +43,7 @@ export 'snackbars.dart';
|
||||
export 'splitview_drawer.dart';
|
||||
export 'splitview_dashboard.dart';
|
||||
export 'splitview_equal.dart';
|
||||
export 'splitview_history.dart';
|
||||
export 'suggestions_menu.dart';
|
||||
export 'tables.dart';
|
||||
export 'tabs.dart';
|
||||
|
@ -648,6 +648,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.0"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -38,7 +38,7 @@ dependencies:
|
||||
just_audio_mpv: ^0.1.7
|
||||
just_audio_windows: ^0.2.0
|
||||
freezed_annotation: ^2.4.1
|
||||
json_annotation: ^4.8.1
|
||||
json_annotation: ^4.9.0
|
||||
printing: ^5.12.0
|
||||
package_info_plus: ^8.0.0
|
||||
flutter_typeahead: ^5.2.0
|
||||
@ -64,6 +64,7 @@ dependencies:
|
||||
flutter_hooks: ^0.20.5
|
||||
flutter_portal: ^1.1.4
|
||||
mention_tag_text_field: ^0.0.5
|
||||
intl: ^0.19.0
|
||||
|
||||
dependency_overrides:
|
||||
web: ^0.5.0
|
||||
|
Reference in New Issue
Block a user