move utils to separate files

This commit is contained in:
otsmr 2025-01-24 15:25:44 +01:00
parent 52ee97c932
commit 084222eee8
14 changed files with 154 additions and 165 deletions

View file

@ -3,8 +3,7 @@ import 'package:twonly/src/providers/api_provider.dart';
import 'package:twonly/src/providers/db_provider.dart';
import 'package:flutter/material.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/settings/settings_controller.dart';
import 'src/settings/settings_service.dart';

View file

@ -1,8 +1,8 @@
import 'package:twonly/main.dart';
import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/onboarding_view.dart';
import 'views/home_view.dart';
import 'views/register_view.dart';
import 'utils.dart';
import 'package:twonly/src/views/home_view.dart';
import 'package:twonly/src/views/register_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

View file

@ -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/signal/signal_helper.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:libsignal_protocol_dart/src/ecc/ed25519.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

View file

@ -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/sender_key_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:twonly/src/utils/misc.dart';
class DbProvider {
Database? db;

View file

@ -1,9 +1,8 @@
import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'package:twonly/src/utils.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/src/utils/misc.dart';
class ConnectSignedPreKeyStore extends SignedPreKeyStore {
// final store = HashMap<int, Uint8List>();

View file

@ -6,7 +6,7 @@ import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:logging/logging.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/utils.dart';
import 'package:twonly/src/utils/misc.dart';
import 'connect_sender_key_store.dart';
import 'connect_signal_protocol_store.dart';

View file

@ -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
View 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
View 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;
}

View 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;
}

View file

@ -1,10 +1,9 @@
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: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 {
const ProfileView({super.key, required this.settingsController});

View file

@ -1,9 +1,9 @@
import 'package:twonly/main.dart';
import 'package:twonly/src/providers/api_provider.dart';
import '../utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/utils/api.dart';
class RegisterView extends StatefulWidget {
const RegisterView({super.key, required this.callbackOnSuccess});
@ -130,9 +130,11 @@ class _RegisterViewState extends State<RegisterView> {
widget.callbackOnSuccess();
return;
}
if (context.mounted) {
final errMsg =
ApiProvider.getLocalizedString(context, res.error);
showAlertDialog(context, "Oh no!", errMsg);
}
},
style: ButtonStyle(
padding: WidgetStateProperty.all<EdgeInsets>(

View file

@ -1,9 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.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';
class SearchUsernameView extends StatefulWidget {

View file

@ -1,8 +1,7 @@
import 'dart:io';
import 'package:flutter/material.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';
class ShareImageEditorView extends StatefulWidget {