mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 17:48:40 +00:00
move utils to separate files
This commit is contained in:
parent
52ee97c932
commit
084222eee8
14 changed files with 154 additions and 165 deletions
|
|
@ -3,8 +3,7 @@ import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import 'package:twonly/src/providers/db_provider.dart';
|
import 'package:twonly/src/providers/db_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
import 'src/app.dart';
|
import 'src/app.dart';
|
||||||
import 'src/settings/settings_controller.dart';
|
import 'src/settings/settings_controller.dart';
|
||||||
import 'src/settings/settings_service.dart';
|
import 'src/settings/settings_service.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:twonly/main.dart';
|
import 'package:twonly/main.dart';
|
||||||
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/onboarding_view.dart';
|
import 'package:twonly/src/views/onboarding_view.dart';
|
||||||
import 'views/home_view.dart';
|
import 'package:twonly/src/views/home_view.dart';
|
||||||
import 'views/register_view.dart';
|
import 'package:twonly/src/views/register_view.dart';
|
||||||
import 'utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ import 'package:twonly/src/proto/api/error.pb.dart';
|
||||||
import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server;
|
import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server;
|
||||||
import 'package:twonly/src/signal/signal_helper.dart';
|
import 'package:twonly/src/signal/signal_helper.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:web_socket_channel/io.dart';
|
import 'package:web_socket_channel/io.dart';
|
||||||
import 'package:libsignal_protocol_dart/src/ecc/ed25519.dart';
|
import 'package:libsignal_protocol_dart/src/ecc/ed25519.dart';
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import 'package:twonly/src/model/model_constants.dart';
|
||||||
import 'package:twonly/src/model/pre_key_model.dart';
|
import 'package:twonly/src/model/pre_key_model.dart';
|
||||||
import 'package:twonly/src/model/sender_key_store_model.dart';
|
import 'package:twonly/src/model/sender_key_store_model.dart';
|
||||||
import 'package:twonly/src/model/session_store_model.dart';
|
import 'package:twonly/src/model/session_store_model.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
|
||||||
import 'package:sqflite_sqlcipher/sqflite.dart';
|
import 'package:sqflite_sqlcipher/sqflite.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
class DbProvider {
|
class DbProvider {
|
||||||
Database? db;
|
Database? db;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:twonly/src/utils.dart';
|
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
class ConnectSignedPreKeyStore extends SignedPreKeyStore {
|
class ConnectSignedPreKeyStore extends SignedPreKeyStore {
|
||||||
// final store = HashMap<int, Uint8List>();
|
// final store = HashMap<int, Uint8List>();
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/src/model/signal_identity_json.dart';
|
import 'package:twonly/src/model/signal_identity_json.dart';
|
||||||
import 'package:twonly/src/proto/api/server_to_client.pb.dart';
|
import 'package:twonly/src/proto/api/server_to_client.pb.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
import 'connect_sender_key_store.dart';
|
import 'connect_sender_key_store.dart';
|
||||||
import 'connect_signal_protocol_store.dart';
|
import 'connect_signal_protocol_store.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:gal/gal.dart';
|
|
||||||
import 'package:logging/logging.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:twonly/main.dart';
|
|
||||||
import 'package:twonly/src/model/contacts_model.dart';
|
|
||||||
import 'package:twonly/src/signal/signal_helper.dart';
|
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
import 'model/user_data_json.dart';
|
|
||||||
|
|
||||||
// Just a helper function to get the secure storage
|
|
||||||
FlutterSecureStorage getSecureStorage() {
|
|
||||||
AndroidOptions _getAndroidOptions() => const AndroidOptions(
|
|
||||||
encryptedSharedPreferences: true,
|
|
||||||
);
|
|
||||||
return FlutterSecureStorage(aOptions: _getAndroidOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> isUserCreated() async {
|
|
||||||
UserData? user = await getUser();
|
|
||||||
if (user == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String?> saveImageToGallery(path) async {
|
|
||||||
final hasAccess = await Gal.hasAccess();
|
|
||||||
if (!hasAccess) {
|
|
||||||
await Gal.requestAccess();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await Gal.putImage(path);
|
|
||||||
return null;
|
|
||||||
} on GalException catch (e) {
|
|
||||||
return e.type.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<UserData?> getUser() async {
|
|
||||||
final storage = getSecureStorage();
|
|
||||||
String? userJson = await storage.read(key: "user_data");
|
|
||||||
if (userJson == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final userMap = jsonDecode(userJson) as Map<String, dynamic>;
|
|
||||||
Logger("get_user").info("Found user: $userMap");
|
|
||||||
final user = UserData.fromJson(userMap);
|
|
||||||
return user;
|
|
||||||
} catch (e) {
|
|
||||||
Logger("get_user").shout("Error getting user: $e");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> deleteLocalUserData() async {
|
|
||||||
final storage = getSecureStorage();
|
|
||||||
var password = await storage.read(key: "sqflite_database_password");
|
|
||||||
await dbProvider.remove();
|
|
||||||
await storage.write(key: "sqflite_database_password", value: password);
|
|
||||||
await storage.deleteAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint8List getRandomUint8List(int length) {
|
|
||||||
final Random random = Random.secure();
|
|
||||||
final Uint8List randomBytes = Uint8List(length);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
randomBytes[i] = random.nextInt(256); // Generate a random byte (0-255)
|
|
||||||
}
|
|
||||||
|
|
||||||
return randomBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
int userIdToRegistrationId(Uint8List userId) {
|
|
||||||
int result = 0;
|
|
||||||
for (int i = 8; i < 16; i++) {
|
|
||||||
result = (result << 8) | userId[i];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
String uint8ListToHex(Uint8List list) {
|
|
||||||
final StringBuffer hexBuffer = StringBuffer();
|
|
||||||
for (int byte in list) {
|
|
||||||
hexBuffer.write(byte.toRadixString(16).padLeft(2, '0'));
|
|
||||||
}
|
|
||||||
return hexBuffer.toString().toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> addNewUser(String username) async {
|
|
||||||
final res = await apiProvider.getUserData(username);
|
|
||||||
|
|
||||||
if (res.isSuccess) {
|
|
||||||
print(res.value);
|
|
||||||
print(res.value.userdata.userId);
|
|
||||||
|
|
||||||
if (await SignalHelper.addNewContact(res.value.userdata)) {
|
|
||||||
await dbProvider.db!.insert(DbContacts.tableName, {
|
|
||||||
DbContacts.columnDisplayName: username,
|
|
||||||
DbContacts.columnUserId: res.value.userdata.userId.toInt()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
print("Add new user: ${res}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.isSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Result> createNewUser(String username, String inviteCode) async {
|
|
||||||
final storage = getSecureStorage();
|
|
||||||
|
|
||||||
await SignalHelper.createIfNotExistsSignalIdentity();
|
|
||||||
|
|
||||||
final res = await apiProvider.register(username, inviteCode);
|
|
||||||
|
|
||||||
if (res.isSuccess) {
|
|
||||||
Logger("create_new_user").info("Got user_id ${res.value} from server");
|
|
||||||
final userData = UserData(
|
|
||||||
userId: res.value.userid, username: username, displayName: username);
|
|
||||||
storage.write(key: "user_data", value: jsonEncode(userData));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> writeLogToFile(LogRecord record) async {
|
|
||||||
final directory = await getApplicationDocumentsDirectory();
|
|
||||||
final logFile = File('${directory.path}/app.log');
|
|
||||||
|
|
||||||
// Prepare the log message
|
|
||||||
final logMessage =
|
|
||||||
'${record.level.name}: ${record.loggerName}: ${record.message}\n';
|
|
||||||
|
|
||||||
// Append the log message to the file
|
|
||||||
await logFile.writeAsString(logMessage, mode: FileMode.append);
|
|
||||||
}
|
|
||||||
44
lib/src/utils/api.dart
Normal file
44
lib/src/utils/api.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:twonly/main.dart';
|
||||||
|
import 'package:twonly/src/model/contacts_model.dart';
|
||||||
|
import 'package:twonly/src/signal/signal_helper.dart';
|
||||||
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/model/user_data_json.dart';
|
||||||
|
|
||||||
|
Future<bool> addNewUser(String username) async {
|
||||||
|
final res = await apiProvider.getUserData(username);
|
||||||
|
|
||||||
|
if (res.isSuccess) {
|
||||||
|
print(res.value);
|
||||||
|
print(res.value.userdata.userId);
|
||||||
|
|
||||||
|
if (await SignalHelper.addNewContact(res.value.userdata)) {
|
||||||
|
await dbProvider.db!.insert(DbContacts.tableName, {
|
||||||
|
DbContacts.columnDisplayName: username,
|
||||||
|
DbContacts.columnUserId: res.value.userdata.userId.toInt()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
print("Add new user: ${res}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.isSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Result> createNewUser(String username, String inviteCode) async {
|
||||||
|
final storage = getSecureStorage();
|
||||||
|
|
||||||
|
await SignalHelper.createIfNotExistsSignalIdentity();
|
||||||
|
|
||||||
|
final res = await apiProvider.register(username, inviteCode);
|
||||||
|
|
||||||
|
if (res.isSuccess) {
|
||||||
|
Logger("create_new_user").info("Got user_id ${res.value} from server");
|
||||||
|
final userData = UserData(
|
||||||
|
userId: res.value.userid, username: username, displayName: username);
|
||||||
|
storage.write(key: "user_data", value: jsonEncode(userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
51
lib/src/utils/misc.dart
Normal file
51
lib/src/utils/misc.dart
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:gal/gal.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
|
||||||
|
Future<void> writeLogToFile(LogRecord record) async {
|
||||||
|
final directory = await getApplicationDocumentsDirectory();
|
||||||
|
final logFile = File('${directory.path}/app.log');
|
||||||
|
|
||||||
|
// Prepare the log message
|
||||||
|
final logMessage =
|
||||||
|
'${record.level.name}: ${record.loggerName}: ${record.message}\n';
|
||||||
|
|
||||||
|
// Append the log message to the file
|
||||||
|
await logFile.writeAsString(logMessage, mode: FileMode.append);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just a helper function to get the secure storage
|
||||||
|
FlutterSecureStorage getSecureStorage() {
|
||||||
|
AndroidOptions _getAndroidOptions() => const AndroidOptions(
|
||||||
|
encryptedSharedPreferences: true,
|
||||||
|
);
|
||||||
|
return FlutterSecureStorage(aOptions: _getAndroidOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> saveImageToGallery(path) async {
|
||||||
|
final hasAccess = await Gal.hasAccess();
|
||||||
|
if (!hasAccess) {
|
||||||
|
await Gal.requestAccess();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await Gal.putImage(path);
|
||||||
|
return null;
|
||||||
|
} on GalException catch (e) {
|
||||||
|
return e.type.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8List getRandomUint8List(int length) {
|
||||||
|
final Random random = Random.secure();
|
||||||
|
final Uint8List randomBytes = Uint8List(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
randomBytes[i] = random.nextInt(256); // Generate a random byte (0-255)
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomBytes;
|
||||||
|
}
|
||||||
39
lib/src/utils/storage.dart
Normal file
39
lib/src/utils/storage.dart
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:twonly/main.dart';
|
||||||
|
import 'package:twonly/src/model/user_data_json.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
|
Future<bool> isUserCreated() async {
|
||||||
|
UserData? user = await getUser();
|
||||||
|
if (user == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<UserData?> getUser() async {
|
||||||
|
final storage = getSecureStorage();
|
||||||
|
String? userJson = await storage.read(key: "user_data");
|
||||||
|
if (userJson == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final userMap = jsonDecode(userJson) as Map<String, dynamic>;
|
||||||
|
Logger("get_user").info("Found user: $userMap");
|
||||||
|
final user = UserData.fromJson(userMap);
|
||||||
|
return user;
|
||||||
|
} catch (e) {
|
||||||
|
Logger("get_user").shout("Error getting user: $e");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> deleteLocalUserData() async {
|
||||||
|
final storage = getSecureStorage();
|
||||||
|
var password = await storage.read(key: "sqflite_database_password");
|
||||||
|
await dbProvider.remove();
|
||||||
|
await storage.write(key: "sqflite_database_password", value: password);
|
||||||
|
await storage.deleteAll();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import 'package:twonly/src/model/user_data_json.dart';
|
import 'package:twonly/src/model/user_data_json.dart';
|
||||||
|
|
||||||
import '../settings/settings_controller.dart';
|
|
||||||
import '../settings/settings_view.dart';
|
|
||||||
import '../utils.dart';
|
|
||||||
import 'package:restart_app/restart_app.dart';
|
import 'package:restart_app/restart_app.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:twonly/src/settings/settings_controller.dart';
|
||||||
|
import 'package:twonly/src/settings/settings_view.dart';
|
||||||
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
class ProfileView extends StatefulWidget {
|
class ProfileView extends StatefulWidget {
|
||||||
const ProfileView({super.key, required this.settingsController});
|
const ProfileView({super.key, required this.settingsController});
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:twonly/main.dart';
|
import 'package:twonly/main.dart';
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import '../utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:twonly/src/utils/api.dart';
|
||||||
|
|
||||||
class RegisterView extends StatefulWidget {
|
class RegisterView extends StatefulWidget {
|
||||||
const RegisterView({super.key, required this.callbackOnSuccess});
|
const RegisterView({super.key, required this.callbackOnSuccess});
|
||||||
|
|
@ -130,9 +130,11 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
widget.callbackOnSuccess();
|
widget.callbackOnSuccess();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (context.mounted) {
|
||||||
final errMsg =
|
final errMsg =
|
||||||
ApiProvider.getLocalizedString(context, res.error);
|
ApiProvider.getLocalizedString(context, res.error);
|
||||||
showAlertDialog(context, "Oh no!", errMsg);
|
showAlertDialog(context, "Oh no!", errMsg);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
padding: WidgetStateProperty.all<EdgeInsets>(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
import 'package:twonly/src/utils/api.dart';
|
||||||
import 'package:twonly/src/views/register_view.dart';
|
import 'package:twonly/src/views/register_view.dart';
|
||||||
|
|
||||||
class SearchUsernameView extends StatefulWidget {
|
class SearchUsernameView extends StatefulWidget {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:twonly/src/utils.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/share_image_view.dart';
|
import 'package:twonly/src/views/share_image_view.dart';
|
||||||
|
|
||||||
class ShareImageEditorView extends StatefulWidget {
|
class ShareImageEditorView extends StatefulWidget {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue