diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7382aba..a43f0c9 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -471,7 +471,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 8; + CURRENT_PROJECT_VERSION = 10; DEVELOPMENT_TEAM = S4AJ4WBQ76; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -480,7 +480,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.3.2; + MARKETING_VERSION = 0.4.2; PRODUCT_BUNDLE_IDENTIFIER = com.31b4.univerx; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -659,7 +659,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 8; + CURRENT_PROJECT_VERSION = 10; DEVELOPMENT_TEAM = S4AJ4WBQ76; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -668,7 +668,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.3.2; + MARKETING_VERSION = 0.4.2; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.31b4.univerx; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -688,7 +688,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 8; + CURRENT_PROJECT_VERSION = 10; DEVELOPMENT_TEAM = S4AJ4WBQ76; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -697,7 +697,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.3.2; + MARKETING_VERSION = 0.4.2; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = com.31b4.univerx; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/lib/database/database_helper.dart b/lib/database/database_helper.dart index ea55f83..5746c41 100644 --- a/lib/database/database_helper.dart +++ b/lib/database/database_helper.dart @@ -18,7 +18,7 @@ class DatabaseHelper { Future get database async { if (_database != null) return _database!; - _database = await _initDB('test_11.db'); + _database = await _initDB('test_12.db'); return _database!; } @@ -60,7 +60,7 @@ class DatabaseHelper { await db.execute(''' CREATE TABLE Exam ( - exam_id INTEGER PRIMARY KEY AUTOINCREMENT, + exam_id INTEGER, class_id INTEGER, title TEXT, description TEXT, diff --git a/lib/features/common/widgets/profile_menu.dart b/lib/features/common/widgets/profile_menu.dart index 4452b0f..ab37e4c 100644 --- a/lib/features/common/widgets/profile_menu.dart +++ b/lib/features/common/widgets/profile_menu.dart @@ -198,7 +198,7 @@ class DrawerMenu extends StatelessWidget { ), SizedBox(height: 10.0), const Text( - 'v0.4.2 beta', + 'v0.4.3 beta', style: TextStyle( color: Colors.white, fontSize: 12.0, diff --git a/lib/features/home/homePage.dart b/lib/features/home/homePage.dart index c2d3298..800c8b9 100644 --- a/lib/features/home/homePage.dart +++ b/lib/features/home/homePage.dart @@ -131,11 +131,8 @@ class _HomeState extends State with RouteAware { Map> _groupEventsByDate(List exams, List assignments) { final Map> groupedEvents = {}; - final now = DateTime(2000, 1, 1, 1, 1); + final now = DateTime.now(); //print exams - for (final exam in exams) { - print(exam.title); - } for (final exam in exams) { if (exam.startTime.isAfter(now) || exam.startTime.isAtSameMomentAs(now)) { @@ -143,7 +140,7 @@ class _HomeState extends State with RouteAware { if (groupedEvents.containsKey(date)) { groupedEvents[date]!.add(UpcomingContainer( homeContext: context, - title: Exam.getFormattedTitle(exam.title), + title: Exam.formatText(30,exam.title), date: date, isExam: true, onDelete: () => _deleteExam(exam), @@ -153,7 +150,7 @@ class _HomeState extends State with RouteAware { groupedEvents[date] = [ UpcomingContainer( homeContext: context, - title: Exam.getFormattedTitle(exam.title), + title: Exam.formatText(40,exam.title), date: date, isExam: true, onDelete: () => _deleteExam(exam), @@ -245,7 +242,7 @@ class _HomeState extends State with RouteAware { // remove events from sorted entries that are in the past sortedEntries.removeWhere((entry) { final date = DateFormat('yyyy MMM d').parse(entry.key); - return date.isBefore(DateTime(2022)); + return date.isBefore(DateTime.now()); }); return sortedEntries.map((entry) { diff --git a/lib/features/neptun_login/login.dart b/lib/features/neptun_login/login.dart index ecfd800..42040dc 100644 --- a/lib/features/neptun_login/login.dart +++ b/lib/features/neptun_login/login.dart @@ -169,7 +169,7 @@ class _LoginPageState extends State { right: 0, child: Center( child: Text( - 'v0.4.2 beta', + 'v0.4.3 beta', style: TextStyle( color: Colors.grey, fontSize: 12.0, diff --git a/lib/models/class.dart b/lib/models/class.dart index cdeecdb..35dcb70 100644 --- a/lib/models/class.dart +++ b/lib/models/class.dart @@ -1,4 +1,5 @@ import 'package:intl/intl.dart'; +import 'package:univerx/models/exam.dart'; class Class { final int id; @@ -41,7 +42,7 @@ class Class { } // ------------------ Helper functions ------------------ - factory Class.fromICS(String icsData) { + static Object fromICS(String icsData) { final lines = icsData.split('\n'); DateTime? startTime; DateTime? endTime; @@ -59,6 +60,19 @@ class Class { location = line.split(':')[1]; } } + //if title starts with vizsga return with Exam() + if (title!.contains('Vizsga')) { + return Exam( + id: -1, + classId: -1, + title: title!, + description: "", + startTime: startTime!, + endTime: endTime!, + location: location!, + isUserCreated: false, + ); + } return Class( id: -1, diff --git a/lib/models/exam.dart b/lib/models/exam.dart index 5d40a18..604825c 100644 --- a/lib/models/exam.dart +++ b/lib/models/exam.dart @@ -45,20 +45,7 @@ class Exam { return formatter.format(startTime); } - static String getFormattedTitle(String title) { - if (title.startsWith('[Óra]')) { - title = title.substring(title.indexOf(']') + 2, title.length); - var sv = title.split(" "); - title = sv[0] + " " + sv[1]; - } - else if (title.startsWith('[Vizsga]')) { - var sv = title.split(" "); - title = sv[0] + " " + sv[1] + " " +sv[2]; - } - - - return title; - } + Class convertExamToClass() { return Class( id: classId, @@ -71,4 +58,27 @@ class Exam { isUserCreated: isUserCreated, ); } + static String formatText(int limit, String text) { + var words = text.split(' '); + var result = ''; + + if (words[0].length > limit){ + return words[0].substring(0,limit-3) + "..."; + } + + + for (var word in words) { + if (result.length + word.length <= limit) { + result += word + ' '; + } else { + //result += '...'; + break; + } + } + //if last character is a comma, remove it + if (result[result.length - 2] == ',') { + result = result.substring(0, result.length - 2); + } + return result; + } } diff --git a/lib/services/neptun_ICS_fetching.dart b/lib/services/neptun_ICS_fetching.dart index 687beb7..e2a26ec 100644 --- a/lib/services/neptun_ICS_fetching.dart +++ b/lib/services/neptun_ICS_fetching.dart @@ -1,7 +1,17 @@ import 'dart:convert'; +import 'dart:math'; import 'package:http/http.dart' as http; import 'package:univerx/database/database_helper.dart'; import 'package:univerx/models/class.dart'; +import 'package:univerx/models/exam.dart'; +import 'package:univerx/services/neptun_API_fetching.dart'; + +class ParsedData { + final List classes; + final List exams; + + ParsedData({required this.classes, required this.exams}); +} class EventService { final String url; @@ -11,50 +21,70 @@ class EventService { Future fetchAndUpdateIcs() async { - // Fetch events from .ics file - List newEvents = await fetchEvents(); - if (newEvents.isEmpty) { - return; - } + // Fetch events from .ics file + ParsedData newEvents = await fetchEvents(); + if (newEvents.classes.isEmpty && newEvents.exams.isEmpty) { + return; + } + + //classes and exams + List newClasses = newEvents.classes; + List newExams = newEvents.exams; + print(newExams); + print(newClasses); - // Fetch existing events from database - DatabaseHelper dbHelper = DatabaseHelper.instance; + // Fetch existing events from database + DatabaseHelper dbHelper = DatabaseHelper.instance; - // Clear the existing events in the database - await dbHelper.deleteNeptunClasses(); + // Clear the existing events in the database + await dbHelper.deleteNeptunClasses(); + await dbHelper.deleteNeptunExams(); - // Save new events to the database - for (Class newEvent in newEvents) { - await dbHelper.insertClass(newEvent); + // Save new events to the database + for (Class newEvent in newClasses) { + await dbHelper.insertClass(newEvent); + } + for (Exam newExam in newExams) { + await dbHelper.insertExam(newExam); + } } -} - Future> fetchEvents() async { + Future fetchEvents() async { try { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final icsData = response.body; - final events = parseICS(icsData); - events.sort((a, b) => a.startTime.compareTo(b.startTime)); // Sort events by start time - return events; + ParsedData parsed = parseICS(icsData); + parsed.exams.sort((a, b) => a.startTime.compareTo(b.startTime)); // Sort events by start time + parsed.classes.sort((a, b) => a.startTime.compareTo(b.startTime)); // Sort events by start time + + + return parsed; } else { throw Exception('Failed to load events'); } } catch (e) { print('Error fetching events: $e'); - return []; + return null!; } } - List parseICS(String icsData) { + ParsedData parseICS(String icsData) { try { - final events = []; + ParsedData parsedData = ParsedData(classes: [], exams: []); final eventStrings = icsData.split('BEGIN:VEVENT'); for (var eventString in eventStrings.skip(1)) { - events.add(Class.fromICS(eventString)); + // if object type exam add to exam else add to event + final event = Class.fromICS(eventString); + if (event.runtimeType == Exam) { + parsedData.exams.add(event as Exam); + } + else if (event.runtimeType == Class) { + parsedData.classes.add(event as Class); + } } - return events; + return parsedData; } catch (e) { print('Error parsing ICS data: $e'); rethrow; @@ -100,7 +130,10 @@ class EventService { break; } } - + //if last character is a comma, remove it + if (result[result.length - 2] == ',') { + result = result.substring(0, result.length - 2); + } return result; }