mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-09-01 07:04:07 +00:00
fix issue with media shares via intent
This commit is contained in:
parent
280519d63a
commit
0c16188877
5 changed files with 89 additions and 53 deletions
|
|
@ -6,6 +6,7 @@
|
|||
- Improve: Backup screen clearer and easier to understand
|
||||
- Improve: Show username above messages in group chats
|
||||
- Fix: Background audio correctly pauses and resumes when viewing videos
|
||||
- Fix: Multiple bug fixes
|
||||
|
||||
## 0.5.0
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:twonly/globals.dart';
|
|||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/keyvalue.keys.dart';
|
||||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
||||
import 'package:twonly/src/model/json/onboarding_state.model.dart';
|
||||
import 'package:twonly/src/providers/routing.provider.dart';
|
||||
|
|
@ -180,9 +181,17 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
|||
}
|
||||
});
|
||||
|
||||
void handleShareMedia(String path, MediaType type) {
|
||||
HomeViewState.pendingSharedMedia = (path, type);
|
||||
routerProvider.go(Routes.home);
|
||||
HomeViewState.streamHomeViewPageIndex.add(0);
|
||||
HomeViewState.streamSharedMedia.add((path, type));
|
||||
}
|
||||
|
||||
_intentStreamSub = initIntentStreams(
|
||||
context,
|
||||
handleShareLink,
|
||||
handleShareMedia,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,11 +227,19 @@ Future<void> finishStartedPreprocessing() async {
|
|||
mediaFile.mediaId,
|
||||
);
|
||||
if (messages.isEmpty) {
|
||||
if (mediaFile.createdAt.isBefore(
|
||||
clock.now().subtract(const Duration(hours: 1)),
|
||||
)) {
|
||||
Log.info(
|
||||
'Deleted orphaned media file ${mediaFile.mediaId} as no messages reference it.',
|
||||
);
|
||||
MediaFileService(mediaFile).fullMediaRemoval();
|
||||
await twonlyDB.mediaFilesDao.deleteMediaFile(mediaFile.mediaId);
|
||||
} else {
|
||||
Log.info(
|
||||
'Media file ${mediaFile.mediaId} has no messages, but is too new to be deleted by finishStartedPreprocessing. Skipping.',
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -484,12 +492,20 @@ Future<void> _startBackgroundMediaUploadInternal(
|
|||
mediaService.mediaFile.mediaId,
|
||||
);
|
||||
if (messages.isEmpty) {
|
||||
if (mediaService.mediaFile.createdAt.isBefore(
|
||||
clock.now().subtract(const Duration(hours: 1)),
|
||||
)) {
|
||||
Log.warn(
|
||||
'Media files ${mediaService.mediaFile.mediaId} has no original, temp, or stored path. Removing it from DB as files are not existent.',
|
||||
);
|
||||
await twonlyDB.mediaFilesDao.deleteMediaFile(
|
||||
mediaService.mediaFile.mediaId,
|
||||
);
|
||||
} else {
|
||||
Log.warn(
|
||||
'Media files ${mediaService.mediaFile.mediaId} has no paths, but is too new to be deleted. Skipping deletion.',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Log.warn(
|
||||
'Media files ${mediaService.mediaFile.mediaId} has no original, temp, or stored path, but messages still reference it. Marking as uploaded to stop retries.',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -12,7 +10,6 @@ import 'package:twonly/locator.dart';
|
|||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/services/api/mediafiles/upload.api.dart';
|
||||
import 'package:twonly/src/services/passwordless_recovery.service.dart'
|
||||
show PasswordlessRecoveryService;
|
||||
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||
|
|
@ -20,7 +17,6 @@ import 'package:twonly/src/utils/log.dart';
|
|||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/qr.utils.dart';
|
||||
import 'package:twonly/src/visual/components/alert.dialog.dart';
|
||||
import 'package:twonly/src/visual/views/camera/share_image_editor.view.dart';
|
||||
import 'package:twonly/src/visual/views/contact/add_contact_via_qr_link.view.dart';
|
||||
import 'package:twonly/src/visual/views/contact/add_new_contact.view.dart';
|
||||
|
||||
|
|
@ -149,53 +145,20 @@ Future<void> _pubKeysDoNotMatch(BuildContext context, String username) async {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> handleIntentMediaFile(
|
||||
BuildContext context,
|
||||
String filePath,
|
||||
MediaType type,
|
||||
) async {
|
||||
final file = File(filePath);
|
||||
if (!file.existsSync()) {
|
||||
Log.error('The shared intent file does not exits.');
|
||||
return;
|
||||
}
|
||||
|
||||
final newMediaService = await initializeMediaUpload(
|
||||
type,
|
||||
userService.currentUser.defaultShowTime,
|
||||
);
|
||||
if (newMediaService == null) {
|
||||
Log.error('Could not create new media file for intent shared file');
|
||||
return;
|
||||
}
|
||||
|
||||
file.copySync(newMediaService.originalPath.path);
|
||||
if (!context.mounted) return;
|
||||
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ShareImageEditorView(
|
||||
mediaFileService: newMediaService,
|
||||
sharedFromGallery: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
StreamSubscription<List<SharedFile>> initIntentStreams(
|
||||
BuildContext context,
|
||||
void Function(Uri) onUrlCallBack,
|
||||
void Function(String, MediaType) onMediaCallBack,
|
||||
) {
|
||||
FlutterSharingIntent.instance.getInitialSharing().then((f) {
|
||||
if (!context.mounted) return;
|
||||
handleIntentSharedFile(context, f, onUrlCallBack);
|
||||
handleIntentSharedFile(context, f, onUrlCallBack, onMediaCallBack);
|
||||
});
|
||||
|
||||
return FlutterSharingIntent.instance.getMediaStream().listen(
|
||||
(f) {
|
||||
if (!context.mounted) return;
|
||||
handleIntentSharedFile(context, f, onUrlCallBack);
|
||||
handleIntentSharedFile(context, f, onUrlCallBack, onMediaCallBack);
|
||||
},
|
||||
// ignore: inference_failure_on_untyped_parameter
|
||||
onError: (err) {
|
||||
|
|
@ -208,6 +171,7 @@ Future<void> handleIntentSharedFile(
|
|||
BuildContext context,
|
||||
List<SharedFile> files,
|
||||
void Function(Uri) onUrlCallBack,
|
||||
void Function(String, MediaType) onMediaCallBack,
|
||||
) async {
|
||||
for (final file in files) {
|
||||
if (file.value == null) {
|
||||
|
|
@ -231,9 +195,9 @@ Future<void> handleIntentSharedFile(
|
|||
if (file.value!.endsWith('.gif')) {
|
||||
type = MediaType.gif;
|
||||
}
|
||||
await handleIntentMediaFile(context, file.value!, type);
|
||||
onMediaCallBack(file.value!, type);
|
||||
case SharedMediaType.VIDEO:
|
||||
await handleIntentMediaFile(context, file.value!, MediaType.video);
|
||||
onMediaCallBack(file.value!, MediaType.video);
|
||||
// ignore: no_default_cases
|
||||
default:
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -9,7 +10,9 @@ import 'package:permission_handler/permission_handler.dart';
|
|||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/locator.dart';
|
||||
import 'package:twonly/src/constants/routes.keys.dart';
|
||||
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||
import 'package:twonly/src/providers/routing.provider.dart';
|
||||
import 'package:twonly/src/services/api/mediafiles/upload.api.dart';
|
||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
|
|
@ -47,10 +50,14 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
|||
StreamSubscription<RemoteMessage>? _onMessageOpenedAppSub;
|
||||
StreamSubscription<int>? _homeViewPageIndexSub;
|
||||
StreamSubscription<NotificationResponse>? _selectNotificationSub;
|
||||
StreamSubscription<(String, MediaType)>? _sharedMediaSub;
|
||||
|
||||
static Uri? pendingSharedLink;
|
||||
static (String, MediaType)? pendingSharedMedia;
|
||||
static final streamHomeViewPageIndex = StreamController<int>.broadcast();
|
||||
static final streamSharedLink = StreamController<Uri>.broadcast();
|
||||
static final streamSharedMedia =
|
||||
StreamController<(String, MediaType)>.broadcast();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -59,6 +66,8 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
|||
var initialPage = widget.initialPage;
|
||||
if (HomeViewState.pendingSharedLink != null) {
|
||||
initialPage = 1;
|
||||
} else if (HomeViewState.pendingSharedMedia != null) {
|
||||
initialPage = 0;
|
||||
} else if (initialPage == 1 &&
|
||||
!userService.currentUser.startWithCameraOpen) {
|
||||
initialPage = 0;
|
||||
|
|
@ -114,12 +123,48 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
|||
});
|
||||
});
|
||||
|
||||
_sharedMediaSub = streamSharedMedia.stream.listen((media) async {
|
||||
HomeViewState.pendingSharedMedia = null;
|
||||
final type = media.$2;
|
||||
final filePath = media.$1;
|
||||
|
||||
final newMediaService = await initializeMediaUpload(
|
||||
type,
|
||||
userService.currentUser.defaultShowTime,
|
||||
);
|
||||
if (newMediaService == null) {
|
||||
Log.error('Could not create new media file for intent shared file');
|
||||
return;
|
||||
}
|
||||
|
||||
final file = File(filePath);
|
||||
if (!file.existsSync()) {
|
||||
Log.error('The shared intent file does not exist.');
|
||||
return;
|
||||
}
|
||||
file.copySync(newMediaService.originalPath.path);
|
||||
if (!mounted) return;
|
||||
|
||||
await context.navPush(
|
||||
ShareImageEditorView(
|
||||
mediaFileService: newMediaService,
|
||||
sharedFromGallery: true,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
if (HomeViewState.pendingSharedLink != null) {
|
||||
final link = HomeViewState.pendingSharedLink!;
|
||||
HomeViewState.pendingSharedLink = null;
|
||||
_mainCameraController.setSharedLinkForPreview(link);
|
||||
}
|
||||
|
||||
if (HomeViewState.pendingSharedMedia != null) {
|
||||
final media = HomeViewState.pendingSharedMedia!;
|
||||
HomeViewState.pendingSharedMedia = null;
|
||||
streamSharedMedia.add(media);
|
||||
}
|
||||
|
||||
if (initialPage == 1) {
|
||||
Permission.camera.isGranted.then((hasPermission) {
|
||||
if (hasPermission && mounted) {
|
||||
|
|
@ -204,6 +249,7 @@ class HomeViewState extends State<HomeView> with WidgetsBindingObserver {
|
|||
_mainCameraController.setState = null;
|
||||
_mainCameraController.closeCamera();
|
||||
_sharedLinkSub?.cancel();
|
||||
_sharedMediaSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue