init
This commit is contained in:
30
filcnaplo/lib/helpers/attachment_helper.dart
Normal file
30
filcnaplo/lib/helpers/attachment_helper.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:filcnaplo/helpers/storage_helper.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/attachment.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
extension AttachmentHelper on Attachment {
|
||||
Future<String> download(BuildContext context, {bool overwrite = false}) async {
|
||||
String downloads = await StorageHelper.downloadsPath();
|
||||
|
||||
if (!overwrite && await File("$downloads/$name").exists()) return "$downloads/$name";
|
||||
|
||||
Uint8List data = await Provider.of<KretaClient>(context, listen: false).getAPI(downloadUrl, rawResponse: true);
|
||||
if (!await StorageHelper.write("$downloads/$name", data)) return "";
|
||||
|
||||
return "$downloads/$name";
|
||||
}
|
||||
|
||||
Future<bool> open(BuildContext context) async {
|
||||
String downloads = await StorageHelper.downloadsPath();
|
||||
|
||||
if (!await File("$downloads/$name").exists()) await download(context);
|
||||
var result = await OpenFile.open("$downloads/$name");
|
||||
return result.type == ResultType.done;
|
||||
}
|
||||
}
|
||||
25
filcnaplo/lib/helpers/average_helper.dart
Normal file
25
filcnaplo/lib/helpers/average_helper.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||
|
||||
class AverageHelper {
|
||||
static double averageEvals(List<Grade> grades, {bool finalAvg = false}) {
|
||||
double average = 0.0;
|
||||
|
||||
List<String> ignoreInFinal = ["5,SzorgalomErtek", "4,MagatartasErtek"];
|
||||
|
||||
if (finalAvg)
|
||||
grades.removeWhere((e) =>
|
||||
(e.value.value == 0) ||
|
||||
(ignoreInFinal.contains(e.gradeType?.id)));
|
||||
|
||||
grades.forEach((e) {
|
||||
average += e.value.value * ((finalAvg ? 100 : e.value.weight) / 100);
|
||||
});
|
||||
|
||||
average = average /
|
||||
grades
|
||||
.map((e) => (finalAvg ? 100 : e.value.weight) / 100)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
|
||||
return average.isNaN ? 0.0 : average;
|
||||
}
|
||||
}
|
||||
14
filcnaplo/lib/helpers/share_helper.dart
Normal file
14
filcnaplo/lib/helpers/share_helper.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:filcnaplo/helpers/attachment_helper.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/attachment.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class ShareHelper {
|
||||
static Future<void> shareText(String text, {String? subject}) => Share.share(text, subject: subject);
|
||||
static Future<void> shareFile(String path, {String? text, String? subject}) => Share.shareFiles([path], text: text, subject: subject);
|
||||
|
||||
static Future<void> shareAttachment(Attachment attachment, {required BuildContext context}) async {
|
||||
String path = await attachment.download(context);
|
||||
await shareFile(path);
|
||||
}
|
||||
}
|
||||
36
filcnaplo/lib/helpers/storage_helper.dart
Normal file
36
filcnaplo/lib/helpers/storage_helper.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class StorageHelper {
|
||||
static Future<bool> write(String path, Uint8List data) async {
|
||||
try {
|
||||
if (await Permission.storage.request().isGranted) {
|
||||
await File(path).writeAsBytes(data);
|
||||
return true;
|
||||
} else {
|
||||
if (await Permission.storage.isPermanentlyDenied) {
|
||||
openAppSettings();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
print("ERROR: StorageHelper.write: $error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> downloadsPath() async {
|
||||
String downloads;
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
downloads = "/storage/self/primary/Download";
|
||||
} else {
|
||||
downloads = (await getTemporaryDirectory()).path;
|
||||
}
|
||||
|
||||
return downloads;
|
||||
}
|
||||
}
|
||||
46
filcnaplo/lib/helpers/subject_icon.dart
Normal file
46
filcnaplo/lib/helpers/subject_icon.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:filcnaplo/icons/filc_icons.dart';
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SubjectIcon {
|
||||
static IconData? lookup({Subject? subject, String? subjectName}) {
|
||||
assert(!(subject == null && subjectName == null));
|
||||
|
||||
String name = subject?.name.toLowerCase().specialChars() ?? subjectName ?? "";
|
||||
String category = subject?.category.description.toLowerCase().specialChars() ?? "";
|
||||
|
||||
// TODO: check for categories
|
||||
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") return Icons.calculate_outlined;
|
||||
if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) return Icons.spellcheck_outlined;
|
||||
if (RegExp("irodalom").hasMatch(name)) return Icons.menu_book_outlined;
|
||||
if (RegExp("rajz|muvtori|muveszet|kultura").hasMatch(name)) return Icons.palette_outlined;
|
||||
if (RegExp("tor(i|tenelem)").hasMatch(name)) return Icons.hourglass_empty_outlined;
|
||||
if (RegExp("foldrajz").hasMatch(name)) return Icons.public_outlined;
|
||||
if (RegExp("fizika").hasMatch(name)) return Icons.emoji_objects_outlined;
|
||||
if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) return Icons.music_note_outlined;
|
||||
if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) return Icons.sports_soccer_outlined;
|
||||
if (RegExp("kemia").hasMatch(name)) return Icons.science_outlined;
|
||||
if (RegExp("biologia").hasMatch(name)) return Icons.pets_outlined;
|
||||
if (RegExp("kornyezet|termeszet(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) return Icons.eco_outlined;
|
||||
if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) return Icons.favorite_border_outlined;
|
||||
if (RegExp("penzugy").hasMatch(name)) return Icons.savings_outlined;
|
||||
if (RegExp("informatika|szoftver|iroda").hasMatch(name)) return Icons.computer_outlined;
|
||||
if (RegExp("prog").hasMatch(name)) return Icons.code_outlined;
|
||||
if (RegExp("halozat").hasMatch(name)) return Icons.wifi_tethering_outlined;
|
||||
if (RegExp("szinhaz").hasMatch(name)) return Icons.theater_comedy_outlined;
|
||||
if (RegExp("film|media").hasMatch(name)) return Icons.theaters_outlined;
|
||||
if (RegExp("elektro(tech)?nika").hasMatch(name)) return Icons.electrical_services_outlined;
|
||||
if (RegExp("gepesz|mernok|ipar").hasMatch(name)) return Icons.precision_manufacturing_outlined;
|
||||
if (RegExp("technika").hasMatch(name)) return Icons.build_outlined;
|
||||
if (RegExp("tanc").hasMatch(name)) return Icons.speaker_outlined;
|
||||
if (RegExp("filozofia").hasMatch(name)) return Icons.psychology_outlined;
|
||||
if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name)) return Icons.groups_outlined;
|
||||
if (RegExp("gazdasag").hasMatch(name)) return Icons.account_balance_outlined;
|
||||
if (RegExp("szorgalom").hasMatch(name)) return Icons.verified_outlined;
|
||||
if (RegExp("magatartas").hasMatch(name)) return Icons.emoji_people_outlined;
|
||||
if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) return Icons.translate_outlined;
|
||||
if (RegExp("linux").hasMatch(name)) return FilcIcons.linux;
|
||||
return Icons.widgets_outlined;
|
||||
}
|
||||
}
|
||||
65
filcnaplo/lib/helpers/update_helper.dart
Normal file
65
filcnaplo/lib/helpers/update_helper.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:filcnaplo/api/client.dart';
|
||||
import 'package:filcnaplo/helpers/storage_helper.dart';
|
||||
import 'package:filcnaplo/models/release.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
|
||||
enum UpdateState { prepare, downloading, installing }
|
||||
typedef UpdateCallback = Function(double progress, UpdateState state);
|
||||
|
||||
extension UpdateHelper on Release {
|
||||
Future<void> install({UpdateCallback? updateCallback}) async {
|
||||
String downloads = await StorageHelper.downloadsPath();
|
||||
File apk = File("$downloads/filcnaplo-${version}.apk");
|
||||
|
||||
if (!await apk.exists()) {
|
||||
updateCallback!(-1, UpdateState.downloading);
|
||||
|
||||
var bytes = await download(updateCallback: updateCallback);
|
||||
if (!await StorageHelper.write(apk.path, bytes)) throw "failed to write apk: permission denied";
|
||||
}
|
||||
|
||||
updateCallback!(-1, UpdateState.installing);
|
||||
|
||||
var result = await OpenFile.open(apk.path);
|
||||
|
||||
if (result.type != ResultType.done) {
|
||||
print("ERROR: installUpdate.openFile: " + result.message);
|
||||
throw result.message;
|
||||
}
|
||||
|
||||
updateCallback(-1, UpdateState.prepare);
|
||||
}
|
||||
|
||||
Future<Uint8List> download({UpdateCallback? updateCallback}) async {
|
||||
var response = await FilcAPI.downloadRelease(this);
|
||||
|
||||
List<List<int>> chunks = [];
|
||||
int downloaded = 0;
|
||||
|
||||
var completer = Completer<Uint8List>();
|
||||
|
||||
response?.stream.listen((List<int> chunk) {
|
||||
updateCallback!(downloaded / (response.contentLength ?? 0), UpdateState.downloading);
|
||||
|
||||
chunks.add(chunk);
|
||||
downloaded += chunk.length;
|
||||
}, onDone: () {
|
||||
// Save the file
|
||||
final Uint8List bytes = Uint8List(response.contentLength ?? 0);
|
||||
int offset = 0;
|
||||
for (List<int> chunk in chunks) {
|
||||
bytes.setRange(offset, offset + chunk.length, chunk);
|
||||
offset += chunk.length;
|
||||
}
|
||||
|
||||
completer.complete(bytes);
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user