import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:loris/business_logic/account/account.dart'; import 'package:loris/business_logic/timeline/media.dart'; import '../../global.dart' as global; class TimelinePartModel { late List threads; late int minId; late int maxId; } enum Visibility { public, unlisted, private, direct } class PostModel implements Comparable { late String id; late String? reblogId; late String createdAt; late String uri; late String content; late Visibility visibility; late bool sensitive; late String spoilerText; late bool favourited; late bool reblogged; late AccountModel account; late AccountModel? rebloggedBy; late List attachments; PostModel.fromJson(Map json) { id = json["id"] as String; reblogId = null; createdAt = json["created_at"]; if (json["reblog"] != null) { rebloggedBy = AccountModel.fromJson(json["account"]); json = json["reblog"]; reblogId = json["id"]; } else { rebloggedBy = null; } uri = json["uri"] as String; content = json["content"] as String; visibility = Visibility.values.firstWhere( // ignore: prefer_interpolation_to_compose_strings (element) => element.toString() == "Visibility." + json["visibility"]); sensitive = json["sensitive"] as bool; spoilerText = json["spoiler_text"] as String; favourited = json["favourited"] as bool; reblogged = json["reblogged"] as bool; account = AccountModel.fromJson(json["account"]); attachments = []; List jsonAttachmentList = json["media_attachments"]; for (int i = 0; i < jsonAttachmentList.length; i++) { attachments.add(MediaAttachmentModel.fromJson(jsonAttachmentList[i])); } } @override int compareTo(dynamic b) { return id.compareTo(b.id); } Future getThread() async { final activeId = global.settings!.activeIdentity; if (global.settings!.identities[activeId] == null) { return ThreadModel([this]); } final token = global.settings!.identities[activeId]!.token; final baseUrl = global.settings!.identities[activeId]!.instanceUrl; Map headers = {"Authorization": "Bearer $token"}; headers.addAll(global.defaultHeaders); String currentId = reblogId ?? id; final url = Uri( scheme: "https", host: baseUrl, path: "/api/v1/statuses/$currentId/context", ); http.Response response = await http.get(url, headers: headers); if (response.statusCode != 200 || response.body.isEmpty) { return ThreadModel([this]); } final json = jsonDecode(response.body); final List ancestorsJson = json["ancestors"]; List posts = [this]; int i = 0; while (i < ancestorsJson.length) { posts.add(PostModel.fromJson(ancestorsJson[i])); i++; } return ThreadModel(posts); } } class ThreadModel { late List posts; ThreadModel(List allPosts) { allPosts.sort(); posts = allPosts; } } Future> getTimelineFromServer(String? index) async { final activeId = global.settings!.activeIdentity; if (global.settings!.identities[activeId] == null) { return []; } final limit = global.settings?.batchSize; final token = global.settings?.identities[activeId]?.token; Map query = {"limit": limit.toString()}; if (index != null) { query.addAll({"max_id": index}); } final baseUrl = global.settings!.identities[activeId]!.instanceUrl; final url = Uri( scheme: "https", host: baseUrl, path: "/api/v1/timelines/home", queryParameters: query, ); Map headers = {"Authorization": "Bearer $token"}; headers.addAll(global.defaultHeaders); http.Response response = await http.get(url, headers: headers); while (response.statusCode != 200) { await Future.delayed(const Duration(seconds: 5)); response = await http.get(url, headers: headers); } final List json = await jsonDecode(response.body); List threads = []; for (int i = 0; i < json.length; i++) { threads.add(await PostModel.fromJson(json[i]).getThread()); } return threads; }