diff --git a/lib/grpc/dm.dart b/lib/grpc/dm.dart index 102e8b9dc..16499a62e 100644 --- a/lib/grpc/dm.dart +++ b/lib/grpc/dm.dart @@ -8,8 +8,8 @@ class DmGrpc { required int cid, required int segmentIndex, int type = 1, - }) async { - final res = await GrpcRepo.request( + }) { + return GrpcRepo.request( GrpcUrl.dmSegMobile, DmSegMobileReq( oid: Int64(cid), @@ -18,10 +18,5 @@ class DmGrpc { ), DmSegMobileReply.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return const Error(''); - } } } diff --git a/lib/grpc/dyn.dart b/lib/grpc/dyn.dart index 4ed6e3166..4dde19c5d 100644 --- a/lib/grpc/dyn.dart +++ b/lib/grpc/dyn.dart @@ -18,12 +18,12 @@ class DynGrpc { // ); // } - static Future dynRed() { - return GrpcRepo.request( + static Future dynRed() async { + final res = await GrpcRepo.request( GrpcUrl.dynRed, DynRedReq(tabOffset: [TabOffset(tab: 1)]), DynRedReply.fromBuffer, - onSuccess: (response) => response.dynRedItem.count.toInt(), ); + return res.dataOrNull?.dynRedItem.count.toInt(); } } diff --git a/lib/grpc/google/rpc/status.pb.dart b/lib/grpc/google/rpc/status.pb.dart new file mode 100644 index 000000000..0d7376ed4 --- /dev/null +++ b/lib/grpc/google/rpc/status.pb.dart @@ -0,0 +1,232 @@ +// +// Generated code. Do not modify. +// source: status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'status.pbenum.dart'; + +export 'status.pbenum.dart'; + +class BiliStatus extends $pb.GeneratedMessage { + factory BiliStatus({ + $core.int? code, + $core.String? message, + }) { + final $result = create(); + if (code != null) { + $result.code = code; + } + if (message != null) { + $result.message = message; + } + return $result; + } + BiliStatus._() : super(); + factory BiliStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BiliStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BiliStatus', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create) + ..a<$core.int>(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.O3) + ..aOS(2, _omitFieldNames ? '' : 'message') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + BiliStatus clone() => BiliStatus()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + BiliStatus copyWith(void Function(BiliStatus) updates) => super.copyWith((message) => updates(message as BiliStatus)) as BiliStatus; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static BiliStatus create() => BiliStatus._(); + BiliStatus createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static BiliStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static BiliStatus? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get code => $_getIZ(0); + @$pb.TagNumber(1) + set code($core.int v) { $_setSignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasCode() => $_has(0); + @$pb.TagNumber(1) + void clearCode() => clearField(1); + + @$pb.TagNumber(2) + $core.String get message => $_getSZ(1); + @$pb.TagNumber(2) + set message($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasMessage() => $_has(1); + @$pb.TagNumber(2) + void clearMessage() => clearField(2); +} + +class GrpcDetail extends $pb.GeneratedMessage { + factory GrpcDetail({ + $core.String? grpcType, + BiliStatus? status, + }) { + final $result = create(); + if (grpcType != null) { + $result.grpcType = grpcType; + } + if (status != null) { + $result.status = status; + } + return $result; + } + GrpcDetail._() : super(); + factory GrpcDetail.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GrpcDetail.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GrpcDetail', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'grpcType') + ..aOM(2, _omitFieldNames ? '' : 'status', subBuilder: BiliStatus.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + GrpcDetail clone() => GrpcDetail()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GrpcDetail copyWith(void Function(GrpcDetail) updates) => super.copyWith((message) => updates(message as GrpcDetail)) as GrpcDetail; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static GrpcDetail create() => GrpcDetail._(); + GrpcDetail createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static GrpcDetail getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GrpcDetail? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get grpcType => $_getSZ(0); + @$pb.TagNumber(1) + set grpcType($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasGrpcType() => $_has(0); + @$pb.TagNumber(1) + void clearGrpcType() => clearField(1); + + @$pb.TagNumber(2) + BiliStatus get status => $_getN(1); + @$pb.TagNumber(2) + set status(BiliStatus v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasStatus() => $_has(1); + @$pb.TagNumber(2) + void clearStatus() => clearField(2); + @$pb.TagNumber(2) + BiliStatus ensureStatus() => $_ensure(1); +} + +class Status extends $pb.GeneratedMessage { + factory Status({ + Code? code, + $core.String? message, + $core.Iterable? details, + }) { + final $result = create(); + if (code != null) { + $result.code = code; + } + if (message != null) { + $result.message = message; + } + if (details != null) { + $result.details.addAll(details); + } + return $result; + } + Status._() : super(); + factory Status.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Status.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Status', package: const $pb.PackageName(_omitMessageNames ? '' : 'google.rpc'), createEmptyInstance: create) + ..e(1, _omitFieldNames ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: Code.OK, valueOf: Code.valueOf, enumValues: Code.values) + ..aOS(2, _omitFieldNames ? '' : 'message') + ..pc(3, _omitFieldNames ? '' : 'details', $pb.PbFieldType.PM, subBuilder: GrpcDetail.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + Status clone() => Status()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + Status copyWith(void Function(Status) updates) => super.copyWith((message) => updates(message as Status)) as Status; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Status create() => Status._(); + Status createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static Status getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Status? _defaultInstance; + + /// The status code, which should be an enum value of + /// [google.rpc.Code][google.rpc.Code]. + @$pb.TagNumber(1) + Code get code => $_getN(0); + @$pb.TagNumber(1) + set code(Code v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasCode() => $_has(0); + @$pb.TagNumber(1) + void clearCode() => clearField(1); + + /// A developer-facing error message, which should be in English. Any + /// user-facing error message should be localized and sent in the + /// [google.rpc.Status.details][google.rpc.Status.details] field, or localized + /// by the client. + @$pb.TagNumber(2) + $core.String get message => $_getSZ(1); + @$pb.TagNumber(2) + set message($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasMessage() => $_has(1); + @$pb.TagNumber(2) + void clearMessage() => clearField(2); + + /// A list of messages that carry the error details. There is a common set of + /// message types for APIs to use. + @$pb.TagNumber(3) + $core.List get details => $_getList(2); +} + + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/lib/grpc/google/rpc/status.pbenum.dart b/lib/grpc/google/rpc/status.pbenum.dart new file mode 100644 index 000000000..ca64f1204 --- /dev/null +++ b/lib/grpc/google/rpc/status.pbenum.dart @@ -0,0 +1,62 @@ +// +// Generated code. Do not modify. +// source: status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class Code extends $pb.ProtobufEnum { + static const Code OK = Code._(0, _omitEnumNames ? '' : 'OK'); + static const Code CANCELLED = Code._(1, _omitEnumNames ? '' : 'CANCELLED'); + static const Code UNKNOWN = Code._(2, _omitEnumNames ? '' : 'UNKNOWN'); + static const Code INVALID_ARGUMENT = Code._(3, _omitEnumNames ? '' : 'INVALID_ARGUMENT'); + static const Code DEADLINE_EXCEEDED = Code._(4, _omitEnumNames ? '' : 'DEADLINE_EXCEEDED'); + static const Code NOT_FOUND = Code._(5, _omitEnumNames ? '' : 'NOT_FOUND'); + static const Code ALREADY_EXISTS = Code._(6, _omitEnumNames ? '' : 'ALREADY_EXISTS'); + static const Code PERMISSION_DENIED = Code._(7, _omitEnumNames ? '' : 'PERMISSION_DENIED'); + static const Code UNAUTHENTICATED = Code._(16, _omitEnumNames ? '' : 'UNAUTHENTICATED'); + static const Code RESOURCE_EXHAUSTED = Code._(8, _omitEnumNames ? '' : 'RESOURCE_EXHAUSTED'); + static const Code FAILED_PRECONDITION = Code._(9, _omitEnumNames ? '' : 'FAILED_PRECONDITION'); + static const Code ABORTED = Code._(10, _omitEnumNames ? '' : 'ABORTED'); + static const Code OUT_OF_RANGE = Code._(11, _omitEnumNames ? '' : 'OUT_OF_RANGE'); + static const Code UNIMPLEMENTED = Code._(12, _omitEnumNames ? '' : 'UNIMPLEMENTED'); + static const Code INTERNAL = Code._(13, _omitEnumNames ? '' : 'INTERNAL'); + static const Code UNAVAILABLE = Code._(14, _omitEnumNames ? '' : 'UNAVAILABLE'); + static const Code DATA_LOSS = Code._(15, _omitEnumNames ? '' : 'DATA_LOSS'); + + static const $core.List values = [ + OK, + CANCELLED, + UNKNOWN, + INVALID_ARGUMENT, + DEADLINE_EXCEEDED, + NOT_FOUND, + ALREADY_EXISTS, + PERMISSION_DENIED, + UNAUTHENTICATED, + RESOURCE_EXHAUSTED, + FAILED_PRECONDITION, + ABORTED, + OUT_OF_RANGE, + UNIMPLEMENTED, + INTERNAL, + UNAVAILABLE, + DATA_LOSS, + ]; + + static final $core.Map<$core.int, Code> _byValue = $pb.ProtobufEnum.initByValue(values); + static Code? valueOf($core.int value) => _byValue[value]; + + const Code._($core.int v, $core.String n) : super(v, n); +} + + +const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/lib/grpc/google/rpc/status.pbjson.dart b/lib/grpc/google/rpc/status.pbjson.dart new file mode 100644 index 000000000..c4e90f4db --- /dev/null +++ b/lib/grpc/google/rpc/status.pbjson.dart @@ -0,0 +1,92 @@ +// +// Generated code. Do not modify. +// source: status.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use codeDescriptor instead') +const Code$json = { + '1': 'Code', + '2': [ + {'1': 'OK', '2': 0}, + {'1': 'CANCELLED', '2': 1}, + {'1': 'UNKNOWN', '2': 2}, + {'1': 'INVALID_ARGUMENT', '2': 3}, + {'1': 'DEADLINE_EXCEEDED', '2': 4}, + {'1': 'NOT_FOUND', '2': 5}, + {'1': 'ALREADY_EXISTS', '2': 6}, + {'1': 'PERMISSION_DENIED', '2': 7}, + {'1': 'UNAUTHENTICATED', '2': 16}, + {'1': 'RESOURCE_EXHAUSTED', '2': 8}, + {'1': 'FAILED_PRECONDITION', '2': 9}, + {'1': 'ABORTED', '2': 10}, + {'1': 'OUT_OF_RANGE', '2': 11}, + {'1': 'UNIMPLEMENTED', '2': 12}, + {'1': 'INTERNAL', '2': 13}, + {'1': 'UNAVAILABLE', '2': 14}, + {'1': 'DATA_LOSS', '2': 15}, + ], +}; + +/// Descriptor for `Code`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List codeDescriptor = $convert.base64Decode( + 'CgRDb2RlEgYKAk9LEAASDQoJQ0FOQ0VMTEVEEAESCwoHVU5LTk9XThACEhQKEElOVkFMSURfQV' + 'JHVU1FTlQQAxIVChFERUFETElORV9FWENFRURFRBAEEg0KCU5PVF9GT1VORBAFEhIKDkFMUkVB' + 'RFlfRVhJU1RTEAYSFQoRUEVSTUlTU0lPTl9ERU5JRUQQBxITCg9VTkFVVEhFTlRJQ0FURUQQEB' + 'IWChJSRVNPVVJDRV9FWEhBVVNURUQQCBIXChNGQUlMRURfUFJFQ09ORElUSU9OEAkSCwoHQUJP' + 'UlRFRBAKEhAKDE9VVF9PRl9SQU5HRRALEhEKDVVOSU1QTEVNRU5URUQQDBIMCghJTlRFUk5BTB' + 'ANEg8KC1VOQVZBSUxBQkxFEA4SDQoJREFUQV9MT1NTEA8='); + +@$core.Deprecated('Use biliStatusDescriptor instead') +const BiliStatus$json = { + '1': 'BiliStatus', + '2': [ + {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, + {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, + ], +}; + +/// Descriptor for `BiliStatus`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List biliStatusDescriptor = $convert.base64Decode( + 'CgpCaWxpU3RhdHVzEhIKBGNvZGUYASABKAVSBGNvZGUSGAoHbWVzc2FnZRgCIAEoCVIHbWVzc2' + 'FnZQ=='); + +@$core.Deprecated('Use grpcDetailDescriptor instead') +const GrpcDetail$json = { + '1': 'GrpcDetail', + '2': [ + {'1': 'grpc_type', '3': 1, '4': 1, '5': 9, '10': 'grpcType'}, + {'1': 'status', '3': 2, '4': 1, '5': 11, '6': '.google.rpc.BiliStatus', '10': 'status'}, + ], +}; + +/// Descriptor for `GrpcDetail`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List grpcDetailDescriptor = $convert.base64Decode( + 'CgpHcnBjRGV0YWlsEhsKCWdycGNfdHlwZRgBIAEoCVIIZ3JwY1R5cGUSLgoGc3RhdHVzGAIgAS' + 'gLMhYuZ29vZ2xlLnJwYy5CaWxpU3RhdHVzUgZzdGF0dXM='); + +@$core.Deprecated('Use statusDescriptor instead') +const Status$json = { + '1': 'Status', + '2': [ + {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.google.rpc.Code', '10': 'code'}, + {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, + {'1': 'details', '3': 3, '4': 3, '5': 11, '6': '.google.rpc.GrpcDetail', '10': 'details'}, + ], +}; + +/// Descriptor for `Status`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List statusDescriptor = $convert.base64Decode( + 'CgZTdGF0dXMSJAoEY29kZRgBIAEoDjIQLmdvb2dsZS5ycGMuQ29kZVIEY29kZRIYCgdtZXNzYW' + 'dlGAIgASgJUgdtZXNzYWdlEjAKB2RldGFpbHMYAyADKAsyFi5nb29nbGUucnBjLkdycGNEZXRh' + 'aWxSB2RldGFpbHM='); + diff --git a/lib/grpc/grpc_repo.dart b/lib/grpc/grpc_repo.dart index 5ac801d1b..e3b8f430b 100644 --- a/lib/grpc/grpc_repo.dart +++ b/lib/grpc/grpc_repo.dart @@ -8,8 +8,10 @@ import 'package:PiliPlus/grpc/bilibili/metadata/fawkes.pb.dart'; import 'package:PiliPlus/grpc/bilibili/metadata/locale.pb.dart'; import 'package:PiliPlus/grpc/bilibili/metadata/network.pb.dart' as network; import 'package:PiliPlus/grpc/bilibili/metadata/restriction.pb.dart'; +import 'package:PiliPlus/grpc/google/rpc/status.pb.dart'; import 'package:PiliPlus/http/constants.dart'; import 'package:PiliPlus/http/init.dart'; +import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/utils/login_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -152,7 +154,7 @@ class GrpcRepo { 'x-bili-exps-bin': '', }; - static final unprintableRegExp = RegExp(r"[^\u4e00-\u9fa5,。;!?UP]"); + static final _unprintableRegExp = RegExp(r"[^\u4e00-\u9fa5,。;!?UP]"); static Uint8List compressProtobuf(Uint8List proto) { proto = const GZipEncoder().encodeBytes(proto); @@ -173,15 +175,14 @@ class GrpcRepo { } } - static Future> request( - url, GeneratedMessage request, Function grpcParser, - {Function? onSuccess}) async { + static Future> request(String url, + GeneratedMessage request, T Function(Uint8List) grpcParser) async { final response = await Request().post(HttpString.appBaseUrl + url, data: compressProtobuf(request.writeToBuffer()), options: Options(headers: headers, responseType: ResponseType.bytes)); if (response.data is Map) { - return {'status': false, 'msg': response.data['message']}; + return LoadingState.error(response.data['message']); } if (response.headers.value('Grpc-Status') == '0') { @@ -189,27 +190,32 @@ class GrpcRepo { Uint8List data = response.data; data = decompressProtobuf(data); final grpcResponse = grpcParser(data); - return { - 'status': true, - 'data': onSuccess == null ? grpcResponse : onSuccess(grpcResponse), - }; + return LoadingState.success(grpcResponse); } catch (e) { - return {'status': false, 'msg': e.toString()}; + return LoadingState.error(e.toString()); } } else { try { String msg = response.headers.value('Grpc-Status-Details-Bin') ?? ''; - if (msg != '') { + if (msg.isNotEmpty) { while (msg.length % 4 != 0) { msg += '='; } - msg = utf8 - .decode(base64Decode(msg), allowMalformed: true) - .replaceAll(unprintableRegExp, ''); + final msgBytes = base64Decode(msg); + try { + final grpcMsg = Status.fromBuffer(msgBytes); + // UNKNOWN : -400 : msg + msg = + '${grpcMsg.code} : ${grpcMsg.message} : ${grpcMsg.details.firstOrNull?.status.message}'; + } catch (e) { + msg = utf8 + .decode(msgBytes, allowMalformed: true) + .replaceAll(_unprintableRegExp, ''); + } } - return {'status': false, 'msg': msg}; + return LoadingState.error(msg); } catch (e) { - return {'status': false, 'msg': e.toString()}; + return LoadingState.error(e.toString()); } } } diff --git a/lib/grpc/im.dart b/lib/grpc/im.dart index 021b18e84..aadb77266 100644 --- a/lib/grpc/im.dart +++ b/lib/grpc/im.dart @@ -8,13 +8,12 @@ import 'package:protobuf/protobuf.dart' show PbMap; import 'package:uuid/uuid.dart'; class ImGrpc { - static Future sendMsg({ + static Future> sendMsg({ required int senderUid, required int receiverId, required String content, MsgType msgType = MsgType.EN_MSG_TYPE_TEXT, }) { - final devId = const Uuid().v4(); return GrpcRepo.request( GrpcUrl.sendMsg, ReqSendMsg( @@ -28,13 +27,13 @@ class ImGrpc { msgStatus: 0, newFaceVersion: 1, ), - devId: devId, + devId: const Uuid().v4(), ), RspSendMsg.fromBuffer, ); } - static Future shareList({int size = 10}) { + static Future> shareList({int size = 10}) { return GrpcRepo.request( GrpcUrl.shareList, ReqShareList(size: size), @@ -42,28 +41,22 @@ class ImGrpc { ); } - static Future> sessionMain({ - PbMap? offset, - }) async { - final res = await GrpcRepo.request( + static Future> sessionMain( + {PbMap? offset}) { + return GrpcRepo.request( GrpcUrl.sessionMain, SessionMainReq( paginationParams: PaginationParams(offsets: offset), ), SessionMainReply.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return LoadingState.error(res['msg']); - } } static Future> sessionSecondary({ PbMap? offset, SessionPageType? pageType, - }) async { - final res = await GrpcRepo.request( + }) { + return GrpcRepo.request( GrpcUrl.sessionSecondary, SessionSecondaryReq( paginationParams: PaginationParams(offsets: offset), @@ -71,14 +64,9 @@ class ImGrpc { ), SessionSecondaryReply.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return LoadingState.error(res['msg']); - } } - static Future clearUnread({ + static Future> clearUnread({ SessionPageType? pageType, SessionId? sessionId, }) { @@ -92,7 +80,7 @@ class ImGrpc { ); } - static Future sessionUpdate({ + static Future> sessionUpdate({ SessionPageType? pageType, SessionId? sessionId, }) { @@ -106,7 +94,7 @@ class ImGrpc { ); } - static Future pinSession({ + static Future> pinSession({ SessionId? sessionId, Int64? topTimeMicros, }) { @@ -120,7 +108,7 @@ class ImGrpc { ); } - static Future unpinSession({ + static Future> unpinSession({ SessionId? sessionId, }) { return GrpcRepo.request( @@ -132,7 +120,7 @@ class ImGrpc { ); } - static Future deleteSessionList({ + static Future> deleteSessionList({ SessionPageType? pageType, }) { return GrpcRepo.request( @@ -145,22 +133,18 @@ class ImGrpc { } static Future> getImSettings( - {IMSettingType? type}) async { - var res = await GrpcRepo.request( + {IMSettingType? type}) { + return GrpcRepo.request( GrpcUrl.getImSettings, GetImSettingsReq( type: type, ), GetImSettingsReply.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return LoadingState.error(res['msg']); - } } - static Future setImSettings({PbMap? settings}) { + static Future> setImSettings( + {PbMap? settings}) { return GrpcRepo.request( GrpcUrl.setImSettings, SetImSettingsReq( @@ -170,21 +154,16 @@ class ImGrpc { ); } - static Future> - keywordBlockingList() async { - var res = await GrpcRepo.request( + static Future> keywordBlockingList() { + return GrpcRepo.request( GrpcUrl.keywordBlockingList, KeywordBlockingListReq(), KeywordBlockingListReply.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return LoadingState.error(res['msg']); - } } - static Future keywordBlockingAdd(String keyword) { + static Future> keywordBlockingAdd( + String keyword) { return GrpcRepo.request( GrpcUrl.keywordBlockingAdd, KeywordBlockingAddReq(keyword: keyword), @@ -192,7 +171,8 @@ class ImGrpc { ); } - static Future keywordBlockingDelete(String keyword) { + static Future> keywordBlockingDelete( + String keyword) { return GrpcRepo.request( GrpcUrl.keywordBlockingDelete, KeywordBlockingDeleteReq(keyword: keyword), diff --git a/lib/grpc/reply.dart b/lib/grpc/reply.dart index c87be3ca5..bfa1df7b8 100644 --- a/lib/grpc/reply.dart +++ b/lib/grpc/reply.dart @@ -17,18 +17,21 @@ class ReplyGrpc { // } // ref BiliRoamingX - static bool needRemoveGrpc(ReplyInfo reply) { - if ((reply.content.urls.isNotEmpty && + static bool needRemoveGoodGrpc(ReplyInfo reply) { + return (reply.content.urls.isNotEmpty && reply.content.urls.values.any((url) { return url.hasExtra() && - (url.extra.goodsCmControl == 1 || - url.extra.goodsItemId != 0 || + (url.extra.goodsCmControl == Int64.ONE || + url.extra.goodsItemId != Int64.ZERO || url.extra.goodsPrefetchedCache.isNotEmpty); })) || - reply.content.message.contains(Constants.goodsUrlPrefix)) { - return true; - } - return false; + reply.content.message.contains(Constants.goodsUrlPrefix); + } + + static bool needRemoveGrpc(ReplyInfo reply, final bool antiGoodsReply) { + return (ReplyHttp.replyRegExp.pattern.isNotEmpty && + ReplyHttp.replyRegExp.hasMatch(reply.content.message)) || + (antiGoodsReply && needRemoveGoodGrpc(reply)); } static Future> mainList({ @@ -37,14 +40,14 @@ class ReplyGrpc { required Mode mode, required String? offset, required Int64? cursorNext, - required bool antiGoodsReply, + required final bool antiGoodsReply, }) async { - dynamic res = await GrpcRepo.request( + final res = await GrpcRepo.request( GrpcUrl.mainList, MainListReq( oid: Int64(oid), type: Int64(type), - rpid: Int64(0), + rpid: Int64.ZERO, cursor: CursorReq( mode: mode, next: cursorNext, @@ -53,59 +56,25 @@ class ReplyGrpc { ), MainListReply.fromBuffer, ); - if (res['status']) { - MainListReply mainListReply = res['data']; + if (res.isSuccess) { + final mainListReply = res.data; // keyword filter - if (ReplyHttp.replyRegExp.pattern.isNotEmpty) { - // upTop - if (mainListReply.hasUpTop() && - ReplyHttp.replyRegExp - .hasMatch(mainListReply.upTop.content.message)) { - mainListReply.clearUpTop(); - } - - // replies - if (mainListReply.replies.isNotEmpty) { - mainListReply.replies.removeWhere((item) { - bool hasMatch = - ReplyHttp.replyRegExp.hasMatch(item.content.message); - // remove subreplies - if (!hasMatch) { - if (item.replies.isNotEmpty) { - item.replies.removeWhere((item) => - ReplyHttp.replyRegExp.hasMatch(item.content.message)); - } - } - return hasMatch; - }); - } + if (mainListReply.hasUpTop() && + needRemoveGrpc(mainListReply.upTop, antiGoodsReply)) { + mainListReply.clearUpTop(); } - // antiGoodsReply - if (antiGoodsReply) { - // upTop - if (mainListReply.hasUpTop() && needRemoveGrpc(mainListReply.upTop)) { - mainListReply.clearUpTop(); - } - - // replies - if (mainListReply.replies.isNotEmpty) { - mainListReply.replies.removeWhere((item) { - bool hasMatch = needRemoveGrpc(item); - // remove subreplies - if (!hasMatch) { - if (item.replies.isNotEmpty) { - item.replies.removeWhere(needRemoveGrpc); - } - } - return hasMatch; - }); - } + if (mainListReply.replies.isNotEmpty) { + mainListReply.replies.removeWhere((item) { + final hasMatch = needRemoveGrpc(item, antiGoodsReply); + if (!hasMatch && item.replies.isNotEmpty) { + item.replies.removeWhere((i) => needRemoveGrpc(i, antiGoodsReply)); + } + return hasMatch; + }); } - return LoadingState.success(mainListReply); - } else { - return LoadingState.error(res['msg']); } + return res; } static Future> detailList({ @@ -115,9 +84,9 @@ class ReplyGrpc { required int rpid, required Mode mode, required String? offset, - required bool antiGoodsReply, + required final bool antiGoodsReply, }) async { - dynamic res = await GrpcRepo.request( + final res = await GrpcRepo.request( GrpcUrl.detailList, DetailListReq( oid: Int64(oid), @@ -130,23 +99,11 @@ class ReplyGrpc { ), DetailListReply.fromBuffer, ); - if (res['status']) { - DetailListReply detailListReply = res['data']; - if (ReplyHttp.replyRegExp.pattern.isNotEmpty) { - if (detailListReply.root.replies.isNotEmpty) { - detailListReply.root.replies.removeWhere( - (item) => ReplyHttp.replyRegExp.hasMatch(item.content.message)); - } - } - if (antiGoodsReply) { - if (detailListReply.root.replies.isNotEmpty) { - detailListReply.root.replies.removeWhere(needRemoveGrpc); - } - } - return LoadingState.success(detailListReply); - } else { - return LoadingState.error(res['msg']); - } + return res + ..dataOrNull + ?.root + .replies + .removeWhere((item) => needRemoveGrpc(item, antiGoodsReply)); } static Future> dialogList({ @@ -155,9 +112,9 @@ class ReplyGrpc { required int root, required int dialog, required String? offset, - required bool antiGoodsReply, + required final bool antiGoodsReply, }) async { - dynamic res = await GrpcRepo.request( + final res = await GrpcRepo.request( GrpcUrl.dialogList, DialogListReq( oid: Int64(oid), @@ -168,22 +125,9 @@ class ReplyGrpc { ), DialogListReply.fromBuffer, ); - if (res['status']) { - DialogListReply dialogListReply = res['data']; - if (ReplyHttp.replyRegExp.pattern.isNotEmpty) { - if (dialogListReply.replies.isNotEmpty) { - dialogListReply.replies.removeWhere( - (item) => ReplyHttp.replyRegExp.hasMatch(item.content.message)); - } - } - if (antiGoodsReply) { - if (dialogListReply.replies.isNotEmpty) { - dialogListReply.replies.removeWhere(needRemoveGrpc); - } - } - return LoadingState.success(dialogListReply); - } else { - return LoadingState.error(res['msg']); - } + return res + ..dataOrNull + ?.replies + .removeWhere((item) => needRemoveGrpc(item, antiGoodsReply)); } } diff --git a/lib/grpc/space.dart b/lib/grpc/space.dart index 5b1b87f7b..58b3102a3 100644 --- a/lib/grpc/space.dart +++ b/lib/grpc/space.dart @@ -9,8 +9,8 @@ class SpaceGrpc { required int hostMid, String? next, required String filterType, - }) async { - final res = await GrpcRepo.request( + }) { + return GrpcRepo.request( GrpcUrl.opusSpaceFlow, OpusSpaceFlowReq( hostMid: Int64(hostMid), @@ -22,10 +22,5 @@ class SpaceGrpc { ), OpusSpaceFlowResp.fromBuffer, ); - if (res['status']) { - return LoadingState.success(res['data']); - } else { - return LoadingState.error(res['msg']); - } } } diff --git a/lib/http/init.dart b/lib/http/init.dart index 7558a6079..b0f0f8e37 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -187,73 +187,75 @@ class Request { /* * get请求 */ - Future get(url, - {queryParameters, options, cancelToken, extra}) async { - Response response; - if (extra != null) { - if (extra['ua'] != null) { - options ??= Options(); - options.headers ??= {}; - options.headers!['user-agent'] = headerUa(type: extra['ua']); - } + Future get( + String url, { + Map? queryParameters, + Options? options, + CancelToken? cancelToken, + String? uaType, + }) async { + if (uaType != null) { + options ??= Options(); + options.headers ??= {}; + options.headers!['user-agent'] = headerUa(type: uaType); } try { - response = await dio.get( + return await dio.get( url, queryParameters: queryParameters, options: options, cancelToken: cancelToken, ); - return response; } on DioException catch (e) { - Response errResponse = Response( + return Response( data: { 'message': await AccountManager.dioError(e) }, // 将自定义 Map 数据赋值给 Response 的 data 属性 statusCode: e.response?.statusCode ?? -1, - requestOptions: RequestOptions(), + requestOptions: e.requestOptions, ); - return errResponse; } } /* * post请求 */ - Future post(url, - {data, queryParameters, options, cancelToken}) async { + Future post( + String url, { + Object? data, + Map? queryParameters, + Options? options, + CancelToken? cancelToken, + }) async { // debugPrint('post-data: $data'); - Response response; try { - response = await dio.post( + return await dio.post( url, data: data, queryParameters: queryParameters, options: options, cancelToken: cancelToken, ); - // debugPrint('post success: ${response.data}'); - return response; } on DioException catch (e) { AccountManager.toast(e); - Response errResponse = Response( + return Response( data: { 'message': await AccountManager.dioError(e) }, // 将自定义 Map 数据赋值给 Response 的 data 属性 statusCode: e.response?.statusCode ?? -1, - requestOptions: RequestOptions(), + requestOptions: e.requestOptions, ); - return errResponse; } } /* * 下载文件 */ - Future downloadFile(urlPath, savePath, {cancelToken}) async { + Future downloadFile(String urlPath, String savePath, + {CancelToken? cancelToken}) async { try { - Response response = await dio.download( + final response = await dio.download( urlPath, savePath, cancelToken: cancelToken, @@ -271,7 +273,7 @@ class Request { 'message': await AccountManager.dioError(e), }, statusCode: e.response?.statusCode ?? -1, - requestOptions: RequestOptions(), + requestOptions: e.requestOptions, ); } } @@ -286,7 +288,7 @@ class Request { token.cancel("cancelled"); } - static String headerUa({type = 'mob'}) { + static String headerUa({String type = 'mob'}) { return switch (type) { 'mob' => 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36', diff --git a/lib/http/loading_state.dart b/lib/http/loading_state.dart index c19e92e89..f81fdb6fe 100644 --- a/lib/http/loading_state.dart +++ b/lib/http/loading_state.dart @@ -1,5 +1,7 @@ import 'dart:core' hide Error; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; + sealed class LoadingState { const LoadingState(); @@ -11,14 +13,15 @@ sealed class LoadingState { T get data => switch (this) { Success(response: final res) => res, - Error() => throw this, - Loading() => throw Exception('ApiException: loading'), + _ => throw this, }; T? get dataOrNull => switch (this) { Success(response: final res) => res, _ => null, }; + + void toast() => SmartDialog.showToast(toString()); } class Loading extends LoadingState { @@ -27,6 +30,11 @@ class Loading extends LoadingState { static const Loading _instance = Loading._internal(); factory Loading() => _instance; + + @override + String toString() { + return 'ApiException: loading'; + } } class Success extends LoadingState { diff --git a/lib/http/member.dart b/lib/http/member.dart index 4c660fcaa..00c96998a 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -266,7 +266,7 @@ class MemberHttp { }) async { String dmImgStr = Utils.base64EncodeRandomString(16, 64); String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128); - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'mid': mid, 'token': token, 'platform': 'web', @@ -332,7 +332,7 @@ class MemberHttp { }) async { String dmImgStr = Utils.base64EncodeRandomString(16, 64); String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128); - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'mid': mid, 'ps': ps, 'tid': tid, @@ -383,7 +383,7 @@ class MemberHttp { }) async { String dmImgStr = Utils.base64EncodeRandomString(16, 64); String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128); - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'mid': mid, 'ps': ps, 'tid': tid, @@ -426,7 +426,7 @@ class MemberHttp { }) async { String dmImgStr = Utils.base64EncodeRandomString(16, 64); String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128); - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'offset': offset ?? '', 'host_mid': mid, 'timezone_offset': '-480', diff --git a/lib/http/msg.dart b/lib/http/msg.dart index 5b8e56246..dac6d340e 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -457,7 +457,7 @@ class MsgHttp { beginSeqno, endSeqno, }) async { - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'talker_id': talkerId, 'session_type': 1, 'size': 20, @@ -486,7 +486,7 @@ class MsgHttp { int? ackSeqno, }) async { String csrf = Accounts.main.csrf; - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'talker_id': talkerId, 'session_type': 1, 'ack_seqno': ackSeqno, diff --git a/lib/http/video.dart b/lib/http/video.dart index 4f91e394d..8fabe9007 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -182,7 +182,7 @@ class VideoHttp { dynamic seasonId, bool? forcePgcApi, }) async { - Map data = { + final params = await WbiSign.makSign({ if (avid != null) 'avid': avid, if (bvid != null) 'bvid': bvid, if (epid != null) 'ep_id': epid, @@ -197,15 +197,11 @@ class VideoHttp { 'gaia_source': 'pre-load', 'isGaiaAvoided': true, 'web_location': 1315873, - }; - - // 免登录查看1080p - if (!Accounts.get(AccountType.video).isLogin && - GStorage.setting.get(SettingBoxKey.p1080, defaultValue: true)) { - data['try_look'] = 1; - } - - Map params = await WbiSign.makSign(data); + // 免登录查看1080p + if (!Accounts.get(AccountType.video).isLogin && + GStorage.setting.get(SettingBoxKey.p1080, defaultValue: true)) + 'try_look': 1, + }); late final usePgcApi = forcePgcApi == true || Accounts.get(AccountType.video).isLogin; @@ -880,7 +876,7 @@ class VideoHttp { int? cid, int? upMid, }) async { - Map params = await WbiSign.makSign({ + final params = await WbiSign.makSign({ 'bvid': bvid, 'cid': cid, 'up_mid': upMid, diff --git a/lib/pages/common/common_whisper_controller.dart b/lib/pages/common/common_whisper_controller.dart index 4e64be964..6d8f805b6 100644 --- a/lib/pages/common/common_whisper_controller.dart +++ b/lib/pages/common/common_whisper_controller.dart @@ -26,7 +26,7 @@ abstract class CommonWhisperController ? await ImGrpc.unpinSession(sessionId: sessionId) : await ImGrpc.pinSession(sessionId: sessionId); - if (res['status']) { + if (res.isSuccess) { List list = loadingState.value.data!; list[index].isPinned = isTop ? false : true; if (!isTop) { @@ -35,14 +35,14 @@ abstract class CommonWhisperController loadingState.refresh(); SmartDialog.showToast('${isTop ? '移除' : ''}置顶成功'); } else { - SmartDialog.showToast(res['msg']); + res.toast(); } } Future onClearUnread() async { final res = await ImGrpc.clearUnread(pageType: sessionPageType); - if (res['status']) { - if (loadingState.value is Success) { + if (res.isSuccess) { + if (loadingState.value.isSuccess) { List? list = loadingState.value.data; if (list?.isNotEmpty == true) { for (var item in list!) { @@ -55,16 +55,16 @@ abstract class CommonWhisperController } SmartDialog.showToast('已标记为已读'); } else { - SmartDialog.showToast(res['msg']); + res.toast(); } } Future onDeleteList() async { var res = await ImGrpc.deleteSessionList(pageType: sessionPageType); - if (res['status']) { + if (res.isSuccess) { loadingState.value = LoadingState.success(null); } else { - SmartDialog.showToast(res['msg']); + res.toast(); } } } diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index ed40753ed..013e40e7a 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -176,8 +176,8 @@ class MainController extends GetxController { return; } DynGrpc.dynRed().then((res) { - if (res['status']) { - setCount(res['data']); + if (res != null) { + setCount(res); } }); } diff --git a/lib/pages/whisper_block/controller.dart b/lib/pages/whisper_block/controller.dart index 9a82554af..8942cc1f7 100644 --- a/lib/pages/whisper_block/controller.dart +++ b/lib/pages/whisper_block/controller.dart @@ -30,8 +30,8 @@ class WhisperBlockController extends CommonListController< ImGrpc.keywordBlockingList(); Future onAdd(String keyword) async { - var res = await ImGrpc.keywordBlockingAdd(keyword); - if (res['status']) { + final res = await ImGrpc.keywordBlockingAdd(keyword); + if (res.isSuccess) { Get.back(); loadingState ..value.data!.add(KeywordBlockingItem(keyword: keyword)) @@ -39,20 +39,20 @@ class WhisperBlockController extends CommonListController< count.value += 1; SmartDialog.showToast('添加成功'); } else { - SmartDialog.showToast(res['msg']); + res.toast(); } } Future onRemove(KeywordBlockingItem item) async { - var res = await ImGrpc.keywordBlockingDelete(item.keyword); - if (res['status']) { + final res = await ImGrpc.keywordBlockingDelete(item.keyword); + if (res.isSuccess) { loadingState ..value.data!.remove(item) ..refresh(); count.value -= 1; SmartDialog.showToast('删除成功'); } else { - SmartDialog.showToast(res['msg']); + res.toast(); } } } diff --git a/lib/pages/whisper_settings/controller.dart b/lib/pages/whisper_settings/controller.dart index 3a66f15a8..ef5766ea5 100644 --- a/lib/pages/whisper_settings/controller.dart +++ b/lib/pages/whisper_settings/controller.dart @@ -3,7 +3,6 @@ import 'package:PiliPlus/grpc/bilibili/app/im/v1.pb.dart' import 'package:PiliPlus/grpc/im.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/pages/common/common_data_controller.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:protobuf/protobuf.dart' show PbMap; @@ -36,10 +35,10 @@ class WhisperSettingsController ImGrpc.getImSettings(type: imSettingType); Future onSet(PbMap settings) async { - var res = await ImGrpc.setImSettings(settings: settings); - if (!res['status']) { - SmartDialog.showToast('err: ${res['msg']}'); + final res = await ImGrpc.setImSettings(settings: settings); + if (!res.isSuccess) { + res.toast(); } - return res['status']; + return res.isSuccess; } } diff --git a/lib/utils/page_utils.dart b/lib/utils/page_utils.dart index 6761ff477..668bcb563 100644 --- a/lib/utils/page_utils.dart +++ b/lib/utils/page_utils.dart @@ -37,9 +37,8 @@ class PageUtils { List userList = []; final shareListRes = await ImGrpc.shareList(size: 3); - if (shareListRes['status'] && shareListRes['data'].sessionList.isNotEmpty) { - userList.addAll(shareListRes['data'] - .sessionList + if (shareListRes.isSuccess && shareListRes.data.sessionList.isNotEmpty) { + userList.addAll(shareListRes.data.sessionList .map((item) => UserModel( mid: item.talkerId.toInt(), name: item.talkerUname, diff --git a/lib/utils/request_utils.dart b/lib/utils/request_utils.dart index 2c7d6da3c..365b927cf 100644 --- a/lib/utils/request_utils.dart +++ b/lib/utils/request_utils.dart @@ -62,7 +62,7 @@ class RequestUtils { : MsgType.EN_MSG_TYPE_SHARE_V2, ); - if (contentRes['status']) { + if (contentRes.isSuccess) { if (message?.isNotEmpty == true) { var msgRes = await MsgHttp.sendMsg( senderUid: ownerMid, @@ -81,7 +81,7 @@ class RequestUtils { SmartDialog.showToast('分享成功'); } } else { - SmartDialog.showToast('分享失败: ${contentRes['msg']}'); + SmartDialog.showToast('分享失败: ${(contentRes as Error).errMsg}'); } SmartDialog.dismiss(); } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 78dfaac8f..2bf8f9310 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -500,8 +500,8 @@ class Utils { if (BuildConfig.isDebug) return; SmartDialog.dismiss(); try { - dynamic res = await Request().get(Api.latestApp, extra: {'ua': 'mob'}); - if (res.data.isEmpty) { + final res = await Request().get(Api.latestApp, uaType: 'mob'); + if (res.data is Map || res.data.isEmpty) { if (isAuto.not) { SmartDialog.showToast('检查更新失败,GitHub接口未返回数据,请检查网络'); }