mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-05-25 05:22:13 +00:00
replace globals with app environment
This commit is contained in:
parent
693c74df46
commit
d9f9f7645e
15 changed files with 48 additions and 45 deletions
|
|
@ -1,17 +1,28 @@
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/services/api.service.dart';
|
import 'package:twonly/src/services/api.service.dart';
|
||||||
import 'package:twonly/src/services/subscription.service.dart';
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
|
|
||||||
|
class AppEnvironment {
|
||||||
|
static late final String cacheDir;
|
||||||
|
static late final String supportDir;
|
||||||
|
static late final List<CameraDescription> cameras;
|
||||||
|
|
||||||
|
static Future<void> init() async {
|
||||||
|
cacheDir = (await getApplicationCacheDirectory()).path;
|
||||||
|
supportDir = (await getApplicationSupportDirectory()).path;
|
||||||
|
cameras = await availableCameras();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
|
|
||||||
// uses for background notification
|
// uses for background notification
|
||||||
late TwonlyDB twonlyDB;
|
late TwonlyDB twonlyDB;
|
||||||
|
|
||||||
List<CameraDescription> gCameras = <CameraDescription>[];
|
|
||||||
|
|
||||||
// Cached UserData in the memory. Every time the user data is changed the `updateUserdata` function is called,
|
// Cached UserData in the memory. Every time the user data is changed the `updateUserdata` function is called,
|
||||||
// which will update this global variable. The variable is set in the main.dart and after the user has registered in the register.view.dart
|
// which will update this global variable. The variable is set in the main.dart and after the user has registered in the register.view.dart
|
||||||
late UserData gUser;
|
late UserData gUser;
|
||||||
|
|
@ -36,8 +47,5 @@ bool globalIsInBackgroundTask = false;
|
||||||
bool globalAllowErrorTrackingViaSentry = false;
|
bool globalAllowErrorTrackingViaSentry = false;
|
||||||
bool globalGotMessageFromServer = false;
|
bool globalGotMessageFromServer = false;
|
||||||
|
|
||||||
late String globalApplicationCacheDirectory;
|
|
||||||
late String globalApplicationSupportDirectory;
|
|
||||||
|
|
||||||
final GlobalKey<ScaffoldMessengerState> globalRootScaffoldMessengerKey =
|
final GlobalKey<ScaffoldMessengerState> globalRootScaffoldMessengerKey =
|
||||||
GlobalKey<ScaffoldMessengerState>();
|
GlobalKey<ScaffoldMessengerState>();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:camera/camera.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
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:path_provider/path_provider.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||||
import 'package:twonly/app.dart';
|
import 'package:twonly/app.dart';
|
||||||
|
|
@ -35,10 +33,7 @@ void main() async {
|
||||||
SentryWidgetsFlutterBinding.ensureInitialized();
|
SentryWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
await RustLib.init();
|
await RustLib.init();
|
||||||
|
await AppEnvironment.init();
|
||||||
globalApplicationCacheDirectory = (await getApplicationCacheDirectory()).path;
|
|
||||||
globalApplicationSupportDirectory =
|
|
||||||
(await getApplicationSupportDirectory()).path;
|
|
||||||
|
|
||||||
initLogger();
|
initLogger();
|
||||||
|
|
||||||
|
|
@ -46,8 +41,8 @@ void main() async {
|
||||||
|
|
||||||
await bridge.initializeTwonlyFlutter(
|
await bridge.initializeTwonlyFlutter(
|
||||||
config: bridge.TwonlyConfig(
|
config: bridge.TwonlyConfig(
|
||||||
databasePath: '$globalApplicationSupportDirectory/twonly.sqlite',
|
databasePath: '${AppEnvironment.supportDir}/twonly.sqlite',
|
||||||
dataDirectory: globalApplicationSupportDirectory,
|
dataDirectory: AppEnvironment.supportDir,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -56,7 +51,7 @@ void main() async {
|
||||||
var user = await getUser();
|
var user = await getUser();
|
||||||
|
|
||||||
if (Platform.isIOS && user != null) {
|
if (Platform.isIOS && user != null) {
|
||||||
final db = File('$globalApplicationSupportDirectory/twonly.sqlite');
|
final db = File('${AppEnvironment.supportDir}/twonly.sqlite');
|
||||||
if (!db.existsSync()) {
|
if (!db.existsSync()) {
|
||||||
Log.error('[twonly] IOS: App was removed and then reinstalled again...');
|
Log.error('[twonly] IOS: App was removed and then reinstalled again...');
|
||||||
await const FlutterSecureStorage().deleteAll();
|
await const FlutterSecureStorage().deleteAll();
|
||||||
|
|
@ -92,8 +87,6 @@ void main() async {
|
||||||
|
|
||||||
unawaited(setupPushNotification());
|
unawaited(setupPushNotification());
|
||||||
|
|
||||||
gCameras = await availableCameras();
|
|
||||||
|
|
||||||
apiService = ApiService();
|
apiService = ApiService();
|
||||||
twonlyDB = TwonlyDB();
|
twonlyDB = TwonlyDB();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0029f698ea3deb47dedc4ee1f37e5688d1f83f9b
|
Subproject commit e1ac9e6c476f82819063a8087af4d42acc1167d4
|
||||||
|
|
@ -62,9 +62,8 @@ Future<bool> initBackgroundExecution() async {
|
||||||
}
|
}
|
||||||
|
|
||||||
SentryWidgetsFlutterBinding.ensureInitialized();
|
SentryWidgetsFlutterBinding.ensureInitialized();
|
||||||
globalApplicationCacheDirectory = (await getApplicationCacheDirectory()).path;
|
AppEnvironment.cacheDir = (await getApplicationCacheDirectory()).path;
|
||||||
globalApplicationSupportDirectory =
|
AppEnvironment.supportDir = (await getApplicationSupportDirectory()).path;
|
||||||
(await getApplicationSupportDirectory()).path;
|
|
||||||
|
|
||||||
initLogger();
|
initLogger();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
||||||
|
|
||||||
Log.info('Starting new twonly Backup!');
|
Log.info('Starting new twonly Backup!');
|
||||||
|
|
||||||
final baseDir = globalApplicationSupportDirectory;
|
final backupDir = Directory(
|
||||||
|
join(AppEnvironment.supportDir, 'backup_twonly_safe/'),
|
||||||
final backupDir = Directory(join(baseDir, 'backup_twonly_safe/'));
|
);
|
||||||
await backupDir.create(recursive: true);
|
await backupDir.create(recursive: true);
|
||||||
|
|
||||||
final backupDatabaseFile = File(join(backupDir.path, 'twonly.backup.sqlite'));
|
final backupDatabaseFile = File(join(backupDir.path, 'twonly.backup.sqlite'));
|
||||||
|
|
@ -53,7 +53,9 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
||||||
);
|
);
|
||||||
|
|
||||||
// copy database
|
// copy database
|
||||||
final originalDatabase = File(join(baseDir, 'twonly.sqlite'));
|
final originalDatabase = File(
|
||||||
|
join(AppEnvironment.supportDir, 'twonly.sqlite'),
|
||||||
|
);
|
||||||
await originalDatabase.copy(backupDatabaseFile.path);
|
await originalDatabase.copy(backupDatabaseFile.path);
|
||||||
|
|
||||||
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ Future<void> handleBackupData(
|
||||||
);
|
);
|
||||||
|
|
||||||
final originalDatabase = File(
|
final originalDatabase = File(
|
||||||
join(globalApplicationSupportDirectory, 'twonly.sqlite'),
|
join(AppEnvironment.supportDir, 'twonly.sqlite'),
|
||||||
);
|
);
|
||||||
await originalDatabase.writeAsBytes(backupContent.twonlyDatabase);
|
await originalDatabase.writeAsBytes(backupContent.twonlyDatabase);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class MediaFileService {
|
||||||
try {
|
try {
|
||||||
final tempDirectory = MediaFileService.buildDirectoryPath(
|
final tempDirectory = MediaFileService.buildDirectoryPath(
|
||||||
'tmp',
|
'tmp',
|
||||||
globalApplicationSupportDirectory,
|
AppEnvironment.supportDir,
|
||||||
);
|
);
|
||||||
|
|
||||||
final files = tempDirectory.listSync();
|
final files = tempDirectory.listSync();
|
||||||
|
|
@ -307,7 +307,7 @@ class MediaFileService {
|
||||||
}
|
}
|
||||||
final mediaBaseDir = buildDirectoryPath(
|
final mediaBaseDir = buildDirectoryPath(
|
||||||
directory,
|
directory,
|
||||||
globalApplicationSupportDirectory,
|
AppEnvironment.supportDir,
|
||||||
);
|
);
|
||||||
return File(
|
return File(
|
||||||
join(mediaBaseDir.path, '${mediaFile.mediaId}$namePrefix.$extension'),
|
join(mediaBaseDir.path, '${mediaFile.mediaId}$namePrefix.$extension'),
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ Future<void> createPushAvatars({int? forceForUserId}) async {
|
||||||
|
|
||||||
File avatarPNGFile(int contactId) {
|
File avatarPNGFile(int contactId) {
|
||||||
final avatarsDirectory = Directory(
|
final avatarsDirectory = Directory(
|
||||||
'$globalApplicationCacheDirectory/avatars',
|
'${AppEnvironment.cacheDir}/avatars',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!avatarsDirectory.existsSync()) {
|
if (!avatarsDirectory.existsSync()) {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ Future<T> exclusiveAccess<T>({
|
||||||
required Future<T> Function() action,
|
required Future<T> Function() action,
|
||||||
required Mutex mutex,
|
required Mutex mutex,
|
||||||
}) async {
|
}) async {
|
||||||
final lockFile = File('$globalApplicationSupportDirectory/$lockName.lock');
|
final lockFile = File('${AppEnvironment.supportDir}/$lockName.lock');
|
||||||
return mutex.protect(() async {
|
return mutex.protect(() async {
|
||||||
var lockAcquired = false;
|
var lockAcquired = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
class KeyValueStore {
|
class KeyValueStore {
|
||||||
static Future<File> _getFilePath(String key) async {
|
static Future<File> _getFilePath(String key) async {
|
||||||
return File('$globalApplicationSupportDirectory/keyvalue/$key.json');
|
return File('${AppEnvironment.supportDir}/keyvalue/$key.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> delete(String key) async {
|
static Future<void> delete(String key) async {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class Log {
|
||||||
|
|
||||||
Future<String> loadLogFile() async {
|
Future<String> loadLogFile() async {
|
||||||
return _protectFileAccess(() async {
|
return _protectFileAccess(() async {
|
||||||
final logFile = File('$globalApplicationSupportDirectory/app.log');
|
final logFile = File('${AppEnvironment.supportDir}/app.log');
|
||||||
|
|
||||||
if (logFile.existsSync()) {
|
if (logFile.existsSync()) {
|
||||||
return logFile.readAsString();
|
return logFile.readAsString();
|
||||||
|
|
@ -84,7 +84,7 @@ Future<String> loadLogFile() async {
|
||||||
|
|
||||||
Future<String> readLast1000Lines() async {
|
Future<String> readLast1000Lines() async {
|
||||||
return _protectFileAccess(() async {
|
return _protectFileAccess(() async {
|
||||||
final file = File('$globalApplicationSupportDirectory/app.log');
|
final file = File('${AppEnvironment.supportDir}/app.log');
|
||||||
if (!file.existsSync()) return '';
|
if (!file.existsSync()) return '';
|
||||||
final all = await file.readAsLines();
|
final all = await file.readAsLines();
|
||||||
final start = all.length > 1000 ? all.length - 1000 : 0;
|
final start = all.length > 1000 ? all.length - 1000 : 0;
|
||||||
|
|
@ -103,7 +103,7 @@ Future<T> _protectFileAccess<T>(Future<T> Function() action) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _writeLogToFile(LogRecord record) async {
|
Future<void> _writeLogToFile(LogRecord record) async {
|
||||||
final logFile = File('$globalApplicationSupportDirectory/app.log');
|
final logFile = File('${AppEnvironment.supportDir}/app.log');
|
||||||
|
|
||||||
final logMessage =
|
final logMessage =
|
||||||
'${clock.now().toString().split(".")[0]} ${record.level.name} [twonly] ${record.loggerName} > ${record.message}\n';
|
'${clock.now().toString().split(".")[0]} ${record.level.name} [twonly] ${record.loggerName} > ${record.message}\n';
|
||||||
|
|
@ -127,7 +127,7 @@ Future<void> _writeLogToFile(LogRecord record) async {
|
||||||
|
|
||||||
Future<void> cleanLogFile() async {
|
Future<void> cleanLogFile() async {
|
||||||
return _protectFileAccess(() async {
|
return _protectFileAccess(() async {
|
||||||
final logFile = File('$globalApplicationSupportDirectory/app.log');
|
final logFile = File('${AppEnvironment.supportDir}/app.log');
|
||||||
|
|
||||||
if (!logFile.existsSync()) {
|
if (!logFile.existsSync()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -162,7 +162,7 @@ Future<void> cleanLogFile() async {
|
||||||
|
|
||||||
Future<bool> deleteLogFile() async {
|
Future<bool> deleteLogFile() async {
|
||||||
return _protectFileAccess(() async {
|
return _protectFileAccess(() async {
|
||||||
final logFile = File('$globalApplicationSupportDirectory/app.log');
|
final logFile = File('${AppEnvironment.supportDir}/app.log');
|
||||||
|
|
||||||
if (logFile.existsSync()) {
|
if (logFile.existsSync()) {
|
||||||
await logFile.delete();
|
await logFile.delete();
|
||||||
|
|
|
||||||
|
|
@ -592,7 +592,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (mc.selectedCameraDetails.cameraId >= gCameras.length ||
|
if (mc.selectedCameraDetails.cameraId >= AppEnvironment.cameras.length ||
|
||||||
mc.cameraController == null) {
|
mc.cameraController == null) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,16 +105,17 @@ class MainCameraController {
|
||||||
initCameraStarted = true;
|
initCameraStarted = true;
|
||||||
|
|
||||||
var cameraId = sCameraId;
|
var cameraId = sCameraId;
|
||||||
if (cameraId >= gCameras.length) {
|
if (cameraId >= AppEnvironment.cameras.length) {
|
||||||
Log.warn(
|
Log.warn(
|
||||||
'Trying to select a non existing camera $cameraId >= ${gCameras.length}',
|
'Trying to select a non existing camera $cameraId >= ${AppEnvironment.cameras.length}',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
for (; cameraId < gCameras.length; cameraId++) {
|
for (; cameraId < AppEnvironment.cameras.length; cameraId++) {
|
||||||
if (gCameras[cameraId].lensDirection == CameraLensDirection.back) {
|
if (AppEnvironment.cameras[cameraId].lensDirection ==
|
||||||
|
CameraLensDirection.back) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +125,7 @@ class MainCameraController {
|
||||||
|
|
||||||
if (cameraController == null) {
|
if (cameraController == null) {
|
||||||
cameraController = CameraController(
|
cameraController = CameraController(
|
||||||
gCameras[cameraId],
|
AppEnvironment.cameras[cameraId],
|
||||||
ResolutionPreset.high,
|
ResolutionPreset.high,
|
||||||
enableAudio: await Permission.microphone.isGranted,
|
enableAudio: await Permission.microphone.isGranted,
|
||||||
imageFormatGroup: Platform.isAndroid
|
imageFormatGroup: Platform.isAndroid
|
||||||
|
|
@ -150,7 +151,7 @@ class MainCameraController {
|
||||||
selectedCameraDetails.scaleFactor = 1;
|
selectedCameraDetails.scaleFactor = 1;
|
||||||
|
|
||||||
await cameraController?.setZoomLevel(1);
|
await cameraController?.setZoomLevel(1);
|
||||||
await cameraController?.setDescription(gCameras[cameraId]);
|
await cameraController?.setDescription(AppEnvironment.cameras[cameraId]);
|
||||||
try {
|
try {
|
||||||
if (!isVideoRecording) {
|
if (!isVideoRecording) {
|
||||||
await cameraController?.startImageStream(_processCameraImage);
|
await cameraController?.startImageStream(_processCameraImage);
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,11 @@ class _CameraZoomButtonsState extends State<CameraZoomButtons> {
|
||||||
Future<void> initAsync() async {
|
Future<void> initAsync() async {
|
||||||
showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1;
|
showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1;
|
||||||
|
|
||||||
var index = gCameras.indexWhere(
|
var index = AppEnvironment.cameras.indexWhere(
|
||||||
(t) => t.lensType == CameraLensType.ultraWide,
|
(t) => t.lensType == CameraLensType.ultraWide,
|
||||||
);
|
);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
index = gCameras.indexWhere(
|
index = AppEnvironment.cameras.indexWhere(
|
||||||
(t) => t.lensType == CameraLensType.wide,
|
(t) => t.lensType == CameraLensType.wide,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class _ExportMediaViewState extends State<ExportMediaView> {
|
||||||
Directory _mediaFolder() {
|
Directory _mediaFolder() {
|
||||||
final dir = MediaFileService.buildDirectoryPath(
|
final dir = MediaFileService.buildDirectoryPath(
|
||||||
'stored',
|
'stored',
|
||||||
globalApplicationSupportDirectory,
|
AppEnvironment.supportDir,
|
||||||
);
|
);
|
||||||
if (!dir.existsSync()) dir.createSync(recursive: true);
|
if (!dir.existsSync()) dir.createSync(recursive: true);
|
||||||
return dir;
|
return dir;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue