⚡ Improved attachments
This commit is contained in:
parent
a651350104
commit
e96b49e3cd
@ -61,6 +61,9 @@ PODS:
|
||||
- SDWebImage (5.19.2):
|
||||
- SDWebImage/Core (= 5.19.2)
|
||||
- SDWebImage/Core (5.19.2)
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SwiftyGif (5.4.5)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
@ -84,6 +87,7 @@ DEPENDENCIES:
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
@ -121,6 +125,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/darwin"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
video_player_avfoundation:
|
||||
@ -144,6 +150,7 @@ SPEC CHECKSUMS:
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
SDWebImage: dfe95b2466a9823cf9f0c6d01217c06550d7b29a
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
|
||||
|
39
lib/platform.dart
Normal file
39
lib/platform.dart
Normal file
@ -0,0 +1,39 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
abstract class PlatformInfo {
|
||||
static bool get isWeb => kIsWeb;
|
||||
|
||||
static bool get isLinux => !kIsWeb && Platform.isLinux;
|
||||
|
||||
static bool get isWindows => !kIsWeb && Platform.isWindows;
|
||||
|
||||
static bool get isMacOS => !kIsWeb && Platform.isMacOS;
|
||||
|
||||
static bool get isIOS => !kIsWeb && Platform.isIOS;
|
||||
|
||||
static bool get isAndroid => !kIsWeb && Platform.isAndroid;
|
||||
|
||||
static bool get isMobile => isAndroid || isIOS;
|
||||
|
||||
// Not first tier supported platform
|
||||
static bool get isBetaDesktop => isWindows || isLinux;
|
||||
|
||||
static bool get isDesktop => isLinux || isWindows || isMacOS;
|
||||
|
||||
static bool get useTouchscreen => !isMobile;
|
||||
|
||||
static bool get canCacheImage => isAndroid || isIOS || isMacOS;
|
||||
|
||||
static bool get canRecord => (isMobile || isMacOS);
|
||||
|
||||
static Future<String> getVersion() async {
|
||||
var version = kIsWeb ? 'Web' : 'Unknown';
|
||||
try {
|
||||
version = (await PackageInfo.fromPlatform()).version;
|
||||
} catch (_) {}
|
||||
return version;
|
||||
}
|
||||
}
|
@ -72,7 +72,7 @@ class AuthProvider extends GetConnect {
|
||||
String username,
|
||||
String password,
|
||||
) async {
|
||||
_cacheUserProfileResponse = null;
|
||||
_cachedUserProfileResponse = null;
|
||||
|
||||
final resp = await oauth2.resourceOwnerPasswordGrant(
|
||||
tokenEndpoint,
|
||||
@ -105,7 +105,7 @@ class AuthProvider extends GetConnect {
|
||||
}
|
||||
|
||||
void signout() {
|
||||
_cacheUserProfileResponse = null;
|
||||
_cachedUserProfileResponse = null;
|
||||
|
||||
Get.find<ChatProvider>().disconnect();
|
||||
Get.find<AccountProvider>().disconnect();
|
||||
@ -115,13 +115,13 @@ class AuthProvider extends GetConnect {
|
||||
storage.deleteAll();
|
||||
}
|
||||
|
||||
Response? _cacheUserProfileResponse;
|
||||
Response? _cachedUserProfileResponse;
|
||||
|
||||
Future<bool> get isAuthorized => storage.containsKey(key: 'auth_credentials');
|
||||
|
||||
Future<Response> getProfile({noCache = false}) async {
|
||||
if (!noCache && _cacheUserProfileResponse != null) {
|
||||
return _cacheUserProfileResponse!;
|
||||
if (!noCache && _cachedUserProfileResponse != null) {
|
||||
return _cachedUserProfileResponse!;
|
||||
}
|
||||
|
||||
final client = GetConnect(maxAuthRetries: 3);
|
||||
@ -132,7 +132,7 @@ class AuthProvider extends GetConnect {
|
||||
if (resp.statusCode != 200) {
|
||||
throw Exception(resp.bodyString);
|
||||
} else {
|
||||
_cacheUserProfileResponse = resp;
|
||||
_cachedUserProfileResponse = resp;
|
||||
}
|
||||
|
||||
return resp;
|
||||
|
@ -25,14 +25,25 @@ Future<double> calculateFileAspectRatio(File file) async {
|
||||
}
|
||||
|
||||
class AttachmentProvider extends GetConnect {
|
||||
static Map<String, String> mimetypeOverrides = {'mov': 'video/quicktime'};
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
httpClient.baseUrl = ServiceFinder.services['paperclip'];
|
||||
}
|
||||
|
||||
static Map<String, String> mimetypeOverrides = {'mov': 'video/quicktime'};
|
||||
final Map<int, Response> _cachedResponses = {};
|
||||
|
||||
Future<Response> getMetadata(int id) => get('/api/attachments/$id/meta');
|
||||
Future<Response> getMetadata(int id, {noCache = false}) async {
|
||||
if (!noCache && _cachedResponses.containsKey(id)) {
|
||||
return _cachedResponses[id]!;
|
||||
}
|
||||
|
||||
final resp = await get('/api/attachments/$id/meta');
|
||||
_cachedResponses[id] = resp;
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
Future<Response> createAttachment(File file, String hash, String usage,
|
||||
{double? ratio}) async {
|
||||
@ -122,4 +133,12 @@ class AttachmentProvider extends GetConnect {
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
void clearCache({int? id}) {
|
||||
if (id != null) {
|
||||
_cachedResponses.remove(id);
|
||||
} else {
|
||||
_cachedResponses.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,13 +155,32 @@ class SolianMessages extends Translations {
|
||||
'Are your sure to delete message @id? This action cannot be undone!',
|
||||
'callOngoing': 'A call is ongoing...',
|
||||
'callJoin': 'Join',
|
||||
'callResume': 'Resume',
|
||||
'callMicrophone': 'Microphone',
|
||||
'callMicrophoneDisabled': 'Microphone Disabled',
|
||||
'callMicrophoneSelect': 'Select Microphone',
|
||||
'callCamera': 'Camera',
|
||||
'callCameraDisabled': 'Camera Disabled',
|
||||
'callCameraSelect': 'Select Camera',
|
||||
'callDisconnected': 'Call has been disconnected... @reason',
|
||||
'callSpeakerSelect': 'Select Speaker',
|
||||
'callDisconnected': 'Call Disconnected... @reason',
|
||||
'callMicrophoneOn': 'Turn Microphone On',
|
||||
'callMicrophoneOff': 'Turn Microphone Off',
|
||||
'callCameraOn': 'Turn Camera On',
|
||||
'callCameraOff': 'Turn Camera Off',
|
||||
'callVideoFlip': 'Flip Video Input',
|
||||
'callSpeakerphoneToggle': 'Toggle Speakerphone Mode',
|
||||
'callScreenOn': 'Start Screen Sharing',
|
||||
'callScreenOff': 'Stop Screen Sharing',
|
||||
'callDisconnect': 'Disconnect',
|
||||
'callDisconnectCaption':
|
||||
'Are you sure you want to disconnect from this call? You can also just return to the page, and the call will continue in the background.',
|
||||
'callParticipantAction': 'Participant Actions',
|
||||
'callParticipantMicrophoneOff': 'Mute Participant',
|
||||
'callParticipantMicrophoneOn': 'Unmute Participant',
|
||||
'callParticipantVideoOff': 'Turn Off Participant Video',
|
||||
'callParticipantVideoOn': 'Turn On Participant Video',
|
||||
'callAlreadyOngoing': 'A call is already ongoing',
|
||||
},
|
||||
'zh_CN': {
|
||||
'hide': '隐藏',
|
||||
|
@ -1,4 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:solian/platform.dart';
|
||||
import 'package:solian/services.dart';
|
||||
|
||||
class AccountAvatar extends StatelessWidget {
|
||||
@ -25,16 +27,18 @@ class AccountAvatar extends StatelessWidget {
|
||||
if (!isEmpty) isEmpty = content.endsWith('/api/attachments/0');
|
||||
}
|
||||
|
||||
final url = direct
|
||||
? content
|
||||
: '${ServiceFinder.services['paperclip']}/api/attachments/$content';
|
||||
|
||||
return CircleAvatar(
|
||||
key: Key('a$content'),
|
||||
radius: radius,
|
||||
backgroundColor: bgColor,
|
||||
backgroundImage: !isEmpty
|
||||
? NetworkImage(
|
||||
direct
|
||||
? content
|
||||
: '${ServiceFinder.services['paperclip']}/api/attachments/$content',
|
||||
)
|
||||
? (PlatformInfo.canCacheImage
|
||||
? CachedNetworkImageProvider(url)
|
||||
: NetworkImage(url)) as ImageProvider<Object>?
|
||||
: null,
|
||||
child: isEmpty
|
||||
? Icon(
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:chewie/chewie.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:solian/models/attachment.dart';
|
||||
import 'package:solian/platform.dart';
|
||||
import 'package:solian/services.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
@ -61,10 +63,33 @@ class _AttachmentItemState extends State<AttachmentItem> {
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.network(
|
||||
'${ServiceFinder.services['paperclip']}/api/attachments/${widget.item.id}',
|
||||
fit: widget.fit,
|
||||
),
|
||||
if (PlatformInfo.canCacheImage)
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
'${ServiceFinder.services['paperclip']}/api/attachments/${widget.item.id}',
|
||||
progressIndicatorBuilder: (context, url, downloadProgress) =>
|
||||
CircularProgressIndicator(
|
||||
value: downloadProgress.progress,
|
||||
),
|
||||
fit: widget.fit,
|
||||
)
|
||||
else
|
||||
Image.network(
|
||||
'${ServiceFinder.services['paperclip']}/api/attachments/${widget.item.id}',
|
||||
fit: widget.fit,
|
||||
loadingBuilder: (BuildContext context, Widget child,
|
||||
ImageChunkEvent? loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (widget.showBadge && widget.badge != null)
|
||||
Positioned(
|
||||
right: 12,
|
||||
|
@ -390,12 +390,16 @@ class _AttachmentEditingDialogState extends State<AttachmentEditingDialog> {
|
||||
: null,
|
||||
isMature: _isMature,
|
||||
);
|
||||
|
||||
Get.find<AttachmentProvider>().clearCache(id: widget.item.id);
|
||||
|
||||
setState(() => _isBusy = false);
|
||||
return Attachment.fromJson(resp.body);
|
||||
} catch (e) {
|
||||
context.showErrorDialog(e);
|
||||
return null;
|
||||
} finally {
|
||||
|
||||
setState(() => _isBusy = false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import flutter_webrtc
|
||||
import livekit_client
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import sqflite
|
||||
import url_launcher_macos
|
||||
import video_player_avfoundation
|
||||
import wakelock_plus
|
||||
@ -28,6 +29,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||
|
64
pubspec.lock
64
pubspec.lock
@ -33,6 +33,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
cached_network_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
cached_network_image_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
cached_network_image_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
carousel_slider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -278,6 +302,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
flutter_cache_manager:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "395d6b7831f21f3b989ebedbb785545932adb9afe2622c1ffacf7f4b53a7e544"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.2"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -680,6 +712,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
octo_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: octo_image
|
||||
sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -856,6 +896,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: rxdart
|
||||
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.27.7"
|
||||
sdp_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -893,6 +941,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.3+1"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -64,6 +64,7 @@ dependencies:
|
||||
flutter_webrtc: ^0.10.7
|
||||
wakelock_plus: ^1.2.5
|
||||
flutter_background: ^1.2.0
|
||||
cached_network_image: ^3.3.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user