restructure of the files

This commit is contained in:
otsmr 2025-05-30 17:24:02 +02:00
parent 608477d07d
commit 9264d5a4b3
66 changed files with 414 additions and 399 deletions

View file

@ -1,13 +1,13 @@
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/localization/generated/app_localizations.dart'; import 'package:twonly/src/localization/generated/app_localizations.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/providers/settings_change_provider.dart'; import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/onboarding/onboarding_view.dart'; import 'package:twonly/src/views/onboarding.view.dart';
import 'package:twonly/src/views/home_view.dart'; import 'package:twonly/src/views/home.view.dart';
import 'package:twonly/src/views/onboarding/register_view.dart'; import 'package:twonly/src/views/register.view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'dart:async'; import 'dart:async';
@ -54,7 +54,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
globalBestFriendUserId = -1; globalBestFriendUserId = -1;
if (user != null && context.mounted) { if (user != null && context.mounted) {
if (user.myBestFriendContactId != null) { if (user.myBestFriendContactId != null) {
final contact = await twonlyDatabase.contactsDao final contact = await twonlyDB.contactsDao
.getContactByUserId(user.myBestFriendContactId!) .getContactByUserId(user.myBestFriendContactId!)
.getSingleOrNull(); .getSingleOrNull();
if (contact != null) { if (contact != null) {
@ -69,7 +69,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
Future initAsync() async { Future initAsync() async {
setUserPlan(); setUserPlan();
apiProvider.connect(); apiService.connect();
} }
@override @override
@ -78,8 +78,8 @@ class _AppState extends State<App> with WidgetsBindingObserver {
if (state == AppLifecycleState.resumed) { if (state == AppLifecycleState.resumed) {
if (wasPaused) { if (wasPaused) {
globalIsAppInBackground = false; globalIsAppInBackground = false;
twonlyDatabase.markUpdated(); twonlyDB.markUpdated();
apiProvider.connect(); apiService.connect();
} }
} else if (state == AppLifecycleState.paused) { } else if (state == AppLifecycleState.paused) {
wasPaused = true; wasPaused = true;

View file

@ -1,10 +1,10 @@
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api_provider.dart'; import 'package:twonly/src/services/api.service.dart';
late ApiProvider apiProvider; late ApiService apiService;
// uses for background notification // uses for background notification
late TwonlyDatabase twonlyDatabase; late TwonlyDatabase twonlyDB;
List<CameraDescription> gCameras = <CameraDescription>[]; List<CameraDescription> gCameras = <CameraDescription>[];

View file

@ -3,16 +3,16 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:twonly/src/providers/api_provider.dart'; import 'package:twonly/src/services/api.service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/providers/hive.dart'; import 'package:twonly/src/utils/hive.dart';
import 'package:twonly/src/providers/settings_change_provider.dart'; import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/fcm_service.dart'; import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/log.dart';
import 'app.dart'; import 'app.dart';
void main() async { void main() async {
@ -24,16 +24,16 @@ void main() async {
// This prevents a sudden theme change when the app is first displayed. // This prevents a sudden theme change when the app is first displayed.
await settingsController.loadSettings(); await settingsController.loadSettings();
setupLogger(); initLogger();
await setupPushNotification(); await setupPushNotification();
await initMediaStorage(); await initMediaStorage();
gCameras = await availableCameras(); gCameras = await availableCameras();
apiProvider = ApiProvider(); apiService = ApiService();
twonlyDatabase = TwonlyDatabase(); twonlyDB = TwonlyDatabase();
await twonlyDatabase.messagesDao.resetPendingDownloadState(); await twonlyDB.messagesDao.resetPendingDownloadState();
await purgeReceivedMediaFiles(); await purgeReceivedMediaFiles();
await purgeSendMediaFiles(); await purgeSendMediaFiles();

View file

@ -13,7 +13,7 @@ class ConnectIdentityKeyStore extends IdentityKeyStore {
@override @override
Future<IdentityKey?> getIdentity(SignalProtocolAddress address) async { Future<IdentityKey?> getIdentity(SignalProtocolAddress address) async {
SignalIdentityKeyStore? identity = SignalIdentityKeyStore? identity =
await (twonlyDatabase.select(twonlyDatabase.signalIdentityKeyStores) await (twonlyDB.select(twonlyDB.signalIdentityKeyStores)
..where((t) => ..where((t) =>
t.deviceId.equals(address.getDeviceId()) & t.deviceId.equals(address.getDeviceId()) &
t.name.equals(address.getName()))) t.name.equals(address.getName())))
@ -47,7 +47,7 @@ class ConnectIdentityKeyStore extends IdentityKeyStore {
return false; return false;
} }
if (await getIdentity(address) == null) { if (await getIdentity(address) == null) {
await twonlyDatabase.into(twonlyDatabase.signalIdentityKeyStores).insert( await twonlyDB.into(twonlyDB.signalIdentityKeyStores).insert(
SignalIdentityKeyStoresCompanion( SignalIdentityKeyStoresCompanion(
deviceId: Value(address.getDeviceId()), deviceId: Value(address.getDeviceId()),
name: Value(address.getName()), name: Value(address.getName()),
@ -55,7 +55,7 @@ class ConnectIdentityKeyStore extends IdentityKeyStore {
), ),
); );
} else { } else {
await (twonlyDatabase.update(twonlyDatabase.signalIdentityKeyStores) await (twonlyDB.update(twonlyDB.signalIdentityKeyStores)
..where((t) => ..where((t) =>
t.deviceId.equals(address.getDeviceId()) & t.deviceId.equals(address.getDeviceId()) &
t.name.equals(address.getName()))) t.name.equals(address.getName())))

View file

@ -7,8 +7,7 @@ import 'package:twonly/src/database/twonly_database.dart';
class ConnectPreKeyStore extends PreKeyStore { class ConnectPreKeyStore extends PreKeyStore {
@override @override
Future<bool> containsPreKey(int preKeyId) async { Future<bool> containsPreKey(int preKeyId) async {
final preKeyRecord = final preKeyRecord = await (twonlyDB.select(twonlyDB.signalPreKeyStores)
await (twonlyDatabase.select(twonlyDatabase.signalPreKeyStores)
..where((tbl) => tbl.preKeyId.equals(preKeyId))) ..where((tbl) => tbl.preKeyId.equals(preKeyId)))
.get(); .get();
return preKeyRecord.isNotEmpty; return preKeyRecord.isNotEmpty;
@ -16,8 +15,7 @@ class ConnectPreKeyStore extends PreKeyStore {
@override @override
Future<PreKeyRecord> loadPreKey(int preKeyId) async { Future<PreKeyRecord> loadPreKey(int preKeyId) async {
final preKeyRecord = final preKeyRecord = await (twonlyDB.select(twonlyDB.signalPreKeyStores)
await (twonlyDatabase.select(twonlyDatabase.signalPreKeyStores)
..where((tbl) => tbl.preKeyId.equals(preKeyId))) ..where((tbl) => tbl.preKeyId.equals(preKeyId)))
.get(); .get();
if (preKeyRecord.isEmpty) { if (preKeyRecord.isEmpty) {
@ -29,7 +27,7 @@ class ConnectPreKeyStore extends PreKeyStore {
@override @override
Future<void> removePreKey(int preKeyId) async { Future<void> removePreKey(int preKeyId) async {
await (twonlyDatabase.delete(twonlyDatabase.signalPreKeyStores) await (twonlyDB.delete(twonlyDB.signalPreKeyStores)
..where((tbl) => tbl.preKeyId.equals(preKeyId))) ..where((tbl) => tbl.preKeyId.equals(preKeyId)))
.go(); .go();
} }
@ -42,9 +40,7 @@ class ConnectPreKeyStore extends PreKeyStore {
); );
try { try {
await twonlyDatabase await twonlyDB.into(twonlyDB.signalPreKeyStores).insert(preKeyCompanion);
.into(twonlyDatabase.signalPreKeyStores)
.insert(preKeyCompanion);
} catch (e) { } catch (e) {
Logger("pre_key_store").shout("$e"); Logger("pre_key_store").shout("$e");
} }

View file

@ -7,7 +7,7 @@ class ConnectSenderKeyStore extends SenderKeyStore {
@override @override
Future<SenderKeyRecord> loadSenderKey(SenderKeyName senderKeyName) async { Future<SenderKeyRecord> loadSenderKey(SenderKeyName senderKeyName) async {
SignalSenderKeyStore? identity = SignalSenderKeyStore? identity =
await (twonlyDatabase.select(twonlyDatabase.signalSenderKeyStores) await (twonlyDB.select(twonlyDB.signalSenderKeyStores)
..where((t) => t.senderKeyName.equals(senderKeyName.serialize()))) ..where((t) => t.senderKeyName.equals(senderKeyName.serialize())))
.getSingleOrNull(); .getSingleOrNull();
if (identity == null) { if (identity == null) {
@ -20,7 +20,7 @@ class ConnectSenderKeyStore extends SenderKeyStore {
@override @override
Future<void> storeSenderKey( Future<void> storeSenderKey(
SenderKeyName senderKeyName, SenderKeyRecord record) async { SenderKeyName senderKeyName, SenderKeyRecord record) async {
await twonlyDatabase.into(twonlyDatabase.signalSenderKeyStores).insert( await twonlyDB.into(twonlyDB.signalSenderKeyStores).insert(
SignalSenderKeyStoresCompanion( SignalSenderKeyStoresCompanion(
senderKey: Value(record.serialize()), senderKey: Value(record.serialize()),
senderKeyName: Value(senderKeyName.serialize()), senderKeyName: Value(senderKeyName.serialize()),

View file

@ -6,8 +6,7 @@ import 'package:twonly/src/database/twonly_database.dart';
class ConnectSessionStore extends SessionStore { class ConnectSessionStore extends SessionStore {
@override @override
Future<bool> containsSession(SignalProtocolAddress address) async { Future<bool> containsSession(SignalProtocolAddress address) async {
final sessions = final sessions = await (twonlyDB.select(twonlyDB.signalSessionStores)
await (twonlyDatabase.select(twonlyDatabase.signalSessionStores)
..where((tbl) => ..where((tbl) =>
tbl.deviceId.equals(address.getDeviceId()) & tbl.deviceId.equals(address.getDeviceId()) &
tbl.name.equals(address.getName()))) tbl.name.equals(address.getName())))
@ -17,14 +16,14 @@ class ConnectSessionStore extends SessionStore {
@override @override
Future<void> deleteAllSessions(String name) async { Future<void> deleteAllSessions(String name) async {
await (twonlyDatabase.delete(twonlyDatabase.signalSessionStores) await (twonlyDB.delete(twonlyDB.signalSessionStores)
..where((tbl) => tbl.name.equals(name))) ..where((tbl) => tbl.name.equals(name)))
.go(); .go();
} }
@override @override
Future<void> deleteSession(SignalProtocolAddress address) async { Future<void> deleteSession(SignalProtocolAddress address) async {
await (twonlyDatabase.delete(twonlyDatabase.signalSessionStores) await (twonlyDB.delete(twonlyDB.signalSessionStores)
..where((tbl) => ..where((tbl) =>
tbl.deviceId.equals(address.getDeviceId()) & tbl.deviceId.equals(address.getDeviceId()) &
tbl.name.equals(address.getName()))) tbl.name.equals(address.getName())))
@ -33,8 +32,7 @@ class ConnectSessionStore extends SessionStore {
@override @override
Future<List<int>> getSubDeviceSessions(String name) async { Future<List<int>> getSubDeviceSessions(String name) async {
final deviceIds = await (twonlyDatabase final deviceIds = await (twonlyDB.select(twonlyDB.signalSessionStores)
.select(twonlyDatabase.signalSessionStores)
..where( ..where(
(tbl) => tbl.deviceId.equals(1).not() & tbl.name.equals(name))) (tbl) => tbl.deviceId.equals(1).not() & tbl.name.equals(name)))
.get(); .get();
@ -43,8 +41,7 @@ class ConnectSessionStore extends SessionStore {
@override @override
Future<SessionRecord> loadSession(SignalProtocolAddress address) async { Future<SessionRecord> loadSession(SignalProtocolAddress address) async {
final dbSession = final dbSession = await (twonlyDB.select(twonlyDB.signalSessionStores)
await (twonlyDatabase.select(twonlyDatabase.signalSessionStores)
..where((tbl) => ..where((tbl) =>
tbl.deviceId.equals(address.getDeviceId()) & tbl.deviceId.equals(address.getDeviceId()) &
tbl.name.equals(address.getName()))) tbl.name.equals(address.getName())))
@ -67,11 +64,11 @@ class ConnectSessionStore extends SessionStore {
); );
if (!await containsSession(address)) { if (!await containsSession(address)) {
await twonlyDatabase await twonlyDB
.into(twonlyDatabase.signalSessionStores) .into(twonlyDB.signalSessionStores)
.insert(sessionCompanion); .insert(sessionCompanion);
} else { } else {
await (twonlyDatabase.update(twonlyDatabase.signalSessionStores) await (twonlyDB.update(twonlyDB.signalSessionStores)
..where((tbl) => ..where((tbl) =>
tbl.deviceId.equals(address.getDeviceId()) & tbl.deviceId.equals(address.getDeviceId()) &
tbl.name.equals(address.getName()))) tbl.name.equals(address.getName())))

View file

@ -1,7 +1,7 @@
import 'package:twonly/src/providers/signal/connect_identitiy_key_store.dart'; import 'package:twonly/src/database/signal/connect_identitiy_key_store.dart';
import 'package:twonly/src/providers/signal/connect_pre_key_store.dart'; import 'package:twonly/src/database/signal/connect_pre_key_store.dart';
import 'package:twonly/src/providers/signal/connect_session_store.dart'; import 'package:twonly/src/database/signal/connect_session_store.dart';
import 'package:twonly/src/providers/signal/connect_signed_pre_key_store.dart'; import 'package:twonly/src/database/signal/connect_signed_pre_key_store.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
class ConnectSignalProtocolStore implements SignalProtocolStore { class ConnectSignalProtocolStore implements SignalProtocolStore {

View file

@ -2,12 +2,12 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/providers/api/media_send.dart' as send; import 'package:twonly/src/services/api/media_send.dart' as send;
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
class GalleryItem { class MemoryItem {
GalleryItem({ MemoryItem({
required this.id, required this.id,
required this.messages, required this.messages,
required this.date, required this.date,
@ -22,9 +22,9 @@ class GalleryItem {
final File? imagePath; final File? imagePath;
final File? videoPath; final File? videoPath;
static Future<Map<int, GalleryItem>> convertFromMessages( static Future<Map<int, MemoryItem>> convertFromMessages(
List<Message> messages) async { List<Message> messages) async {
Map<int, GalleryItem> items = {}; Map<int, MemoryItem> items = {};
for (final message in messages) { for (final message in messages) {
bool isSend = message.messageOtherId == null; bool isSend = message.messageOtherId == null;
int id = message.mediaUploadId ?? message.messageId; int id = message.mediaUploadId ?? message.messageId;
@ -41,7 +41,7 @@ class GalleryItem {
} else { } else {
if (message.mediaStored) { if (message.mediaStored) {
/// media file was deleted, ... remove the file /// media file was deleted, ... remove the file
twonlyDatabase.messagesDao.updateMessageByMessageId( twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId, MessagesCompanion(mediaStored: Value(false))); message.messageId, MessagesCompanion(mediaStored: Value(false)));
} }
continue; continue;
@ -56,7 +56,7 @@ class GalleryItem {
items items
.putIfAbsent( .putIfAbsent(
id, id,
() => GalleryItem( () => MemoryItem(
id: id.toString(), id: id.toString(),
messages: [], messages: [],
date: message.sendAt, date: message.sendAt,

View file

@ -6,7 +6,6 @@ import 'dart:math';
import 'package:fixnum/fixnum.dart'; import 'package:fixnum/fixnum.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:logging/logging.dart';
import 'package:mutex/mutex.dart'; import 'package:mutex/mutex.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
@ -17,14 +16,15 @@ import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart' import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'
as server; as server;
import 'package:twonly/src/model/protobuf/api/server_to_client.pbserver.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pbserver.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:twonly/src/providers/api/server_messages.dart'; import 'package:twonly/src/services/api/server_messages.dart';
import 'package:twonly/src/providers/hive.dart'; import 'package:twonly/src/utils/hive.dart';
import 'package:twonly/src/services/fcm_service.dart'; import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/flame_service.dart'; import 'package:twonly/src/services/flame.service.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
// ignore: library_prefixes // ignore: library_prefixes
@ -39,14 +39,12 @@ final lockConnecting = Mutex();
/// The ApiProvider is responsible for communicating with the server. /// The ApiProvider is responsible for communicating with the server.
/// It handles errors and does automatically tries to reconnect on /// It handles errors and does automatically tries to reconnect on
/// errors or network changes. /// errors or network changes.
class ApiProvider { class ApiService {
final String apiHost = (kDebugMode) ? "10.99.0.140:3030" : "api.twonly.eu"; final String apiHost = (kDebugMode) ? "10.99.0.140:3030" : "api.twonly.eu";
final String apiSecure = (kDebugMode) ? "" : "s"; final String apiSecure = (kDebugMode) ? "" : "s";
bool isAuthenticated = false; bool isAuthenticated = false;
ApiProvider(); ApiService();
final log = Logger("ApiProvider");
// reconnection params // reconnection params
Timer? reconnectionTimer; Timer? reconnectionTimer;
@ -63,10 +61,10 @@ class ApiProvider {
_channel = channel; _channel = channel;
_channel!.stream.listen(_onData, onDone: _onDone, onError: _onError); _channel!.stream.listen(_onData, onDone: _onDone, onError: _onError);
await _channel!.ready; await _channel!.ready;
log.info("Websocket is connected!"); Log.info("websocket connected to $apiUrl");
return true; return true;
} on WebSocketChannelException catch (e) { } on WebSocketChannelException catch (e) {
log.shout("Error: $e"); Log.error("could not connect to api got: $e");
return false; return false;
} }
} }
@ -83,7 +81,7 @@ class ApiProvider {
retryMediaUpload(); retryMediaUpload();
tryDownloadAllMediaFiles(); tryDownloadAllMediaFiles();
notifyContactsAboutProfileChange(); notifyContactsAboutProfileChange();
twonlyDatabase.markUpdated(); twonlyDB.markUpdated();
syncFlameCounters(); syncFlameCounters();
} }
} }
@ -97,11 +95,11 @@ class ApiProvider {
_channel = null; _channel = null;
isAuthenticated = false; isAuthenticated = false;
globalCallbackConnectionState(false); globalCallbackConnectionState(false);
await twonlyDatabase.messagesDao.resetPendingDownloadState(); await twonlyDB.messagesDao.resetPendingDownloadState();
} }
Future close(Function callback) async { Future close(Function callback) async {
log.info("Closing the websocket connection!"); Log.info("closing websocket connection");
if (_channel != null) { if (_channel != null) {
await _channel!.sink.close(); await _channel!.sink.close();
onClosed(); onClosed();
@ -125,7 +123,7 @@ class ApiProvider {
String apiUrl = "ws$apiSecure://$apiHost/api/client"; String apiUrl = "ws$apiSecure://$apiHost/api/client";
log.fine("Trying to connect to the backend $apiUrl!"); Log.info("connecting to $apiUrl");
if (await _connectTo(apiUrl)) { if (await _connectTo(apiUrl)) {
await onConnected(); await onConnected();
return true; return true;
@ -137,12 +135,12 @@ class ApiProvider {
bool get isConnected => _channel != null && _channel!.closeCode != null; bool get isConnected => _channel != null && _channel!.closeCode != null;
void _onDone() { void _onDone() {
log.info("WebSocket Closed"); Log.info("websocket closed without error");
onClosed(); onClosed();
} }
void _onError(dynamic e) { void _onError(dynamic e) {
log.info("WebSocket Error: $e"); Log.error("websocket error: $e");
onClosed(); onClosed();
} }
@ -156,7 +154,7 @@ class ApiProvider {
await handleServerMessage(msg); await handleServerMessage(msg);
} }
} catch (e) { } catch (e) {
log.shout("Error parsing the servers message: $e"); Log.error("Error parsing the servers message: $e");
} }
} }
@ -172,7 +170,7 @@ class ApiProvider {
return tmp; return tmp;
} }
if (DateTime.now().difference(startTime) > timeout) { if (DateTime.now().difference(startTime) > timeout) {
log.shout("Timeout for message $seq"); Log.error("Timeout for message $seq");
return null; return null;
} }
await Future.delayed(Duration(milliseconds: 10)); await Future.delayed(Duration(milliseconds: 10));
@ -196,13 +194,12 @@ class ApiProvider {
Future retransmitRawBytes() async { Future retransmitRawBytes() async {
var retransmit = await getRetransmission(); var retransmit = await getRetransmission();
Logger("api_provider.dart") Log.info("retransmitting ${retransmit.keys.length} messages");
.info("Retransmit: ${retransmit.keys.length} messages");
for (final seq in retransmit.keys) { for (final seq in retransmit.keys) {
try { try {
_channel!.sink.add(base64Decode(retransmit[seq])); _channel!.sink.add(base64Decode(retransmit[seq]));
} catch (e) { } catch (e) {
Logger("api_provider.dart").shout("$e"); Log.error("$e");
} }
} }
} }
@ -237,7 +234,7 @@ class ApiProvider {
} }
if (_channel == null) { if (_channel == null) {
log.shout("sending request, but api is not connected."); Log.warn("sending request while api is not connected");
if (!await connect()) { if (!await connect()) {
return Result.error(ErrorCode.InternalError); return Result.error(ErrorCode.InternalError);
} }
@ -250,7 +247,7 @@ class ApiProvider {
Result res = asResult(await _waitForResponse(seq)); Result res = asResult(await _waitForResponse(seq));
if (res.isError) { if (res.isError) {
Logger("api_provider").shout("Got error from SERVER: ${res.error}"); Log.error("got error from server: ${res.error}");
if (res.error == ErrorCode.SessionNotAuthenticated) { if (res.error == ErrorCode.SessionNotAuthenticated) {
isAuthenticated = false; isAuthenticated = false;
if (authenticated) { if (authenticated) {
@ -259,7 +256,7 @@ class ApiProvider {
// this will send the request one more time. // this will send the request one more time.
return sendRequestSync(request, authenticated: false); return sendRequestSync(request, authenticated: false);
} else { } else {
log.shout("Session is not authenticated."); Log.error("session is not authenticated");
return Result.error(ErrorCode.InternalError); return Result.error(ErrorCode.InternalError);
} }
} }
@ -293,13 +290,13 @@ class ApiProvider {
await updateUser(user); await updateUser(user);
} }
} }
log.info("Authenticated using api_auth_token"); Log.info("websocket is authenticated");
onAuthenticated(); onAuthenticated();
return true; return true;
} }
if (result.isError) { if (result.isError) {
if (result.error != ErrorCode.AuthTokenNotValid) { if (result.error != ErrorCode.AuthTokenNotValid) {
log.shout("Error while authenticating using token", result); Log.error("got error while authenticating to the server", result);
return false; return false;
} }
} }
@ -326,7 +323,7 @@ class ApiProvider {
final result = await sendRequestSync(req, authenticated: false); final result = await sendRequestSync(req, authenticated: false);
if (result.isError) { if (result.isError) {
log.shout("Error requesting auth challenge", result); Log.error("could not request auth challenge", result);
return; return;
} }
@ -347,7 +344,7 @@ class ApiProvider {
final result2 = await sendRequestSync(req2, authenticated: false); final result2 = await sendRequestSync(req2, authenticated: false);
if (result2.isError) { if (result2.isError) {
log.shout("Error while sending auth challenge: ${result2.error}"); Log.error("could not send auth response: ${result2.error}");
return; return;
} }
@ -370,7 +367,6 @@ class ApiProvider {
await SignalHelper.getSignalStoreFromIdentity(signalIdentity); await SignalHelper.getSignalStoreFromIdentity(signalIdentity);
final signedPreKey = (await signalStore.loadSignedPreKeys())[0]; final signedPreKey = (await signalStore.loadSignedPreKeys())[0];
log.shout("handle registrationId", signalIdentity.registrationId);
var register = Handshake_Register() var register = Handshake_Register()
..username = username ..username = username
@ -385,7 +381,7 @@ class ApiProvider {
if (inviteCode != null && inviteCode != "") { if (inviteCode != null && inviteCode != "") {
register.inviteCode = inviteCode; register.inviteCode = inviteCode;
} }
// Create the Handshake message
var handshake = Handshake()..register = register; var handshake = Handshake()..register = register;
var req = createClientToServerFromHandshake(handshake); var req = createClientToServerFromHandshake(handshake);

View file

@ -10,7 +10,7 @@ import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
// import 'package:twonly/src/providers/api/api_utils.dart'; // import 'package:twonly/src/providers/api/api_utils.dart';
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:cryptography_plus/cryptography_plus.dart'; import 'package:cryptography_plus/cryptography_plus.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:twonly/src/model/protobuf/api/client_to_server.pb.dart' import 'package:twonly/src/model/protobuf/api/client_to_server.pb.dart'
@ -23,7 +23,7 @@ Future tryDownloadAllMediaFiles({bool force = false}) async {
// this is called when websocket is newly connected, so allow all downloads to be restarted. // this is called when websocket is newly connected, so allow all downloads to be restarted.
downloadStartedForMediaReceived = {}; downloadStartedForMediaReceived = {};
List<Message> messages = List<Message> messages =
await twonlyDatabase.messagesDao.getAllMessagesPendingDownloading(); await twonlyDB.messagesDao.getAllMessagesPendingDownloading();
for (Message message in messages) { for (Message message in messages) {
await startDownloadMedia(message, force); await startDownloadMedia(message, force);
@ -91,17 +91,17 @@ Future startDownloadMedia(Message message, bool force) async {
if (content is! MediaMessageContent) return; if (content is! MediaMessageContent) return;
if (content.downloadToken == null) return; if (content.downloadToken == null) return;
var media = await twonlyDatabase.mediaDownloadsDao var media = await twonlyDB.mediaDownloadsDao
.getMediaDownloadById(message.messageId) .getMediaDownloadById(message.messageId)
.getSingleOrNull(); .getSingleOrNull();
if (media == null) { if (media == null) {
await twonlyDatabase.mediaDownloadsDao.insertMediaDownload( await twonlyDB.mediaDownloadsDao.insertMediaDownload(
MediaDownloadsCompanion( MediaDownloadsCompanion(
messageId: Value(message.messageId), messageId: Value(message.messageId),
downloadToken: Value(content.downloadToken!), downloadToken: Value(content.downloadToken!),
), ),
); );
media = await twonlyDatabase.mediaDownloadsDao media = await twonlyDB.mediaDownloadsDao
.getMediaDownloadById(message.messageId) .getMediaDownloadById(message.messageId)
.getSingleOrNull(); .getSingleOrNull();
} }
@ -113,7 +113,7 @@ Future startDownloadMedia(Message message, bool force) async {
} }
if (message.downloadState != DownloadState.downloaded) { if (message.downloadState != DownloadState.downloaded) {
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId, message.messageId,
MessagesCompanion( MessagesCompanion(
downloadState: Value(DownloadState.downloading), downloadState: Value(DownloadState.downloading),
@ -131,7 +131,7 @@ Future startDownloadMedia(Message message, bool force) async {
String downloadToken = uint8ListToHex(content.downloadToken!); String downloadToken = uint8ListToHex(content.downloadToken!);
String apiUrl = String apiUrl =
"http${apiProvider.apiSecure}://${apiProvider.apiHost}/api/download/$downloadToken"; "http${apiService.apiSecure}://${apiService.apiHost}/api/download/$downloadToken";
var httpClient = http.Client(); var httpClient = http.Client();
var request = http.Request('GET', Uri.parse(apiUrl)); var request = http.Request('GET', Uri.parse(apiUrl));
@ -150,7 +150,7 @@ Future startDownloadMedia(Message message, bool force) async {
}, onDone: () async { }, onDone: () async {
if (r.statusCode != 200) { if (r.statusCode != 200) {
Logger("media_received.dart").shout("Download error: $r"); Logger("media_received.dart").shout("Download error: $r");
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId, message.messageId,
MessagesCompanion( MessagesCompanion(
errorWhileSending: Value(true), errorWhileSending: Value(true),
@ -211,7 +211,7 @@ Future handleEncryptedFile(Message msg, {Uint8List? encryptedBytesTmp}) async {
await writeMediaFile(msg.messageId, "png", imageBytes); await writeMediaFile(msg.messageId, "png", imageBytes);
} catch (e) { } catch (e) {
Logger("media_received.dart").info("Decryption error: $e"); Logger("media_received.dart").info("Decryption error: $e");
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
msg.messageId, msg.messageId,
MessagesCompanion( MessagesCompanion(
errorWhileSending: Value(true), errorWhileSending: Value(true),
@ -222,14 +222,14 @@ Future handleEncryptedFile(Message msg, {Uint8List? encryptedBytesTmp}) async {
return client.Response()..ok = ok; return client.Response()..ok = ok;
} }
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
msg.messageId, msg.messageId,
MessagesCompanion(downloadState: Value(DownloadState.downloaded)), MessagesCompanion(downloadState: Value(DownloadState.downloaded)),
); );
await deleteMediaFile(msg.messageId, "encrypted"); await deleteMediaFile(msg.messageId, "encrypted");
apiProvider.downloadDone(content.downloadToken!); apiService.downloadDone(content.downloadToken!);
} }
Future<Uint8List?> getImageBytes(int mediaId) async { Future<Uint8List?> getImageBytes(int mediaId) async {
@ -301,8 +301,8 @@ Future<void> purgeMediaFiles(Directory directory) async {
try { try {
if (directory.path.endsWith("send")) { if (directory.path.endsWith("send")) {
List<Message> messages = await twonlyDatabase.messagesDao List<Message> messages =
.getMessagesByMediaUploadId(fileId); await twonlyDB.messagesDao.getMessagesByMediaUploadId(fileId);
bool canBeDeleted = true; bool canBeDeleted = true;
for (final message in messages) { for (final message in messages) {
@ -319,7 +319,7 @@ Future<void> purgeMediaFiles(Directory directory) async {
file.deleteSync(); file.deleteSync();
} }
} else { } else {
Message? message = await twonlyDatabase.messagesDao Message? message = await twonlyDB.messagesDao
.getMessageByMessageId(fileId) .getMessageByMessageId(fileId)
.getSingleOrNull(); .getSingleOrNull();
if ((message == null) || if ((message == null) ||

View file

@ -18,10 +18,10 @@ import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:video_compress/video_compress.dart'; import 'package:video_compress/video_compress.dart';
@ -66,8 +66,7 @@ Future<ErrorCode?> isAllowedToSend() async {
final lockingHandleMediaFile = Mutex(); final lockingHandleMediaFile = Mutex();
Future retryMediaUpload({int maxRetries = 3}) async { Future retryMediaUpload({int maxRetries = 3}) async {
await lockingHandleMediaFile.protect(() async { await lockingHandleMediaFile.protect(() async {
final mediaFiles = final mediaFiles = await twonlyDB.mediaUploadsDao.getMediaUploadsForRetry();
await twonlyDatabase.mediaUploadsDao.getMediaUploadsForRetry();
if (mediaFiles.isEmpty) return; if (mediaFiles.isEmpty) return;
for (final mediaFile in mediaFiles) { for (final mediaFile in mediaFiles) {
if (mediaFile.messageIds == null || mediaFile.metadata == null) { if (mediaFile.messageIds == null || mediaFile.metadata == null) {
@ -75,9 +74,9 @@ Future retryMediaUpload({int maxRetries = 3}) async {
if (mediaFile.uploadTokens != null) { if (mediaFile.uploadTokens != null) {
/// the file was already uploaded. /// the file was already uploaded.
/// notify the server to remove the upload /// notify the server to remove the upload
apiProvider.getDownloadTokens(mediaFile.uploadTokens!.uploadToken, 0); apiService.getDownloadTokens(mediaFile.uploadTokens!.uploadToken, 0);
} }
await twonlyDatabase.mediaUploadsDao await twonlyDB.mediaUploadsDao
.deleteMediaUpload(mediaFile.mediaUploadId); .deleteMediaUpload(mediaFile.mediaUploadId);
Logger("media_send.dart").shout( Logger("media_send.dart").shout(
"upload can be removed, the finalized function was never called..."); "upload can be removed, the finalized function was never called...");
@ -94,7 +93,7 @@ Future retryMediaUpload({int maxRetries = 3}) async {
} }
Future<int?> initMediaUpload() async { Future<int?> initMediaUpload() async {
return await twonlyDatabase.mediaUploadsDao return await twonlyDB.mediaUploadsDao
.insertMediaUpload(MediaUploadsCompanion()); .insertMediaUpload(MediaUploadsCompanion());
} }
@ -133,7 +132,7 @@ Future<Uint8List> addOrModifyImageToUpload(
/// in case the media file was already encrypted of even uploaded /// in case the media file was already encrypted of even uploaded
/// remove the data so it will be done again. /// remove the data so it will be done again.
/// TODO: when the uploadTokens are already set notify the server... /// TODO: when the uploadTokens are already set notify the server...
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
mediaUploadId, mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
encryptionData: Value(null), encryptionData: Value(null),
@ -195,7 +194,7 @@ Future encryptAndPreUploadMediaFiles(
encryptedBytes, encryptedBytes,
); );
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
mediaUploadId, mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
state: Value(UploadState.readyToUpload), state: Value(UploadState.readyToUpload),
@ -206,7 +205,7 @@ Future encryptAndPreUploadMediaFiles(
} }
Future cancelSendMediaFile(int mediaUploadId) async { Future cancelSendMediaFile(int mediaUploadId) async {
await twonlyDatabase.mediaUploadsDao.deleteMediaUpload(mediaUploadId); await twonlyDB.mediaUploadsDao.deleteMediaUpload(mediaUploadId);
/// server should purge the uploads... when it did not receive a /// server should purge the uploads... when it did not receive a
} }
@ -224,7 +223,7 @@ Future finalizeUpload(int mediaUploadId, List<int> contactIds,
List<int> messageIds = []; List<int> messageIds = [];
for (final contactId in contactIds) { for (final contactId in contactIds) {
int? messageId = await twonlyDatabase.messagesDao.insertMessage( int? messageId = await twonlyDB.messagesDao.insertMessage(
MessagesCompanion( MessagesCompanion(
contactId: Value(contactId), contactId: Value(contactId),
kind: Value(MessageKind.media), kind: Value(MessageKind.media),
@ -244,7 +243,7 @@ Future finalizeUpload(int mediaUploadId, List<int> contactIds,
), ),
); );
// de-archive contact when sending a new message // de-archive contact when sending a new message
await twonlyDatabase.contactsDao.updateContact( await twonlyDB.contactsDao.updateContact(
contactId, contactId,
ContactsCompanion( ContactsCompanion(
archived: Value(false), archived: Value(false),
@ -258,7 +257,7 @@ Future finalizeUpload(int mediaUploadId, List<int> contactIds,
} }
} }
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
mediaUploadId, mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
messageIds: Value(messageIds), messageIds: Value(messageIds),
@ -270,7 +269,7 @@ Future finalizeUpload(int mediaUploadId, List<int> contactIds,
final lockingHandleNextMediaUploadStep = Mutex(); final lockingHandleNextMediaUploadStep = Mutex();
Future handleNextMediaUploadSteps(int mediaUploadId) async { Future handleNextMediaUploadSteps(int mediaUploadId) async {
bool rerun = await lockingHandleNextMediaUploadStep.protect<bool>(() async { bool rerun = await lockingHandleNextMediaUploadStep.protect<bool>(() async {
var mediaUpload = await twonlyDatabase.mediaUploadsDao var mediaUpload = await twonlyDB.mediaUploadsDao
.getMediaUploadById(mediaUploadId) .getMediaUploadById(mediaUploadId)
.getSingleOrNull(); .getSingleOrNull();
@ -328,7 +327,7 @@ Future handleUploadError(MediaUpload mediaUpload) async {
// if the messageIds are already there notify the user about this error... // if the messageIds are already there notify the user about this error...
if (mediaUpload.messageIds != null) { if (mediaUpload.messageIds != null) {
for (int messageId in mediaUpload.messageIds!) { for (int messageId in mediaUpload.messageIds!) {
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
messageId, messageId,
MessagesCompanion( MessagesCompanion(
errorWhileSending: Value(true), errorWhileSending: Value(true),
@ -336,12 +335,11 @@ Future handleUploadError(MediaUpload mediaUpload) async {
); );
} }
} }
await twonlyDatabase.mediaUploadsDao await twonlyDB.mediaUploadsDao.deleteMediaUpload(mediaUpload.mediaUploadId);
.deleteMediaUpload(mediaUpload.mediaUploadId);
} }
Future<bool> handleUploadDone(MediaUpload media) async { Future<bool> handleUploadDone(MediaUpload media) async {
Result res = await apiProvider.getDownloadTokens( Result res = await apiService.getDownloadTokens(
media.uploadTokens!.uploadToken, media.messageIds!.length); media.uploadTokens!.uploadToken, media.messageIds!.length);
if (res.isError || !res.value.hasDownloadtokens()) { if (res.isError || !res.value.hasDownloadtokens()) {
@ -363,7 +361,7 @@ Future<bool> handleUploadDone(MediaUpload media) async {
token.uploadToken = media.uploadTokens!.uploadToken; token.uploadToken = media.uploadTokens!.uploadToken;
token.downloadTokens = tokens.downloadTokens; token.downloadTokens = tokens.downloadTokens;
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
media.mediaUploadId, media.mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
uploadTokens: Value(token), uploadTokens: Value(token),
@ -383,7 +381,7 @@ Future<bool> handleMediaUpload(int mediaUploadId) async {
} }
String apiUrl = String apiUrl =
"http${apiProvider.apiSecure}://${apiProvider.apiHost}/api/upload"; "http${apiService.apiSecure}://${apiService.apiHost}/api/upload";
var requestMultipart = http.MultipartRequest( var requestMultipart = http.MultipartRequest(
"POST", "POST",
@ -415,7 +413,7 @@ Future<bool> handleMediaUpload(int mediaUploadId) async {
token.uploadToken = uploadToken; token.uploadToken = uploadToken;
token.downloadTokens = []; token.downloadTokens = [];
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
mediaUploadId, mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
uploadTokens: Value(token), uploadTokens: Value(token),
@ -439,12 +437,12 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
continue; continue;
} }
Message? message = await twonlyDatabase.messagesDao Message? message = await twonlyDB.messagesDao
.getMessageByMessageId(messageId) .getMessageByMessageId(messageId)
.getSingleOrNull(); .getSingleOrNull();
if (message == null) continue; if (message == null) continue;
await twonlyDatabase.contactsDao.incFlameCounter( await twonlyDB.contactsDao.incFlameCounter(
message.contactId, message.contactId,
false, false,
message.sendAt, message.sendAt,
@ -477,7 +475,7 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
); );
alreadyNotified.add(messageId); alreadyNotified.add(messageId);
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
media.mediaUploadId, media.mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
alreadyNotified: Value(alreadyNotified), alreadyNotified: Value(alreadyNotified),
@ -485,7 +483,7 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
); );
} }
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( await twonlyDB.mediaUploadsDao.updateMediaUpload(
media.mediaUploadId, media.mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
state: Value(UploadState.receiverNotified), state: Value(UploadState.receiverNotified),

View file

@ -9,9 +9,9 @@ import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/model/json/userdata.dart'; import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/providers/hive.dart'; import 'package:twonly/src/utils/hive.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
// ignore: library_prefixes // ignore: library_prefixes
import 'package:twonly/src/utils/signal.dart' as SignalHelper; import 'package:twonly/src/utils/signal.dart' as SignalHelper;
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
@ -35,7 +35,7 @@ Future tryTransmitMessages() async {
RetransmitMessage msg = RetransmitMessage msg =
RetransmitMessage.fromJson(jsonDecode(element.value)); RetransmitMessage.fromJson(jsonDecode(element.value));
Result resp = await apiProvider.sendTextMessage( Result resp = await apiService.sendTextMessage(
msg.userId, msg.userId,
msg.bytes, msg.bytes,
msg.pushData, msg.pushData,
@ -43,7 +43,7 @@ Future tryTransmitMessages() async {
if (resp.isSuccess) { if (resp.isSuccess) {
if (msg.messageId != null) { if (msg.messageId != null) {
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
msg.messageId!, msg.messageId!,
MessagesCompanion( MessagesCompanion(
acknowledgeByServer: Value(true), acknowledgeByServer: Value(true),
@ -113,7 +113,7 @@ Future<Map<String, dynamic>> getAllMessagesForRetransmitting() async {
Future<Result> sendRetransmitMessage( Future<Result> sendRetransmitMessage(
String stateId, RetransmitMessage msg) async { String stateId, RetransmitMessage msg) async {
Result resp = Result resp =
await apiProvider.sendTextMessage(msg.userId, msg.bytes, msg.pushData); await apiService.sendTextMessage(msg.userId, msg.bytes, msg.pushData);
if (resp.isSuccess) { if (resp.isSuccess) {
{ {
@ -123,7 +123,7 @@ Future<Result> sendRetransmitMessage(
box.put("messages-to-retransmit", jsonEncode(retransmit)); box.put("messages-to-retransmit", jsonEncode(retransmit));
} }
if (msg.messageId != null) { if (msg.messageId != null) {
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
msg.messageId!, msg.messageId!,
MessagesCompanion(acknowledgeByServer: Value(true)), MessagesCompanion(acknowledgeByServer: Value(true)),
); );
@ -195,7 +195,7 @@ Future sendTextMessage(
int target, TextMessageContent content, PushKind? pushKind) async { int target, TextMessageContent content, PushKind? pushKind) async {
DateTime messageSendAt = DateTime.now(); DateTime messageSendAt = DateTime.now();
int? messageId = await twonlyDatabase.messagesDao.insertMessage( int? messageId = await twonlyDB.messagesDao.insertMessage(
MessagesCompanion( MessagesCompanion(
contactId: Value(target), contactId: Value(target),
kind: Value(MessageKind.textMessage), kind: Value(MessageKind.textMessage),
@ -239,7 +239,7 @@ Future notifyContactAboutOpeningMessage(
Future notifyContactsAboutProfileChange() async { Future notifyContactsAboutProfileChange() async {
List<Contact> contacts = List<Contact> contacts =
await twonlyDatabase.contactsDao.getAllNotBlockedContacts(); await twonlyDB.contactsDao.getAllNotBlockedContacts();
UserData? user = await getUser(); UserData? user = await getUser();
if (user == null) return; if (user == null) return;
@ -248,7 +248,7 @@ Future notifyContactsAboutProfileChange() async {
for (Contact contact in contacts) { for (Contact contact in contacts) {
if (contact.myAvatarCounter < user.avatarCounter!) { if (contact.myAvatarCounter < user.avatarCounter!) {
twonlyDatabase.contactsDao.updateContact(contact.userId, twonlyDB.contactsDao.updateContact(contact.userId,
ContactsCompanion(myAvatarCounter: Value(user.avatarCounter!))); ContactsCompanion(myAvatarCounter: Value(user.avatarCounter!)));
await encryptAndSendMessageAsync( await encryptAndSendMessageAsync(
null, null,

View file

@ -14,10 +14,10 @@ import 'package:twonly/src/model/protobuf/api/client_to_server.pbserver.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart' import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'
as server; as server;
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
// ignore: library_prefixes // ignore: library_prefixes
import 'package:twonly/src/utils/signal.dart' as SignalHelper; import 'package:twonly/src/utils/signal.dart' as SignalHelper;
@ -48,7 +48,7 @@ Future handleServerMessage(server.ServerToClient msg) async {
..seq = msg.v0.seq ..seq = msg.v0.seq
..response = response; ..response = response;
apiProvider.sendResponse(ClientToServer()..v0 = v0); apiService.sendResponse(ClientToServer()..v0 = v0);
}); });
} }
@ -67,7 +67,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
return handleContactRequest(fromUserId, message); return handleContactRequest(fromUserId, message);
case MessageKind.flameSync: case MessageKind.flameSync:
Contact? contact = await twonlyDatabase.contactsDao Contact? contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId) .getContactByUserId(fromUserId)
.getSingleOrNull(); .getSingleOrNull();
if (contact != null && contact.lastFlameCounterChange != null) { if (contact != null && contact.lastFlameCounterChange != null) {
@ -85,23 +85,23 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
); );
} }
} }
await twonlyDatabase.contactsDao.updateContact(fromUserId, updates); await twonlyDB.contactsDao.updateContact(fromUserId, updates);
} }
} }
case MessageKind.opened: case MessageKind.opened:
final update = MessagesCompanion(openedAt: Value(message.timestamp)); final update = MessagesCompanion(openedAt: Value(message.timestamp));
await twonlyDatabase.messagesDao.updateMessageByOtherUser( await twonlyDB.messagesDao.updateMessageByOtherUser(
fromUserId, fromUserId,
message.messageId!, message.messageId!,
update, update,
); );
final openedMessage = await twonlyDatabase.messagesDao final openedMessage = await twonlyDB.messagesDao
.getMessageByMessageId(message.messageId!) .getMessageByMessageId(message.messageId!)
.getSingleOrNull(); .getSingleOrNull();
if (openedMessage != null && if (openedMessage != null &&
openedMessage.kind == MessageKind.textMessage) { openedMessage.kind == MessageKind.textMessage) {
await twonlyDatabase.messagesDao.openedAllNonMediaMessagesFromOtherUser( await twonlyDB.messagesDao.openedAllNonMediaMessagesFromOtherUser(
fromUserId, fromUserId,
); );
} }
@ -109,12 +109,12 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
break; break;
case MessageKind.rejectRequest: case MessageKind.rejectRequest:
await twonlyDatabase.contactsDao.deleteContactByUserId(fromUserId); await twonlyDB.contactsDao.deleteContactByUserId(fromUserId);
break; break;
case MessageKind.acceptRequest: case MessageKind.acceptRequest:
final update = ContactsCompanion(accepted: Value(true)); final update = ContactsCompanion(accepted: Value(true));
await twonlyDatabase.contactsDao.updateContact(fromUserId, update); await twonlyDB.contactsDao.updateContact(fromUserId, update);
notifyContactsAboutProfileChange(); notifyContactsAboutProfileChange();
break; break;
@ -125,7 +125,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
avatarSvg: Value(content.avatarSvg), avatarSvg: Value(content.avatarSvg),
displayName: Value(content.displayName), displayName: Value(content.displayName),
); );
twonlyDatabase.contactsDao.updateContact(fromUserId, update); twonlyDB.contactsDao.updateContact(fromUserId, update);
} }
break; break;
@ -134,7 +134,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
acknowledgeByUser: Value(true), acknowledgeByUser: Value(true),
errorWhileSending: Value(false), errorWhileSending: Value(false),
); );
await twonlyDatabase.messagesDao.updateMessageByOtherUser( await twonlyDB.messagesDao.updateMessageByOtherUser(
fromUserId, fromUserId,
message.messageId!, message.messageId!,
update, update,
@ -164,7 +164,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
if (content is StoredMediaFileContent) { if (content is StoredMediaFileContent) {
/// stored media file just updates the message /// stored media file just updates the message
await twonlyDatabase.messagesDao.updateMessageByOtherUser( await twonlyDB.messagesDao.updateMessageByOtherUser(
fromUserId, fromUserId,
content.messageId, content.messageId,
MessagesCompanion( MessagesCompanion(
@ -173,7 +173,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
); );
} else { } else {
// when a message is received doubled ignore it... // when a message is received doubled ignore it...
if ((await twonlyDatabase.messagesDao if ((await twonlyDB.messagesDao
.containsOtherMessageId(fromUserId, message.messageId!))) { .containsOtherMessageId(fromUserId, message.messageId!))) {
var ok = client.Response_Ok()..none = true; var ok = client.Response_Ok()..none = true;
return client.Response()..ok = ok; return client.Response()..ok = ok;
@ -216,7 +216,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
sendAt: Value(message.timestamp), sendAt: Value(message.timestamp),
); );
messageId = await twonlyDatabase.messagesDao.insertMessage( messageId = await twonlyDB.messagesDao.insertMessage(
update, update,
); );
@ -224,13 +224,13 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
return client.Response()..error = ErrorCode.InternalError; return client.Response()..error = ErrorCode.InternalError;
} }
if (message.kind == MessageKind.media) { if (message.kind == MessageKind.media) {
twonlyDatabase.contactsDao.incFlameCounter( twonlyDB.contactsDao.incFlameCounter(
fromUserId, fromUserId,
true, true,
message.timestamp, message.timestamp,
); );
final msg = await twonlyDatabase.messagesDao final msg = await twonlyDB.messagesDao
.getMessageByMessageId(messageId) .getMessageByMessageId(messageId)
.getSingleOrNull(); .getSingleOrNull();
if (msg != null) { if (msg != null) {
@ -251,7 +251,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
); );
// unarchive contact when receiving a new message // unarchive contact when receiving a new message
await twonlyDatabase.contactsDao.updateContact( await twonlyDB.contactsDao.updateContact(
fromUserId, fromUserId,
ContactsCompanion( ContactsCompanion(
archived: Value(false), archived: Value(false),
@ -281,10 +281,10 @@ Future<client.Response> handleContactRequest(
int fromUserId, MessageJson message) async { int fromUserId, MessageJson message) async {
// request the username by the server so an attacker can not // request the username by the server so an attacker can not
// forge the displayed username in the contact request // forge the displayed username in the contact request
Result username = await apiProvider.getUsername(fromUserId); Result username = await apiService.getUsername(fromUserId);
if (username.isSuccess) { if (username.isSuccess) {
Uint8List name = username.value.userdata.username; Uint8List name = username.value.userdata.username;
await twonlyDatabase.contactsDao.insertContact( await twonlyDB.contactsDao.insertContact(
ContactsCompanion( ContactsCompanion(
username: Value(utf8.decode(name)), username: Value(utf8.decode(name)),
userId: Value(fromUserId), userId: Value(fromUserId),

View file

@ -5,8 +5,8 @@ import 'package:logging/logging.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/app.dart'; import 'package:twonly/app.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/log.dart';
import 'dart:io' show Platform; import 'dart:io' show Platform;
import '../../firebase_options.dart'; import '../../firebase_options.dart';
@ -27,12 +27,12 @@ Future initFCMAfterAuthenticated() async {
} }
if (storedToken == null || fcmToken != storedToken) { if (storedToken == null || fcmToken != storedToken) {
await apiProvider.updateFCMToken(fcmToken); await apiService.updateFCMToken(fcmToken);
await storage.write(key: "google_fcm", value: fcmToken); await storage.write(key: "google_fcm", value: fcmToken);
} }
FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) async { FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) async {
await apiProvider.updateFCMToken(fcmToken); await apiService.updateFCMToken(fcmToken);
await storage.write(key: "google_fcm", value: fcmToken); await storage.write(key: "google_fcm", value: fcmToken);
}).onError((err) { }).onError((err) {
// Logger("init_fcm_service").shout("Error getting fcmToken"); // Logger("init_fcm_service").shout("Error getting fcmToken");
@ -78,10 +78,10 @@ Future initFCMService() async {
@pragma('vm:entry-point') @pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
setupLogger(); initLogger();
Logger("firebase-background") Logger("firebase-background")
.info('Handling a background message: ${message.messageId}'); .info('Handling a background message: ${message.messageId}');
twonlyDatabase = TwonlyDatabase(); twonlyDB = TwonlyDatabase();
await handleRemoteMessage(message); await handleRemoteMessage(message);
// make sure every thing run... // make sure every thing run...

View file

@ -4,7 +4,7 @@ import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/model/json/message.dart' as my; import 'package:twonly/src/model/json/message.dart' as my;
@ -14,7 +14,7 @@ Future syncFlameCounters() async {
if (user == null) return; if (user == null) return;
List<Contact> contacts = List<Contact> contacts =
await twonlyDatabase.contactsDao.getAllNotBlockedContacts(); await twonlyDB.contactsDao.getAllNotBlockedContacts();
if (contacts.isEmpty) return; if (contacts.isEmpty) return;
int maxMessageCounter = contacts.map((x) => x.totalMediaCounter).max; int maxMessageCounter = contacts.map((x) => x.totalMediaCounter).max;
Contact bestFriend = Contact bestFriend =
@ -50,7 +50,7 @@ Future syncFlameCounters() async {
), ),
); );
await twonlyDatabase.contactsDao.updateContact( await twonlyDB.contactsDao.updateContact(
contact.userId, contact.userId,
ContactsCompanion( ContactsCompanion(
lastFlameSync: Value(DateTime.now()), lastFlameSync: Value(DateTime.now()),

View file

@ -15,7 +15,7 @@ import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/message.dart' as my; import 'package:twonly/src/model/json/message.dart' as my;
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
class PushUser { class PushUser {
String displayName; String displayName;
@ -83,7 +83,7 @@ Future setupNotificationWithUsers({bool force = false}) async {
final random = Random.secure(); final random = Random.secure();
final contacts = await twonlyDatabase.contactsDao.getAllNotBlockedContacts(); final contacts = await twonlyDB.contactsDao.getAllNotBlockedContacts();
for (final contact in contacts) { for (final contact in contacts) {
if (pushKeys.containsKey(contact.userId)) { if (pushKeys.containsKey(contact.userId)) {
// make it harder to predict the change of the key // make it harder to predict the change of the key
@ -427,7 +427,7 @@ Future showLocalPushNotification(
String? title; String? title;
String? body; String? body;
Contact? user = await twonlyDatabase.contactsDao Contact? user = await twonlyDB.contactsDao
.getContactByUserId(fromUserId) .getContactByUserId(fromUserId)
.getSingleOrNull(); .getSingleOrNull();

View file

@ -3,7 +3,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
Future initMediaStorage() async { Future initMediaStorage() async {
final storage = FlutterSecureStorage(); final storage = FlutterSecureStorage();

61
lib/src/utils/log.dart Normal file
View file

@ -0,0 +1,61 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
void initLogger() {
Logger.root.level = kReleaseMode ? Level.INFO : Level.ALL;
Logger.root.onRecord.listen((record) async {
await _writeLogToFile(record);
if (kDebugMode) {
print(
'${record.level.name} [twonly] ${record.loggerName} > ${record.message}');
}
});
}
class Log {
static void error(Object? message, [Object? error, StackTrace? stackTrace]) {
Logger(_getCallerSourceCodeFilename()).shout(message, error, stackTrace);
}
static void warn(Object? message, [Object? error, StackTrace? stackTrace]) {
Logger(_getCallerSourceCodeFilename()).warning(message, error, stackTrace);
}
static void info(Object? message, [Object? error, StackTrace? stackTrace]) {
Logger(_getCallerSourceCodeFilename()).fine(message, error, stackTrace);
}
}
Future<void> _writeLogToFile(LogRecord record) async {
final directory = await getApplicationSupportDirectory();
final logFile = File('${directory.path}/app.log');
// Prepare the log message
final logMessage =
'${DateTime.now()} ${record.level.name} [twonly] ${record.loggerName} > ${record.message}\n';
// Append the log message to the file
await logFile.writeAsString(logMessage, mode: FileMode.append);
}
String _getCallerSourceCodeFilename() {
StackTrace stackTrace = StackTrace.current;
String stackTraceString = stackTrace.toString();
String fileName = "";
String lineNumber = "";
List<String> stackLines = stackTraceString.split('\n');
if (stackLines.length > 2) {
String callerInfo = stackLines[2];
List<String> parts = callerInfo.split('/');
fileName = parts.last.split(':').first; // Extract the file name
lineNumber = parts.last.split(':')[1]; // Extract the line number
} else {
String firstLine = stackTraceString.split('\n')[0];
fileName =
firstLine.split('/').last.split(':').first; // Extract the file name
lineNumber = firstLine.split(':')[1]; // Extract the line number
}
return '$fileName:$lineNumber';
}

View file

@ -6,13 +6,12 @@ import 'package:flutter/services.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:gal/gal.dart'; import 'package:gal/gal.dart';
import 'package:local_auth/local_auth.dart'; import 'package:local_auth/local_auth.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/localization/generated/app_localizations.dart'; import 'package:twonly/src/localization/generated/app_localizations.dart';
import 'package:twonly/src/providers/settings_change_provider.dart'; import 'package:twonly/src/providers/settings.provider.dart';
extension ShortCutsExtension on BuildContext { extension ShortCutsExtension on BuildContext {
AppLocalizations get lang => AppLocalizations.of(this)!; AppLocalizations get lang => AppLocalizations.of(this)!;
@ -20,18 +19,6 @@ extension ShortCutsExtension on BuildContext {
ColorScheme get color => Theme.of(this).colorScheme; ColorScheme get color => Theme.of(this).colorScheme;
} }
Future<void> writeLogToFile(LogRecord record) async {
final directory = await getApplicationSupportDirectory();
final logFile = File('${directory.path}/app.log');
// Prepare the log message
final logMessage =
'${DateTime.now()}: ${record.level.name}: ${record.loggerName}: ${record.message}\n';
// Append the log message to the file
await logFile.writeAsString(logMessage, mode: FileMode.append);
}
Future<bool> deleteLogFile() async { Future<bool> deleteLogFile() async {
final directory = await getApplicationSupportDirectory(); final directory = await getApplicationSupportDirectory();
final logFile = File('${directory.path}/app.log'); final logFile = File('${directory.path}/app.log');
@ -165,17 +152,6 @@ Future<bool> authenticateUser(String localizedReason,
return false; return false;
} }
void setupLogger() {
Logger.root.level = kReleaseMode ? Level.INFO : Level.ALL;
Logger.root.onRecord.listen((record) async {
await writeLogToFile(record);
if (kDebugMode) {
print(
'${record.level.name}: twonly:${record.loggerName}: ${record.message}');
}
});
}
Uint8List intToBytes(int value) { Uint8List intToBytes(int value) {
final byteData = ByteData(4); final byteData = ByteData(4);
byteData.setInt32(0, value, Endian.big); byteData.setInt32(0, value, Endian.big);

View file

@ -8,7 +8,7 @@ import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/model/json/signal_identity.dart'; import 'package:twonly/src/model/json/signal_identity.dart';
import 'package:twonly/src/model/json/userdata.dart'; import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/signal/connect_signal_protocol_store.dart'; import 'package:twonly/src/database/signal/connect_signal_protocol_store.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';

View file

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart'; import 'package:screenshot/screenshot.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart'; import 'package:twonly/src/views/camera/camera_send_to_view.dart';
import 'package:twonly/src/views/components/media_view_sizing.dart'; import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:twonly/src/views/home_view.dart'; import 'package:twonly/src/views/home.view.dart';
class HomeViewCameraPreview extends StatefulWidget { class HomeViewCameraPreview extends StatefulWidget {
const HomeViewCameraPreview({ const HomeViewCameraPreview({

View file

@ -3,7 +3,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';

View file

@ -21,7 +21,7 @@ import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:twonly/src/views/camera/camera_preview_components/permissions_view.dart'; import 'package:twonly/src/views/camera/camera_preview_components/permissions_view.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/camera/share_image_editor_view.dart'; import 'package:twonly/src/views/camera/share_image_editor_view.dart';
import 'package:twonly/src/views/home_view.dart'; import 'package:twonly/src/views/home.view.dart';
int maxVideoRecordingTime = 15; int maxVideoRecordingTime = 15;

View file

@ -27,7 +27,7 @@ class _LocationFilterState extends State<LocationFilter> {
} }
Future initAsync() async { Future initAsync() async {
final res = await apiProvider.getCurrentLocation(); final res = await apiService.getCurrentLocation();
if (res.isSuccess) { if (res.isSuccess) {
location = res.value.location; location = res.value.location;
_searchForImage(); _searchForImage();

View file

@ -170,8 +170,7 @@ class UserCheckbox extends StatelessWidget {
], ],
), ),
StreamBuilder( StreamBuilder(
stream: twonlyDatabase.contactsDao stream: twonlyDB.contactsDao.watchFlameCounter(user.userId),
.watchFlameCounter(user.userId),
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.data! == 0) { if (!snapshot.hasData || snapshot.data! == 0) {
return Container(); return Container();

View file

@ -6,7 +6,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart' show ErrorCode; import 'package:twonly/src/model/protobuf/api/error.pb.dart' show ErrorCode;
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:twonly/src/views/camera/camera_preview_components/save_to_gallery.dart'; import 'package:twonly/src/views/camera/camera_preview_components/save_to_gallery.dart';
import 'package:twonly/src/views/camera/image_editor/action_button.dart'; import 'package:twonly/src/views/camera/image_editor/action_button.dart';
import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/alert_dialog.dart';
@ -135,9 +135,8 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
Future updateAsync(int userId) async { Future updateAsync(int userId) async {
if (sendNextMediaToUserName != null) return; if (sendNextMediaToUserName != null) return;
Contact? contact = await twonlyDatabase.contactsDao Contact? contact =
.getContactByUserId(userId) await twonlyDB.contactsDao.getContactByUserId(userId).getSingleOrNull();
.getSingleOrNull();
if (contact != null) { if (contact != null) {
sendNextMediaToUserName = getContactDisplayName(contact); sendNextMediaToUserName = getContactDisplayName(contact);
} }

View file

@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/providers/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:twonly/src/views/camera/share_image_components/best_friends_selector.dart'; import 'package:twonly/src/views/camera/share_image_components/best_friends_selector.dart';
import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/headline.dart'; import 'package:twonly/src/views/components/headline.dart';
@ -60,7 +60,7 @@ class _ShareImageView extends State<ShareImageView> {
super.initState(); super.initState();
Stream<List<Contact>> allContacts = Stream<List<Contact>> allContacts =
twonlyDatabase.contactsDao.watchContactsForShareView(); twonlyDB.contactsDao.watchContactsForShareView();
contactSub = allContacts.listen((allContacts) { contactSub = allContacts.listen((allContacts) {
setState(() { setState(() {

View file

@ -4,31 +4,31 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/alert_dialog.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/views/components/headline.dart'; import 'package:twonly/src/views/components/headline.dart';
import 'package:twonly/src/views/components/initialsavatar.dart'; import 'package:twonly/src/views/components/initialsavatar.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
// ignore: library_prefixes // ignore: library_prefixes
import 'package:twonly/src/utils/signal.dart' as SignalHelper; import 'package:twonly/src/utils/signal.dart' as SignalHelper;
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/settings/subscription/subscription_view.dart'; import 'package:twonly/src/views/settings/subscription/subscription_view.dart';
class SearchUsernameView extends StatefulWidget { class AddNewUserView extends StatefulWidget {
const SearchUsernameView({super.key}); const AddNewUserView({super.key});
@override @override
State<SearchUsernameView> createState() => _SearchUsernameView(); State<AddNewUserView> createState() => _SearchUsernameView();
} }
class _SearchUsernameView extends State<SearchUsernameView> { class _SearchUsernameView extends State<AddNewUserView> {
final TextEditingController searchUserName = TextEditingController(); final TextEditingController searchUserName = TextEditingController();
bool _isLoading = false; bool _isLoading = false;
bool hasRequestedUsers = false; bool hasRequestedUsers = false;
@ -50,7 +50,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
void initStreams() { void initStreams() {
contactsStream = contactsStream =
twonlyDatabase.contactsDao.watchNotAcceptedContacts().listen((update) { twonlyDB.contactsDao.watchNotAcceptedContacts().listen((update) {
setState(() { setState(() {
contacts = update; contacts = update;
}); });
@ -67,7 +67,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
_isLoading = true; _isLoading = true;
}); });
final res = await apiProvider.getUserData(searchUserName.text); final res = await apiService.getUserData(searchUserName.text);
if (!context.mounted) { if (!context.mounted) {
return; return;
@ -83,7 +83,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
return; return;
} }
int added = await twonlyDatabase.contactsDao.insertContact( int added = await twonlyDB.contactsDao.insertContact(
ContactsCompanion( ContactsCompanion(
username: Value(searchUserName.text), username: Value(searchUserName.text),
userId: Value(res.value.userdata.userId.toInt()), userId: Value(res.value.userdata.userId.toInt()),
@ -237,8 +237,7 @@ class _ContactsListViewState extends State<ContactsListView> {
icon: FaIcon(FontAwesomeIcons.boxArchive, size: 15), icon: FaIcon(FontAwesomeIcons.boxArchive, size: 15),
onPressed: () async { onPressed: () async {
final update = ContactsCompanion(archived: Value(true)); final update = ContactsCompanion(archived: Value(true));
await twonlyDatabase.contactsDao await twonlyDB.contactsDao.updateContact(contact.userId, update);
.updateContact(contact.userId, update);
}, },
), ),
), ),
@ -255,8 +254,7 @@ class _ContactsListViewState extends State<ContactsListView> {
color: const Color.fromARGB(164, 244, 67, 54)), color: const Color.fromARGB(164, 244, 67, 54)),
onPressed: () async { onPressed: () async {
final update = ContactsCompanion(blocked: Value(true)); final update = ContactsCompanion(blocked: Value(true));
await twonlyDatabase.contactsDao await twonlyDB.contactsDao.updateContact(contact.userId, update);
.updateContact(contact.userId, update);
}, },
), ),
), ),
@ -265,8 +263,7 @@ class _ContactsListViewState extends State<ContactsListView> {
child: IconButton( child: IconButton(
icon: Icon(Icons.close, color: Colors.red), icon: Icon(Icons.close, color: Colors.red),
onPressed: () async { onPressed: () async {
await twonlyDatabase.contactsDao await twonlyDB.contactsDao.deleteContactByUserId(contact.userId);
.deleteContactByUserId(contact.userId);
await encryptAndSendMessageAsync( await encryptAndSendMessageAsync(
null, null,
contact.userId, contact.userId,
@ -283,8 +280,7 @@ class _ContactsListViewState extends State<ContactsListView> {
icon: Icon(Icons.check, color: Colors.green), icon: Icon(Icons.check, color: Colors.green),
onPressed: () async { onPressed: () async {
final update = ContactsCompanion(accepted: Value(true)); final update = ContactsCompanion(accepted: Value(true));
await twonlyDatabase.contactsDao await twonlyDB.contactsDao.updateContact(contact.userId, update);
.updateContact(contact.userId, update);
await encryptAndSendMessageAsync( await encryptAndSendMessageAsync(
null, null,
contact.userId, contact.userId,

View file

@ -2,8 +2,8 @@ import 'dart:async';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/views/components/connection_state.dart'; import 'package:twonly/src/views/chats/chat_list_components/connection_info.comp.dart';
import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/initialsavatar.dart'; import 'package:twonly/src/views/components/initialsavatar.dart';
import 'package:twonly/src/views/components/message_send_state_icon.dart'; import 'package:twonly/src/views/components/message_send_state_icon.dart';
@ -12,14 +12,14 @@ import 'package:twonly/src/views/components/user_context_menu.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart'; import 'package:twonly/src/views/camera/camera_send_to_view.dart';
import 'package:twonly/src/views/chats/chat_messages_view.dart'; import 'package:twonly/src/views/chats/chat_messages.view.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart'; import 'package:twonly/src/views/chats/media_viewer.view.dart';
import 'package:twonly/src/views/chats/start_new_chat.dart'; import 'package:twonly/src/views/chats/start_new_chat.view.dart';
import 'package:twonly/src/views/settings/settings_main_view.dart'; import 'package:twonly/src/views/settings/settings_main_view.dart';
import 'package:twonly/src/views/chats/search_username_view.dart'; import 'package:twonly/src/views/chats/add_new_user.view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/views/settings/subscription/subscription_view.dart'; import 'package:twonly/src/views/settings/subscription/subscription_view.dart';
@ -62,7 +62,7 @@ class _ChatListViewState extends State<ChatListView> {
]), ]),
actions: [ actions: [
StreamBuilder( StreamBuilder(
stream: twonlyDatabase.contactsDao.watchContactsRequested(), stream: twonlyDB.contactsDao.watchContactsRequested(),
builder: (context, snapshot) { builder: (context, snapshot) {
var count = 0; var count = 0;
if (snapshot.hasData && snapshot.data != null) { if (snapshot.hasData && snapshot.data != null) {
@ -76,7 +76,7 @@ class _ChatListViewState extends State<ChatListView> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => SearchUsernameView(), builder: (context) => AddNewUserView(),
), ),
); );
}, },
@ -107,7 +107,7 @@ class _ChatListViewState extends State<ChatListView> {
), ),
Positioned.fill( Positioned.fill(
child: StreamBuilder( child: StreamBuilder(
stream: twonlyDatabase.contactsDao.watchContactsForChatList(), stream: twonlyDB.contactsDao.watchContactsForChatList(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.data == null) { if (!snapshot.hasData || snapshot.data == null) {
return Container(); return Container();
@ -124,7 +124,7 @@ class _ChatListViewState extends State<ChatListView> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => SearchUsernameView(), builder: (context) => AddNewUserView(),
), ),
); );
}, },
@ -138,8 +138,8 @@ class _ChatListViewState extends State<ChatListView> {
return RefreshIndicator( return RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await apiProvider.close(() {}); await apiService.close(() {});
await apiProvider.connect(); await apiService.connect();
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
}, },
child: ListView.builder( child: ListView.builder(
@ -196,7 +196,7 @@ class _ChatListViewState extends State<ChatListView> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return StartNewChat(); return StartNewChatView();
}), }),
); );
}, },
@ -250,13 +250,13 @@ class _UserListItem extends State<UserListItem> {
} }
void initStreams() { void initStreams() {
lastMessageStream = twonlyDatabase.messagesDao lastMessageStream = twonlyDB.messagesDao
.watchLastMessage(widget.user.userId) .watchLastMessage(widget.user.userId)
.listen((update) { .listen((update) {
updateState(update, messagesNotOpened); updateState(update, messagesNotOpened);
}); });
messagesNotOpenedStream = twonlyDatabase.messagesDao messagesNotOpenedStream = twonlyDB.messagesDao
.watchMessageNotOpened(widget.user.userId) .watchMessageNotOpened(widget.user.userId)
.listen((update) { .listen((update) {
updateState(lastMessages, update); updateState(lastMessages, update);

View file

@ -13,12 +13,12 @@ import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart'; import 'package:twonly/src/views/camera/camera_send_to_view.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/contact/contact_view.dart'; import 'package:twonly/src/views/contact/contact.view.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
Color getMessageColor(Message message) { Color getMessageColor(Message message) {
return (message.messageOtherId == null) return (message.messageOtherId == null)
@ -44,7 +44,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
late StreamSubscription<Contact> userSub; late StreamSubscription<Contact> userSub;
late StreamSubscription<List<Message>> messageSub; late StreamSubscription<List<Message>> messageSub;
List<Message> messages = []; List<Message> messages = [];
List<GalleryItem> galleryItems = []; List<MemoryItem> galleryItems = [];
Map<int, List<Message>> textReactionsToMessageId = {}; Map<int, List<Message>> textReactionsToMessageId = {};
Map<int, List<Message>> emojiReactionsToMessageId = {}; Map<int, List<Message>> emojiReactionsToMessageId = {};
Message? responseToMessage; Message? responseToMessage;
@ -67,9 +67,9 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
} }
Future initStreams() async { Future initStreams() async {
await twonlyDatabase.messagesDao.removeOldMessages(); await twonlyDB.messagesDao.removeOldMessages();
Stream<Contact> contact = Stream<Contact> contact =
twonlyDatabase.contactsDao.watchContact(widget.contact.userId); twonlyDB.contactsDao.watchContact(widget.contact.userId);
userSub = contact.listen((contact) { userSub = contact.listen((contact) {
setState(() { setState(() {
user = contact; user = contact;
@ -77,7 +77,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
}); });
Stream<List<Message>> msgStream = Stream<List<Message>> msgStream =
twonlyDatabase.messagesDao.watchAllMessagesFrom(widget.contact.userId); twonlyDB.messagesDao.watchAllMessagesFrom(widget.contact.userId);
messageSub = msgStream.listen((msgs) async { messageSub = msgStream.listen((msgs) async {
// if (!context.mounted) return; // if (!context.mounted) return;
if (Platform.isAndroid) { if (Platform.isAndroid) {
@ -139,8 +139,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
widget.contact.userId, openedMessageOtherIds); widget.contact.userId, openedMessageOtherIds);
} }
twonlyDatabase.messagesDao twonlyDB.messagesDao.openedAllNonMediaMessages(widget.contact.userId);
.openedAllNonMediaMessages(widget.contact.userId);
setState(() { setState(() {
textReactionsToMessageId = tmpTextReactionsToMessageId; textReactionsToMessageId = tmpTextReactionsToMessageId;
@ -153,7 +152,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
.toList() .toList()
.reversed .reversed
.toList(); .toList();
final items = await GalleryItem.convertFromMessages(filteredMediaFiles); final items = await MemoryItem.convertFromMessages(filteredMediaFiles);
setState(() { setState(() {
galleryItems = items.values.toList(); galleryItems = items.values.toList();
}); });

View file

@ -5,11 +5,11 @@ import 'package:twonly/src/views/chats/chat_messages_components/in_chat_media_vi
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/providers/api/media_received.dart' as received; import 'package:twonly/src/services/api/media_received.dart' as received;
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart'; import 'package:twonly/src/views/chats/media_viewer.view.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
class ChatMediaEntry extends StatelessWidget { class ChatMediaEntry extends StatelessWidget {
const ChatMediaEntry({ const ChatMediaEntry({
@ -23,7 +23,7 @@ class ChatMediaEntry extends StatelessWidget {
final Message message; final Message message;
final Contact contact; final Contact contact;
final MessageContent content; final MessageContent content;
final List<GalleryItem> galleryItems; final List<MemoryItem> galleryItems;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -52,7 +52,7 @@ class ChatMediaEntry extends StatelessWidget {
), ),
pushKind: PushKind.reopenedMedia, pushKind: PushKind.reopenedMedia,
); );
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId, message.messageId,
MessagesCompanion(openedAt: Value(null)), MessagesCompanion(openedAt: Value(null)),
); );

View file

@ -1,13 +1,13 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_media_entry.dart'; import 'package:twonly/src/views/chats/chat_messages_components/chat_media_entry.dart';
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_reaction_row.dart'; import 'package:twonly/src/views/chats/chat_messages_components/chat_reaction_row.dart';
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_text_entry.dart'; import 'package:twonly/src/views/chats/chat_messages_components/chat_text_entry.dart';
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_text_response_columns.dart'; import 'package:twonly/src/views/chats/chat_messages_components/chat_text_response_columns.dart';
import 'package:twonly/src/views/chats/chat_messages_components/sliding_response.dart'; import 'package:twonly/src/views/chats/chat_messages_components/sliding_response.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
class ChatListEntry extends StatefulWidget { class ChatListEntry extends StatefulWidget {
const ChatListEntry( const ChatListEntry(
@ -25,7 +25,7 @@ class ChatListEntry extends StatefulWidget {
final bool lastMessageFromSameUser; final bool lastMessageFromSameUser;
final List<Message> textReactions; final List<Message> textReactions;
final List<Message> otherReactions; final List<Message> otherReactions;
final List<GalleryItem> galleryItems; final List<MemoryItem> galleryItems;
final Function(Message) onResponseTriggered; final Function(Message) onResponseTriggered;
@override @override

View file

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/views/chats/chat_messages_view.dart'; import 'package:twonly/src/views/chats/chat_messages.view.dart';
import 'package:twonly/src/views/components/animate_icon.dart'; import 'package:twonly/src/views/components/animate_icon.dart';
import 'package:twonly/src/views/components/better_text.dart'; import 'package:twonly/src/views/components/better_text.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';

View file

@ -1,7 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/views/chats/chat_messages_view.dart'; import 'package:twonly/src/views/chats/chat_messages.view.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';

View file

@ -3,13 +3,13 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/providers/api/media_send.dart' as send; import 'package:twonly/src/services/api/media_send.dart' as send;
import 'package:twonly/src/views/components/message_send_state_icon.dart'; import 'package:twonly/src/views/components/message_send_state_icon.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
import 'package:twonly/src/views/gallery/gallery_photo_view.dart'; import 'package:twonly/src/views/memories/memories_photo_slider.view.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
class InChatMediaViewer extends StatefulWidget { class InChatMediaViewer extends StatefulWidget {
@ -23,7 +23,7 @@ class InChatMediaViewer extends StatefulWidget {
final Message message; final Message message;
final Contact contact; final Contact contact;
final List<GalleryItem> galleryItems; final List<MemoryItem> galleryItems;
final Color color; final Color color;
@override @override
@ -60,7 +60,7 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
/// image is already show /// image is already show
if (widget.message.mediaStored) return; if (widget.message.mediaStored) return;
final stream = twonlyDatabase.messagesDao final stream = twonlyDB.messagesDao
.getMessageByMessageId(widget.message.messageId) .getMessageByMessageId(widget.message.messageId)
.watchSingleOrNull(); .watchSingleOrNull();
messageStream = stream.listen((updated) async { messageStream = stream.listen((updated) async {
@ -116,7 +116,7 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => GalleryPhotoViewWrapper( builder: (context) => MemoriesPhotoSliderView(
galleryItems: widget.galleryItems, galleryItems: widget.galleryItems,
initialIndex: widget.galleryItems.indexWhere((x) => initialIndex: widget.galleryItems.indexWhere((x) =>
x.id == x.id ==

View file

@ -15,9 +15,9 @@ import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart'; import 'package:twonly/src/views/camera/camera_send_to_view.dart';
@ -90,8 +90,8 @@ class _MediaViewerViewState extends State<MediaViewerView> {
} }
Future asyncLoadNextMedia(bool firstRun) async { Future asyncLoadNextMedia(bool firstRun) async {
Stream<List<Message>> messages = twonlyDatabase.messagesDao Stream<List<Message>> messages =
.watchMediaMessageNotOpened(widget.contact.userId); twonlyDB.messagesDao.watchMediaMessageNotOpened(widget.contact.userId);
_subscription = messages.listen((messages) { _subscription = messages.listen((messages) {
for (Message msg in messages) { for (Message msg in messages) {
@ -172,7 +172,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
}); });
await startDownloadMedia(allMediaFiles.first, true); await startDownloadMedia(allMediaFiles.first, true);
final stream = twonlyDatabase.messagesDao final stream = twonlyDB.messagesDao
.getMessageByMessageId(allMediaFiles.first.messageId) .getMessageByMessageId(allMediaFiles.first.messageId)
.watchSingleOrNull(); .watchSingleOrNull();
downloadStateListener?.cancel(); downloadStateListener?.cancel();
@ -216,7 +216,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
[current.messageOtherId!], [current.messageOtherId!],
); );
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
current.messageId, current.messageId,
MessagesCompanion(openedAt: Value(DateTime.now())), MessagesCompanion(openedAt: Value(DateTime.now())),
); );
@ -255,7 +255,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
if ((imageBytes == null && !content.isVideo) || if ((imageBytes == null && !content.isVideo) ||
(content.isVideo && videoController == null)) { (content.isVideo && videoController == null)) {
// When the message should be downloaded but imageBytes are null then a error happened // When the message should be downloaded but imageBytes are null then a error happened
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
current.messageId, current.messageId,
MessagesCompanion( MessagesCompanion(
errorWhileSending: Value(true), errorWhileSending: Value(true),
@ -304,7 +304,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
setState(() { setState(() {
imageSaving = true; imageSaving = true;
}); });
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
allMediaFiles.first.messageId, allMediaFiles.first.messageId,
MessagesCompanion(mediaStored: Value(true)), MessagesCompanion(mediaStored: Value(true)),
); );

View file

@ -10,16 +10,16 @@ import 'package:twonly/src/views/components/user_context_menu.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/chats/chat_messages_view.dart'; import 'package:twonly/src/views/chats/chat_messages.view.dart';
import 'package:twonly/src/views/chats/search_username_view.dart'; import 'package:twonly/src/views/chats/add_new_user.view.dart';
class StartNewChat extends StatefulWidget { class StartNewChatView extends StatefulWidget {
const StartNewChat({super.key}); const StartNewChatView({super.key});
@override @override
State<StartNewChat> createState() => _StartNewChat(); State<StartNewChatView> createState() => _StartNewChatView();
} }
class _StartNewChat extends State<StartNewChat> { class _StartNewChatView extends State<StartNewChatView> {
List<Contact> contacts = []; List<Contact> contacts = [];
List<Contact> allContacts = []; List<Contact> allContacts = [];
final TextEditingController searchUserName = TextEditingController(); final TextEditingController searchUserName = TextEditingController();
@ -30,7 +30,7 @@ class _StartNewChat extends State<StartNewChat> {
super.initState(); super.initState();
Stream<List<Contact>> stream = Stream<List<Contact>> stream =
twonlyDatabase.contactsDao.watchContactsForShareView(); twonlyDB.contactsDao.watchContactsForShareView();
contactSub = stream.listen((update) { contactSub = stream.listen((update) {
update.sort((a, b) => update.sort((a, b) =>
@ -133,7 +133,7 @@ class UserList extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => SearchUsernameView(), builder: (context) => AddNewUserView(),
), ),
); );
}, },
@ -168,7 +168,7 @@ class UserList extends StatelessWidget {
? () async { ? () async {
final update = final update =
ContactsCompanion(archived: Value(false)); ContactsCompanion(archived: Value(false));
await twonlyDatabase.contactsDao await twonlyDB.contactsDao
.updateContact(user.userId, update); .updateContact(user.userId, update);
} }
: null) : null)

View file

@ -5,8 +5,8 @@ import 'package:pie_menu/pie_menu.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/chats/chat_messages_view.dart'; import 'package:twonly/src/views/chats/chat_messages.view.dart';
import 'package:twonly/src/views/contact/contact_verify_view.dart'; import 'package:twonly/src/views/contact/contact_verify.view.dart';
class UserContextMenu extends StatefulWidget { class UserContextMenu extends StatefulWidget {
final Widget child; final Widget child;
@ -31,7 +31,7 @@ class _UserContextMenuState extends State<UserContextMenu> {
onSelect: () async { onSelect: () async {
final update = ContactsCompanion(archived: Value(true)); final update = ContactsCompanion(archived: Value(true));
if (context.mounted) { if (context.mounted) {
await twonlyDatabase.contactsDao await twonlyDB.contactsDao
.updateContact(widget.contact.userId, update); .updateContact(widget.contact.userId, update);
} }
}, },
@ -43,7 +43,7 @@ class _UserContextMenuState extends State<UserContextMenu> {
onSelect: () async { onSelect: () async {
final update = ContactsCompanion(archived: Value(false)); final update = ContactsCompanion(archived: Value(false));
if (context.mounted) { if (context.mounted) {
await twonlyDatabase.contactsDao await twonlyDB.contactsDao
.updateContact(widget.contact.userId, update); .updateContact(widget.contact.userId, update);
} }
}, },
@ -82,7 +82,7 @@ class _UserContextMenuState extends State<UserContextMenu> {
final update = final update =
ContactsCompanion(pinned: Value(!widget.contact.pinned)); ContactsCompanion(pinned: Value(!widget.contact.pinned));
if (context.mounted) { if (context.mounted) {
await twonlyDatabase.contactsDao await twonlyDB.contactsDao
.updateContact(widget.contact.userId, update); .updateContact(widget.contact.userId, update);
} }
}, },

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/views/contact/contact_verify_view.dart'; import 'package:twonly/src/views/contact/contact_verify.view.dart';
class VerifiedShield extends StatelessWidget { class VerifiedShield extends StatelessWidget {
final Contact contact; final Contact contact;

View file

@ -9,7 +9,7 @@ import 'package:twonly/src/views/components/verified_shield.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/contact/contact_verify_view.dart'; import 'package:twonly/src/views/contact/contact_verify.view.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
class ContactView extends StatefulWidget { class ContactView extends StatefulWidget {
@ -24,7 +24,7 @@ class ContactView extends StatefulWidget {
class _ContactViewState extends State<ContactView> { class _ContactViewState extends State<ContactView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Stream<Contact?> contact = twonlyDatabase.contactsDao Stream<Contact?> contact = twonlyDB.contactsDao
.getContactByUserId(widget.userId) .getContactByUserId(widget.userId)
.watchSingleOrNull(); .watchSingleOrNull();
@ -76,8 +76,7 @@ class _ContactViewState extends State<ContactView> {
if (context.mounted && nickName != null && nickName != "") { if (context.mounted && nickName != null && nickName != "") {
final update = ContactsCompanion(nickName: Value(nickName)); final update = ContactsCompanion(nickName: Value(nickName));
twonlyDatabase.contactsDao twonlyDB.contactsDao.updateContact(contact.userId, update);
.updateContact(contact.userId, update);
} }
}, },
), ),
@ -105,7 +104,7 @@ class _ContactViewState extends State<ContactView> {
); );
if (block) { if (block) {
if (context.mounted) { if (context.mounted) {
await twonlyDatabase.messagesDao await twonlyDB.messagesDao
.deleteMessagesByContactId(contact.userId); .deleteMessagesByContactId(contact.userId);
} }
} }
@ -125,7 +124,7 @@ class _ContactViewState extends State<ContactView> {
if (block) { if (block) {
final update = ContactsCompanion(blocked: Value(true)); final update = ContactsCompanion(blocked: Value(true));
if (context.mounted) { if (context.mounted) {
await twonlyDatabase.contactsDao await twonlyDB.contactsDao
.updateContact(contact.userId, update); .updateContact(contact.userId, update);
} }
if (context.mounted) { if (context.mounted) {

View file

@ -14,7 +14,6 @@ import 'package:url_launcher/url_launcher.dart';
class ContactVerifyView extends StatefulWidget { class ContactVerifyView extends StatefulWidget {
const ContactVerifyView(this.contact, {super.key}); const ContactVerifyView(this.contact, {super.key});
final Contact contact; final Contact contact;
@override @override
@ -37,7 +36,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Stream<Contact?> contact = twonlyDatabase.contactsDao Stream<Contact?> contact = twonlyDB.contactsDao
.getContactByUserId(widget.contact.userId) .getContactByUserId(widget.contact.userId)
.watchSingleOrNull(); .watchSingleOrNull();
@ -114,7 +113,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
launchUrl(Uri.parse( launchUrl(Uri.parse(
"https://twonly.eu/faq/security/verify-security-number")); "https://twonly.eu/en/faq/security/verify-security-number.html"));
}, },
child: Text( child: Text(
"Read more.", "Read more.",
@ -146,7 +145,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
onPressed: () { onPressed: () {
final update = final update =
ContactsCompanion(verified: Value(false)); ContactsCompanion(verified: Value(false));
twonlyDatabase.contactsDao twonlyDB.contactsDao
.updateContact(contact.userId, update); .updateContact(contact.userId, update);
}, },
label: Text( label: Text(
@ -157,7 +156,7 @@ class _ContactVerifyViewState extends State<ContactVerifyView> {
icon: FaIcon(FontAwesomeIcons.shieldHeart), icon: FaIcon(FontAwesomeIcons.shieldHeart),
onPressed: () { onPressed: () {
final update = ContactsCompanion(verified: Value(true)); final update = ContactsCompanion(verified: Value(true));
twonlyDatabase.contactsDao twonlyDB.contactsDao
.updateContact(contact.userId, update); .updateContact(contact.userId, update);
}, },
label: Text(context.lang.contactVerifyNumberMarkAsVerified), label: Text(context.lang.contactVerifyNumberMarkAsVerified),

View file

@ -7,10 +7,10 @@ import 'package:screenshot/screenshot.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart'; import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
import 'package:twonly/src/views/components/user_context_menu.dart'; import 'package:twonly/src/views/components/user_context_menu.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/views/gallery/gallery_main_view.dart'; import 'package:twonly/src/views/memories/memories.view.dart';
import 'camera/camera_preview_controller_view.dart'; import 'camera/camera_preview_controller_view.dart';
import 'chats/chat_list_view.dart'; import 'chats/chat_list.view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
Function(int) globalUpdateOfHomeViewPageIndex = (a) {}; Function(int) globalUpdateOfHomeViewPageIndex = (a) {};
@ -163,7 +163,7 @@ class HomeViewState extends State<HomeView> {
children: [ children: [
ChatListView(), ChatListView(),
Container(), Container(),
GalleryMainView(), MemoriesView(),
], ],
), ),
), ),

View file

@ -1,24 +1,24 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:twonly/src/providers/api/media_send.dart' as send; import 'package:twonly/src/services/api/media_send.dart' as send;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
import 'package:twonly/src/views/gallery/gallery_item_thumbnail.dart'; import 'package:twonly/src/views/memories/memories_item_thumbnail.dart';
import 'package:twonly/src/views/gallery/gallery_photo_view.dart'; import 'package:twonly/src/views/memories/memories_photo_slider.view.dart';
class GalleryMainView extends StatefulWidget { class MemoriesView extends StatefulWidget {
const GalleryMainView({super.key}); const MemoriesView({super.key});
@override @override
State<GalleryMainView> createState() => GalleryMainViewState(); State<MemoriesView> createState() => MemoriesViewState();
} }
class GalleryMainViewState extends State<GalleryMainView> { class MemoriesViewState extends State<MemoriesView> {
bool verticalGallery = false; bool verticalGallery = false;
List<GalleryItem> galleryItems = []; List<MemoryItem> galleryItems = [];
Map<String, List<int>> orderedByMonth = {}; Map<String, List<int>> orderedByMonth = {};
List<String> months = []; List<String> months = [];
bool mounted = true; bool mounted = true;
@ -37,11 +37,11 @@ class GalleryMainViewState extends State<GalleryMainView> {
super.dispose(); super.dispose();
} }
Future<List<GalleryItem>> loadMemoriesDirectory() async { Future<List<MemoryItem>> loadMemoriesDirectory() async {
final directoryPath = await send.getMediaBaseFilePath("memories"); final directoryPath = await send.getMediaBaseFilePath("memories");
final directory = Directory(directoryPath); final directory = Directory(directoryPath);
List<GalleryItem> items = []; List<MemoryItem> items = [];
if (await directory.exists()) { if (await directory.exists()) {
final files = directory.listSync(); final files = directory.listSync();
@ -58,7 +58,7 @@ class GalleryMainViewState extends State<GalleryMainView> {
break; break;
} }
final creationDate = await file.lastModified(); final creationDate = await file.lastModified();
items.add(GalleryItem( items.add(MemoryItem(
id: fileName, id: fileName,
messages: [], messages: [],
date: creationDate, date: creationDate,
@ -75,10 +75,10 @@ class GalleryMainViewState extends State<GalleryMainView> {
Future initAsync() async { Future initAsync() async {
messageSub?.cancel(); messageSub?.cancel();
Stream<List<Message>> msgStream = Stream<List<Message>> msgStream =
twonlyDatabase.messagesDao.getAllStoredMediaFiles(); twonlyDB.messagesDao.getAllStoredMediaFiles();
messageSub = msgStream.listen((msgs) async { messageSub = msgStream.listen((msgs) async {
Map<int, GalleryItem> items = await GalleryItem.convertFromMessages(msgs); Map<int, MemoryItem> items = await MemoryItem.convertFromMessages(msgs);
// Group items by month // Group items by month
orderedByMonth = {}; orderedByMonth = {};
months = []; months = [];
@ -126,7 +126,7 @@ class GalleryMainViewState extends State<GalleryMainView> {
itemCount: orderedByMonth[months[index]]!.length, itemCount: orderedByMonth[months[index]]!.length,
itemBuilder: (context, gIndex) { itemBuilder: (context, gIndex) {
int gaIndex = orderedByMonth[months[index]]![gIndex]; int gaIndex = orderedByMonth[months[index]]![gIndex];
return GalleryItemThumbnail( return MemoriesItemThumbnail(
galleryItem: galleryItems[gaIndex], galleryItem: galleryItems[gaIndex],
onTap: () { onTap: () {
open(context, gaIndex); open(context, gaIndex);
@ -144,7 +144,7 @@ class GalleryMainViewState extends State<GalleryMainView> {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => GalleryPhotoViewWrapper( builder: (context) => MemoriesPhotoSliderView(
galleryItems: galleryItems, galleryItems: galleryItems,
initialIndex: index, initialIndex: index,
scrollDirection: verticalGallery ? Axis.vertical : Axis.horizontal, scrollDirection: verticalGallery ? Axis.vertical : Axis.horizontal,

View file

@ -1,22 +1,22 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
class GalleryItemThumbnail extends StatefulWidget { class MemoriesItemThumbnail extends StatefulWidget {
const GalleryItemThumbnail({ const MemoriesItemThumbnail({
super.key, super.key,
required this.galleryItem, required this.galleryItem,
required this.onTap, required this.onTap,
}); });
final GalleryItem galleryItem; final MemoryItem galleryItem;
final GestureTapCallback onTap; final GestureTapCallback onTap;
@override @override
State<GalleryItemThumbnail> createState() => _GalleryItemThumbnailState(); State<MemoriesItemThumbnail> createState() => _MemoriesItemThumbnailState();
} }
class _GalleryItemThumbnailState extends State<GalleryItemThumbnail> { class _MemoriesItemThumbnailState extends State<MemoriesItemThumbnail> {
VideoPlayerController? _controller; VideoPlayerController? _controller;
@override @override

View file

@ -5,17 +5,17 @@ import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart'; import 'package:photo_view/photo_view_gallery.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/api/media_received.dart' as received; import 'package:twonly/src/services/api/media_received.dart' as received;
import 'package:twonly/src/providers/api/media_send.dart' as send; import 'package:twonly/src/services/api/media_send.dart' as send;
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/share_image_editor_view.dart'; import 'package:twonly/src/views/camera/share_image_editor_view.dart';
import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/alert_dialog.dart';
import 'package:twonly/src/views/components/media_view_sizing.dart'; import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:twonly/src/views/components/video_player_wrapper.dart'; import 'package:twonly/src/views/components/video_player_wrapper.dart';
import 'package:twonly/src/views/gallery/gallery_item.dart'; import 'package:twonly/src/model/memory_item.model.dart';
class GalleryPhotoViewWrapper extends StatefulWidget { class MemoriesPhotoSliderView extends StatefulWidget {
GalleryPhotoViewWrapper({ MemoriesPhotoSliderView({
super.key, super.key,
this.loadingBuilder, this.loadingBuilder,
this.backgroundDecoration, this.backgroundDecoration,
@ -32,16 +32,16 @@ class GalleryPhotoViewWrapper extends StatefulWidget {
final dynamic maxScale; final dynamic maxScale;
final int initialIndex; final int initialIndex;
final PageController pageController; final PageController pageController;
final List<GalleryItem> galleryItems; final List<MemoryItem> galleryItems;
final Axis scrollDirection; final Axis scrollDirection;
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
return _GalleryPhotoViewWrapperState(); return _MemoriesPhotoSliderViewState();
} }
} }
class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> { class _MemoriesPhotoSliderViewState extends State<MemoriesPhotoSliderView> {
late int currentIndex = widget.initialIndex; late int currentIndex = widget.initialIndex;
void onPageChanged(int index) { void onPageChanged(int index) {
@ -60,7 +60,7 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
widget.galleryItems[currentIndex].imagePath?.deleteSync(); widget.galleryItems[currentIndex].imagePath?.deleteSync();
widget.galleryItems[currentIndex].videoPath?.deleteSync(); widget.galleryItems[currentIndex].videoPath?.deleteSync();
for (final message in messages) { for (final message in messages) {
await twonlyDatabase.messagesDao.updateMessageByMessageId( await twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId, message.messageId,
MessagesCompanion(mediaStored: Value(false)), MessagesCompanion(mediaStored: Value(false)),
); );
@ -166,7 +166,7 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
} }
PhotoViewGalleryPageOptions _buildItem(BuildContext context, int index) { PhotoViewGalleryPageOptions _buildItem(BuildContext context, int index) {
final GalleryItem item = widget.galleryItems[index]; final MemoryItem item = widget.galleryItems[index];
return item.videoPath != null return item.videoPath != null
? PhotoViewGalleryPageOptions.customChild( ? PhotoViewGalleryPageOptions.customChild(
child: VideoPlayerWrapper( child: VideoPlayerWrapper(

View file

@ -35,7 +35,7 @@ class _RegisterViewState extends State<RegisterView> {
await createIfNotExistsSignalIdentity(); await createIfNotExistsSignalIdentity();
final res = await apiProvider.register(username, inviteCode); final res = await apiService.register(username, inviteCode);
setState(() { setState(() {
_isTryingToRegister = false; _isTryingToRegister = false;
@ -50,7 +50,7 @@ class _RegisterViewState extends State<RegisterView> {
subscriptionPlan: "Preview", subscriptionPlan: "Preview",
); );
storage.write(key: "userData", value: jsonEncode(userData)); storage.write(key: "userData", value: jsonEncode(userData));
apiProvider.authenticate(); apiService.authenticate();
widget.callbackOnSuccess(); widget.callbackOnSuccess();
return; return;
} }

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/src/views/components/radio_button.dart'; import 'package:twonly/src/views/components/radio_button.dart';
import 'package:twonly/src/providers/settings_change_provider.dart'; import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
class AppearanceView extends StatelessWidget { class AppearanceView extends StatelessWidget {

View file

@ -1,6 +1,6 @@
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:twonly/src/providers/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';

View file

@ -5,8 +5,8 @@ import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/alert_dialog.dart';
import 'package:twonly/src/services/fcm_service.dart'; import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/services/notification.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
@ -48,7 +48,7 @@ class NotificationView extends StatelessWidget {
user.userId, user.userId,
PushKind.testNotification, PushKind.testNotification,
); );
await apiProvider.sendTextMessage( await apiService.sendTextMessage(
user.userId, user.userId,
Uint8List(0), Uint8List(0),
pushData, pushData,

View file

@ -27,7 +27,7 @@ class _PrivacyViewState extends State<PrivacyView> {
ListTile( ListTile(
title: Text(context.lang.settingsPrivacyBlockUsers), title: Text(context.lang.settingsPrivacyBlockUsers),
subtitle: StreamBuilder( subtitle: StreamBuilder(
stream: twonlyDatabase.contactsDao.watchContactsBlocked(), stream: twonlyDB.contactsDao.watchContactsBlocked(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data != null) { if (snapshot.hasData && snapshot.data != null) {
return Text( return Text(

View file

@ -21,7 +21,7 @@ class _PrivacyViewBlockUsers extends State<PrivacyViewBlockUsers> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
allUsers = twonlyDatabase.contactsDao.watchAllContacts(); allUsers = twonlyDB.contactsDao.watchAllContacts();
loadAsync(); loadAsync();
} }
@ -91,7 +91,7 @@ class UserList extends StatelessWidget {
Future block(BuildContext context, int userId, bool? value) async { Future block(BuildContext context, int userId, bool? value) async {
if (value != null) { if (value != null) {
final update = ContactsCompanion(blocked: Value(value)); final update = ContactsCompanion(blocked: Value(value));
await twonlyDatabase.contactsDao.updateContact(userId, update); await twonlyDB.contactsDao.updateContact(userId, update);
} }
} }

View file

@ -3,7 +3,7 @@ import 'package:avatar_maker/avatar_maker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/model/json/userdata.dart'; import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import "package:get/get.dart"; import "package:get/get.dart";
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';

View file

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/views/components/better_list_title.dart'; import 'package:twonly/src/views/components/better_list_title.dart';
import 'package:twonly/src/model/json/userdata.dart'; import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/settings/profile/modify_avatar_view.dart'; import 'package:twonly/src/views/settings/profile/modify_avatar_view.dart';

View file

@ -7,7 +7,7 @@ import 'package:logging/logging.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/views/components/alert_dialog.dart';
@ -17,7 +17,7 @@ Future<List<Response_AddAccountsInvite>?> loadAdditionalUserInvites() async {
List<Response_AddAccountsInvite>? ballance; List<Response_AddAccountsInvite>? ballance;
final user = await getUser(); final user = await getUser();
if (user == null) return ballance; if (user == null) return ballance;
ballance = await apiProvider.getAdditionalUserInvites(); ballance = await apiService.getAdditionalUserInvites();
if (ballance != null) { if (ballance != null) {
user.additionalUserInvites = user.additionalUserInvites =
jsonEncode(ballance.map((x) => x.writeToJson()).toList()); jsonEncode(ballance.map((x) => x.writeToJson()).toList());
@ -147,7 +147,7 @@ class _AdditionalAccountState extends State<AdditionalAccount> {
} }
Future initAsync() async { Future initAsync() async {
final contact = await twonlyDatabase.contactsDao final contact = await twonlyDB.contactsDao
.getContactByUserId(widget.account.userId.toInt()) .getContactByUserId(widget.account.userId.toInt())
.getSingleOrNull(); .getSingleOrNull();
if (contact != null) { if (contact != null) {
@ -188,7 +188,7 @@ class _AdditionalAccountState extends State<AdditionalAccount> {
"Remove this additional user", "Remove this additional user",
"The additional user will automatically be downgraded to the preview plan after removal and you will receive a new invitation code to give to another person."); "The additional user will automatically be downgraded to the preview plan after removal and you will receive a new invitation code to give to another person.");
if (remove) { if (remove) {
Result res = await apiProvider Result res = await apiService
.removeAdditionalUser(widget.account.userId); .removeAdditionalUser(widget.account.userId);
if (!context.mounted) return; if (!context.mounted) return;
if (res.isSuccess) { if (res.isSuccess) {

View file

@ -3,8 +3,8 @@ import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/api/api_utils.dart'; import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/settings/subscription/subscription_view.dart'; import 'package:twonly/src/views/settings/subscription/subscription_view.dart';
@ -44,7 +44,7 @@ class _ManageSubscriptionViewState extends State<ManageSubscriptionView> {
} }
Future toggleRenewalOption() async { Future toggleRenewalOption() async {
Result res = await apiProvider.updatePlanOptions(!autoRenewal!); Result res = await apiService.updatePlanOptions(!autoRenewal!);
if (res.isError) { if (res.isError) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(errorCodeToText(context, res.error))), SnackBar(content: Text(errorCodeToText(context, res.error))),

View file

@ -2,7 +2,7 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/settings/subscription/subscription_view.dart'; import 'package:twonly/src/views/settings/subscription/subscription_view.dart';
@ -213,7 +213,7 @@ class _SelectPaymentViewState extends State<SelectPaymentView> {
child: FilledButton( child: FilledButton(
onPressed: (canPay) onPressed: (canPay)
? () async { ? () async {
final res = await apiProvider.switchToPayedPlan( final res = await apiService.switchToPayedPlan(
widget.planId!, widget.payMonthly!, tryAutoRenewal); widget.planId!, widget.payMonthly!, tryAutoRenewal);
if (!context.mounted) return; if (!context.mounted) return;
if (res.isSuccess) { if (res.isSuccess) {

View file

@ -9,7 +9,7 @@ import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/components/better_list_title.dart'; import 'package:twonly/src/views/components/better_list_title.dart';
@ -39,7 +39,7 @@ Future<Response_PlanBallance?> loadPlanBallance() async {
Response_PlanBallance? ballance; Response_PlanBallance? ballance;
final user = await getUser(); final user = await getUser();
if (user == null) return ballance; if (user == null) return ballance;
ballance = await apiProvider.getPlanBallance(); ballance = await apiService.getPlanBallance();
if (ballance != null) { if (ballance != null) {
user.lastPlanBallance = ballance.writeToJson(); user.lastPlanBallance = ballance.writeToJson();
await updateUser(user); await updateUser(user);
@ -116,7 +116,7 @@ class _SubscriptionViewState extends State<SubscriptionView> {
ballance = await loadPlanBallance(); ballance = await loadPlanBallance();
if (ballance != null && ballance!.hasAdditionalAccountOwnerId()) { if (ballance != null && ballance!.hasAdditionalAccountOwnerId()) {
final ownerId = ballance!.additionalAccountOwnerId.toInt(); final ownerId = ballance!.additionalAccountOwnerId.toInt();
Contact? contact = await twonlyDatabase.contactsDao Contact? contact = await twonlyDB.contactsDao
.getContactByUserId(ownerId) .getContactByUserId(ownerId)
.getSingleOrNull(); .getSingleOrNull();
if (contact != null) { if (contact != null) {
@ -551,7 +551,7 @@ Future redeemUserInviteCode(BuildContext context, String newPlan) async {
), ),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
final res = await apiProvider.redeemUserInviteCode(inviteCode); final res = await apiService.redeemUserInviteCode(inviteCode);
if (!context.mounted) return; if (!context.mounted) return;
if (res.isSuccess) { if (res.isSuccess) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
@ -559,8 +559,8 @@ Future redeemUserInviteCode(BuildContext context, String newPlan) async {
content: Text(context.lang.redeemUserInviteCodeSuccess)), content: Text(context.lang.redeemUserInviteCodeSuccess)),
); );
// reconnect to load new plan. // reconnect to load new plan.
apiProvider.close(() { apiService.close(() {
apiProvider.connect(); apiService.connect();
}); });
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(

View file

@ -22,7 +22,7 @@ class _VoucherViewState extends State<VoucherView> {
} }
Future initAsync() async { Future initAsync() async {
Response_Vouchers? resVouchers = await apiProvider.getVoucherList(); Response_Vouchers? resVouchers = await apiService.getVoucherList();
if (resVouchers != null) { if (resVouchers != null) {
setState(() { setState(() {
vouchers = resVouchers.vouchers; vouchers = resVouchers.vouchers;
@ -193,7 +193,7 @@ Future redeemVoucher(BuildContext context) async {
), ),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
final res = await apiProvider.redeemVoucher(voucherCode); final res = await apiService.redeemVoucher(voucherCode);
if (!context.mounted) return; if (!context.mounted) return;
if (res.isSuccess) { if (res.isSuccess) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
@ -284,7 +284,7 @@ Future showBuyVoucher(BuildContext context) async {
), ),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
final res = await apiProvider.buyVoucher(quantity); final res = await apiService.buyVoucher(quantity);
if (!context.mounted) return; if (!context.mounted) return;
if (res.isSuccess) { if (res.isSuccess) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(