| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- import 'dart:convert';
- import 'dart:io';
- import 'dart:typed_data';
- import 'package:dio/dio.dart';
- import 'package:flutter/cupertino.dart';
- import 'package:flutter_easyloading/flutter_easyloading.dart';
- import 'package:flutter_styled_toast/flutter_styled_toast.dart';
- import 'package:path_provider/path_provider.dart';
- import 'package:permission_handler/permission_handler.dart';
- import 'package:prime_chat/basic/Api.dart';
- import 'package:shared_preferences/shared_preferences.dart';
- import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
- import 'Entities.dart';
- import 'Global.dart';
- class Handler {
- Handler(this.name) : value = prefs.getString(name) ?? "";
- final String name;
- late String value;
- Future<bool> set(String value) async {
- this.value = value;
- return prefs.setString(name, value);
- }
- }
- final method = Method._();
- class Method {
- Method._();
- Future init() async {
- _token = Handler("token");
- _name = Handler("name");
- _password = Handler("password");
- _uid = Handler("uid");
- return await preLogin();
- }
- late Handler _token;
- late Handler _name;
- late Handler _password;
- late Handler _uid;
- get dio => token.isEmpty
- ? Dio()
- : Dio(BaseOptions(
- headers: {HttpHeaders.authorizationHeader: "Bearer $token"}));
- get token => _token.value;
- set token(value) => _token.set(value);
- get name => _name.value;
- set name(value) => _name.set(value);
- get password => _password.value;
- set password(value) => _password.set(value);
- get uid => _uid.value;
- set uid(value) => _uid.set(value);
- get user => types.User(id: uid);
- Future _handleDioError(DioError e, {int retry = 0}) async {
- final res = e.response;
- final req = e.requestOptions;
- final data = jsonDecode(res.toString());
- final code = res == null ? -1 : res.statusCode;
- debugPrint("api error, path=${req.path} code=$code error=${data['error']}");
- switch (code) {
- case HttpStatus.unauthorized:
- if (await login()) {
- final res = await request(req.path,
- data: req.data,
- queryParameters: req.queryParameters,
- options: Options(method: req.method),
- retry: retry);
- return res;
- }
- break;
- }
- }
- Future<Response?> request(String path,
- {data,
- Map<String, dynamic>? queryParameters,
- Options? options,
- int retry = 0}) async {
- if (retry < 0) return null;
- try {
- final res = await dio.request(
- path,
- data: data,
- queryParameters: queryParameters,
- options: options,
- );
- return res;
- } on DioError catch (e) {
- final ret = await _handleDioError(e, retry: retry);
- if (ret is Response) {
- return ret;
- }
- }
- return null;
- }
- Future<bool> get authorized async {
- final res = await request("$server/home", options: Options(method: "get"));
- if (res?.statusCode == HttpStatus.ok) {
- debugPrint("token=$token authorized");
- final data = jsonDecode(res.toString());
- debugPrint("authorized: ${data.toString()}");
- uid = data["uid"].toString();
- return true;
- }
- return false;
- }
- Future<bool> login() async {
- final name = _name.value, password = _password.value;
- debugPrint('login: name=$name password=$password');
- if (name.isEmpty || password.isEmpty) return false;
- final res = await request("$server/token",
- data: {"name": name, "password": password},
- options: Options(method: "post"));
- if (res?.statusCode == HttpStatus.ok) {
- final data = jsonDecode(res.toString());
- token = data['token'];
- debugPrint('login ok, token=$token');
- // Todo: 修改uid的更新方式为:login时获取profile
- return authorized;
- }
- return false;
- }
- logout() {
- token = "";
- password = "";
- }
- Future<bool> preLogin() async {
- if (await authorized) return true;
- return login();
- }
- Future<List<Profile>?> getFriends() async {
- final res =
- await request('$server/friends', options: Options(method: "get"));
- if (res?.statusCode == HttpStatus.ok) {
- var data = jsonDecode(res.toString());
- List<Profile> friends = [];
- data["friends"].forEach((v) => friends.add(Profile.fromJson(v)));
- // debugPrint(friends.toString());
- return friends;
- }
- return null;
- }
- Future<Profile?> getProfile({String? name}) async {
- name = name ?? _name.value;
- debugPrint("get profile of $name");
- final res =
- await request("$server/profile/$name", options: Options(method: "get"));
- if (res?.statusCode == HttpStatus.ok) {
- final data = jsonDecode(res.toString());
- final profile = Profile.fromJson(data["profile"]);
- debugPrint("profile get, name=${profile.name}");
- return profile;
- }
- return null;
- }
- Future download(
- String url,
- String savePath, {
- Map<String, dynamic>? queryParams,
- CancelToken? cancelToken,
- dynamic data,
- Options? options,
- void Function(int, int)? onReceiveProgress,
- }) async {
- try {
- return await dio.download(
- url,
- savePath,
- queryParameters: queryParams,
- cancelToken: cancelToken,
- onReceiveProgress: onReceiveProgress,
- );
- } on DioError catch (e) {
- print(e);
- if (CancelToken.isCancel(e)) {
- EasyLoading.showInfo('下载已取消!');
- } else {
- if (e.response != null) {
- // _handleErrorResponse(e.response);
- } else {
- EasyLoading.showError(e.message);
- }
- }
- } on Exception catch (e) {
- // EasyLoading.showError(e.toString());
- }
- }
- Future<String?> downloadImage(String path, String fileServer) async {
- Directory dir = await getApplicationDocumentsDirectory();
- String dirPath = dir.path;
- final savePath = "$dirPath/$path";
- File file = File(savePath);
- debugPrint("savePath=$savePath");
- if (file.existsSync()) return savePath;
- try {
- final res = await dio.download('$fileServer/$path', savePath);
- debugPrint(res.toString());
- } on Exception catch (e) {
- debugPrint("文件下载失败");
- return null;
- }
- return savePath;
- }
- Future<bool> updateAvatar(Uint8List buff, String suf) async {
- final file = MultipartFile.fromBytes(buff, filename: 'avatar$suf');
- final res =
- await request("$server/avatar", data: FormData.fromMap({"file": file}));
- return res?.statusCode == HttpStatus.ok;
- }
- Future<List<types.Message>?> getMessages(String roomId) async {
- final res = await request("$server/messages/$roomId", options: Options(method: "get"));
- if (res?.statusCode != HttpStatus.ok) return null;
- final data = jsonDecode(res.toString());
- List<types.Message> messages = [];
- debugPrint(data.toString());
- for (var msg in data["messages"]) {
- messages.add(types.TextMessage(
- author: types.User(id: msg["authorId"].toString()),
- id: msg["id"],
- text: msg["content"],
- createdAt: msg["createdAt"]*1000 ?? 0
- ));
- }
- messages.sort((a, b) => b.createdAt!.compareTo(a.createdAt!));
- debugPrint(messages.toString());
- return messages;
- }
- Future<bool> sendMessage(
- String roomId, types.MessageType type, String content,
- {int receiverId = 0}) async {
- final res = await request("$server/message", data: {
- "roomId": roomId,
- "type": type.name,
- "content": content,
- "receiverId": receiverId
- }, options: Options(method: "post"));
- return res?.statusCode == HttpStatus.ok;
- }
- String directRoomId(String id) {
- String a = uid, b = id;
- final res = a.compareTo(b);
- switch (res) {
- case 0: throw Exception("id equals to current user's id");
- case 1: return "direct:$b,$a";
- case -1: return "direct:$a,$b";
- }
- return "";
- }
- }
|