Compare commits
2 Commits
b35656d4ce
...
3119e5fdbf
| Author | SHA1 | Date | |
|---|---|---|---|
| 3119e5fdbf | |||
| 5d461d5b0f |
@ -3,6 +3,10 @@
|
||||
android:label="rtime"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Ucrop.CropTheme"/>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
||||
7
android/app/src/main/res/values-v35/styles.xml
Normal file
7
android/app/src/main/res/values-v35/styles.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Ucrop.CropTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@ -15,4 +15,5 @@
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
<style name="Ucrop.CropTheme" parent="Theme.AppCompat.Light.NoActionBar"/> <!--add this line-->
|
||||
</resources>
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
// This file holds a class to represent the configuration/settings of the app
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
part 'generated/config.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
@ -10,7 +16,24 @@ class RTimeConfig {
|
||||
RTimeConfig({required this.language});
|
||||
|
||||
factory RTimeConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$PersonFromJson(json);
|
||||
_$RTimeConfigFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$PersonToJson(this);
|
||||
Map<String, dynamic> toJson() => _$RTimeConfigToJson(this);
|
||||
|
||||
static Future<RTimeConfig?> readFromConfig() async {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final configName = "rtime_config.json";
|
||||
final configPath = path.join(directory.path, configName);
|
||||
|
||||
final string = jsonDecode(await File(configPath).readAsString());
|
||||
return RTimeConfig.fromJson(string);
|
||||
}
|
||||
|
||||
void writeConfig() async {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final configName = "rtime_config.json";
|
||||
final configPath = path.join(directory.path, configName);
|
||||
|
||||
await File(configPath).writeAsString(jsonEncode(toJson()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,6 +160,34 @@ class DbHelper {
|
||||
return maps.map((e) => Flight.fromMap(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Flight>> getFlightsBetween(
|
||||
int startTimestamp,
|
||||
int endTimestamp,
|
||||
) async {
|
||||
final db = await database;
|
||||
final maps = await db.rawQuery('''
|
||||
SELECT * FROM flights AS F
|
||||
WHERE F.start_timestamp >= $startTimestamp AND F.end_timestamp <= $endTimestamp
|
||||
''');
|
||||
return maps.map((e) => Flight.fromMap(e)).toList();
|
||||
}
|
||||
|
||||
Future<int?> getTotalFlightTime() async {
|
||||
final db = await database;
|
||||
final ft = await db.rawQuery('''
|
||||
SELECT SUM(F.end_timestamp - F.startTimestamp) FROM flights AS F
|
||||
''');
|
||||
final mapping = ft.firstOrNull;
|
||||
if (mapping == null) {
|
||||
return null;
|
||||
}
|
||||
final val = mapping["SUM(F.end_timestamp - F.startTimestamp)"];
|
||||
if (val is! int) {
|
||||
return null;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
Future closeDb() async {
|
||||
final db = await database;
|
||||
log.info("Closing database.");
|
||||
|
||||
@ -7,73 +7,97 @@ import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
import 'package:image_cropper/image_cropper.dart' as img_cropper;
|
||||
import 'package:uuid/v5.dart';
|
||||
|
||||
class ImagesManager
|
||||
{
|
||||
static final ImagesManager instance = ImagesManager._internal();
|
||||
ImagesManager._internal();
|
||||
class ImagesManager {
|
||||
static final ImagesManager instance = ImagesManager._internal();
|
||||
ImagesManager._internal();
|
||||
|
||||
static final Logger log = Logger("ImagesManager");
|
||||
static final Logger log = Logger("ImagesManager");
|
||||
|
||||
static Uri? _imagesDirectory;
|
||||
static Uri? _imagesDirectory;
|
||||
|
||||
Future<Uri> get imageDirectory async
|
||||
{
|
||||
if(_imagesDirectory != null) return _imagesDirectory!;
|
||||
await _initImagesDirectory();
|
||||
return _imagesDirectory!;
|
||||
Future<Uri> get imageDirectory async {
|
||||
if (_imagesDirectory != null) return _imagesDirectory!;
|
||||
await _initImagesDirectory();
|
||||
return _imagesDirectory!;
|
||||
}
|
||||
|
||||
Future _initImagesDirectory() async {
|
||||
final directoryLoc = await getApplicationDocumentsDirectory();
|
||||
final directoryName = "images";
|
||||
final directoryPath = path.join(directoryLoc.path, directoryName);
|
||||
final directoryUri = Uri.directory(directoryPath);
|
||||
final directory = Directory.fromUri(directoryUri);
|
||||
|
||||
if (!await directory.exists()) {
|
||||
log.info("Image directory does not yet extists. Creating it.");
|
||||
}
|
||||
|
||||
Future _initImagesDirectory() async
|
||||
{
|
||||
final directoryLoc = await getApplicationDocumentsDirectory();
|
||||
final directoryName = "images";
|
||||
final directoryPath = path.join(directoryLoc.path, directoryName);
|
||||
final directoryUri = Uri.directory(directoryPath);
|
||||
final directory = Directory.fromUri(directoryUri);
|
||||
|
||||
if(!await directory.exists())
|
||||
{
|
||||
log.info("Image directory does not yet extists. Creating it.");
|
||||
}
|
||||
directory.create(recursive: false);
|
||||
|
||||
directory.create(recursive: false);
|
||||
|
||||
log.info("Image directory set up at '$directory'");
|
||||
|
||||
_imagesDirectory = directoryUri;
|
||||
log.info("Image directory set up at '$directory'");
|
||||
|
||||
_imagesDirectory = directoryUri;
|
||||
}
|
||||
|
||||
Future<String?> createImage(ImageSource source) async {
|
||||
// Get image from camera or not
|
||||
final XFile? ximage = await ImagePicker().pickImage(source: source);
|
||||
if (ximage == null) return null;
|
||||
|
||||
// Crop image
|
||||
final uuid = Uuid().v6();
|
||||
final imageDir = await imageDirectory;
|
||||
final finalPath = path.join(
|
||||
imageDir.path,
|
||||
uuid + path.extension(ximage.name),
|
||||
);
|
||||
final tempPath = path.join(
|
||||
imageDir.path,
|
||||
"${uuid}_tocrop${path.extension(ximage.name)}",
|
||||
);
|
||||
await ximage.saveTo(tempPath);
|
||||
|
||||
img_cropper.CroppedFile? cropped = await img_cropper.ImageCropper()
|
||||
.cropImage(
|
||||
sourcePath: tempPath,
|
||||
aspectRatio: img_cropper.CropAspectRatio(ratioX: 1.0, ratioY: 1.0),
|
||||
uiSettings: [
|
||||
img_cropper.AndroidUiSettings(
|
||||
toolbarTitle: "Crop image",
|
||||
toolbarColor: Colors.black,
|
||||
toolbarWidgetColor: Colors.white,
|
||||
),
|
||||
img_cropper.IOSUiSettings(title: "Crop image"),
|
||||
],
|
||||
);
|
||||
|
||||
if (cropped == null) return null;
|
||||
|
||||
await File(finalPath).writeAsBytes(await cropped.readAsBytes());
|
||||
await File(tempPath).delete();
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
Future<Image?> loadImage(String imageUuid) async {
|
||||
final imageDir = await imageDirectory;
|
||||
if (!Uuid.isValidUUID(fromString: imageUuid)) {
|
||||
log.warning(
|
||||
"Tried to load an image with an invalid UUID : '$imageUuid'.",
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String?> createImage(ImageSource source) async
|
||||
{
|
||||
// Get image from camera or not
|
||||
final XFile? ximage = await ImagePicker().pickImage(source: source);
|
||||
if(ximage == null) return null;
|
||||
|
||||
final uuid = Uuid().v6();
|
||||
final imageDir = await imageDirectory;
|
||||
ximage.saveTo(path.join(imageDir.path, uuid + path.extension(ximage.name)));
|
||||
return uuid;
|
||||
final imagePath = path.join(imageDir.path, "$imageUuid.jpg");
|
||||
final file = File(imagePath);
|
||||
if (!await file.exists()) {
|
||||
log.warning("Tried to load an image that does not extist: '$imagePath'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Image?> loadImage(String imageUuid) async
|
||||
{
|
||||
final imageDir = await imageDirectory;
|
||||
if(!Uuid.isValidUUID(fromString: imageUuid))
|
||||
{
|
||||
log.warning("Tried to load an image with an invalid UUID : '$imageUuid'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
final imagePath = path.join(imageDir.path, "$imageUuid.jpg");
|
||||
final file = File(imagePath);
|
||||
if(!await file.exists())
|
||||
{
|
||||
log.warning("Tried to load an image that does not extist: '$imagePath'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return Image.file(file);
|
||||
}
|
||||
return Image.file(file);
|
||||
}
|
||||
}
|
||||
|
||||
24
pubspec.lock
24
pubspec.lock
@ -344,6 +344,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.4"
|
||||
image_cropper:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_cropper
|
||||
sha256: "4e9c96c029eb5a23798da1b6af39787f964da6ffc78fd8447c140542a9f7c6fc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.0"
|
||||
image_cropper_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_cropper_for_web
|
||||
sha256: fd81ebe36f636576094377aab32673c4e5d1609b32dec16fad98d2b71f1250a9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
image_cropper_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_cropper_platform_interface
|
||||
sha256: "6ca6b81769abff9a4dcc3bbd3d75f5dfa9de6b870ae9613c8cd237333a4283af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.1.0"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@ -44,6 +44,7 @@ dependencies:
|
||||
image_picker: ^1.1.2
|
||||
uuid: ^4.5.1
|
||||
json_serializable: ^6.9.5
|
||||
image_cropper: ^9.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user