Compare commits
9 Commits
d4fbdd397e
...
2.2.1+42
Author | SHA1 | Date | |
---|---|---|---|
96fd64d85d | |||
e236b7f98b | |||
5c7929e618 | |||
7ba5260246 | |||
a6d4947a23 | |||
7fbd4e9647 | |||
95d926b29f | |||
f6cf6d0440 | |||
e503c3f02f |
@ -458,6 +458,7 @@
|
|||||||
"accountJoinedAt": "Joined at {}",
|
"accountJoinedAt": "Joined at {}",
|
||||||
"accountBirthday": "Born on {}",
|
"accountBirthday": "Born on {}",
|
||||||
"accountBadge": "Badge",
|
"accountBadge": "Badge",
|
||||||
|
"accountCheckInNoRecords": "No check-in records",
|
||||||
"badgeCompanyStaff": "Solsynth Staff",
|
"badgeCompanyStaff": "Solsynth Staff",
|
||||||
"badgeSiteMigration": "Solar Network Native",
|
"badgeSiteMigration": "Solar Network Native",
|
||||||
"accountStatus": "Status",
|
"accountStatus": "Status",
|
||||||
@ -466,6 +467,7 @@
|
|||||||
"accountStatusLastSeen": "Last seen at {}",
|
"accountStatusLastSeen": "Last seen at {}",
|
||||||
"postArticle": "Article on the Solar Network",
|
"postArticle": "Article on the Solar Network",
|
||||||
"postStory": "Story on the Solar Network",
|
"postStory": "Story on the Solar Network",
|
||||||
|
"postLocalDraftRestored": "Restored from device",
|
||||||
"articleWrittenAt": "Written at {}",
|
"articleWrittenAt": "Written at {}",
|
||||||
"articleEditedAt": "Edited at {}",
|
"articleEditedAt": "Edited at {}",
|
||||||
"attachmentSaved": "Saved to album",
|
"attachmentSaved": "Saved to album",
|
||||||
|
@ -456,6 +456,7 @@
|
|||||||
"accountJoinedAt": "加入于 {}",
|
"accountJoinedAt": "加入于 {}",
|
||||||
"accountBirthday": "出生于 {}",
|
"accountBirthday": "出生于 {}",
|
||||||
"accountBadge": "徽章",
|
"accountBadge": "徽章",
|
||||||
|
"accountCheckInNoRecords": "暂无运势记录",
|
||||||
"badgeCompanyStaff": "索尔辛茨士大夫 · 员工",
|
"badgeCompanyStaff": "索尔辛茨士大夫 · 员工",
|
||||||
"badgeSiteMigration": "Solar Network 原住民",
|
"badgeSiteMigration": "Solar Network 原住民",
|
||||||
"accountStatus": "状态",
|
"accountStatus": "状态",
|
||||||
@ -464,6 +465,7 @@
|
|||||||
"accountStatusLastSeen": "最后一次上线于 {}",
|
"accountStatusLastSeen": "最后一次上线于 {}",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
|
"postLocalDraftRestored": "从本地恢复草稿",
|
||||||
"articleWrittenAt": "发表于 {}",
|
"articleWrittenAt": "发表于 {}",
|
||||||
"articleEditedAt": "编辑于 {}",
|
"articleEditedAt": "编辑于 {}",
|
||||||
"attachmentSaved": "已保存到相册",
|
"attachmentSaved": "已保存到相册",
|
||||||
|
@ -456,6 +456,7 @@
|
|||||||
"accountJoinedAt": "加入於 {}",
|
"accountJoinedAt": "加入於 {}",
|
||||||
"accountBirthday": "出生於 {}",
|
"accountBirthday": "出生於 {}",
|
||||||
"accountBadge": "徽章",
|
"accountBadge": "徽章",
|
||||||
|
"accountCheckInNoRecords": "暫無運勢記錄",
|
||||||
"badgeCompanyStaff": "索爾辛茨士大夫 · 員工",
|
"badgeCompanyStaff": "索爾辛茨士大夫 · 員工",
|
||||||
"badgeSiteMigration": "Solar Network 原住民",
|
"badgeSiteMigration": "Solar Network 原住民",
|
||||||
"accountStatus": "狀態",
|
"accountStatus": "狀態",
|
||||||
@ -464,6 +465,7 @@
|
|||||||
"accountStatusLastSeen": "最後一次上線於 {}",
|
"accountStatusLastSeen": "最後一次上線於 {}",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
|
"postLocalDraftRestored": "從本地恢復草稿",
|
||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
"articleEditedAt": "編輯於 {}",
|
"articleEditedAt": "編輯於 {}",
|
||||||
"attachmentSaved": "已保存到相冊",
|
"attachmentSaved": "已保存到相冊",
|
||||||
|
@ -456,6 +456,7 @@
|
|||||||
"accountJoinedAt": "加入於 {}",
|
"accountJoinedAt": "加入於 {}",
|
||||||
"accountBirthday": "出生於 {}",
|
"accountBirthday": "出生於 {}",
|
||||||
"accountBadge": "徽章",
|
"accountBadge": "徽章",
|
||||||
|
"accountCheckInNoRecords": "暫無運勢記錄",
|
||||||
"badgeCompanyStaff": "索爾辛茨士大夫 · 員工",
|
"badgeCompanyStaff": "索爾辛茨士大夫 · 員工",
|
||||||
"badgeSiteMigration": "Solar Network 原住民",
|
"badgeSiteMigration": "Solar Network 原住民",
|
||||||
"accountStatus": "狀態",
|
"accountStatus": "狀態",
|
||||||
@ -464,6 +465,7 @@
|
|||||||
"accountStatusLastSeen": "最後一次上線於 {}",
|
"accountStatusLastSeen": "最後一次上線於 {}",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
|
"postLocalDraftRestored": "從本地恢復草稿",
|
||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
"articleEditedAt": "編輯於 {}",
|
"articleEditedAt": "編輯於 {}",
|
||||||
"attachmentSaved": "已保存到相冊",
|
"attachmentSaved": "已保存到相冊",
|
||||||
|
@ -173,7 +173,7 @@ PODS:
|
|||||||
- in_app_review (2.0.0):
|
- in_app_review (2.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Kingfisher (8.1.3)
|
- Kingfisher (8.1.3)
|
||||||
- livekit_client (2.3.3):
|
- livekit_client (2.3.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- WebRTC-SDK (= 125.6422.06)
|
- WebRTC-SDK (= 125.6422.06)
|
||||||
@ -211,9 +211,6 @@ PODS:
|
|||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqflite_darwin (0.0.4):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- SwiftyGif (5.4.5)
|
- SwiftyGif (5.4.5)
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -259,7 +256,6 @@ DEPENDENCIES:
|
|||||||
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
|
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
|
||||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
- video_compress (from `.symlinks/plugins/video_compress/ios`)
|
- video_compress (from `.symlinks/plugins/video_compress/ios`)
|
||||||
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
||||||
@ -347,8 +343,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/share_plus/ios"
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
sqflite_darwin:
|
|
||||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
video_compress:
|
video_compress:
|
||||||
@ -391,7 +385,7 @@ SPEC CHECKSUMS:
|
|||||||
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
||||||
in_app_review: a31b5257259646ea78e0e35fc914979b0031d011
|
in_app_review: a31b5257259646ea78e0e35fc914979b0031d011
|
||||||
Kingfisher: f2af9028b16baf9dc6c07c570072bc41cbf009ef
|
Kingfisher: f2af9028b16baf9dc6c07c570072bc41cbf009ef
|
||||||
livekit_client: 02cf2cc4357a655af12ccee70ff5596ae4e6feef
|
livekit_client: 4eaa7a2968fc7e7c57888f43d90394547cc8d9e9
|
||||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||||
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
||||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||||
@ -407,7 +401,6 @@ SPEC CHECKSUMS:
|
|||||||
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
|
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
|
||||||
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||||
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe
|
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
@ -8,6 +11,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:surface/providers/post.dart';
|
import 'package:surface/providers/post.dart';
|
||||||
import 'package:surface/providers/sn_attachment.dart';
|
import 'package:surface/providers/sn_attachment.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
@ -151,8 +155,18 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
final TextEditingController aliasController = TextEditingController();
|
final TextEditingController aliasController = TextEditingController();
|
||||||
|
|
||||||
PostWriteController() {
|
PostWriteController() {
|
||||||
titleController.addListener(() => notifyListeners());
|
titleController.addListener(() {
|
||||||
descriptionController.addListener(() => notifyListeners());
|
_temporaryPlanSave();
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
descriptionController.addListener(() {
|
||||||
|
_temporaryPlanSave();
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
contentController.addListener(() {
|
||||||
|
_temporaryPlanSave();
|
||||||
|
});
|
||||||
|
_temporaryLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
String mode = kTitleMap.keys.first;
|
String mode = kTitleMap.keys.first;
|
||||||
@ -247,6 +261,7 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
media.toFile()!,
|
media.toFile()!,
|
||||||
place.$1,
|
place.$1,
|
||||||
place.$2,
|
place.$2,
|
||||||
|
analyzeNow: media.type == SnMediaType.image,
|
||||||
onProgress: (value) {
|
onProgress: (value) {
|
||||||
progress = value;
|
progress = value;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -297,6 +312,81 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
return compressedAttachment;
|
return compressedAttachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const kTemporaryStorageKey = 'int_draft_post';
|
||||||
|
|
||||||
|
Timer? _temporarySaveTimer;
|
||||||
|
|
||||||
|
void _temporaryPlanSave() {
|
||||||
|
_temporarySaveTimer?.cancel();
|
||||||
|
_temporarySaveTimer = Timer(const Duration(seconds: 1), () {
|
||||||
|
_temporarySave();
|
||||||
|
log("[PostWriter] Temporary save saved.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _temporarySave() {
|
||||||
|
SharedPreferences.getInstance().then((prefs) {
|
||||||
|
if (titleController.text.isEmpty &&
|
||||||
|
descriptionController.text.isEmpty &&
|
||||||
|
contentController.text.isEmpty &&
|
||||||
|
thumbnail == null &&
|
||||||
|
attachments.isEmpty) {
|
||||||
|
prefs.remove(kTemporaryStorageKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs.setString(
|
||||||
|
kTemporaryStorageKey,
|
||||||
|
jsonEncode({
|
||||||
|
'publisher': publisher,
|
||||||
|
'content': contentController.text,
|
||||||
|
if (aliasController.text.isNotEmpty) 'alias': aliasController.text,
|
||||||
|
if (titleController.text.isNotEmpty) 'title': titleController.text,
|
||||||
|
if (descriptionController.text.isNotEmpty) 'description': descriptionController.text,
|
||||||
|
if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.toJson(),
|
||||||
|
'attachments': attachments.where((e) => e.attachment != null).map((e) => e.attachment!.toJson()).toList(),
|
||||||
|
'tags': tags.map((ele) => {'alias': ele}).toList(),
|
||||||
|
'categories': categories.map((ele) => {'alias': ele}).toList(),
|
||||||
|
'visibility': visibility,
|
||||||
|
'visible_users_list': visibleUsers,
|
||||||
|
'invisible_users_list': invisibleUsers,
|
||||||
|
if (publishedAt != null) 'published_at': publishedAt!.toUtc().toIso8601String(),
|
||||||
|
if (publishedUntil != null) 'published_until': publishedAt!.toUtc().toIso8601String(),
|
||||||
|
if (replyingPost != null) 'reply_to': replyingPost!.toJson(),
|
||||||
|
if (repostingPost != null) 'repost_to': repostingPost!.toJson(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool temporaryRestored = false;
|
||||||
|
|
||||||
|
void _temporaryLoad() {
|
||||||
|
SharedPreferences.getInstance().then((prefs) {
|
||||||
|
final raw = prefs.getString(kTemporaryStorageKey);
|
||||||
|
if (raw == null) return;
|
||||||
|
final data = jsonDecode(raw);
|
||||||
|
contentController.text = data['content'];
|
||||||
|
aliasController.text = data['alias'] ?? '';
|
||||||
|
titleController.text = data['title'] ?? '';
|
||||||
|
descriptionController.text = data['description'] ?? '';
|
||||||
|
if (data['thumbnail'] != null) thumbnail = PostWriteMedia(SnAttachment.fromJson(data['thumbnail']));
|
||||||
|
attachments
|
||||||
|
.addAll(data['attachments'].map((ele) => PostWriteMedia(SnAttachment.fromJson(ele))).cast<PostWriteMedia>());
|
||||||
|
tags = List.from(data['tags'].map((ele) => ele['alias']));
|
||||||
|
categories = List.from(data['categories'].map((ele) => ele['alias']));
|
||||||
|
visibility = data['visibility'];
|
||||||
|
visibleUsers = List.from(data['visible_users_list'] ?? []);
|
||||||
|
invisibleUsers = List.from(data['invisible_users_list'] ?? []);
|
||||||
|
if (data['published_at'] != null) publishedAt = DateTime.tryParse(data['published_at'])?.toLocal();
|
||||||
|
if (data['published_until'] != null) publishedUntil = DateTime.tryParse(data['published_until'])?.toLocal();
|
||||||
|
replyingPost = data['reply_to'] != null ? SnPost.fromJson(data['reply_to']) : null;
|
||||||
|
repostingPost = data['repost_to'] != null ? SnPost.fromJson(data['repost_to']) : null;
|
||||||
|
temporaryRestored = true;
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> uploadSingleAttachment(BuildContext context, int idx) async {
|
Future<void> uploadSingleAttachment(BuildContext context, int idx) async {
|
||||||
if (isBusy) return;
|
if (isBusy) return;
|
||||||
|
|
||||||
@ -353,9 +443,11 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final compressedAttachment = await _tryCompressVideoCopy(context, media);
|
if (context.mounted) {
|
||||||
if (compressedAttachment != null) {
|
final compressedAttachment = await _tryCompressVideoCopy(context, media);
|
||||||
item = await attach.updateOne(item, compressedId: compressedAttachment.id);
|
if (compressedAttachment != null) {
|
||||||
|
item = await attach.updateOne(item, compressedId: compressedAttachment.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (context.mounted) context.showErrorDialog(err);
|
if (context.mounted) context.showErrorDialog(err);
|
||||||
@ -414,6 +506,7 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
method: editingPost != null ? 'PUT' : 'POST',
|
method: editingPost != null ? 'PUT' : 'POST',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
reset();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
@ -462,56 +555,67 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
|
|
||||||
void setPublisher(SnPublisher? item) {
|
void setPublisher(SnPublisher? item) {
|
||||||
publisher = item;
|
publisher = item;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPublishedAt(DateTime? value) {
|
void setPublishedAt(DateTime? value) {
|
||||||
publishedAt = value;
|
publishedAt = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPublishedUntil(DateTime? value) {
|
void setPublishedUntil(DateTime? value) {
|
||||||
publishedUntil = value;
|
publishedUntil = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTags(List<String> value) {
|
void setTags(List<String> value) {
|
||||||
tags = value;
|
tags = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCategories(List<String> value) {
|
void setCategories(List<String> value) {
|
||||||
categories = value;
|
categories = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVisibility(int value) {
|
void setVisibility(int value) {
|
||||||
visibility = value;
|
visibility = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVisibleUsers(List<int> value) {
|
void setVisibleUsers(List<int> value) {
|
||||||
visibleUsers = value;
|
visibleUsers = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInvisibleUsers(List<int> value) {
|
void setInvisibleUsers(List<int> value) {
|
||||||
invisibleUsers = value;
|
invisibleUsers = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setProgress(double? value) {
|
void setProgress(double? value) {
|
||||||
progress = value;
|
progress = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIsBusy(bool value) {
|
void setIsBusy(bool value) {
|
||||||
isBusy = value;
|
isBusy = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMode(String value) {
|
void setMode(String value) {
|
||||||
mode = value;
|
mode = value;
|
||||||
|
_temporaryPlanSave();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +633,8 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
replyingPost = null;
|
replyingPost = null;
|
||||||
repostingPost = null;
|
repostingPost = null;
|
||||||
mode = kTitleMap.keys.first;
|
mode = kTitleMap.keys.first;
|
||||||
|
temporaryRestored = false;
|
||||||
|
SharedPreferences.getInstance().then((prefs) => prefs.remove(kTemporaryStorageKey));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,10 +154,12 @@ class SnAttachmentProvider {
|
|||||||
String rid,
|
String rid,
|
||||||
String cid, {
|
String cid, {
|
||||||
Function(double progress)? onProgress,
|
Function(double progress)? onProgress,
|
||||||
|
bool analyzeNow = false,
|
||||||
}) async {
|
}) async {
|
||||||
final resp = await _sn.client.post(
|
final resp = await _sn.client.post(
|
||||||
'/cgi/uc/fragments/$rid/$cid',
|
'/cgi/uc/fragments/$rid/$cid',
|
||||||
data: data,
|
data: data,
|
||||||
|
queryParameters: {'analyzeNow': analyzeNow},
|
||||||
options: Options(headers: {'Content-Type': 'application/octet-stream'}),
|
options: Options(headers: {'Content-Type': 'application/octet-stream'}),
|
||||||
onSendProgress: (count, total) {
|
onSendProgress: (count, total) {
|
||||||
if (onProgress != null) {
|
if (onProgress != null) {
|
||||||
@ -178,6 +180,7 @@ class SnAttachmentProvider {
|
|||||||
SnAttachmentFragment place,
|
SnAttachmentFragment place,
|
||||||
int chunkSize, {
|
int chunkSize, {
|
||||||
Function(double progress)? onProgress,
|
Function(double progress)? onProgress,
|
||||||
|
bool analyzeNow = false,
|
||||||
}) async {
|
}) async {
|
||||||
final Map<String, dynamic> chunks = place.fileChunks;
|
final Map<String, dynamic> chunks = place.fileChunks;
|
||||||
var completedTasks = 0;
|
var completedTasks = 0;
|
||||||
@ -200,6 +203,7 @@ class SnAttachmentProvider {
|
|||||||
data,
|
data,
|
||||||
place.rid,
|
place.rid,
|
||||||
entry.key,
|
entry.key,
|
||||||
|
analyzeNow: analyzeNow,
|
||||||
onProgress: (progress) {
|
onProgress: (progress) {
|
||||||
final overallProgress = (completedTasks + progress) / chunks.length;
|
final overallProgress = (completedTasks + progress) / chunks.length;
|
||||||
onProgress?.call(overallProgress);
|
onProgress?.call(overallProgress);
|
||||||
|
@ -517,6 +517,12 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
|||||||
future: _getCheckInRecords(),
|
future: _getCheckInRecords(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) return const SizedBox.shrink();
|
if (!snapshot.hasData) return const SizedBox.shrink();
|
||||||
|
if (snapshot.data!.length <= 1) {
|
||||||
|
return Text(
|
||||||
|
'accountCheckInNoRecords',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
).tr().fontWeight(FontWeight.bold).center().padding(horizontal: 20, vertical: 8);
|
||||||
|
}
|
||||||
final records = snapshot.data!;
|
final records = snapshot.data!;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
@ -364,6 +364,35 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(top: 4, bottom: 4, left: 28, right: 22),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 1 / MediaQuery.of(context).devicePixelRatio,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: _writeController.temporaryRestored
|
||||||
|
? Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.restore, size: 20),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(child: Text('postLocalDraftRestored').tr()),
|
||||||
|
InkWell(
|
||||||
|
child: Text('dialogDismiss').tr(),
|
||||||
|
onTap: () {
|
||||||
|
_writeController.reset();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
)
|
||||||
|
.height(_writeController.temporaryRestored ? 32 : 0, animate: true)
|
||||||
|
.animate(const Duration(milliseconds: 300), Curves.fastLinearToSlowEaseIn),
|
||||||
LoadingIndicator(isActive: _isLoading),
|
LoadingIndicator(isActive: _isLoading),
|
||||||
if (_writeController.isBusy && _writeController.progress != null)
|
if (_writeController.isBusy && _writeController.progress != null)
|
||||||
TweenAnimationBuilder<double>(
|
TweenAnimationBuilder<double>(
|
||||||
|
@ -20,9 +20,11 @@ import 'package:uuid/uuid.dart';
|
|||||||
class AttachmentItem extends StatelessWidget {
|
class AttachmentItem extends StatelessWidget {
|
||||||
final SnAttachment? data;
|
final SnAttachment? data;
|
||||||
final String? heroTag;
|
final String? heroTag;
|
||||||
|
final BoxFit fit;
|
||||||
|
|
||||||
const AttachmentItem({
|
const AttachmentItem({
|
||||||
super.key,
|
super.key,
|
||||||
|
this.fit = BoxFit.cover,
|
||||||
required this.data,
|
required this.data,
|
||||||
required this.heroTag,
|
required this.heroTag,
|
||||||
});
|
});
|
||||||
@ -43,7 +45,7 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
child: AutoResizeUniversalImage(
|
child: AutoResizeUniversalImage(
|
||||||
sn.getAttachmentUrl(data!.rid),
|
sn.getAttachmentUrl(data!.rid),
|
||||||
key: Key('attachment-${data!.rid}-$tag'),
|
key: Key('attachment-${data!.rid}-$tag'),
|
||||||
fit: BoxFit.cover,
|
fit: fit,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case 'video':
|
case 'video':
|
||||||
@ -322,7 +324,9 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo
|
|||||||
MaterialDesktopCustomButton(
|
MaterialDesktopCustomButton(
|
||||||
iconSize: 24,
|
iconSize: 24,
|
||||||
onPressed: _toggleOriginal,
|
onPressed: _toggleOriginal,
|
||||||
icon: _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24),
|
icon: Builder(builder: (context) {
|
||||||
|
return _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -4,8 +4,8 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:responsive_framework/responsive_framework.dart';
|
|
||||||
import 'package:surface/types/attachment.dart';
|
import 'package:surface/types/attachment.dart';
|
||||||
import 'package:surface/widgets/attachment/attachment_zoom.dart';
|
import 'package:surface/widgets/attachment/attachment_zoom.dart';
|
||||||
import 'package:surface/widgets/attachment/attachment_item.dart';
|
import 'package:surface/widgets/attachment/attachment_item.dart';
|
||||||
@ -14,19 +14,23 @@ import 'package:uuid/uuid.dart';
|
|||||||
class AttachmentList extends StatefulWidget {
|
class AttachmentList extends StatefulWidget {
|
||||||
final List<SnAttachment?> data;
|
final List<SnAttachment?> data;
|
||||||
final bool bordered;
|
final bool bordered;
|
||||||
|
final bool gridded;
|
||||||
final bool noGrow;
|
final bool noGrow;
|
||||||
final bool isFlatted;
|
final BoxFit fit;
|
||||||
final double? maxHeight;
|
final double? maxHeight;
|
||||||
final EdgeInsets? listPadding;
|
final double? minWidth;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
|
||||||
const AttachmentList({
|
const AttachmentList({
|
||||||
super.key,
|
super.key,
|
||||||
required this.data,
|
required this.data,
|
||||||
this.bordered = false,
|
this.bordered = false,
|
||||||
|
this.gridded = false,
|
||||||
this.noGrow = false,
|
this.noGrow = false,
|
||||||
this.isFlatted = false,
|
this.fit = BoxFit.cover,
|
||||||
this.maxHeight,
|
this.maxHeight,
|
||||||
this.listPadding,
|
this.minWidth,
|
||||||
|
this.padding,
|
||||||
});
|
});
|
||||||
|
|
||||||
static const BorderRadius kDefaultRadius = BorderRadius.all(Radius.circular(8));
|
static const BorderRadius kDefaultRadius = BorderRadius.all(Radius.circular(8));
|
||||||
@ -41,8 +45,6 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
(_) => const Uuid().v4(),
|
(_) => const Uuid().v4(),
|
||||||
);
|
);
|
||||||
|
|
||||||
static const double kAttachmentMaxWidth = 640;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
@ -51,9 +53,8 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
widget.bordered ? BorderSide(width: 1, color: Theme.of(context).dividerColor) : BorderSide.none;
|
widget.bordered ? BorderSide(width: 1, color: Theme.of(context).dividerColor) : BorderSide.none;
|
||||||
final backgroundColor = Theme.of(context).colorScheme.surfaceContainer;
|
final backgroundColor = Theme.of(context).colorScheme.surfaceContainer;
|
||||||
final constraints = BoxConstraints(
|
final constraints = BoxConstraints(
|
||||||
minWidth: 80,
|
minWidth: widget.minWidth ?? 80,
|
||||||
maxHeight: widget.maxHeight ?? double.infinity,
|
maxHeight: widget.maxHeight ?? MediaQuery.of(context).size.height,
|
||||||
maxWidth: layoutConstraints.maxWidth - 20,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.data.isEmpty) return const SizedBox.shrink();
|
if (widget.data.isEmpty) return const SizedBox.shrink();
|
||||||
@ -67,97 +68,90 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
.toDouble();
|
.toDouble();
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: ResponsiveBreakpoints.of(context).largerThan(MOBILE)
|
padding: widget.padding ?? EdgeInsets.zero,
|
||||||
? constraints.copyWith(
|
constraints: constraints,
|
||||||
maxWidth: math.min(
|
child: GestureDetector(
|
||||||
constraints.maxWidth,
|
child: AspectRatio(
|
||||||
kAttachmentMaxWidth,
|
aspectRatio: singleAspectRatio,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: backgroundColor,
|
||||||
|
border: Border.fromBorderSide(borderSide),
|
||||||
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
|
child: AttachmentItem(
|
||||||
|
data: widget.data[0],
|
||||||
|
heroTag: heroTags[0],
|
||||||
|
fit: widget.fit,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
: null,
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: singleAspectRatio,
|
|
||||||
child: GestureDetector(
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
if (ResponsiveBreakpoints.of(context).largerThan(MOBILE) || widget.noGrow) {
|
|
||||||
return Padding(
|
|
||||||
// Single child list-like displaying
|
|
||||||
padding: widget.listPadding ?? EdgeInsets.zero,
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: backgroundColor,
|
|
||||||
border: Border(top: borderSide, bottom: borderSide),
|
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
|
||||||
),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
|
||||||
child: AttachmentItem(
|
|
||||||
data: widget.data[0],
|
|
||||||
heroTag: heroTags[0],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: backgroundColor,
|
|
||||||
border: Border(top: borderSide, bottom: borderSide),
|
|
||||||
),
|
|
||||||
child: AttachmentItem(
|
|
||||||
data: widget.data[0],
|
|
||||||
heroTag: heroTags.first,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
if (widget.data.firstOrNull?.mediaType != SnMediaType.image) return;
|
|
||||||
context.pushTransparentRoute(
|
|
||||||
AttachmentZoomView(
|
|
||||||
data: widget.data.where((ele) => ele != null).cast(),
|
|
||||||
initialIndex: 0,
|
|
||||||
heroTags: heroTags,
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black.withOpacity(0.7),
|
|
||||||
rootNavigator: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (widget.data.firstOrNull?.mediaType != SnMediaType.image) return;
|
||||||
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data.where((ele) => ele != null).cast(),
|
||||||
|
initialIndex: 0,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.isFlatted) {
|
if (widget.gridded) {
|
||||||
return Wrap(
|
return Padding(
|
||||||
spacing: 4,
|
padding: widget.padding ?? EdgeInsets.zero,
|
||||||
runSpacing: 4,
|
child: Container(
|
||||||
children: widget.data
|
decoration: BoxDecoration(
|
||||||
.mapIndexed(
|
color: backgroundColor,
|
||||||
(idx, ele) => AspectRatio(
|
border: Border(
|
||||||
aspectRatio: (ele?.data['ratio'] ?? 1).toDouble(),
|
top: borderSide,
|
||||||
child: Container(
|
bottom: borderSide,
|
||||||
decoration: BoxDecoration(
|
),
|
||||||
color: backgroundColor,
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
border: Border(
|
),
|
||||||
top: borderSide,
|
child: ClipRRect(
|
||||||
bottom: borderSide,
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
|
child: StaggeredGrid.count(
|
||||||
|
crossAxisCount: math.min(widget.data.length, 2),
|
||||||
|
crossAxisSpacing: 4,
|
||||||
|
mainAxisSpacing: 4,
|
||||||
|
children: widget.data
|
||||||
|
.mapIndexed(
|
||||||
|
(idx, ele) => GestureDetector(
|
||||||
|
child: Container(
|
||||||
|
constraints: constraints,
|
||||||
|
child: AttachmentItem(
|
||||||
|
data: ele,
|
||||||
|
heroTag: heroTags[idx],
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (widget.data[idx]!.mediaType != SnMediaType.image) return;
|
||||||
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data.where((ele) => ele != null).cast(),
|
||||||
|
initialIndex: idx,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
)
|
||||||
),
|
.toList(),
|
||||||
child: ClipRRect(
|
),
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
),
|
||||||
child: AttachmentItem(
|
),
|
||||||
data: ele,
|
|
||||||
heroTag: heroTags[idx],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +217,7 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => const Gap(8),
|
separatorBuilder: (context, index) => const Gap(8),
|
||||||
padding: widget.listPadding,
|
padding: widget.padding,
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
),
|
),
|
||||||
|
@ -159,9 +159,10 @@ class ChatMessage extends StatelessWidget {
|
|||||||
AttachmentList(
|
AttachmentList(
|
||||||
data: data.preload!.attachments!,
|
data: data.preload!.attachments!,
|
||||||
bordered: true,
|
bordered: true,
|
||||||
|
gridded: true,
|
||||||
noGrow: true,
|
noGrow: true,
|
||||||
maxHeight: 520,
|
maxHeight: 520,
|
||||||
listPadding: const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
),
|
),
|
||||||
if (!hasMerged && !isCompact) const Gap(12) else if (!isCompact) const Gap(6),
|
if (!hasMerged && !isCompact) const Gap(12) else if (!isCompact) const Gap(6),
|
||||||
],
|
],
|
||||||
|
@ -83,6 +83,7 @@ class ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
media.toFile()!,
|
media.toFile()!,
|
||||||
place.$1,
|
place.$1,
|
||||||
place.$2,
|
place.$2,
|
||||||
|
analyzeNow: media.type == SnMediaType.image,
|
||||||
onProgress: (progress) {
|
onProgress: (progress) {
|
||||||
// Calculate overall progress for attachments
|
// Calculate overall progress for attachments
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -251,8 +251,11 @@ class PostItem extends StatelessWidget {
|
|||||||
AttachmentList(
|
AttachmentList(
|
||||||
data: data.preload!.attachments!,
|
data: data.preload!.attachments!,
|
||||||
bordered: true,
|
bordered: true,
|
||||||
maxHeight: 560,
|
gridded: true,
|
||||||
listPadding: const EdgeInsets.symmetric(horizontal: 12),
|
maxHeight: showFullPost ? null : 480,
|
||||||
|
minWidth: 640,
|
||||||
|
fit: showFullPost ? BoxFit.cover : BoxFit.contain,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
),
|
),
|
||||||
if (data.body['content'] != null)
|
if (data.body['content'] != null)
|
||||||
LinkPreviewWidget(
|
LinkPreviewWidget(
|
||||||
@ -332,13 +335,12 @@ class PostShareImageWidget extends StatelessWidget {
|
|||||||
_PostQuoteContent(
|
_PostQuoteContent(
|
||||||
child: data.repostTo!,
|
child: data.repostTo!,
|
||||||
isRelativeDate: false,
|
isRelativeDate: false,
|
||||||
isFlatted: true,
|
|
||||||
).padding(horizontal: 16, bottom: 8),
|
).padding(horizontal: 16, bottom: 8),
|
||||||
if (data.type != 'article' && (data.preload?.attachments?.isNotEmpty ?? false))
|
if (data.type != 'article' && (data.preload?.attachments?.isNotEmpty ?? false))
|
||||||
AttachmentList(
|
StyledWidget(AttachmentList(
|
||||||
data: data.preload!.attachments!,
|
data: data.preload!.attachments!,
|
||||||
isFlatted: true,
|
gridded: true,
|
||||||
).padding(horizontal: 16, bottom: 8),
|
)).padding(horizontal: 16, bottom: 8),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -884,11 +886,9 @@ class _PostContentBody extends StatelessWidget {
|
|||||||
class _PostQuoteContent extends StatelessWidget {
|
class _PostQuoteContent extends StatelessWidget {
|
||||||
final SnPost child;
|
final SnPost child;
|
||||||
final bool isRelativeDate;
|
final bool isRelativeDate;
|
||||||
final bool isFlatted;
|
|
||||||
|
|
||||||
const _PostQuoteContent({
|
const _PostQuoteContent({
|
||||||
this.isRelativeDate = true,
|
this.isRelativeDate = true,
|
||||||
this.isFlatted = false,
|
|
||||||
required this.child,
|
required this.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -930,12 +930,15 @@ class _PostQuoteContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: AttachmentList(
|
child: AttachmentList(
|
||||||
data: child.preload!.attachments!,
|
data: child.preload!.attachments!,
|
||||||
isFlatted: isFlatted,
|
maxHeight: 360,
|
||||||
listPadding: const EdgeInsets.symmetric(horizontal: 12),
|
minWidth: 640,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
gridded: true,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
),
|
),
|
||||||
).padding(
|
).padding(
|
||||||
top: 8,
|
top: 8,
|
||||||
bottom: (child.preload?.attachments?.length ?? 0) > 1 ? 12 : 0,
|
bottom: 12,
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:extended_image/extended_image.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
@ -7,7 +7,6 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
|
|
||||||
// Keep this import to make the web image render work
|
// Keep this import to make the web image render work
|
||||||
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
|
|
||||||
import 'package:surface/providers/config.dart';
|
import 'package:surface/providers/config.dart';
|
||||||
|
|
||||||
class UniversalImage extends StatelessWidget {
|
class UniversalImage extends StatelessWidget {
|
||||||
@ -34,64 +33,54 @@ class UniversalImage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
final quality = filterQuality ?? context.read<ConfigProvider>().imageQuality;
|
||||||
final double? resizeHeight = cacheHeight != null ? (cacheHeight! * devicePixelRatio) : null;
|
|
||||||
final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null;
|
|
||||||
|
|
||||||
return Image(
|
return ExtendedImage.network(
|
||||||
filterQuality: filterQuality ?? context.read<ConfigProvider>().imageQuality,
|
url,
|
||||||
image: kIsWeb
|
|
||||||
? UniversalImage.provider(url)
|
|
||||||
: ResizeImage(
|
|
||||||
UniversalImage.provider(url),
|
|
||||||
width: resizeWidth?.round(),
|
|
||||||
height: resizeHeight?.round(),
|
|
||||||
policy: ResizeImagePolicy.fit,
|
|
||||||
),
|
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
fit: fit,
|
fit: fit,
|
||||||
loadingBuilder: noProgressIndicator
|
cache: true,
|
||||||
? null
|
compressionRatio: kIsWeb ? 1 : switch(quality) {
|
||||||
: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
|
FilterQuality.high => 1,
|
||||||
if (loadingProgress == null) return child;
|
FilterQuality.medium => 0.75,
|
||||||
return Center(
|
FilterQuality.low => 0.5,
|
||||||
child: TweenAnimationBuilder(
|
FilterQuality.none => 0.25,
|
||||||
tween: Tween(
|
},
|
||||||
begin: 0,
|
filterQuality: quality,
|
||||||
end: loadingProgress.expectedTotalBytes != null
|
enableLoadState: true,
|
||||||
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
retries: 3,
|
||||||
: 0,
|
loadStateChanged: (ExtendedImageState state) {
|
||||||
|
if (state.extendedImageLoadState == LoadState.completed) {
|
||||||
|
return state.completedWidget;
|
||||||
|
} else if (state.extendedImageLoadState == LoadState.failed) {
|
||||||
|
return Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
AnimateWidgetExtensions(Icon(Symbols.close, size: 24))
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
Text(
|
||||||
|
state.lastException.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
duration: const Duration(milliseconds: 300),
|
],
|
||||||
builder: (context, value, _) => CircularProgressIndicator(
|
).center(),
|
||||||
value: loadingProgress.expectedTotalBytes != null ? value.toDouble() : null,
|
),
|
||||||
),
|
);
|
||||||
),
|
}
|
||||||
);
|
return Center(
|
||||||
},
|
child: CircularProgressIndicator(
|
||||||
errorBuilder: noErrorWidget
|
value: state.loadingProgress != null
|
||||||
? null
|
? state.loadingProgress!.cumulativeBytesLoaded / state.loadingProgress!.expectedTotalBytes!
|
||||||
: (context, error, stackTrace) {
|
: null,
|
||||||
return Material(
|
),
|
||||||
color: Theme.of(context).colorScheme.surface,
|
);
|
||||||
child: Container(
|
},
|
||||||
constraints: const BoxConstraints(maxWidth: 280),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
AnimateWidgetExtensions(Icon(Symbols.close, size: 24))
|
|
||||||
.animate(onPlay: (e) => e.repeat(reverse: true))
|
|
||||||
.fade(duration: 500.ms),
|
|
||||||
Text(
|
|
||||||
error.toString(),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).center(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +88,10 @@ class UniversalImage extends StatelessWidget {
|
|||||||
// This place used to use network image or cached network image depending on the platform.
|
// This place used to use network image or cached network image depending on the platform.
|
||||||
// But now the cached network image is working on every platform.
|
// But now the cached network image is working on every platform.
|
||||||
// So we just use it now.
|
// So we just use it now.
|
||||||
return CachedNetworkImageProvider(
|
return ExtendedNetworkImageProvider(
|
||||||
url,
|
url,
|
||||||
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
|
cache: true,
|
||||||
|
retries: 3,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ import path_provider_foundation
|
|||||||
import screen_brightness_macos
|
import screen_brightness_macos
|
||||||
import share_plus
|
import share_plus
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite_darwin
|
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
import video_compress
|
import video_compress
|
||||||
import wakelock_plus
|
import wakelock_plus
|
||||||
@ -53,7 +52,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
|
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
|
||||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
|
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
|
||||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||||
|
@ -134,7 +134,7 @@ PODS:
|
|||||||
- GoogleUtilities/Privacy
|
- GoogleUtilities/Privacy
|
||||||
- in_app_review (2.0.0):
|
- in_app_review (2.0.0):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- livekit_client (2.3.3):
|
- livekit_client (2.3.4):
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 125.6422.06)
|
- WebRTC-SDK (= 125.6422.06)
|
||||||
@ -165,9 +165,6 @@ PODS:
|
|||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqflite_darwin (0.0.4):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- url_launcher_macos (0.0.1):
|
- url_launcher_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- video_compress (0.3.0):
|
- video_compress (0.3.0):
|
||||||
@ -201,7 +198,6 @@ DEPENDENCIES:
|
|||||||
- screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`)
|
- screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`)
|
||||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
|
||||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||||
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
|
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
|
||||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||||
@ -271,8 +267,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
sqflite_darwin:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||||
video_compress:
|
video_compress:
|
||||||
@ -304,7 +298,7 @@ SPEC CHECKSUMS:
|
|||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
||||||
in_app_review: a6a031b9acd03c7d103e341aa334adf2c493fb93
|
in_app_review: a6a031b9acd03c7d103e341aa334adf2c493fb93
|
||||||
livekit_client: 8b1b90a6f2445d127a018ce93cc8cf6d8ab62982
|
livekit_client: b7ab91e79e657d7d40da16cb2f90d517cb72d406
|
||||||
media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82
|
media_kit_libs_macos_video: b3e2bbec2eef97c285f2b1baa7963c67c753fb82
|
||||||
media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5
|
media_kit_native_event_loop: 81fd5b45192b72f8b5b69eaf5b540f45777eb8d5
|
||||||
media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5
|
media_kit_video: c75b07f14d59706c775778e4dd47dd027de8d1e5
|
||||||
@ -317,7 +311,6 @@ SPEC CHECKSUMS:
|
|||||||
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
|
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
|
||||||
share_plus: 1fa619de8392a4398bfaf176d441853922614e89
|
share_plus: 1fa619de8392a4398bfaf176d441853922614e89
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
|
||||||
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
|
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
|
||||||
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
|
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
|
||||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||||
|
116
pubspec.lock
116
pubspec.lock
@ -182,30 +182,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.3"
|
version: "8.9.3"
|
||||||
cached_network_image:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: cached_network_image
|
|
||||||
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.4.1"
|
|
||||||
cached_network_image_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cached_network_image_platform_interface
|
|
||||||
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.1"
|
|
||||||
cached_network_image_web:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cached_network_image_web
|
|
||||||
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
cassowary:
|
cassowary:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -454,6 +430,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.7"
|
version: "2.0.7"
|
||||||
|
extended_image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: extended_image
|
||||||
|
sha256: "93890a88d89ce017789f6c031c32ad8d2c685f1a5c25c169550746d973ca5e44"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "9.0.9"
|
||||||
|
extended_image_library:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: extended_image_library
|
||||||
|
sha256: "9a94ec9314aa206cfa35f16145c3cd6e2c924badcc670eaaca8a3a8063a68cd7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.5"
|
||||||
fading_edge_scrollview:
|
fading_edge_scrollview:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -643,14 +635,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.2"
|
version: "3.2.2"
|
||||||
flutter_cache_manager:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_cache_manager
|
|
||||||
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.4.1"
|
|
||||||
flutter_colorpicker:
|
flutter_colorpicker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -890,6 +874,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.2.2"
|
||||||
|
http_client_helper:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_client_helper
|
||||||
|
sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1086,10 +1078,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: livekit_client
|
name: livekit_client
|
||||||
sha256: a3ff529fe6745ee40cdedcd021d81c4a6ad946dd495e782596f2856eeeabc739
|
sha256: "7cdeb3eaeec7fb70a4cf88d9caabccbef9e3bd5f0b23c086320bc5c9acb2770b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.3"
|
version: "2.3.4"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1250,14 +1242,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.0"
|
||||||
octo_image:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: octo_image
|
|
||||||
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.0"
|
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1546,14 +1530,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
rxdart:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: rxdart
|
|
||||||
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.28.0"
|
|
||||||
safe_local_storage:
|
safe_local_storage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1767,46 +1743,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
version: "7.0.0"
|
||||||
sqflite:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sqflite
|
|
||||||
sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.1"
|
|
||||||
sqflite_android:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sqflite_android
|
|
||||||
sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.0"
|
|
||||||
sqflite_common:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sqflite_common
|
|
||||||
sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.5.4+6"
|
|
||||||
sqflite_darwin:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sqflite_darwin
|
|
||||||
sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.1"
|
|
||||||
sqflite_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sqflite_platform_interface
|
|
||||||
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.0"
|
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2.2.1+40
|
version: 2.2.1+42
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
@ -53,7 +53,6 @@ dependencies:
|
|||||||
markdown: ^7.2.2
|
markdown: ^7.2.2
|
||||||
flutter_markdown: ^0.7.4+1
|
flutter_markdown: ^0.7.4+1
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
cached_network_image: ^3.4.1
|
|
||||||
flutter_animate: ^4.5.0
|
flutter_animate: ^4.5.0
|
||||||
syntax_highlight: ^0.4.0
|
syntax_highlight: ^0.4.0
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
@ -116,6 +115,7 @@ dependencies:
|
|||||||
flutter_webrtc: ^0.12.5+hotfix.1
|
flutter_webrtc: ^0.12.5+hotfix.1
|
||||||
slide_countdown: ^2.0.2
|
slide_countdown: ^2.0.2
|
||||||
video_compress: ^3.1.3
|
video_compress: ^3.1.3
|
||||||
|
extended_image: ^9.0.9
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user