mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 07:48:40 +00:00
commit
112f7feb7d
11 changed files with 114 additions and 57 deletions
|
|
@ -241,7 +241,7 @@ PODS:
|
|||
- sqlite3/perf-threadsafe
|
||||
- sqlite3/rtree
|
||||
- sqlite3/session
|
||||
- SwiftProtobuf (1.32.0)
|
||||
- SwiftProtobuf (1.33.1)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- video_player_avfoundation (0.0.1):
|
||||
|
|
@ -421,7 +421,7 @@ SPEC CHECKSUMS:
|
|||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
||||
SwiftProtobuf: 81e341191afbddd64aa031bd12862dccfab2f639
|
||||
SwiftProtobuf: 533a18409c3ca3a6156b2b1e46afd0f69e751aba
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ final lockRetransStore = Mutex();
|
|||
/// errors or network changes.
|
||||
class ApiService {
|
||||
ApiService();
|
||||
// final String apiHost = kReleaseMode ? 'api.twonly.eu' : '10.99.0.140:3030';
|
||||
final String apiHost = kReleaseMode ? 'api.twonly.eu' : 'dev.twonly.eu';
|
||||
final String apiSecure = kReleaseMode ? 's' : 's';
|
||||
final String apiHost = kReleaseMode ? 'api.twonly.eu' : '10.99.0.140:3030';
|
||||
// final String apiHost = kReleaseMode ? 'api.twonly.eu' : 'dev.twonly.eu';
|
||||
final String apiSecure = kReleaseMode ? 's' : '';
|
||||
|
||||
bool appIsOutdated = false;
|
||||
bool isAuthenticated = false;
|
||||
|
|
|
|||
|
|
@ -66,15 +66,23 @@ Future<void> handleMedia(
|
|||
mediaType = MediaType.audio;
|
||||
}
|
||||
|
||||
int? displayLimitInMilliseconds;
|
||||
if (media.hasDisplayLimitInMilliseconds()) {
|
||||
if (media.displayLimitInMilliseconds.toInt() < 1000) {
|
||||
displayLimitInMilliseconds =
|
||||
media.displayLimitInMilliseconds.toInt() * 1000;
|
||||
} else {
|
||||
displayLimitInMilliseconds = media.displayLimitInMilliseconds.toInt();
|
||||
}
|
||||
}
|
||||
|
||||
final mediaFile = await twonlyDB.mediaFilesDao.insertMedia(
|
||||
MediaFilesCompanion(
|
||||
downloadState: const Value(DownloadState.pending),
|
||||
type: Value(mediaType),
|
||||
requiresAuthentication: Value(media.requiresAuthentication),
|
||||
displayLimitInMilliseconds: Value(
|
||||
media.hasDisplayLimitInMilliseconds()
|
||||
? media.displayLimitInMilliseconds.toInt()
|
||||
: null,
|
||||
displayLimitInMilliseconds,
|
||||
),
|
||||
downloadToken: Value(Uint8List.fromList(media.downloadToken)),
|
||||
encryptionKey: Value(Uint8List.fromList(media.encryptionKey)),
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ Future<MediaFileService?> initializeMediaUpload(
|
|||
int? displayLimitInMilliseconds, {
|
||||
bool isDraftMedia = false,
|
||||
}) async {
|
||||
if (displayLimitInMilliseconds != null && displayLimitInMilliseconds < 1000) {
|
||||
// in case the time was set in seconds...
|
||||
// ignore: parameter_assignments
|
||||
displayLimitInMilliseconds = displayLimitInMilliseconds * 1000;
|
||||
}
|
||||
final chacha20 = FlutterChacha20.poly1305Aead();
|
||||
final encryptionKey = await (await chacha20.newSecretKey()).extract();
|
||||
final encryptionNonce = chacha20.newNonce();
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class MediaFileService {
|
|||
MediaFilesCompanion(
|
||||
requiresAuthentication: Value(requiresAuthentication),
|
||||
displayLimitInMilliseconds:
|
||||
requiresAuthentication ? const Value(12) : const Value.absent(),
|
||||
requiresAuthentication ? const Value(12000) : const Value.absent(),
|
||||
),
|
||||
);
|
||||
await updateFromDB();
|
||||
|
|
|
|||
|
|
@ -362,36 +362,49 @@ Future<Uint8List?> encryptPushNotification(
|
|||
|
||||
Future<List<PushUser>> getPushKeys(String storageKey) async {
|
||||
const storage = FlutterSecureStorage();
|
||||
final pushKeysProto = await storage.read(
|
||||
key: storageKey,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
if (pushKeysProto == null) return [];
|
||||
final pushKeysRaw = base64Decode(pushKeysProto);
|
||||
return PushUsers.fromBuffer(pushKeysRaw).users;
|
||||
try {
|
||||
final pushKeysProto = await storage.read(
|
||||
key: storageKey,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
if (pushKeysProto == null) return [];
|
||||
final pushKeysRaw = base64Decode(pushKeysProto);
|
||||
return PushUsers.fromBuffer(pushKeysRaw).users;
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
Future<void> setPushKeys(String storageKey, List<PushUser> pushKeys) async {
|
||||
const storage = FlutterSecureStorage();
|
||||
|
||||
await storage.delete(
|
||||
key: storageKey,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
try {
|
||||
await storage.delete(
|
||||
key: storageKey,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
|
||||
final jsonString = base64Encode(PushUsers(users: pushKeys).writeToBuffer());
|
||||
await storage.write(
|
||||
key: storageKey,
|
||||
value: jsonString,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
try {
|
||||
await storage.write(
|
||||
key: storageKey,
|
||||
value: jsonString,
|
||||
iOptions: const IOSOptions(
|
||||
groupId: 'CN332ZUGRP.eu.twonly.shared',
|
||||
accessibility: KeychainAccessibility.first_unlock,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
? '0'
|
||||
: media.displayLimitInMilliseconds == null
|
||||
? '∞'
|
||||
: media.displayLimitInMilliseconds.toString(),
|
||||
: (media.displayLimitInMilliseconds! ~/ 1000).toString(),
|
||||
child: ActionButton(
|
||||
(media.type == MediaType.video)
|
||||
? media.displayLimitInMilliseconds == null
|
||||
|
|
@ -211,11 +211,13 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
}
|
||||
int? maxShowTime;
|
||||
if (media.displayLimitInMilliseconds == null) {
|
||||
maxShowTime = 1;
|
||||
} else if (media.displayLimitInMilliseconds == 1) {
|
||||
maxShowTime = 5;
|
||||
} else if (media.displayLimitInMilliseconds == 5) {
|
||||
maxShowTime = 20;
|
||||
maxShowTime = 1000;
|
||||
} else if (media.displayLimitInMilliseconds == 1000) {
|
||||
maxShowTime = 5000;
|
||||
} else if (media.displayLimitInMilliseconds == 5000) {
|
||||
maxShowTime = 12000;
|
||||
} else if (media.displayLimitInMilliseconds == 12000) {
|
||||
maxShowTime = 20000;
|
||||
}
|
||||
await mediaService.setDisplayLimit(maxShowTime);
|
||||
if (!mounted) return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
|
@ -54,7 +55,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
|
||||
bool imageSaved = false;
|
||||
bool imageSaving = false;
|
||||
bool displayTwonlyPresent = true;
|
||||
bool displayTwonlyPresent = false;
|
||||
final emojiKey = GlobalKey<EmojiFloatWidgetState>();
|
||||
|
||||
StreamSubscription<MediaFile?>? downloadStateListener;
|
||||
|
|
@ -63,6 +64,8 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
late StreamSubscription<List<Message>> _subscription;
|
||||
TextEditingController textMessageController = TextEditingController();
|
||||
|
||||
final HashSet<String> _alreadyOpenedMediaIds = HashSet();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
@ -92,6 +95,13 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
|
||||
_subscription = messages.listen((messages) async {
|
||||
for (final msg in messages) {
|
||||
if (_alreadyOpenedMediaIds.contains(msg.mediaId)) {
|
||||
continue;
|
||||
}
|
||||
if (msg.mediaId == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg.mediaId == currentMedia?.mediaFile.mediaId) {
|
||||
// The update of the current Media in case of a download is done in loadCurrentMediaFile
|
||||
continue;
|
||||
|
|
@ -195,13 +205,17 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
bool showTwonly,
|
||||
) async {
|
||||
if (allMediaFiles.isEmpty) return;
|
||||
currentMessage = allMediaFiles.removeAt(0);
|
||||
final currentMediaLocal =
|
||||
await MediaFileService.fromMediaId(currentMessage!.mediaId!);
|
||||
await MediaFileService.fromMediaId(allMediaFiles.first.mediaId!);
|
||||
if (currentMediaLocal == null || !mounted) return;
|
||||
|
||||
if (currentMediaLocal.mediaFile.requiresAuthentication) {
|
||||
if (!showTwonly) return;
|
||||
if (!showTwonly) {
|
||||
setState(() {
|
||||
displayTwonlyPresent = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final isAuth = await authenticateUser(
|
||||
context.lang.mediaViewerAuthReason,
|
||||
|
|
@ -209,10 +223,20 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
);
|
||||
if (!isAuth) {
|
||||
await nextMediaOrExit();
|
||||
setState(() {
|
||||
displayTwonlyPresent = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_alreadyOpenedMediaIds.add(allMediaFiles.first.mediaId!);
|
||||
currentMessage = allMediaFiles.removeAt(0);
|
||||
|
||||
setState(() {
|
||||
displayTwonlyPresent = false;
|
||||
});
|
||||
|
||||
await notifyContactAboutOpeningMessage(
|
||||
currentMessage!.senderId!,
|
||||
[currentMessage!.messageId],
|
||||
|
|
@ -490,9 +514,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (currentMedia != null &&
|
||||
currentMedia!.mediaFile.requiresAuthentication &&
|
||||
displayTwonlyPresent)
|
||||
if (displayTwonlyPresent)
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
|
|
|
|||
15
pubspec.lock
15
pubspec.lock
|
|
@ -705,18 +705,19 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: flutter_secure_storage
|
||||
ref: "71b75a36f35f2ce945998e20c6c6aa1820babfc6"
|
||||
resolved-ref: "71b75a36f35f2ce945998e20c6c6aa1820babfc6"
|
||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
||||
resolved-ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
||||
url: "https://github.com/juliansteenbakker/flutter_secure_storage.git"
|
||||
source: git
|
||||
version: "10.0.0-beta.4"
|
||||
flutter_secure_storage_darwin:
|
||||
dependency: transitive
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
name: flutter_secure_storage_darwin
|
||||
sha256: f226f2a572bed96bc6542198ebaec227150786e34311d455a7e2d3d06d951845
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
path: flutter_secure_storage_darwin
|
||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
||||
resolved-ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
||||
url: "https://github.com/juliansteenbakker/flutter_secure_storage.git"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
|
|
|
|||
10
pubspec.yaml
10
pubspec.yaml
|
|
@ -3,7 +3,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec
|
|||
|
||||
publish_to: 'none'
|
||||
|
||||
version: 0.0.64+64
|
||||
version: 0.0.66+66
|
||||
|
||||
environment:
|
||||
sdk: ^3.6.0
|
||||
|
|
@ -36,7 +36,7 @@ dependencies:
|
|||
flutter_secure_storage:
|
||||
git:
|
||||
url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
||||
ref: 71b75a36f35f2ce945998e20c6c6aa1820babfc6 # from develop
|
||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
||||
path: flutter_secure_storage/
|
||||
flutter_svg: ^2.0.17
|
||||
flutter_volume_controller: ^1.3.4
|
||||
|
|
@ -77,6 +77,12 @@ dependencies:
|
|||
|
||||
dependency_overrides:
|
||||
|
||||
flutter_secure_storage_darwin:
|
||||
git:
|
||||
url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
||||
path: flutter_secure_storage_darwin/
|
||||
|
||||
flutter_android_volume_keydown:
|
||||
git:
|
||||
url: https://github.com/yenchieh/flutter_android_volume_keydown.git
|
||||
|
|
|
|||
Loading…
Reference in a new issue