Merge branch 'refilc:dev' into dev

This commit is contained in:
Geryy 2024-05-06 06:03:34 +02:00 committed by GitHub
commit 7cec2ff525
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 2784 additions and 695 deletions

30
refilc/.gitignore vendored
View File

@ -46,4 +46,32 @@ app.*.map.json
.symlinks/ .symlinks/
Pods Pods
Podfile.lock Podfile.lock
UserInterfaceState.xcuserstate UserInterfaceState.xcuserstate
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/.last_build_id
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/ephemeral
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*

0
refilc/build-ipa.sh Normal file → Executable file
View File

View File

@ -517,8 +517,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -528,7 +528,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -549,8 +549,8 @@
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements; CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -566,7 +566,7 @@
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -591,8 +591,8 @@
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements; CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -607,7 +607,7 @@
); );
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -631,8 +631,8 @@
CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements; CODE_SIGN_ENTITLEMENTS = livecard/livecard.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = livecard/Info.plist; INFOPLIST_FILE = livecard/Info.plist;
@ -647,7 +647,7 @@
); );
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo.livecardpro; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo.livecardpro;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -775,8 +775,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -786,7 +786,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -803,8 +803,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 250; CURRENT_PROJECT_VERSION = 255;
DEVELOPMENT_TEAM = UT7MSP4GWZ; DEVELOPMENT_TEAM = 4DKAF249F3;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = reFilc; INFOPLIST_KEY_CFBundleDisplayName = reFilc;
@ -814,7 +814,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 5.0.0; MARKETING_VERSION = 5.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.refilcrel.naplo; PRODUCT_BUNDLE_IDENTIFIER = com.refilc2.naplo;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -12,7 +12,7 @@
<key>livecard.xcscheme_^#shared#^_</key> <key>livecard.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>78</integer> <integer>83</integer>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -5,8 +5,6 @@
<key>aps-environment</key> <key>aps-environment</key>
<string>development</string> <string>development</string>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array> <array/>
<string>group.refilc2.livecard</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -5,8 +5,6 @@
<key>aps-environment</key> <key>aps-environment</key>
<string>development</string> <string>development</string>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array> <array/>
<string>group.refilc2.livecard</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -7,23 +7,33 @@ import 'package:provider/provider.dart';
class SelfNoteProvider with ChangeNotifier { class SelfNoteProvider with ChangeNotifier {
late List<SelfNote> _notes; late List<SelfNote> _notes;
late List<TodoItem> _todoItems;
late BuildContext _context; late BuildContext _context;
List<SelfNote> get notes => _notes; List<SelfNote> get notes => _notes;
List<TodoItem> get todos => _todoItems;
SelfNoteProvider({ SelfNoteProvider({
List<SelfNote> initialNotes = const [], List<SelfNote> initialNotes = const [],
List<TodoItem> initialTodoItems = const [],
required BuildContext context, required BuildContext context,
}) { }) {
_notes = List.castFrom(initialNotes); _notes = List.castFrom(initialNotes);
_todoItems = List.castFrom(initialTodoItems);
_context = context; _context = context;
if (_notes.isEmpty) restore(); if (_notes.isEmpty) restore();
if (_todoItems.isEmpty) restoreTodo();
} }
// restore self notes from db // restore self notes from db
Future<void> restore() async { Future<void> restore() async {
String? userId = Provider.of<UserProvider>(_context, listen: false).id; String? userId = Provider.of<UserProvider>(_context, listen: false).id;
// await Provider.of<DatabaseProvider>(_context, listen: false)
// .userStore
// .storeSelfNotes([], userId: userId!);
// load self notes from db // load self notes from db
if (userId != null) { if (userId != null) {
var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false) var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false)
@ -34,6 +44,24 @@ class SelfNoteProvider with ChangeNotifier {
} }
} }
// restore todo items from db
Future<void> restoreTodo() async {
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
// await Provider.of<DatabaseProvider>(_context, listen: false)
// .userStore
// .storeSelfNotes([], userId: userId!);
// load self notes from db
if (userId != null) {
var dbTodo = await Provider.of<DatabaseProvider>(_context, listen: false)
.userQuery
.getTodoItems(userId: userId);
_todoItems = dbTodo;
notifyListeners();
}
}
// fetches fresh data from api (not needed, cuz no api for that) // fetches fresh data from api (not needed, cuz no api for that)
// Future<void> fetch() async { // Future<void> fetch() async {
// } // }
@ -50,4 +78,17 @@ class SelfNoteProvider with ChangeNotifier {
_notes = notes; _notes = notes;
notifyListeners(); notifyListeners();
} }
// store todo items in db
Future<void> storeTodo(List<TodoItem> todos) async {
User? user = Provider.of<UserProvider>(_context, listen: false).user;
if (user == null) throw "Cannot store Self Notes for User null";
String userId = user.id;
await Provider.of<DatabaseProvider>(_context, listen: false)
.userStore
.storeSelfTodoItems(todos, userId: userId);
_todoItems = todos;
notifyListeners();
}
} }

View File

@ -52,6 +52,9 @@ const settingsDB = DatabaseStruct("settings", {
"nav_shadow": int, "nav_shadow": int,
"new_colors": int, "new_colors": int,
"uwu_mode": int, "uwu_mode": int,
// quick settings
"q_timetable_lesson_num": int, "q_timetable_sub_tiles": int,
"q_subjects_sub_tiles": int,
}); });
// DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING // DON'T FORGET TO UPDATE DEFAULT VALUES IN `initDB` MIGRATION OR ELSE PARENTS WILL COMPLAIN ABOUT THEIR CHILDREN MISSING
// YOU'VE BEEN WARNED!!! // YOU'VE BEEN WARNED!!!
@ -81,7 +84,7 @@ const userDataDB = DatabaseStruct("user_data", {
"goal_befores": String, "goal_befores": String,
"goal_pin_dates": String, "goal_pin_dates": String,
// todo and notes // todo and notes
"todo_items": String, "self_notes": String, "todo_items": String, "self_notes": String, "self_todo": String,
// v5 shit // v5 shit
"roundings": String, "roundings": String,
"grade_rarities": String, "grade_rarities": String,
@ -149,7 +152,7 @@ Future<Database> initDB(DatabaseProvider database) async {
"goal_befores": "{}", "goal_befores": "{}",
"goal_pin_dates": "{}", "goal_pin_dates": "{}",
// todo and notes // todo and notes
"todo_items": "{}", "self_notes": "[]", "todo_items": "{}", "self_notes": "[]", "self_todo": "[]",
// v5 shit // v5 shit
"roundings": "{}", "roundings": "{}",
"grade_rarities": "{}", "grade_rarities": "{}",

View File

@ -317,6 +317,18 @@ class UserDatabaseQuery {
return selfNotes; return selfNotes;
} }
Future<List<TodoItem>> getTodoItems({required String userId}) async {
List<Map> userData =
await db.query("user_data", where: "id = ?", whereArgs: [userId]);
if (userData.isEmpty) return [];
String? todoItemsJson = userData.elementAt(0)["self_todo"] as String?;
if (todoItemsJson == null) return [];
List<TodoItem> todoItems = (jsonDecode(todoItemsJson) as List)
.map((e) => TodoItem.fromJson(e))
.toList();
return todoItems;
}
// v5 // v5
Future<Map<String, String>> getRoundings({required String userId}) async { Future<Map<String, String>> getRoundings({required String userId}) async {
List<Map> userData = List<Map> userData =

View File

@ -196,6 +196,13 @@ class UserDatabaseStore {
where: "id = ?", whereArgs: [userId]); where: "id = ?", whereArgs: [userId]);
} }
Future<void> storeSelfTodoItems(List<TodoItem> todoItems,
{required String userId}) async {
String todoItemsJson = jsonEncode(todoItems.map((e) => e.json).toList());
await db.update("user_data", {"self_todo": todoItemsJson},
where: "id = ?", whereArgs: [userId]);
}
// v5 // v5
Future<void> storeRoundings(Map<String, String> roundings, Future<void> storeRoundings(Map<String, String> roundings,
{required String userId}) async { {required String userId}) async {

View File

@ -1,13 +1,18 @@
enum NoteType { text, image }
class SelfNote { class SelfNote {
String id; String id;
String? title; String? title;
String content; String content;
NoteType noteType;
Map? json; Map? json;
SelfNote({ SelfNote({
required this.id, required this.id,
this.title, this.title,
required this.content, required this.content,
required this.noteType,
this.json, this.json,
}); });
@ -16,6 +21,7 @@ class SelfNote {
id: json['id'], id: json['id'],
title: json['title'], title: json['title'],
content: json['content'], content: json['content'],
noteType: json['note_type'] == 'image' ? NoteType.image : NoteType.text,
json: json, json: json,
); );
} }
@ -24,5 +30,40 @@ class SelfNote {
'id': id, 'id': id,
'title': title, 'title': title,
'content': content, 'content': content,
'note_type': noteType == NoteType.image ? 'image' : 'text',
};
}
class TodoItem {
String id;
String title;
String content;
bool done;
Map? json;
TodoItem({
required this.id,
required this.title,
required this.content,
required this.done,
this.json,
});
factory TodoItem.fromJson(Map json) {
return TodoItem(
id: json['id'],
title: json['title'],
content: json['content'],
done: json['done'],
json: json,
);
}
get toJson => {
'id': id,
'title': title,
'content': content,
'done': done,
}; };
} }

View File

@ -105,6 +105,10 @@ class SettingsProvider extends ChangeNotifier {
bool _navShadow; bool _navShadow;
bool _newColors; bool _newColors;
bool _uwuMode; bool _uwuMode;
// quick settings
bool _qTimetableLessonNum;
bool _qTimetableSubTiles;
bool _qSubjectsSubTiles;
SettingsProvider({ SettingsProvider({
DatabaseProvider? database, DatabaseProvider? database,
@ -172,6 +176,9 @@ class SettingsProvider extends ChangeNotifier {
required bool navShadow, required bool navShadow,
required bool newColors, required bool newColors,
required bool uwuMode, required bool uwuMode,
required bool qTimetableLessonNum,
required bool qTimetableSubTiles,
required bool qSubjectsSubTiles,
}) : _database = database, }) : _database = database,
_language = language, _language = language,
_startPage = startPage, _startPage = startPage,
@ -236,7 +243,10 @@ class SettingsProvider extends ChangeNotifier {
_calendarId = calendarId, _calendarId = calendarId,
_navShadow = navShadow, _navShadow = navShadow,
_newColors = newColors, _newColors = newColors,
_uwuMode = uwuMode; _uwuMode = uwuMode,
_qTimetableLessonNum = qTimetableLessonNum,
_qTimetableSubTiles = qTimetableSubTiles,
_qSubjectsSubTiles = qSubjectsSubTiles;
factory SettingsProvider.fromMap(Map map, factory SettingsProvider.fromMap(Map map,
{required DatabaseProvider database}) { {required DatabaseProvider database}) {
@ -321,6 +331,9 @@ class SettingsProvider extends ChangeNotifier {
navShadow: map['nav_shadow'] == 1, navShadow: map['nav_shadow'] == 1,
newColors: map['new_colors'] == 1, newColors: map['new_colors'] == 1,
uwuMode: map['uwu_mode'] == 1, uwuMode: map['uwu_mode'] == 1,
qTimetableLessonNum: map['q_timetable_lesson_num'] == 1,
qTimetableSubTiles: map['q_timetable_sub_tiles'] == 1,
qSubjectsSubTiles: map['q_subjects_sub_tiles'] == 1,
); );
} }
@ -393,6 +406,9 @@ class SettingsProvider extends ChangeNotifier {
"nav_shadow": _navShadow ? 1 : 0, "nav_shadow": _navShadow ? 1 : 0,
"new_colors": _newColors ? 1 : 0, "new_colors": _newColors ? 1 : 0,
"uwu_mode": _uwuMode ? 1 : 0, "uwu_mode": _uwuMode ? 1 : 0,
"q_timetable_lesson_num": _qTimetableLessonNum ? 1 : 0,
"q_timetable_sub_tiles": _qTimetableSubTiles ? 1 : 0,
"q_subjects_sub_tiles": _qSubjectsSubTiles ? 1 : 0,
}; };
} }
@ -469,6 +485,9 @@ class SettingsProvider extends ChangeNotifier {
navShadow: true, navShadow: true,
newColors: true, newColors: true,
uwuMode: false, uwuMode: false,
qTimetableLessonNum: true,
qTimetableSubTiles: true,
qSubjectsSubTiles: true,
); );
} }
@ -536,6 +555,9 @@ class SettingsProvider extends ChangeNotifier {
bool get navShadow => _navShadow; bool get navShadow => _navShadow;
bool get newColors => _newColors; bool get newColors => _newColors;
bool get uwuMode => _uwuMode; bool get uwuMode => _uwuMode;
bool get qTimetableLessonNum => _qTimetableLessonNum;
bool get qTimetableSubTiles => _qTimetableSubTiles;
bool get qSubjectsSubTiles => _qSubjectsSubTiles;
Future<void> update({ Future<void> update({
bool store = true, bool store = true,
@ -599,6 +621,9 @@ class SettingsProvider extends ChangeNotifier {
bool? navShadow, bool? navShadow,
bool? newColors, bool? newColors,
bool? uwuMode, bool? uwuMode,
bool? qTimetableLessonNum,
bool? qTimetableSubTiles,
bool? qSubjectsSubTiles,
}) async { }) async {
if (language != null && language != _language) _language = language; if (language != null && language != _language) _language = language;
if (startPage != null && startPage != _startPage) _startPage = startPage; if (startPage != null && startPage != _startPage) _startPage = startPage;
@ -669,7 +694,7 @@ class SettingsProvider extends ChangeNotifier {
if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay; if (bellDelay != null && bellDelay != _bellDelay) _bellDelay = bellDelay;
if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) { if (bellDelayEnabled != null && bellDelayEnabled != _bellDelayEnabled) {
_bellDelayEnabled = bellDelayEnabled; _bellDelayEnabled = bellDelayEnabled;
if(Platform.isIOS){ if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true; LiveCardProvider.hasActivitySettingsChanged = true;
} }
} }
@ -781,6 +806,17 @@ class SettingsProvider extends ChangeNotifier {
if (uwuMode != null && uwuMode != _uwuMode) { if (uwuMode != null && uwuMode != _uwuMode) {
_uwuMode = uwuMode; _uwuMode = uwuMode;
} }
if (qTimetableLessonNum != null &&
qTimetableLessonNum != _qTimetableLessonNum) {
_qTimetableLessonNum = qTimetableLessonNum;
}
if (qTimetableSubTiles != null &&
qTimetableSubTiles != _qTimetableSubTiles) {
_qTimetableSubTiles = qTimetableSubTiles;
}
if (qSubjectsSubTiles != null && qSubjectsSubTiles != _qSubjectsSubTiles) {
_qSubjectsSubTiles = qSubjectsSubTiles;
}
// store or not // store or not
if (store) await _database?.store.storeSettings(this); if (store) await _database?.store.storeSettings(this);
notifyListeners(); notifyListeners();

View File

@ -31,3 +31,66 @@ Map<AccentColor, Color> accentColorMap = {
AccentColor.adaptive: const Color(0xFF3D7BF4), AccentColor.adaptive: const Color(0xFF3D7BF4),
AccentColor.custom: const Color(0xFF3D7BF4), AccentColor.custom: const Color(0xFF3D7BF4),
}; };
// new v5 things
Map<AccentColor, Color> lightPrimary = {
AccentColor.filc: const Color(0xFF050B15),
};
Map<AccentColor, Color> lightSecondary = {
AccentColor.filc: const Color(0xFF3F444F),
};
Map<AccentColor, Color> lightTeritary = {
AccentColor.filc: const Color(0xFF1C469A),
};
Map<AccentColor, Color> lightIcon = {
AccentColor.filc: const Color(0xFF0A2456),
};
Map<AccentColor, Color> lightAccent = {
AccentColor.filc: const Color(0xFF487DE6),
};
Map<AccentColor, Color> lightBgDarkened = {
AccentColor.filc: const Color(0xFFB9C8E5),
};
Map<AccentColor, Color> lightBtnSecStrk = {
AccentColor.filc: const Color(0xFFCEDBF5),
};
Map<AccentColor, Color> lightBg = {
AccentColor.filc: const Color(0xFFDAE4F7),
};
Map<AccentColor, Color> lightCard = {
AccentColor.filc: const Color(0xFFEDF3FF),
};
Map<AccentColor, Color> lightBtnSec = {
AccentColor.filc: const Color(0xFFFBFCFF),
};
Map<AccentColor, Color> darkPrimary = {
AccentColor.filc: const Color(0xFFEBF1FD),
};
Map<AccentColor, Color> darkSecondary = {
AccentColor.filc: const Color(0xFFCFD8E9),
};
Map<AccentColor, Color> darkTeritary = {
AccentColor.filc: const Color(0xFFAEC8FC),
};
Map<AccentColor, Color> darkIcon = {
AccentColor.filc: const Color(0xFFBAD1FF),
};
Map<AccentColor, Color> darkAccent = {
AccentColor.filc: const Color(0xFF487DE6),
};
Map<AccentColor, Color> darkBgDarkened = {
AccentColor.filc: const Color(0xFF010205),
};
Map<AccentColor, Color> darkBtnSecStrk = {
AccentColor.filc: const Color(0xFF1C2230),
};
Map<AccentColor, Color> darkBg = {
AccentColor.filc: const Color(0xFF070A0E),
};
Map<AccentColor, Color> darkCard = {
AccentColor.filc: const Color(0xFF0F131B),
};
Map<AccentColor, Color> darkBtnSec = {
AccentColor.filc: const Color(0xFF131822),
};

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
class NewColors extends ThemeExtension<NewColors> {
const NewColors({
required this.accent,
required this.primary,
required this.secondary,
required this.teritary,
required this.icon,
required this.darkenBg,
required this.btnSecStrk,
required this.background,
required this.card,
required this.btnSec,
});
final Color? accent;
final Color? primary;
final Color? secondary;
final Color? teritary;
final Color? icon;
final Color? darkenBg;
final Color? btnSecStrk;
final Color? background;
final Color? card;
final Color? btnSec;
@override
NewColors copyWith({
Color? accent,
Color? primary,
Color? secondary,
Color? teritary,
Color? icon,
Color? darkenBg,
Color? btnSecStrk,
Color? background,
Color? card,
Color? btnSec,
}) {
return NewColors(
accent: accent ?? this.accent,
primary: primary ?? this.primary,
secondary: secondary ?? this.secondary,
teritary: teritary ?? this.teritary,
icon: icon ?? this.icon,
darkenBg: darkenBg ?? this.darkenBg,
btnSecStrk: btnSecStrk ?? this.btnSecStrk,
background: background ?? this.background,
card: card ?? this.card,
btnSec: btnSec ?? this.btnSec,
);
}
@override
NewColors lerp(NewColors? other, double t) {
if (other is! NewColors) {
return this;
}
return NewColors(
accent: Color.lerp(accent, other.accent, t),
primary: Color.lerp(primary, other.primary, t),
secondary: Color.lerp(secondary, other.secondary, t),
teritary: Color.lerp(teritary, other.teritary, t),
icon: Color.lerp(icon, other.icon, t),
darkenBg: Color.lerp(darkenBg, other.darkenBg, t),
btnSecStrk: Color.lerp(btnSecStrk, other.btnSecStrk, t),
background: Color.lerp(background, other.background, t),
card: Color.lerp(card, other.card, t),
btnSec: Color.lerp(btnSec, other.btnSec, t),
);
}
}

View File

@ -87,6 +87,20 @@ class AppTheme {
amount: 0.4); // white mode: same tertiary as secondary amount: 0.4); // white mode: same tertiary as secondary
return ThemeData( return ThemeData(
// extensions: [
// NewColors(
// accent: lightAccent[accentColor]!,
// primary: lightPrimary[accentColor]!,
// secondary: lightSecondary[accentColor]!,
// teritary: lightTeritary[accentColor]!,
// icon: lightIcon[accentColor]!,
// darkenBg: lightBgDarkened[accentColor]!,
// btnSecStrk: lightBtnSecStrk[accentColor]!,
// background: lightBg[accentColor]!,
// card: lightCard[accentColor]!,
// btnSec: lightBtnSec[accentColor]!,
// ),
// ],
brightness: Brightness.light, brightness: Brightness.light,
useMaterial3: true, useMaterial3: true,
fontFamily: _defaultFontFamily, fontFamily: _defaultFontFamily,
@ -198,6 +212,20 @@ class AppTheme {
amount: 0.1); // dark mode: tertiary is way darker than secondary amount: 0.1); // dark mode: tertiary is way darker than secondary
return ThemeData( return ThemeData(
// extensions: [
// NewColors(
// accent: darkAccent[accentColor]!,
// primary: darkPrimary[accentColor]!,
// secondary: darkSecondary[accentColor]!,
// teritary: darkTeritary[accentColor]!,
// icon: darkIcon[accentColor]!,
// darkenBg: darkBgDarkened[accentColor]!,
// btnSecStrk: darkBtnSecStrk[accentColor]!,
// background: darkBg[accentColor]!,
// card: darkCard[accentColor]!,
// btnSec: darkBtnSec[accentColor]!,
// ),
// ],
brightness: Brightness.dark, brightness: Brightness.dark,
useMaterial3: true, useMaterial3: true,
fontFamily: _defaultFontFamily, fontFamily: _defaultFontFamily,

View File

@ -1,8 +1,11 @@
import 'dart:developer'; import 'dart:developer';
import 'package:refilc_kreta_api/models/absence.dart'; import 'package:refilc_kreta_api/models/absence.dart';
import 'package:refilc_kreta_api/models/exam.dart';
import 'package:refilc_kreta_api/models/lesson.dart'; import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/week.dart'; import 'package:refilc_kreta_api/models/week.dart';
import 'package:refilc_kreta_api/providers/grade_provider.dart';
import 'package:refilc_kreta_api/providers/timetable_provider.dart'; import 'package:refilc_kreta_api/providers/timetable_provider.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -38,7 +41,54 @@ class ReverseSearch {
} }
} }
static Future<Lesson?> getLessonByExam(
Exam exam, BuildContext context) async {
final timetableProvider =
Provider.of<TimetableProvider>(context, listen: false);
List<Lesson> lessons = [];
final week = Week.fromDate(exam.writeDate);
try {
await timetableProvider.fetch(week: week);
} catch (e) {
log("[ERROR] getLessonByAbsence: $e");
}
lessons = timetableProvider.getWeek(week) ?? [];
// Find absence lesson in timetable
Lesson lesson = lessons.firstWhere(
(l) =>
_sameDate(l.date, exam.writeDate) && l.subject.id == exam.subject.id,
orElse: () => Lesson.fromJson({'isEmpty': true}),
);
if (lesson.isEmpty) {
return null;
} else {
return lesson;
}
}
// difference.inDays is not reliable // difference.inDays is not reliable
static bool _sameDate(DateTime a, DateTime b) => static bool _sameDate(DateTime a, DateTime b) =>
(a.year == b.year && a.month == b.month && a.day == b.day); (a.year == b.year && a.month == b.month && a.day == b.day);
static Future<GradeSubject?> getSubjectByLesson(
Lesson lesson, BuildContext context) async {
final gradeProvider = Provider.of<GradeProvider>(context, listen: false);
try {
await gradeProvider.fetch();
} catch (e) {
log("[ERROR] getSubjectByLesson: $e");
}
try {
return gradeProvider.grades.map((e) => e.subject).firstWhere(
(s) => s.id == lesson.subject.id,
);
} catch (e) {
return null;
}
}
} }

View File

@ -3,7 +3,7 @@ description: "Egy nem hivatalos e-KRÉTA kliens, diákoktól diákoknak."
homepage: https://refilc.hu homepage: https://refilc.hu
publish_to: "none" publish_to: "none"
version: 5.0.0+253 version: 5.0.0+258
environment: environment:
sdk: ">=2.17.0 <=3.3.2" sdk: ">=2.17.0 <=3.3.2"

View File

@ -8,19 +8,21 @@ class RoundedBottomSheet extends StatelessWidget {
this.borderRadius = 16.0, this.borderRadius = 16.0,
this.shrink = true, this.shrink = true,
this.showHandle = true, this.showHandle = true,
this.backgroundColor,
}); });
final Widget? child; final Widget? child;
final double borderRadius; final double borderRadius;
final bool shrink; final bool shrink;
final bool showHandle; final bool showHandle;
final Color? backgroundColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedContainer( return AnimatedContainer(
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background, color: backgroundColor ?? Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(borderRadius), topLeft: Radius.circular(borderRadius),
topRight: Radius.circular(borderRadius), topRight: Radius.circular(borderRadius),
@ -52,6 +54,7 @@ Future<T?> showRoundedModalBottomSheet<T>(
required Widget child, required Widget child,
bool rootNavigator = true, bool rootNavigator = true,
bool showHandle = true, bool showHandle = true,
Color? backgroundColor,
}) async { }) async {
return await showModalBottomSheet<T>( return await showModalBottomSheet<T>(
useSafeArea: false, useSafeArea: false,
@ -62,6 +65,7 @@ Future<T?> showRoundedModalBottomSheet<T>(
useRootNavigator: rootNavigator, useRootNavigator: rootNavigator,
isScrollControlled: true, isScrollControlled: true,
builder: (context) => RoundedBottomSheet( builder: (context) => RoundedBottomSheet(
backgroundColor: backgroundColor,
showHandle: showHandle, showHandle: showHandle,
child: child, child: child,
), ),

View File

@ -1,8 +1,19 @@
// ignore_for_file: use_build_context_synchronously
import 'package:flutter_svg/svg.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:refilc/helpers/subject.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/colors/utils.dart';
import 'package:refilc/utils/format.dart';
import 'package:refilc/utils/reverse_search.dart';
import 'package:refilc_kreta_api/models/exam.dart'; import 'package:refilc_kreta_api/models/exam.dart';
import 'package:refilc_mobile_ui/common/viewable.dart'; import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_mobile_ui/common/widgets/card_handle.dart'; import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/round_border_icon.dart';
import 'package:refilc_mobile_ui/common/widgets/exam/exam_tile.dart'; import 'package:refilc_mobile_ui/common/widgets/exam/exam_tile.dart';
import 'package:refilc_mobile_ui/common/widgets/exam/exam_view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ExamViewable extends StatelessWidget { class ExamViewable extends StatelessWidget {
@ -15,13 +26,335 @@ class ExamViewable extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Viewable( return GestureDetector(
tile: ExamTile( onTap: () => ExamPopup.show(context: context, exam: exam),
child: ExamTile(
exam, exam,
showSubject: showSubject, showSubject: showSubject,
padding: tilePadding, padding: tilePadding,
), ),
view: CardHandle(child: ExamView(exam)), );
// return Viewable(
// tile: ExamTile(
// exam,
// showSubject: showSubject,
// padding: tilePadding,
// ),
// view: CardHandle(child: ExamView(exam)),
// );
}
}
class ExamPopup extends StatelessWidget {
const ExamPopup({
super.key,
required this.exam,
required this.outsideContext,
required this.lesson,
});
final Exam exam;
final BuildContext outsideContext;
final Lesson? lesson;
static void show({
required BuildContext context,
required Exam exam,
}) async =>
showRoundedModalBottomSheet(
context,
child: ExamPopup(
exam: exam,
outsideContext: context,
lesson: (await ReverseSearch.getLessonByExam(exam, context)),
),
showHandle: false,
);
// IconData _getIcon() => _featureLevels[feature] == PremiumFeatureLevel.cap
// ? FilcIcons.kupak
// : _featureLevels[feature] == PremiumFeatureLevel.ink
// ? FilcIcons.tinta
// : FilcIcons.tinta;
// Color _getColor(BuildContext context) =>
// _featureLevels[feature] == PremiumFeatureLevel.gold
// ? const Color(0xFFC89B08)
// : Theme.of(context).brightness == Brightness.light
// ? const Color(0xff691A9B)
// : const Color(0xffA66FC8);
// String? _getAsset() => _featureAssets[feature];
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
),
),
child: Stack(
children: [
Stack(
children: [
SvgPicture.asset(
"assets/svg/mesh_bg.svg",
// ignore: deprecated_member_use
color: ColorsUtils()
.fade(context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
width: MediaQuery.of(context).size.width,
),
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
),
gradient: LinearGradient(
colors: [
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context).scaffoldBackgroundColor,
],
stops: const [0.1, 0.5, 0.7, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
width: MediaQuery.of(context).size.width,
height: 175.0,
),
],
),
SizedBox(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: ColorsUtils()
.fade(
context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
borderRadius: BorderRadius.circular(
2.0,
),
),
),
const SizedBox(
height: 38.0,
),
Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: RoundBorderIcon(
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.9),
width: 1.5,
padding: 10.0,
icon: Icon(
SubjectIcon.resolveVariant(
context: context, subject: exam.subject),
size: 32.0,
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.8),
),
),
),
const SizedBox(
height: 55.0,
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(6.0)),
),
padding: const EdgeInsets.all(14.0),
child: Row(
children: [
const RoundBorderIcon(
padding: 8.0,
icon: Icon(
Icons.edit_document,
size: 20.0,
),
),
const SizedBox(
width: 10.0,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: Text(
exam.description.capital(),
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(0.9),
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
Text(
(exam.mode?.description ?? 'Ismeretlen')
.capital(),
style: TextStyle(
color: AppColors.of(context).text,
fontSize: 14.0,
fontWeight: FontWeight.w500,
),
),
],
),
],
),
),
if (lesson != null)
const SizedBox(
height: 6.0,
),
if (lesson != null)
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(6.0),
bottom: Radius.circular(12.0)),
),
padding: const EdgeInsets.all(14.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
SubjectIcon.resolveVariant(
context: context, subject: exam.subject),
size: 20.0,
),
const SizedBox(
width: 10.0,
),
Text(
(((lesson?.subject.isRenamed ?? false) &&
Provider.of<SettingsProvider>(
context,
listen: false)
.renamedSubjectsEnabled)
? lesson?.subject.renamedTo
: (lesson?.subject.name ?? '')
.capital()) ??
'Ismeretlen',
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(0.9),
fontSize: 16.0,
fontWeight: FontWeight.w600,
fontStyle: ((lesson?.subject.isRenamed ??
false) &&
Provider.of<SettingsProvider>(context,
listen: false)
.renamedSubjectsItalics)
? FontStyle.italic
: null,
),
),
],
),
Text(
'${DateFormat('H:mm').format(lesson!.start)} - ${DateFormat('H:mm').format(lesson!.end)}',
style: TextStyle(
color:
AppColors.of(context).text.withOpacity(0.85),
fontSize: 14.0,
fontWeight: FontWeight.w500,
),
),
],
),
),
// const SizedBox(
// height: 24.0,
// ),
// GestureDetector(
// onTap: () async {
// ReverseSearch.getSubjectByLesson(lesson, context)
// .then((subject) {
// if (subject != null) {
// GradesPage.jump(outsideContext, subject: subject);
// } else {
// ScaffoldMessenger.of(context)
// .showSnackBar(CustomSnackBar(
// content: Text("Cannot find subject".i18n,
// style: const TextStyle(color: Colors.white)),
// backgroundColor: AppColors.of(context).red,
// context: context,
// ));
// }
// });
// },
// child: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// color: Theme.of(context).colorScheme.background,
// borderRadius: BorderRadius.circular(12.0),
// ),
// padding: const EdgeInsets.all(16.0),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text(
// 'view_subject'.i18n,
// style: TextStyle(
// color:
// AppColors.of(context).text.withOpacity(0.9),
// fontSize: 18.0,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// ),
// ),
// ),
],
),
),
),
],
),
); );
} }
} }

View File

@ -9,12 +9,14 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class GradeSubjectTile extends StatelessWidget { class GradeSubjectTile extends StatelessWidget {
const GradeSubjectTile(this.subject, const GradeSubjectTile(
{super.key, this.subject, {
this.average = 0.0, super.key,
this.groupAverage = 0.0, this.average = 0.0,
this.onTap, this.groupAverage = 0.0,
this.averageBefore = 0.0}); this.onTap,
this.averageBefore = 0.0,
});
final GradeSubject subject; final GradeSubject subject;
final void Function()? onTap; final void Function()? onTap;

View File

@ -1,32 +1,32 @@
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:refilc/api/providers/database_provider.dart'; import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart'; import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/helpers/subject.dart'; import 'package:refilc/helpers/subject.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/colors/utils.dart'; import 'package:refilc/theme/colors/utils.dart';
import 'package:refilc/utils/format.dart';
import 'package:refilc_kreta_api/models/lesson.dart'; import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart'; import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_mobile_ui/common/round_border_icon.dart'; import 'package:refilc_mobile_ui/common/round_border_icon.dart';
import 'package:refilc_mobile_ui/common/viewable.dart';
import 'package:refilc_mobile_ui/common/widgets/card_handle.dart';
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart'; import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
import 'package:refilc_mobile_ui/common/widgets/lesson/lesson_view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:refilc_plus/models/premium_scopes.dart';
import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
import 'lesson_view.i18n.dart';
class LessonViewable extends StatefulWidget { class LessonViewable extends StatefulWidget {
const LessonViewable(this.lesson, const LessonViewable(
{super.key, this.swapDesc = false, required this.customDesc}); this.lesson, {
super.key,
this.swapDesc = false,
required this.customDesc,
this.showSubTiles = true,
});
final Lesson lesson; final Lesson lesson;
final bool swapDesc; final bool swapDesc;
final String customDesc; final String customDesc;
final bool showSubTiles;
@override @override
State<LessonViewable> createState() => LessonViewableState(); State<LessonViewable> createState() => LessonViewableState();
@ -51,14 +51,28 @@ class LessonViewableState extends State<LessonViewable> {
Lesson lsn = widget.lesson; Lesson lsn = widget.lesson;
lsn.description = widget.customDesc; lsn.description = widget.customDesc;
final tile = LessonTile(lsn, swapDesc: widget.swapDesc); final tile = LessonTile(
lsn,
swapDesc: widget.swapDesc,
showSubTiles: widget.showSubTiles,
);
if (lsn.subject.id == '' || tile.lesson.isEmpty) return tile; if (lsn.subject.id == '' || tile.lesson.isEmpty) return tile;
return LessonTile( return GestureDetector(
lsn, onTap: () => TimetableLessonPopup.show(
swapDesc: widget.swapDesc, context: context,
onTap: () => TimetableLessonPopup.show(context: context, lesson: lsn), lesson: lsn,
),
child: LessonTile(
lsn,
swapDesc: widget.swapDesc,
showSubTiles: widget.showSubTiles,
// onTap: () => TimetableLessonPopup.show(
// context: context,
// lesson: lsn,
// ),
),
); );
// return Viewable( // return Viewable(
@ -232,9 +246,14 @@ class LessonViewableState extends State<LessonViewable> {
} }
class TimetableLessonPopup extends StatelessWidget { class TimetableLessonPopup extends StatelessWidget {
const TimetableLessonPopup({super.key, required this.lesson}); const TimetableLessonPopup({
super.key,
required this.lesson,
required this.outsideContext,
});
final Lesson lesson; final Lesson lesson;
final BuildContext outsideContext;
static void show({ static void show({
required BuildContext context, required BuildContext context,
@ -244,6 +263,7 @@ class TimetableLessonPopup extends StatelessWidget {
context, context,
child: TimetableLessonPopup( child: TimetableLessonPopup(
lesson: lesson, lesson: lesson,
outsideContext: context,
), ),
showHandle: false, showHandle: false,
); );
@ -272,13 +292,42 @@ class TimetableLessonPopup extends StatelessWidget {
), ),
child: Stack( child: Stack(
children: [ children: [
SvgPicture.asset( Stack(
"assets/svg/mesh_bg.svg", children: [
// ignore: deprecated_member_use SvgPicture.asset(
color: ColorsUtils().fade( "assets/svg/mesh_bg.svg",
context, Theme.of(context).scaffoldBackgroundColor, // ignore: deprecated_member_use
darkenAmount: 0.1, lightenAmount: 0.1), color: ColorsUtils()
width: MediaQuery.of(context).size.width, .fade(context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
width: MediaQuery.of(context).size.width,
),
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
),
gradient: LinearGradient(
colors: [
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context)
.scaffoldBackgroundColor
.withOpacity(0.1),
Theme.of(context).scaffoldBackgroundColor,
],
stops: const [0.1, 0.5, 0.7, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
width: MediaQuery.of(context).size.width,
height: 175.0,
),
],
), ),
SizedBox( SizedBox(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
@ -291,9 +340,11 @@ class TimetableLessonPopup extends StatelessWidget {
width: 40, width: 40,
height: 4, height: 4,
decoration: BoxDecoration( decoration: BoxDecoration(
color: ColorsUtils().fade( color: ColorsUtils()
context, Theme.of(context).scaffoldBackgroundColor, .fade(
darkenAmount: 0.2, lightenAmount: 0.2), context, Theme.of(context).colorScheme.secondary,
darkenAmount: 0.1, lightenAmount: 0.1)
.withOpacity(0.33),
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
2.0, 2.0,
), ),
@ -302,10 +353,31 @@ class TimetableLessonPopup extends StatelessWidget {
const SizedBox( const SizedBox(
height: 38.0, height: 38.0,
), ),
RoundBorderIcon( Container(
icon: Icon( decoration: BoxDecoration(
SubjectIcon.resolveVariant( color: Theme.of(context).scaffoldBackgroundColor,
context: context, subject: lesson.subject), borderRadius: BorderRadius.circular(50.0),
),
child: RoundBorderIcon(
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.9),
width: 1.5,
padding: 10.0,
icon: Icon(
SubjectIcon.resolveVariant(
context: context, subject: lesson.subject),
size: 32.0,
color: ColorsUtils()
.darken(
Theme.of(context).colorScheme.secondary,
amount: 0.1,
)
.withOpacity(0.8),
),
), ),
), ),
const SizedBox( const SizedBox(
@ -315,39 +387,92 @@ class TimetableLessonPopup extends StatelessWidget {
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical( borderRadius: BorderRadius.vertical(
top: Radius.circular(12.0), top: const Radius.circular(12.0),
bottom: Radius.circular(6.0), bottom: (lesson.description.replaceAll(' ', '') != '')
? const Radius.circular(6.0)
: const Radius.circular(12.0),
), ),
), ),
padding: const EdgeInsets.all(14.0), padding: const EdgeInsets.all(14.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Row(
'6:09 - 4:20', children: [
style: TextStyle( Text(
color: AppColors.of(context).text.withOpacity(0.85), '${DateFormat('H:mm').format(lesson.start)} - ${DateFormat('H:mm').format(lesson.end)}',
fontSize: 14.0, style: TextStyle(
fontWeight: FontWeight.w500, color: AppColors.of(context)
), .text
.withOpacity(0.85),
fontSize: 14.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(
width: 8.0,
),
Container(
width: lesson.room.length > 20 ? 111 : null,
padding: const EdgeInsets.symmetric(
horizontal: 5.5, vertical: 3.0),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.tertiary
.withOpacity(.15),
borderRadius: BorderRadius.circular(10.0),
),
child: Text(
lesson.room,
overflow: TextOverflow.ellipsis,
style: TextStyle(
height: 1.1,
fontSize: 12.0,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.9),
),
),
),
],
), ),
const SizedBox( const SizedBox(
height: 12.0, height: 12.0,
), ),
Text( Text(
lesson.name, lesson.subject.isRenamed &&
Provider.of<SettingsProvider>(context,
listen: false)
.renamedSubjectsEnabled
? lesson.subject.renamedTo!
: lesson.subject.name.capital(),
style: TextStyle( style: TextStyle(
color: AppColors.of(context).text, color: AppColors.of(context).text,
fontSize: 20.0, fontSize: 20.0,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
fontStyle: Provider.of<SettingsProvider>(context,
listen: false)
.renamedSubjectsItalics &&
lesson.subject.isRenamed
? FontStyle.italic
: null,
), ),
), ),
const SizedBox( const SizedBox(
height: 8.0, height: 8.0,
), ),
Text( Text(
lesson.teacher.name, (lesson.teacher.isRenamed &&
Provider.of<SettingsProvider>(context,
listen: false)
.renamedTeachersEnabled)
? (lesson.teacher.renamedTo ??
lesson.teacher.name)
: lesson.teacher.name,
style: TextStyle( style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.9), color: AppColors.of(context).text.withOpacity(0.9),
fontSize: 14.0, fontSize: 14.0,
@ -357,64 +482,79 @@ class TimetableLessonPopup extends StatelessWidget {
], ],
), ),
), ),
const SizedBox( if (lesson.description.replaceAll(' ', '') != '')
height: 6.0, const SizedBox(
), height: 6.0,
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(6.0),
bottom: Radius.circular(12.0),
),
), ),
padding: const EdgeInsets.all(14.0), if (lesson.description.replaceAll(' ', '') != '')
child: Column( Container(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
lesson.description,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.9),
fontSize: 14.0,
fontWeight: FontWeight.w600,
),
),
],
),
),
const SizedBox(
height: 24.0,
),
GestureDetector(
onTap: () {
Navigator.of(context, rootNavigator: true)
.pushReplacementNamed('/');
},
child: Container(
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(12.0), borderRadius: const BorderRadius.vertical(
top: Radius.circular(6.0),
bottom: Radius.circular(12.0),
),
), ),
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(14.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'view_subject'.i18n, lesson.description,
style: TextStyle( style: TextStyle(
color: color:
AppColors.of(context).text.withOpacity(0.9), AppColors.of(context).text.withOpacity(0.9),
fontSize: 18.0, fontSize: 14.0,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
), ),
), ),
], ],
), ),
), ),
), // const SizedBox(
// height: 24.0,
// ),
// GestureDetector(
// onTap: () async {
// ReverseSearch.getSubjectByLesson(lesson, context)
// .then((subject) {
// if (subject != null) {
// GradesPage.jump(outsideContext, subject: subject);
// } else {
// ScaffoldMessenger.of(context)
// .showSnackBar(CustomSnackBar(
// content: Text("Cannot find subject".i18n,
// style: const TextStyle(color: Colors.white)),
// backgroundColor: AppColors.of(context).red,
// context: context,
// ));
// }
// });
// },
// child: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// color: Theme.of(context).colorScheme.background,
// borderRadius: BorderRadius.circular(12.0),
// ),
// padding: const EdgeInsets.all(16.0),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text(
// 'view_subject'.i18n,
// style: TextStyle(
// color:
// AppColors.of(context).text.withOpacity(0.9),
// fontSize: 18.0,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// ),
// ),
// ),
], ],
), ),
), ),

View File

@ -19,6 +19,7 @@ import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/group_average.dart'; import 'package:refilc_kreta_api/models/group_average.dart';
import 'package:refilc_kreta_api/providers/homework_provider.dart'; import 'package:refilc_kreta_api/providers/homework_provider.dart';
import 'package:refilc_mobile_ui/common/average_display.dart'; import 'package:refilc_mobile_ui/common/average_display.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart'; import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/empty.dart'; import 'package:refilc_mobile_ui/common/empty.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart'; import 'package:refilc_mobile_ui/common/panel/panel.dart';
@ -32,6 +33,8 @@ import 'package:refilc_mobile_ui/pages/grades/fail_warning.dart';
import 'package:refilc_mobile_ui/pages/grades/grades_count.dart'; import 'package:refilc_mobile_ui/pages/grades/grades_count.dart';
import 'package:refilc_mobile_ui/pages/grades/graph.dart'; import 'package:refilc_mobile_ui/pages/grades/graph.dart';
import 'package:refilc_mobile_ui/pages/grades/grade_subject_view.dart'; import 'package:refilc_mobile_ui/pages/grades/grade_subject_view.dart';
import 'package:refilc_mobile_ui/screens/navigation/navigation_route_handler.dart';
import 'package:refilc_mobile_ui/screens/navigation/navigation_screen.dart';
import 'package:refilc_plus/models/premium_scopes.dart'; import 'package:refilc_plus/models/premium_scopes.dart';
import 'package:refilc_plus/providers/plus_provider.dart'; import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -48,6 +51,19 @@ import 'grades_page.i18n.dart';
class GradesPage extends StatefulWidget { class GradesPage extends StatefulWidget {
const GradesPage({super.key}); const GradesPage({super.key});
static void jump(BuildContext context, {GradeSubject? subject}) {
// Go to timetable page with arguments
NavigationScreen.of(context)
?.customRoute(navigationPageRoute((context) => const GradesPage()));
NavigationScreen.of(context)?.setPage("grades");
// Show initial Lesson
if (subject != null) {
GradeSubjectView(subject, groupAverage: 0.0).push(context, root: true);
}
}
@override @override
GradesPageState createState() => GradesPageState(); GradesPageState createState() => GradesPageState();
} }
@ -147,7 +163,8 @@ class GradesPageState extends State<GradesPage> {
Exam? nearestExam = allExams.firstWhereOrNull((e) => Exam? nearestExam = allExams.firstWhereOrNull((e) =>
e.subject.id == subject.id && e.writeDate.isAfter(DateTime.now())); e.subject.id == subject.id && e.writeDate.isAfter(DateTime.now()));
bool hasUnder = hasHomework || nearestExam != null; bool hasUnder = (hasHomework || nearestExam != null) &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles;
return Padding( return Padding(
padding: i > 1 ? const EdgeInsets.only(top: 9.0) : EdgeInsets.zero, padding: i > 1 ? const EdgeInsets.only(top: 9.0) : EdgeInsets.zero,
@ -201,7 +218,8 @@ class GradesPageState extends State<GradesPage> {
const SizedBox( const SizedBox(
height: 6.0, height: 6.0,
), ),
if (hasHomework) if (hasHomework &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
boxShadow: [ boxShadow: [
@ -249,7 +267,14 @@ class GradesPageState extends State<GradesPage> {
), ),
), ),
), ),
if (nearestExam != null) if (hasHomework &&
nearestExam != null &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
const SizedBox(
height: 6.0,
),
if (nearestExam != null &&
Provider.of<SettingsProvider>(context).qSubjectsSubTiles)
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
boxShadow: [ boxShadow: [
@ -519,19 +544,10 @@ class GradesPageState extends State<GradesPage> {
child: IconButton( child: IconButton(
splashRadius: 24.0, splashRadius: 24.0,
onPressed: () { onPressed: () {
if (!Provider.of<PlusProvider>(context, listen: false) showQuickSettings(context);
.hasScope(PremiumScopes.totalGradeCalculator)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.gradeCalculation);
return;
}
// SoonAlert.show(context: context);
gradeCalcTotal(context);
}, },
icon: Icon( icon: Icon(
FeatherIcons.plus, FeatherIcons.moreHorizontal,
color: AppColors.of(context).text, color: AppColors.of(context).text,
), ),
), ),
@ -627,4 +643,69 @@ class GradesPageState extends State<GradesPage> {
} }
}); });
} }
void showQuickSettings(BuildContext context) {
showRoundedModalBottomSheet(
context,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: BottomSheetMenu(items: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
title: Row(
children: [
const Icon(FeatherIcons.plusCircle),
const SizedBox(
width: 10.0,
),
Text('grade_calc'.i18n),
],
),
onTap: () {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.totalGradeCalculator)) {
PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.gradeCalculation);
return;
}
// SoonAlert.show(context: context);
gradeCalcTotal(context);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
title: Row(
children: [
const Icon(Icons.edit_document),
const SizedBox(
width: 10.0,
),
Text('show_exams_homework'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.qSubjectsSubTiles,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(qSubjectsSubTiles: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
]),
);
}
} }

View File

@ -27,6 +27,8 @@ extension Localization on String {
"exams": "Exams", "exams": "Exams",
"timetable": "Timetable", "timetable": "Timetable",
"grades": "Grades", "grades": "Grades",
"show_exams_homework": "Exams and Homework",
"grade_calc": "Grade Calculator",
}, },
"hu_hu": { "hu_hu": {
"Grades": "Tantárgyak", "Grades": "Tantárgyak",
@ -51,6 +53,8 @@ extension Localization on String {
"exams": "Számonkérések", "exams": "Számonkérések",
"timetable": "Órarend", "timetable": "Órarend",
"grades": "Jegyek", "grades": "Jegyek",
"show_exams_homework": "Dolgozatok és házik",
"grade_calc": "Jegy kalkulátor",
}, },
"de_de": { "de_de": {
"Grades": "Fächer", "Grades": "Fächer",
@ -75,6 +79,8 @@ extension Localization on String {
"exams": "Prüfungen", "exams": "Prüfungen",
"timetable": "Stundenplan", "timetable": "Stundenplan",
"grades": "Noten", "grades": "Noten",
"show_exams_homework": "Referate und Hausaufgaben",
"grade_calc": "Noten-Rechner",
}, },
}; };

View File

@ -161,6 +161,11 @@ class GradeGraphState extends State<GradeGraph> {
final x = halfYearGrade.writeDate.month + final x = halfYearGrade.writeDate.month +
(halfYearGrade.writeDate.day / 31) + (halfYearGrade.writeDate.day / 31) +
((halfYearGrade.writeDate.year - data.last.writeDate.year) * 12); ((halfYearGrade.writeDate.year - data.last.writeDate.year) * 12);
List<Grade> dataBeforeMidYr = data
.where((e) => e.writeDate.isBefore(halfYearGrade.writeDate))
.toList();
if (x <= maxX) { if (x <= maxX) {
extraLinesV.add( extraLinesV.add(
VerticalLine( VerticalLine(
@ -170,7 +175,9 @@ class GradeGraphState extends State<GradeGraph> {
label: VerticalLineLabel( label: VerticalLineLabel(
labelResolver: (_) => " ${"mid".i18n} ", // <- zwsp for padding labelResolver: (_) => " ${"mid".i18n} ", // <- zwsp for padding
show: true, show: true,
alignment: Alignment.topLeft, alignment: dataBeforeMidYr.length < 2
? Alignment.topRight
: Alignment.topLeft,
style: TextStyle( style: TextStyle(
backgroundColor: Theme.of(context).colorScheme.background, backgroundColor: Theme.of(context).colorScheme.background,
color: AppColors.of(context).text, color: AppColors.of(context).text,
@ -218,11 +225,12 @@ class GradeGraphState extends State<GradeGraph> {
horizontalLines: extraLinesH), horizontalLines: extraLinesH),
lineBarsData: [ lineBarsData: [
LineChartBarData( LineChartBarData(
preventCurveOverShooting: true, preventCurveOverShooting: false,
spots: subjectSpots, spots: subjectSpots,
isCurved: true, isCurved: true,
colors: averageColors.reversed.toList(), colors: averageColors.reversed.toList(),
barWidth: 8, barWidth: 6,
curveSmoothness: 0.2,
isStrokeCapRound: true, isStrokeCapRound: true,
dotData: FlDotData(show: false), dotData: FlDotData(show: false),
belowBarData: BarAreaData( belowBarData: BarAreaData(
@ -339,11 +347,13 @@ class GradeGraphState extends State<GradeGraph> {
ghostData.isNotEmpty ? ghostData : data; ghostData.isNotEmpty ? ghostData : data;
tData.sort((a, b) => tData.sort((a, b) =>
a.writeDate.compareTo(b.writeDate)); a.writeDate.compareTo(b.writeDate));
return tData.first.writeDate return ghostData.isNotEmpty
.add(const Duration(days: 120)) ? 3.0
.isBefore(tData.last.writeDate) : tData.first.writeDate
? 2.0 .add(const Duration(days: 120))
: 1.0; .isBefore(tData.last.writeDate)
? 2.0
: 2.5;
}(), }(),
checkToShowTitle: (double minValue, checkToShowTitle: (double minValue,
double maxValue, double maxValue,

View File

@ -214,7 +214,7 @@ class HomePageState extends State<HomePage> with TickerProviderStateMixin {
// TODO: REMOVE IN PRODUCTION BUILD!!! // TODO: REMOVE IN PRODUCTION BUILD!!!
// print(_liveCard.currentState); // print(_liveCard.currentState);
_liveCard.currentState = LiveCardState.duringLesson; // _liveCard.currentState = LiveCardState.duringLesson;
return Scaffold( return Scaffold(
body: Stack( body: Stack(

View File

@ -6,17 +6,9 @@ import 'package:refilc/helpers/subject.dart';
import 'package:refilc/models/settings.dart'; import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart'; import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
import 'package:refilc_kreta_api/models/category.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/teacher.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart'; import 'package:refilc_mobile_ui/common/panel/panel.dart';
import 'package:refilc_mobile_ui/common/progress_bar.dart'; import 'package:refilc_mobile_ui/common/progress_bar.dart';
import 'package:refilc_mobile_ui/common/round_border_icon.dart'; import 'package:refilc_mobile_ui/common/round_border_icon.dart';
// import 'package:refilc_kreta_api/models/category.dart';
// import 'package:refilc_kreta_api/models/lesson.dart';
// import 'package:refilc_kreta_api/models/subject.dart';
// import 'package:refilc_kreta_api/models/teacher.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart'; import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
import 'package:refilc_mobile_ui/pages/home/live_card/heads_up_countdown.dart'; import 'package:refilc_mobile_ui/pages/home/live_card/heads_up_countdown.dart';
import 'package:refilc_mobile_ui/pages/home/live_card/segmented_countdown.dart'; import 'package:refilc_mobile_ui/pages/home/live_card/segmented_countdown.dart';
@ -71,19 +63,19 @@ class LiveCardStateA extends State<LiveCard> {
// test // test
// TODO: REMOVE IN PRODUCTION BUILD!!! // TODO: REMOVE IN PRODUCTION BUILD!!!
liveCard.currentState = LiveCardState.duringLesson; /*liveCard.currentState = LiveCardState.duringLesson;
liveCard.currentLesson = Lesson( liveCard.currentLesson = Lesson(
date: DateTime.now().add(Duration( date: DateTime.now().add(const Duration(
minutes: 30, minutes: 30,
)), )),
subject: GradeSubject( subject: GradeSubject(
category: Category(id: 'asd'), id: 'asd', name: 'Matematika'), category: Category(id: 'asd'), id: 'asd', name: 'Matematika'),
lessonIndex: '1', lessonIndex: '1',
teacher: Teacher(id: 'id', name: 'name'), teacher: Teacher(id: 'id', name: 'name'),
start: DateTime.now().subtract(Duration( start: DateTime.now().subtract(const Duration(
minutes: 30, minutes: 30,
)), )),
end: DateTime.now().add(Duration( end: DateTime.now().add(const Duration(
minutes: 15, minutes: 15,
)), )),
homeworkId: 'homeworkId', homeworkId: 'homeworkId',
@ -92,9 +84,9 @@ class LiveCardStateA extends State<LiveCard> {
room: 'ABC69', room: 'ABC69',
groupName: 'groupName', groupName: 'groupName',
name: 'name', name: 'name',
); );*/
liveCard.nextLesson = liveCard.currentLesson; // liveCard.nextLesson = liveCard.currentLesson;
// final dt = DateTime(2024, 3, 22, 17, 12, 1, 1, 1); // final dt = DateTime(2024, 3, 22, 17, 12, 1, 1, 1);

View File

@ -1,5 +1,6 @@
// ignore_for_file: no_leading_underscores_for_local_identifiers, use_build_context_synchronously // ignore_for_file: no_leading_underscores_for_local_identifiers, use_build_context_synchronously
import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -7,6 +8,8 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:refilc/api/providers/database_provider.dart'; import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/self_note_provider.dart'; import 'package:refilc/api/providers/self_note_provider.dart';
import 'package:refilc/api/providers/update_provider.dart'; import 'package:refilc/api/providers/update_provider.dart';
import 'package:refilc/models/self_note.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/utils/format.dart'; import 'package:refilc/utils/format.dart';
import 'package:refilc_kreta_api/models/absence.dart'; import 'package:refilc_kreta_api/models/absence.dart';
import 'package:refilc_kreta_api/models/homework.dart'; import 'package:refilc_kreta_api/models/homework.dart';
@ -14,6 +17,8 @@ import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc/api/providers/user_provider.dart'; import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_kreta_api/providers/homework_provider.dart'; import 'package:refilc_kreta_api/providers/homework_provider.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/empty.dart'; import 'package:refilc_mobile_ui/common/empty.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart'; import 'package:refilc_mobile_ui/common/panel/panel.dart';
import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart'; import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
@ -23,12 +28,14 @@ import 'package:refilc_mobile_ui/common/widgets/tick_tile.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:refilc_mobile_ui/pages/notes/submenu/add_note_screen.dart'; import 'package:refilc_mobile_ui/pages/notes/submenu/add_note_screen.dart';
import 'package:refilc_mobile_ui/pages/notes/submenu/create_image_note.dart';
import 'package:refilc_mobile_ui/pages/notes/submenu/note_view_screen.dart'; import 'package:refilc_mobile_ui/pages/notes/submenu/note_view_screen.dart';
import 'package:refilc_mobile_ui/pages/notes/submenu/self_note_tile.dart'; import 'package:refilc_mobile_ui/pages/notes/submenu/self_note_tile.dart';
import 'package:refilc_plus/models/premium_scopes.dart'; import 'package:refilc_plus/models/premium_scopes.dart';
import 'package:refilc_plus/providers/plus_provider.dart'; import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:refilc_plus/ui/mobile/plus/premium_inline.dart'; import 'package:refilc_plus/ui/mobile/plus/premium_inline.dart';
import 'package:refilc_plus/ui/mobile/plus/upsell.dart'; import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
import 'package:uuid/uuid.dart';
import 'notes_page.i18n.dart'; import 'notes_page.i18n.dart';
enum AbsenceFilter { absences, delays, misses } enum AbsenceFilter { absences, delays, misses }
@ -59,9 +66,14 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
Map<String, bool> doneItems = {}; Map<String, bool> doneItems = {};
List<Widget> noteTiles = []; List<Widget> noteTiles = [];
List<TodoItem> todoItems = [];
final TextEditingController _taskName = TextEditingController();
final TextEditingController _taskContent = TextEditingController();
void generateTiles() async { void generateTiles() async {
doneItems = await databaseProvider.userQuery.toDoItems(userId: user.id!); doneItems = await databaseProvider.userQuery.toDoItems(userId: user.id!);
todoItems = await databaseProvider.userQuery.getTodoItems(userId: user.id!);
List<Widget> tiles = []; List<Widget> tiles = [];
@ -76,7 +88,7 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
List<Widget> toDoTiles = []; List<Widget> toDoTiles = [];
if (hw.isNotEmpty && if (hw.isNotEmpty &&
!Provider.of<PlusProvider>(context, listen: false) Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.unlimitedSelfNotes)) { .hasScope(PremiumScopes.unlimitedSelfNotes)) {
toDoTiles.addAll(hw.map((e) => TickTile( toDoTiles.addAll(hw.map((e) => TickTile(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -96,6 +108,21 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
))); )));
} }
if (selfNoteProvider.todos.isNotEmpty) {
toDoTiles.addAll(selfNoteProvider.todos.map((e) => TickTile(
padding: EdgeInsets.zero,
title: e.title,
description: e.content,
isTicked: e.done,
onTap: (p0) async {
todoItems.firstWhere((element) => element.id == e.id).done = p0;
await databaseProvider.userStore
.storeSelfTodoItems(todoItems, userId: user.id!);
},
)));
}
if (toDoTiles.isNotEmpty) { if (toDoTiles.isNotEmpty) {
tiles.add(const SizedBox( tiles.add(const SizedBox(
height: 10.0, height: 10.0,
@ -114,13 +141,42 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
if (selfNoteProvider.notes.isNotEmpty) { if (selfNoteProvider.notes.isNotEmpty) {
selfNoteTiles.addAll(selfNoteProvider.notes.reversed.map( selfNoteTiles.addAll(selfNoteProvider.notes.reversed.map(
(e) => SelfNoteTile( (e) => e.noteType == NoteType.text
title: e.title ?? e.content.split(' ')[0], ? SelfNoteTile(
content: e.content, title: e.title ?? e.content.split(' ')[0],
onTap: () => Navigator.of(context, rootNavigator: true).push( content: e.content,
CupertinoPageRoute( onTap: () => Navigator.of(context, rootNavigator: true).push(
builder: (context) => NoteViewScreen(note: e))), CupertinoPageRoute(
), builder: (context) => NoteViewScreen(note: e))),
)
: GestureDetector(
onTap: () => Navigator.of(context, rootNavigator: true).push(
CupertinoPageRoute(
builder: (context) => NoteViewScreen(note: e))),
child: Container(
height: MediaQuery.of(context).size.width / 2.42,
width: MediaQuery.of(context).size.width / 2.42,
decoration: BoxDecoration(
boxShadow: [
if (Provider.of<SettingsProvider>(context, listen: false)
.shadowEffect)
BoxShadow(
offset: const Offset(0, 21),
blurRadius: 23.0,
color: Theme.of(context).shadowColor,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Image.memory(
const Base64Decoder().convert(e.content),
fit: BoxFit.cover,
gaplessPlayback: true,
),
),
),
),
)); ));
} }
@ -235,9 +291,7 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
feature: PremiumFeature.selfNotes); feature: PremiumFeature.selfNotes);
} }
Navigator.of(context, rootNavigator: true).push( showCreationModal(context);
CupertinoPageRoute(
builder: (context) => const AddNoteScreen()));
}, },
child: Icon( child: Icon(
FeatherIcons.plus, FeatherIcons.plus,
@ -285,6 +339,8 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
.fetch( .fetch(
from: DateTime.now().subtract(const Duration(days: 30))); from: DateTime.now().subtract(const Duration(days: 30)));
Provider.of<SelfNoteProvider>(context, listen: false).restore(); Provider.of<SelfNoteProvider>(context, listen: false).restore();
Provider.of<SelfNoteProvider>(context, listen: false)
.restoreTodo();
generateTiles(); generateTiles();
@ -312,4 +368,229 @@ class NotesPageState extends State<NotesPage> with TickerProviderStateMixin {
), ),
); );
} }
void showCreationModal(BuildContext context) {
// _sheetController = _scaffoldKey.currentState?.showBottomSheet(
// (context) => RoundedBottomSheet(
// borderRadius: 14.0,
// child: BottomSheetMenu(items: [
// SwitchListTile(
// title: Text('show_lesson_num'.i18n),
// value:
// Provider.of<SettingsProvider>(context).qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// })
// ])),
// backgroundColor: const Color(0x00000000),
// elevation: 12.0,
// );
// _sheetController!.closed.then((value) {
// // Show fab and grades
// if (mounted) {}
// });
showRoundedModalBottomSheet(
context,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: BottomSheetMenu(items: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
title: Row(
children: [
const Icon(Icons.sticky_note_2_outlined),
const SizedBox(
width: 10.0,
),
Text('new_note'.i18n),
],
),
onTap: () => Navigator.of(context, rootNavigator: true).push(
CupertinoPageRoute(
builder: (context) => const AddNoteScreen())),
),
),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
title: Row(
children: [
const Icon(Icons.photo_library_outlined),
const SizedBox(
width: 10.0,
),
Text('new_image'.i18n),
],
),
onTap: () {
showDialog(
context: context,
builder: (context) => ImageNoteEditor(user.user!));
},
),
),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
title: Row(
children: [
const Icon(Icons.task_outlined),
const SizedBox(
width: 10.0,
),
Text('new_task'.i18n),
],
),
onTap: () {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.unlimitedSelfNotes)) {
PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.selfNotes);
return;
}
showTaskCreation(context);
},
),
),
]),
);
}
void showTaskCreation(context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(14.0))),
contentPadding: const EdgeInsets.only(top: 10.0),
title: Text("new_task".i18n),
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _taskName,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.grey, width: 1.5),
borderRadius: BorderRadius.circular(12.0),
),
focusedBorder: OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.grey, width: 1.5),
borderRadius: BorderRadius.circular(12.0),
),
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
hintText: "task_name".i18n,
suffixIcon: IconButton(
icon: const Icon(
FeatherIcons.x,
color: Colors.grey,
),
onPressed: () {
setState(() {
_taskName.text = "";
});
},
),
),
),
const SizedBox(
height: 10.0,
),
TextField(
controller: _taskContent,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.grey, width: 1.5),
borderRadius: BorderRadius.circular(12.0),
),
focusedBorder: OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.grey, width: 1.5),
borderRadius: BorderRadius.circular(12.0),
),
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
hintText: "task_content".i18n,
suffixIcon: IconButton(
icon: const Icon(
FeatherIcons.x,
color: Colors.grey,
),
onPressed: () {
setState(() {
_taskContent.text = "";
});
},
),
),
),
],
),
),
actions: [
TextButton(
child: Text(
"cancel".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).maybePop();
},
),
TextButton(
child: Text(
"next".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () async {
todoItems.add(TodoItem.fromJson({
'id': const Uuid().v4(),
'title': _taskName.text.replaceAll(' ', '') != ""
? _taskName.text
: 'no_title'.i18n,
'content': _taskContent.text,
'done': false,
}));
await databaseProvider.userStore
.storeSelfTodoItems(todoItems, userId: user.id!);
setState(() {
_taskName.text = "";
_taskContent.text = "";
});
Provider.of<SelfNoteProvider>(context, listen: false).restore();
Provider.of<SelfNoteProvider>(context, listen: false)
.restoreTodo();
generateTiles();
Navigator.of(context).pop(true);
},
),
],
),
);
}
} }

View File

@ -13,6 +13,11 @@ extension ScreensLocalization on String {
"hint": "Note content...", "hint": "Note content...",
"hint_t": "Note title...", "hint_t": "Note title...",
"your_notes": "Your Notes", "your_notes": "Your Notes",
"new_image": "New Image",
"no_title": "No title",
"task_content": "Task content...",
"task_name": "Task title...",
"new_task": "New Task",
}, },
"hu_hu": { "hu_hu": {
"notes": "Füzet", "notes": "Füzet",
@ -24,6 +29,11 @@ extension ScreensLocalization on String {
"hint": "Jegyzet tartalma...", "hint": "Jegyzet tartalma...",
"hint_t": "Jegyzet címe...", "hint_t": "Jegyzet címe...",
"your_notes": "Jegyzeteid", "your_notes": "Jegyzeteid",
"new_image": "Új kép",
"no_title": "Nincs cím",
"task_content": "Feladat tartalma...",
"task_name": "Feladat címe...",
"new_task": "Új feladat",
}, },
"de_de": { "de_de": {
"notes": "Broschüre", "notes": "Broschüre",
@ -35,6 +45,11 @@ extension ScreensLocalization on String {
"hint": "Inhalt beachten...", "hint": "Inhalt beachten...",
"hint_t": "Titel notieren...", "hint_t": "Titel notieren...",
"your_notes": "Deine Noten", "your_notes": "Deine Noten",
"new_image": "Neues Bild",
"no_title": "Kein Titel",
"task_content": "Aufgabeninhalt...",
"task_name": "Aufgabentitel...",
"new_task": "Neue Aufgabe",
}, },
}; };

View File

@ -153,7 +153,8 @@ class AddNoteScreenState extends State<AddNoteScreen> {
'title': _titleController.text.replaceAll(' ', '') == '' 'title': _titleController.text.replaceAll(' ', '') == ''
? null ? null
: _titleController.text, : _titleController.text,
'content': _contentController.text 'content': _contentController.text,
'note_type': 'text',
})); }));
} else { } else {
var i = var i =
@ -165,6 +166,7 @@ class AddNoteScreenState extends State<AddNoteScreen> {
? null ? null
: _titleController.text, : _titleController.text,
'content': _contentController.text, 'content': _contentController.text,
'note_type': 'text',
}); });
} }

View File

@ -0,0 +1,215 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_crop/image_crop.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/self_note_provider.dart';
import 'package:refilc/models/self_note.dart';
import 'package:refilc/models/user.dart';
import 'package:uuid/uuid.dart';
import 'notes_screen.i18n.dart';
// ignore: must_be_immutable
class ImageNoteEditor extends StatefulWidget {
late User u;
ImageNoteEditor(this.u, {super.key});
@override
State<ImageNoteEditor> createState() => _ImageNoteEditorState();
}
class _ImageNoteEditorState extends State<ImageNoteEditor> {
final cropKey = GlobalKey<CropState>();
File? _file;
File? _sample;
File? _lastCropped;
File? image;
Future pickImage() async {
try {
final image = await ImagePicker().pickImage(source: ImageSource.gallery);
if (image == null) return;
File imageFile = File(image.path);
final sample = await ImageCrop.sampleImage(
file: imageFile,
preferredSize: context.size!.longestSide.ceil(),
);
_sample?.delete();
_file?.delete();
setState(() {
_sample = sample;
_file = imageFile;
});
} on PlatformException catch (e) {
log('Failed to pick image: $e');
}
}
Widget cropImageWidget() {
return SizedBox(
height: 300,
child: Crop.file(
_sample!,
key: cropKey,
aspectRatio: 1.0,
),
);
}
Widget openImageWidget() {
return InkWell(
customBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14.0),
),
onTap: () => pickImage(),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(14.0),
),
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 32.0, horizontal: 8.0),
child: Column(
children: [
Text(
"click_here".i18n,
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.w600,
),
),
Text(
"select_image".i18n,
style: const TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
),
)
],
),
),
);
}
Future<void> _cropImage() async {
final scale = cropKey.currentState!.scale;
final area = cropKey.currentState!.area;
if (area == null || _file == null) {
return;
}
final sample = await ImageCrop.sampleImage(
file: _file!,
preferredSize: (2000 / scale).round(),
);
final file = await ImageCrop.cropImage(
file: sample,
area: area,
);
sample.delete();
_lastCropped?.delete();
_lastCropped = file;
List<int> imageBytes = await _lastCropped!.readAsBytes();
String base64Image = base64Encode(imageBytes);
List<SelfNote> selfNotes =
await Provider.of<DatabaseProvider>(context, listen: false)
.userQuery
.getSelfNotes(userId: widget.u.id);
selfNotes.add(SelfNote.fromJson({
'id': const Uuid().v4(),
'content': base64Image,
'note_type': 'image'
}));
await Provider.of<DatabaseProvider>(context, listen: false)
.userStore
.storeSelfNotes(selfNotes, userId: widget.u.id);
Provider.of<SelfNoteProvider>(context, listen: false).restore();
Provider.of<SelfNoteProvider>(context, listen: false).restoreTodo();
debugPrint('$file');
}
@override
void dispose() {
super.dispose();
_file?.delete();
_sample?.delete();
_lastCropped?.delete();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(14.0))),
contentPadding: const EdgeInsets.only(top: 10.0),
title: Text("new_image".i18n),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
child: _sample == null ? openImageWidget() : cropImageWidget(),
),
// if (widget.u.picture != "")
// TextButton(
// child: Text(
// "remove_profile_picture".i18n,
// style: const TextStyle(
// fontWeight: FontWeight.w500, color: Colors.red),
// ),
// onPressed: () {
// widget.u.picture = "";
// Provider.of<DatabaseProvider>(context, listen: false)
// .store
// .storeUser(widget.u);
// Provider.of<UserProvider>(context, listen: false).refresh();
// Navigator.of(context).pop(true);
// },
// ),
],
),
actions: [
TextButton(
child: Text(
"cancel".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).maybePop();
},
),
TextButton(
child: Text(
"next".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () async {
await _cropImage();
Navigator.of(context).pop(true);
},
),
],
);
}
}

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:refilc/api/providers/self_note_provider.dart'; import 'package:refilc/api/providers/self_note_provider.dart';
import 'package:refilc/models/self_note.dart'; import 'package:refilc/models/self_note.dart';
@ -8,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:markdown/markdown.dart' as md; import 'package:markdown/markdown.dart' as md;
import 'notes_screen.i18n.dart';
class NoteViewScreen extends StatefulWidget { class NoteViewScreen extends StatefulWidget {
const NoteViewScreen({super.key, required this.note}); const NoteViewScreen({super.key, required this.note});
@ -30,7 +33,9 @@ class NoteViewScreenState extends State<NoteViewScreen> {
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text), leading: BackButton(color: AppColors.of(context).text),
title: Text( title: Text(
widget.note.title ?? '${widget.note.content.split(' ')[0]}...', widget.note.noteType == NoteType.text
? (widget.note.title ?? '${widget.note.content.split(' ')[0]}...')
: 'image_note'.i18n,
style: TextStyle( style: TextStyle(
color: AppColors.of(context).text, color: AppColors.of(context).text,
fontSize: 26.0, fontSize: 26.0,
@ -38,52 +43,55 @@ class NoteViewScreenState extends State<NoteViewScreen> {
), ),
), ),
actions: [ actions: [
ClipRRect( if (widget.note.noteType == NoteType.text)
borderRadius: BorderRadius.circular(10.1), ClipRRect(
child: GestureDetector( borderRadius: BorderRadius.circular(10.1),
onTap: () { child: GestureDetector(
// handle tap onTap: () {
Navigator.of(context, rootNavigator: true).push( // handle tap
CupertinoPageRoute( Navigator.of(context, rootNavigator: true).push(
builder: (context) => CupertinoPageRoute(
AddNoteScreen(initialNote: widget.note))); builder: (context) =>
}, AddNoteScreen(initialNote: widget.note)));
child: Container( },
color: Theme.of(context).colorScheme.secondary.withOpacity(0.2), child: Container(
child: Padding( color:
padding: const EdgeInsets.all(8.0), Theme.of(context).colorScheme.secondary.withOpacity(0.2),
child: Stack( child: Padding(
children: [ padding: const EdgeInsets.all(8.0),
IconTheme( child: Stack(
data: IconThemeData( children: [
color: Theme.of(context).colorScheme.secondary, IconTheme(
data: IconThemeData(
color: Theme.of(context).colorScheme.secondary,
),
child: const Icon(
FeatherIcons.edit,
size: 20.0,
),
), ),
child: const Icon( IconTheme(
FeatherIcons.edit, data: IconThemeData(
size: 20.0, color:
Theme.of(context).brightness == Brightness.light
? Colors.black.withOpacity(.5)
: Colors.white.withOpacity(.3),
),
child: const Icon(
FeatherIcons.edit,
size: 20.0,
),
), ),
), ],
IconTheme( ),
data: IconThemeData(
color:
Theme.of(context).brightness == Brightness.light
? Colors.black.withOpacity(.5)
: Colors.white.withOpacity(.3),
),
child: const Icon(
FeatherIcons.edit,
size: 20.0,
),
),
],
), ),
), ),
), ),
), ),
), if (widget.note.noteType == NoteType.text)
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(10.1), borderRadius: BorderRadius.circular(10.1),
child: GestureDetector( child: GestureDetector(
@ -140,21 +148,30 @@ class NoteViewScreenState extends State<NoteViewScreen> {
child: Column( child: Column(
children: [ children: [
Expanded( Expanded(
child: MarkdownBody( child: widget.note.noteType == NoteType.text
data: widget.note.content, ? MarkdownBody(
extensionSet: md.ExtensionSet( data: widget.note.content,
md.ExtensionSet.gitHubFlavored.blockSyntaxes, extensionSet: md.ExtensionSet(
<md.InlineSyntax>[ md.ExtensionSet.gitHubFlavored.blockSyntaxes,
md.EmojiSyntax(), <md.InlineSyntax>[
...md.ExtensionSet.gitHubFlavored.inlineSyntaxes md.EmojiSyntax(),
], ...md.ExtensionSet.gitHubFlavored.inlineSyntaxes
), ],
styleSheet: MarkdownStyleSheet( ),
p: const TextStyle( styleSheet: MarkdownStyleSheet(
fontSize: 15.0, p: const TextStyle(
), fontSize: 15.0,
), ),
), ),
)
: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.memory(
const Base64Decoder().convert(widget.note.content),
fit: BoxFit.contain,
gaplessPlayback: true,
),
),
), ),
// Expanded( // Expanded(
// child: Text( // child: Text(

View File

@ -268,6 +268,7 @@ class NotesScreenState extends State<NotesScreen> {
Provider.of<HomeworkProvider>(context, listen: false) Provider.of<HomeworkProvider>(context, listen: false)
.fetch(from: DateTime.now().subtract(const Duration(days: 30))); .fetch(from: DateTime.now().subtract(const Duration(days: 30)));
Provider.of<SelfNoteProvider>(context, listen: false).restore(); Provider.of<SelfNoteProvider>(context, listen: false).restore();
Provider.of<SelfNoteProvider>(context, listen: false).restoreTodo();
return Future(() => null); return Future(() => null);
}, },

View File

@ -13,6 +13,12 @@ extension SettingsLocalization on String {
"hint": "Note content...", "hint": "Note content...",
"hint_t": "Note title...", "hint_t": "Note title...",
"your_notes": "Your Notes", "your_notes": "Your Notes",
"next": "Next",
"cancel": "Cancel",
"click_here": "Click here",
"select_image": "to select an image",
"new_image": "New Image",
"image_note": "Image",
}, },
"hu_hu": { "hu_hu": {
"notes": "Füzet", "notes": "Füzet",
@ -24,6 +30,12 @@ extension SettingsLocalization on String {
"hint": "Jegyzet tartalma...", "hint": "Jegyzet tartalma...",
"hint_t": "Jegyzet címe...", "hint_t": "Jegyzet címe...",
"your_notes": "Jegyzeteid", "your_notes": "Jegyzeteid",
"next": "Tovább",
"cancel": "Mégse",
"click_here": "Kattints ide",
"select_image": "kép kiválasztásához",
"new_image": "Új kép",
"image_note": "Kép",
}, },
"de_de": { "de_de": {
"notes": "Broschüre", "notes": "Broschüre",
@ -35,6 +47,12 @@ extension SettingsLocalization on String {
"hint": "Inhalt beachten...", "hint": "Inhalt beachten...",
"hint_t": "Titel notieren...", "hint_t": "Titel notieren...",
"your_notes": "Deine Noten", "your_notes": "Deine Noten",
"next": "Weiter",
"cancel": "Abbrechen",
"click_here": "Klicken Sie hier",
"select_image": "um ein Bild auszuwählen",
"new_image": "Neues Bild",
"image_note": "Bild",
}, },
}; };

View File

@ -12,6 +12,8 @@ import 'package:refilc_kreta_api/providers/timetable_provider.dart';
import 'package:refilc/api/providers/user_provider.dart'; import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_kreta_api/models/lesson.dart'; import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/dot.dart'; import 'package:refilc_mobile_ui/common/dot.dart';
import 'package:refilc_mobile_ui/common/empty.dart'; import 'package:refilc_mobile_ui/common/empty.dart';
import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart'; import 'package:refilc_mobile_ui/common/profile_image/profile_button.dart';
@ -67,6 +69,8 @@ class TimetablePage extends StatefulWidget {
class TimetablePageState extends State<TimetablePage> class TimetablePageState extends State<TimetablePage>
with TickerProviderStateMixin, WidgetsBindingObserver { with TickerProviderStateMixin, WidgetsBindingObserver {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
late UserProvider user; late UserProvider user;
late TimetableProvider timetableProvider; late TimetableProvider timetableProvider;
late UpdateProvider updateProvider; late UpdateProvider updateProvider;
@ -213,6 +217,7 @@ class TimetablePageState extends State<TimetablePage>
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0]; firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
return Scaffold( return Scaffold(
key: _scaffoldKey,
body: Padding( body: Padding(
padding: const EdgeInsets.only(top: 9.0), padding: const EdgeInsets.only(top: 9.0),
child: RefreshIndicator( child: RefreshIndicator(
@ -233,8 +238,53 @@ class TimetablePageState extends State<TimetablePage>
snap: false, snap: false,
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor, surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
actions: [ actions: [
// Padding(
// padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
// child: IconButton(
// splashRadius: 24.0,
// // tested timetable sync
// // onPressed: () async {
// // ThirdPartyProvider tpp =
// // Provider.of<ThirdPartyProvider>(context,
// // listen: false);
// // await tpp.pushTimetable(context, _controller);
// // },
// onPressed: () {
// // If timetable empty, show empty
// if (_tabController.length == 0) {
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
// content: Text("empty_timetable".i18n),
// duration: const Duration(seconds: 2),
// ));
// return;
// }
// Navigator.of(context, rootNavigator: true)
// .push(PageRouteBuilder(
// pageBuilder:
// (context, animation, secondaryAnimation) =>
// FSTimetable(
// controller: _controller,
// ),
// ))
// .then((_) {
// SystemChrome.setPreferredOrientations(
// [DeviceOrientation.portraitUp]);
// setSystemChrome(context);
// });
// },
// icon: Icon(FeatherIcons.trello,
// color: AppColors.of(context).text),
// ),
// ),
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.only(
right: 5.0,
bottom: 8.0,
top: 8.0,
),
child: IconButton( child: IconButton(
splashRadius: 24.0, splashRadius: 24.0,
// tested timetable sync // tested timetable sync
@ -246,30 +296,9 @@ class TimetablePageState extends State<TimetablePage>
// await tpp.pushTimetable(context, _controller); // await tpp.pushTimetable(context, _controller);
// }, // },
onPressed: () { onPressed: () {
// If timetable empty, show empty showQuickSettings(context);
if (_tabController.length == 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("empty_timetable".i18n),
duration: const Duration(seconds: 2),
));
return;
}
Navigator.of(context, rootNavigator: true)
.push(PageRouteBuilder(
pageBuilder:
(context, animation, secondaryAnimation) =>
FSTimetable(
controller: _controller,
),
))
.then((_) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
setSystemChrome(context);
});
}, },
icon: Icon(FeatherIcons.trello, icon: Icon(FeatherIcons.moreHorizontal,
color: AppColors.of(context).text), color: AppColors.of(context).text),
), ),
), ),
@ -685,6 +714,9 @@ class TimetablePageState extends State<TimetablePage>
customLessonDesc[ customLessonDesc[
lesson.id] ?? lesson.id] ??
lesson.description, lesson.description,
showSubTiles:
settingsProvider
.qTimetableSubTiles,
), ),
), ),
), ),
@ -817,6 +849,152 @@ class TimetablePageState extends State<TimetablePage>
), ),
); );
} }
void showQuickSettings(BuildContext context) {
// _sheetController = _scaffoldKey.currentState?.showBottomSheet(
// (context) => RoundedBottomSheet(
// borderRadius: 14.0,
// child: BottomSheetMenu(items: [
// SwitchListTile(
// title: Text('show_lesson_num'.i18n),
// value:
// Provider.of<SettingsProvider>(context).qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// })
// ])),
// backgroundColor: const Color(0x00000000),
// elevation: 12.0,
// );
// _sheetController!.closed.then((value) {
// // Show fab and grades
// if (mounted) {}
// });
showRoundedModalBottomSheet(
context,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: BottomSheetMenu(items: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: ListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(FeatherIcons.trello),
const SizedBox(
width: 10.0,
),
Text('full_screen_timetable'.i18n),
],
),
onTap: () {
if (_tabController.length == 0) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("empty_timetable".i18n),
duration: const Duration(seconds: 2),
));
return;
}
Navigator.of(context, rootNavigator: true).pop();
Navigator.of(context, rootNavigator: true)
.push(PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
FSTimetable(
controller: _controller,
),
))
.then((_) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
setSystemChrome(context);
});
},
),
),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(Icons.local_cafe_rounded),
const SizedBox(
width: 10.0,
),
Text('show_breaks'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.showBreaks,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(showBreaks: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
// SwitchListTile(
// title: Row(
// children: [
// const Icon(FeatherIcons.clock),
// const SizedBox(
// width: 10.0,
// ),
// Text('show_lesson_num'.i18n),
// ],
// ),
// value: Provider.of<SettingsProvider>(context, listen: false)
// .qTimetableLessonNum,
// onChanged: (v) {
// Provider.of<SettingsProvider>(context, listen: false)
// .update(qTimetableLessonNum: v);
// Navigator.of(context, rootNavigator: true).pop();
// },
// ),
const SizedBox(
height: 10.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Theme.of(context).colorScheme.background),
child: SwitchListTile(
contentPadding: const EdgeInsets.only(left: 16.0, right: 10.0),
title: Row(
children: [
const Icon(Icons.edit_document),
const SizedBox(
width: 10.0,
),
Text('show_exams_homework'.i18n),
],
),
value: Provider.of<SettingsProvider>(context, listen: false)
.qTimetableSubTiles,
onChanged: (v) {
Provider.of<SettingsProvider>(context, listen: false)
.update(qTimetableSubTiles: v);
Navigator.of(context, rootNavigator: true).pop();
},
),
),
]),
);
}
} }
// difference.inDays is not reliable // difference.inDays is not reliable

View File

@ -10,6 +10,9 @@ extension Localization on String {
"error": "Failed to fetch timetable!", "error": "Failed to fetch timetable!",
"empty_timetable": "Timetable is empty!", "empty_timetable": "Timetable is empty!",
"break": "Break", "break": "Break",
"full_screen_timetable": "Full Screen Timetable",
"show_breaks": "Show Breaks",
"show_exams_homework": "Exams and Homework",
}, },
"hu_hu": { "hu_hu": {
"timetable": "Órarend", "timetable": "Órarend",
@ -18,6 +21,9 @@ extension Localization on String {
"error": "Nem sikerült lekérni az órarendet!", "error": "Nem sikerült lekérni az órarendet!",
"empty_timetable": "Az órarend üres!", "empty_timetable": "Az órarend üres!",
"break": "Szünet", "break": "Szünet",
"full_screen_timetable": "Teljes képernyős órarend",
"show_breaks": "Szünetek megjelenítése",
"show_exams_homework": "Dolgozatok és házik",
}, },
"de_de": { "de_de": {
"timetable": "Zeitplan", "timetable": "Zeitplan",
@ -26,6 +32,9 @@ extension Localization on String {
"error": "Der Fahrplan konnte nicht abgerufen werden!", "error": "Der Fahrplan konnte nicht abgerufen werden!",
"empty_timetable": "Der Zeitplan ist blank!", "empty_timetable": "Der Zeitplan ist blank!",
"break": "Pause", "break": "Pause",
"full_screen_timetable": "Vollbildfahrplan",
"show_breaks": "Pausen anzeigen",
"show_exams_homework": "Referate und Hausaufgaben",
}, },
}; };

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc_plus/providers/plus_provider.dart'; import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:refilc_plus/ui/mobile/plus/activation_view/activation_view.dart'; import 'package:refilc_plus/ui/mobile/plus/activation_view/activation_view.dart';
import 'package:refilc_mobile_ui/plus/plus_screen.i18n.dart'; import 'package:refilc_mobile_ui/plus/plus_screen.i18n.dart';
@ -50,6 +51,19 @@ class PlusPlanCard extends StatelessWidget {
return; return;
} }
if (Provider.of<SettingsProvider>(context).xFilcId == "none") {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
"Be kell kapcsolnod a Névtelen Analitikát a beállítások főoldalán, mielőtt reFilc+ előfizetést vásárolnál!",
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
));
return;
}
if (Provider.of<PlusProvider>(context, listen: false).hasPremium) { if (Provider.of<PlusProvider>(context, listen: false).hasPremium) {
if (!active) { if (!active) {
launchUrl( launchUrl(

View File

@ -3,10 +3,8 @@
import 'package:refilc/api/client.dart'; import 'package:refilc/api/client.dart';
import 'package:refilc/api/login.dart'; import 'package:refilc/api/login.dart';
import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/custom_snack_bar.dart'; import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
import 'package:refilc_mobile_ui/common/system_chrome.dart'; import 'package:refilc_mobile_ui/common/system_chrome.dart';
import 'package:refilc_mobile_ui/common/widgets/absence/absence_display.dart';
import 'package:refilc_mobile_ui/screens/login/login_button.dart'; import 'package:refilc_mobile_ui/screens/login/login_button.dart';
import 'package:refilc_mobile_ui/screens/login/login_input.dart'; import 'package:refilc_mobile_ui/screens/login/login_input.dart';
import 'package:refilc_mobile_ui/screens/login/school_input/school_input.dart'; import 'package:refilc_mobile_ui/screens/login/school_input/school_input.dart';
@ -14,8 +12,6 @@ import 'package:refilc_mobile_ui/screens/settings/privacy_view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'login_screen.i18n.dart'; import 'login_screen.i18n.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter_svg/flutter_svg.dart';
class LoginScreen extends StatefulWidget { class LoginScreen extends StatefulWidget {
const LoginScreen({super.key, this.back = false}); const LoginScreen({super.key, this.back = false});
@ -79,450 +75,223 @@ class LoginScreenState extends State<LoginScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
precacheImage(const AssetImage('assets/images/showcase1.png'), context);
precacheImage(const AssetImage('assets/images/showcase2.png'), context);
precacheImage(const AssetImage('assets/images/showcase3.png'), context);
precacheImage(const AssetImage('assets/images/showcase4.png'), context);
bool selected = false;
return Scaffold( return Scaffold(
body: Container( body: Container(
decoration: const BoxDecoration(color: Color(0xFFDAE4F7)), decoration: BoxDecoration(color: AppColors.of(context).loginBackground),
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
controller: _scrollController, controller: _scrollController,
child: Container( child: Container(
decoration: const BoxDecoration(color: Color(0xFFDAE4F7)), decoration:
BoxDecoration(color: AppColors.of(context).loginBackground),
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
child: SafeArea( child: SafeArea(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// app icon Container(
Padding( alignment: Alignment.topLeft,
padding: const EdgeInsets.only(left: 24, top: 20), padding: const EdgeInsets.only(left: 16.0, top: 12.0),
child: Row( child: ClipOval(
children: [ child: Material(
Image.asset( type: MaterialType.transparency,
'assets/icons/ic_rounded.png', child: showBack
width: 30.0, ? BackButton(
), color: AppColors.of(context).loginPrimary)
const SizedBox(width: 8), : const SizedBox(height: 48.0),
const Text(
'reFilc',
style: TextStyle(
color: Color(0xFF050B15),
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat'),
),
Material(
type: MaterialType.transparency,
child: showBack
? BackButton(color: AppColors.of(context).text)
: const SizedBox(height: 48.0),
),
],
)),
Stack(
alignment: Alignment.bottomCenter,
children: [
Column(
//login buttons and ui starts here
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const SizedBox(height: 21),
CarouselSlider(
options: CarouselOptions(
height: MediaQuery.of(context).size.height,
viewportFraction: 1,
autoPlay: true,
autoPlayInterval: const Duration(seconds: 6),
pauseAutoPlayOnTouch: true),
items: [1, 2, 3, 4].map((i) {
return Builder(
builder: (BuildContext context) {
return Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsets.only(left: 24),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Text(
"welcome_title_$i".i18n,
style: const TextStyle(
color: Color(0xFF050B15),
fontSize: 19,
fontFamily: 'Montserrat',
fontWeight: FontWeight.w700,
height: 1.3),
),
const SizedBox(
height: 14.375), //meth
Padding(
padding: const EdgeInsets.only(
right: 20),
child: Text(
"welcome_text_$i".i18n,
style: const TextStyle(
color: Color(0xFF050B15),
fontFamily: 'FigTree',
fontWeight:
FontWeight.w500,
fontSize: 17,
height: 1.3),
),
),
],
)),
const SizedBox(height: 15.625),
Padding(
padding: const EdgeInsets.only(
left: 16, right: 16),
child: Image.asset(
'assets/images/showcase$i.png'))
],
);
},
);
}).toList(),
),
],
), ),
Container( ),
height: 300,
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0x00DAE4F7), Color(0xFFDAE4F7)],
stops: [0, 0.12],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Padding(
padding: EdgeInsets.only(top: 50, bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
children: [
SizedBox(
height: 48,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16),
child: FilledButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12)),
))),
onPressed: () {
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (BuildContext context) {
return Container(
height: MediaQuery.of(context)
.size
.height *
0.5 + MediaQuery.of(context).viewInsets.bottom,
decoration: const BoxDecoration(
color: Color(0xFFDAE4F7),
borderRadius: BorderRadius.only(
topRight:
Radius.circular(24.0),
topLeft:
Radius.circular(24.0),
),
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsets.only(
top: 18),
child: Container(
decoration:
const BoxDecoration(
color:
Color(0xFFB9C8E5),
borderRadius:
BorderRadius.only(
topRight:
Radius.circular(
2.0),
topLeft:
Radius.circular(
2.0),
),
),
width: 40,
height: 4,
),
),
Container(
width: double.infinity,
child: AutofillGroup(
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.end,
children: [
// username
Padding(
padding:
const EdgeInsets
.only(
bottom:
6.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
child: Text(
"username"
.i18n,
maxLines:
1,
style:
TextStyle(
color: AppColors.of(context)
.loginPrimary,
fontWeight:
FontWeight.w500,
fontSize:
12.0,
),
),
),
Expanded(
child: Text(
"usernameHint"
.i18n,
maxLines:
1,
textAlign:
TextAlign
.right,
style:
TextStyle(
color: AppColors.of(context)
.loginSecondary,
fontWeight:
FontWeight.w500,
fontSize:
12.0,
),
),
),
],
),
),
Padding(
padding:
const EdgeInsets
.only(
bottom:
12.0),
child: LoginInput(
style:
LoginInputStyle
.username,
controller:
usernameController,
),
),
// password
Padding(
padding:
const EdgeInsets
.only(
bottom:
6.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Expanded(
child: Text(
"password"
.i18n,
maxLines:
1,
style:
TextStyle(
color: AppColors.of(context)
.loginPrimary,
fontWeight:
FontWeight.w500,
fontSize:
12.0,
),
),
),
Expanded(
child: Text(
"passwordHint"
.i18n,
maxLines:
1,
textAlign:
TextAlign
.right,
style:
TextStyle(
color: AppColors.of(context)
.loginSecondary,
fontWeight:
FontWeight.w500,
fontSize:
12.0,
),
),
),
],
),
),
Padding(
padding:
const EdgeInsets
.only(
bottom:
12.0),
child: LoginInput(
style:
LoginInputStyle
.password,
controller:
passwordController,
),
),
// school
Padding(
padding:
const EdgeInsets
.only(
bottom:
6.0),
child: Text(
"school".i18n,
maxLines: 1,
style:
TextStyle(
color: AppColors.of(
context)
.loginPrimary,
fontWeight:
FontWeight
.w500,
fontSize:
12.0,
),
),
),
SchoolInput(
scroll:
_scrollController,
controller:
schoolController,
),
],
),
),
),
const Padding(
padding: EdgeInsets.only(
left: 22.0,
right: 22.0,
top: 0.0,
),
),
Padding(
padding:
const EdgeInsets.only(
top: 35.0,
left: 22.0,
right: 22.0,
),
child: Visibility(
visible: _loginState !=
LoginState
.inProgress,
replacement:
const Padding(
padding: EdgeInsets
.symmetric(
vertical:
6.0),
child:
CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<
Color>(
Colors
.white),
),
),
child: LoginButton(
child: Text(
"login".i18n,
maxLines: 1,
style:
const TextStyle(
fontWeight:
FontWeight
.bold,
fontSize: 20.0,
)),
onPressed: () =>
_loginAPI(
context:
context),
),
),
),
]),
);
},
);
},
child: Text(
"login".i18n,
style: const TextStyle(
fontFamily: 'Montserrat',
fontSize: 20,
fontWeight: FontWeight.w700),
)),
),
),
const SizedBox(height: 8),
],
),
),
),
],
), ),
// app icon
Padding(
padding: EdgeInsets.zero,
child: Image.asset(
'assets/icons/ic_rounded.png',
width: 50.0,
),
),
// texts
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 12.0,
),
child: Text(
'reFilc',
style: TextStyle(
color: AppColors.of(context).loginPrimary,
fontSize: 28.0,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
),
child: Text(
'login_w_kreten'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
color: AppColors.of(context).loginPrimary,
fontSize: 18.0,
fontWeight: FontWeight.w500,
height: 1.2,
),
),
),
const Spacer(
flex: 2,
),
// inputs
Padding(
padding: const EdgeInsets.only(
left: 22.0,
right: 22.0,
top: 0.0,
),
child: AutofillGroup(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// username
Padding(
padding: const EdgeInsets.only(bottom: 6.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
"username".i18n,
maxLines: 1,
style: TextStyle(
color: AppColors.of(context).loginPrimary,
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
),
),
Expanded(
child: Text(
"usernameHint".i18n,
maxLines: 1,
textAlign: TextAlign.right,
style: TextStyle(
color:
AppColors.of(context).loginSecondary,
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: LoginInput(
style: LoginInputStyle.username,
controller: usernameController,
),
),
// password
Padding(
padding: const EdgeInsets.only(bottom: 6.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
"password".i18n,
maxLines: 1,
style: TextStyle(
color: AppColors.of(context).loginPrimary,
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
),
),
Expanded(
child: Text(
"passwordHint".i18n,
maxLines: 1,
textAlign: TextAlign.right,
style: TextStyle(
color:
AppColors.of(context).loginSecondary,
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: LoginInput(
style: LoginInputStyle.password,
controller: passwordController,
),
),
// school
Padding(
padding: const EdgeInsets.only(bottom: 6.0),
child: Text(
"school".i18n,
maxLines: 1,
style: TextStyle(
color: AppColors.of(context).loginPrimary,
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
),
),
SchoolInput(
scroll: _scrollController,
controller: schoolController,
),
],
),
),
),
// login button
Padding(
padding: const EdgeInsets.only(
top: 35.0,
left: 22.0,
right: 22.0,
),
child: Visibility(
visible: _loginState != LoginState.inProgress,
replacement: const Padding(
padding: EdgeInsets.symmetric(vertical: 6.0),
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation<Color>(Colors.white),
),
),
child: LoginButton(
child: Text("login".i18n,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
)),
onPressed: () => _loginAPI(context: context),
),
),
),
// error messages
if (_loginState == LoginState.missingFields || if (_loginState == LoginState.missingFields ||
_loginState == LoginState.invalidGrant || _loginState == LoginState.invalidGrant ||
_loginState == LoginState.failed) _loginState == LoginState.failed)
@ -543,6 +312,8 @@ class LoginScreenState extends State<LoginScreen> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
const SizedBox(height: 22.0),
// privacy policy // privacy policy
GestureDetector( GestureDetector(
onTap: () => PrivacyView.show(context), onTap: () => PrivacyView.show(context),
@ -555,6 +326,10 @@ class LoginScreenState extends State<LoginScreen> {
), ),
), ),
), ),
const Spacer(
flex: 1,
),
], ],
), ),
), ),

View File

@ -0,0 +1,618 @@
// // import 'dart:async';
// import 'package:refilc/api/client.dart';
// import 'package:refilc/api/login.dart';
// import 'package:refilc/theme/colors/colors.dart';
// import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
// import 'package:refilc_mobile_ui/common/custom_snack_bar.dart';
// import 'package:refilc_mobile_ui/common/system_chrome.dart';
// import 'package:refilc_mobile_ui/common/widgets/absence/absence_display.dart';
// import 'package:refilc_mobile_ui/screens/login/login_button.dart';
// import 'package:refilc_mobile_ui/screens/login/login_input.dart';
// import 'package:refilc_mobile_ui/screens/login/school_input/school_input.dart';
// import 'package:refilc_mobile_ui/screens/settings/privacy_view.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'login_screen.i18n.dart';
// import 'package:carousel_slider/carousel_slider.dart';
// import 'package:flutter_svg/flutter_svg.dart';
// class LoginScreen extends StatefulWidget {
// const LoginScreen({super.key, this.back = false});
// final bool back;
// @override
// LoginScreenState createState() => LoginScreenState();
// }
// class LoginScreenState extends State<LoginScreen> {
// final usernameController = TextEditingController();
// final passwordController = TextEditingController();
// final schoolController = SchoolInputController();
// final _scrollController = ScrollController();
// LoginState _loginState = LoginState.normal;
// bool showBack = false;
// // Scaffold Gradient background
// // final LinearGradient _backgroundGradient = const LinearGradient(
// // colors: [
// // Color.fromARGB(255, 61, 122, 244),
// // Color.fromARGB(255, 23, 77, 185),
// // Color.fromARGB(255, 7, 42, 112),
// // ],
// // begin: Alignment(-0.8, -1.0),
// // end: Alignment(0.8, 1.0),
// // stops: [-1.0, 0.0, 1.0],
// // );
// late String tempUsername = '';
// @override
// void initState() {
// super.initState();
// showBack = widget.back;
// SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
// statusBarColor: Colors.transparent,
// statusBarIconBrightness: Brightness.light,
// systemNavigationBarColor: Colors.white,
// systemNavigationBarIconBrightness: Brightness.dark,
// ));
// FilcAPI.getSchools().then((schools) {
// if (schools != null) {
// schoolController.update(() {
// schoolController.schools = schools;
// });
// } else {
// ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
// content: Text("schools_error".i18n,
// style: const TextStyle(color: Colors.white)),
// backgroundColor: AppColors.of(context).red,
// context: context,
// ));
// }
// });
// }
// @override
// Widget build(BuildContext context) {
// precacheImage(const AssetImage('assets/images/showcase1.png'), context);
// precacheImage(const AssetImage('assets/images/showcase2.png'), context);
// precacheImage(const AssetImage('assets/images/showcase3.png'), context);
// precacheImage(const AssetImage('assets/images/showcase4.png'), context);
// bool selected = false;
// return Scaffold(
// body: Container(
// decoration: const BoxDecoration(color: Color(0xFFDAE4F7)),
// child: SingleChildScrollView(
// physics: const ClampingScrollPhysics(),
// controller: _scrollController,
// child: Container(
// decoration: const BoxDecoration(color: Color(0xFFDAE4F7)),
// width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height,
// child: SafeArea(
// child: Column(
// children: [
// // app icon
// Padding(
// padding: const EdgeInsets.only(left: 24, top: 20),
// child: Row(
// children: [
// Image.asset(
// 'assets/icons/ic_rounded.png',
// width: 30.0,
// ),
// const SizedBox(width: 8),
// const Text(
// 'reFilc',
// style: TextStyle(
// color: Color(0xFF050B15),
// fontSize: 18.0,
// fontWeight: FontWeight.bold,
// fontFamily: 'Montserrat'),
// ),
// Material(
// type: MaterialType.transparency,
// child: showBack
// ? BackButton(color: AppColors.of(context).text)
// : const SizedBox(height: 48.0),
// ),
// ],
// )),
// Stack(
// alignment: Alignment.bottomCenter,
// children: [
// Column(
// //login buttons and ui starts here
// mainAxisAlignment: MainAxisAlignment.end,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// const SizedBox(height: 21),
// CarouselSlider(
// options: CarouselOptions(
// height: MediaQuery.of(context).size.height,
// viewportFraction: 1,
// autoPlay: true,
// autoPlayInterval: const Duration(seconds: 6),
// pauseAutoPlayOnTouch: true),
// items: [1, 2, 3, 4].map((i) {
// return Builder(
// builder: (BuildContext context) {
// return Column(
// crossAxisAlignment:
// CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Padding(
// padding:
// const EdgeInsets.only(left: 24),
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment.start,
// mainAxisAlignment:
// MainAxisAlignment.start,
// children: [
// Text(
// "welcome_title_$i".i18n,
// style: const TextStyle(
// color: Color(0xFF050B15),
// fontSize: 19,
// fontFamily: 'Montserrat',
// fontWeight: FontWeight.w700,
// height: 1.3),
// ),
// const SizedBox(
// height: 14.375), //meth
// Padding(
// padding: const EdgeInsets.only(
// right: 20),
// child: Text(
// "welcome_text_$i".i18n,
// style: const TextStyle(
// color: Color(0xFF050B15),
// fontFamily: 'FigTree',
// fontWeight:
// FontWeight.w500,
// fontSize: 17,
// height: 1.3),
// ),
// ),
// ],
// )),
// const SizedBox(height: 15.625),
// Padding(
// padding: const EdgeInsets.only(
// left: 16, right: 16),
// child: Image.asset(
// 'assets/images/showcase$i.png'))
// ],
// );
// },
// );
// }).toList(),
// ),
// ],
// ),
// Container(
// height: 300,
// width: double.infinity,
// decoration: const BoxDecoration(
// gradient: LinearGradient(
// colors: [Color(0x00DAE4F7), Color(0xFFDAE4F7)],
// stops: [0, 0.12],
// begin: Alignment.topCenter,
// end: Alignment.bottomCenter,
// ),
// ),
// child: Padding(
// padding: EdgeInsets.only(top: 50, bottom: MediaQuery.of(context).viewInsets.bottom),
// child: Column(
// children: [
// SizedBox(
// height: 48,
// width: double.infinity,
// child: Padding(
// padding: const EdgeInsets.symmetric(
// horizontal: 16),
// child: FilledButton(
// style: ButtonStyle(
// shape: MaterialStateProperty.all<
// RoundedRectangleBorder>(
// const RoundedRectangleBorder(
// borderRadius: BorderRadius.all(
// Radius.circular(12)),
// ))),
// onPressed: () {
// showModalBottomSheet(
// backgroundColor: Colors.transparent,
// context: context,
// builder: (BuildContext context) {
// return Container(
// height: MediaQuery.of(context)
// .size
// .height *
// 0.5 + MediaQuery.of(context).viewInsets.bottom,
// decoration: const BoxDecoration(
// color: Color(0xFFDAE4F7),
// borderRadius: BorderRadius.only(
// topRight:
// Radius.circular(24.0),
// topLeft:
// Radius.circular(24.0),
// ),
// ),
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment.center,
// mainAxisAlignment:
// MainAxisAlignment.start,
// children: [
// Padding(
// padding:
// const EdgeInsets.only(
// top: 18),
// child: Container(
// decoration:
// const BoxDecoration(
// color:
// Color(0xFFB9C8E5),
// borderRadius:
// BorderRadius.only(
// topRight:
// Radius.circular(
// 2.0),
// topLeft:
// Radius.circular(
// 2.0),
// ),
// ),
// width: 40,
// height: 4,
// ),
// ),
// Container(
// width: double.infinity,
// child: AutofillGroup(
// child: Column(
// crossAxisAlignment:
// CrossAxisAlignment
// .end,
// children: [
// // username
// Padding(
// padding:
// const EdgeInsets
// .only(
// bottom:
// 6.0),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment
// .spaceBetween,
// children: [
// Expanded(
// child: Text(
// "username"
// .i18n,
// maxLines:
// 1,
// style:
// TextStyle(
// color: AppColors.of(context)
// .loginPrimary,
// fontWeight:
// FontWeight.w500,
// fontSize:
// 12.0,
// ),
// ),
// ),
// Expanded(
// child: Text(
// "usernameHint"
// .i18n,
// maxLines:
// 1,
// textAlign:
// TextAlign
// .right,
// style:
// TextStyle(
// color: AppColors.of(context)
// .loginSecondary,
// fontWeight:
// FontWeight.w500,
// fontSize:
// 12.0,
// ),
// ),
// ),
// ],
// ),
// ),
// Padding(
// padding:
// const EdgeInsets
// .only(
// bottom:
// 12.0),
// child: LoginInput(
// style:
// LoginInputStyle
// .username,
// controller:
// usernameController,
// ),
// ),
// // password
// Padding(
// padding:
// const EdgeInsets
// .only(
// bottom:
// 6.0),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment
// .spaceBetween,
// children: [
// Expanded(
// child: Text(
// "password"
// .i18n,
// maxLines:
// 1,
// style:
// TextStyle(
// color: AppColors.of(context)
// .loginPrimary,
// fontWeight:
// FontWeight.w500,
// fontSize:
// 12.0,
// ),
// ),
// ),
// Expanded(
// child: Text(
// "passwordHint"
// .i18n,
// maxLines:
// 1,
// textAlign:
// TextAlign
// .right,
// style:
// TextStyle(
// color: AppColors.of(context)
// .loginSecondary,
// fontWeight:
// FontWeight.w500,
// fontSize:
// 12.0,
// ),
// ),
// ),
// ],
// ),
// ),
// Padding(
// padding:
// const EdgeInsets
// .only(
// bottom:
// 12.0),
// child: LoginInput(
// style:
// LoginInputStyle
// .password,
// controller:
// passwordController,
// ),
// ),
// // school
// Padding(
// padding:
// const EdgeInsets
// .only(
// bottom:
// 6.0),
// child: Text(
// "school".i18n,
// maxLines: 1,
// style:
// TextStyle(
// color: AppColors.of(
// context)
// .loginPrimary,
// fontWeight:
// FontWeight
// .w500,
// fontSize:
// 12.0,
// ),
// ),
// ),
// SchoolInput(
// scroll:
// _scrollController,
// controller:
// schoolController,
// ),
// ],
// ),
// ),
// ),
// const Padding(
// padding: EdgeInsets.only(
// left: 22.0,
// right: 22.0,
// top: 0.0,
// ),
// ),
// Padding(
// padding:
// const EdgeInsets.only(
// top: 35.0,
// left: 22.0,
// right: 22.0,
// ),
// child: Visibility(
// visible: _loginState !=
// LoginState
// .inProgress,
// replacement:
// const Padding(
// padding: EdgeInsets
// .symmetric(
// vertical:
// 6.0),
// child:
// CircularProgressIndicator(
// valueColor:
// AlwaysStoppedAnimation<
// Color>(
// Colors
// .white),
// ),
// ),
// child: LoginButton(
// child: Text(
// "login".i18n,
// maxLines: 1,
// style:
// const TextStyle(
// fontWeight:
// FontWeight
// .bold,
// fontSize: 20.0,
// )),
// onPressed: () =>
// _loginAPI(
// context:
// context),
// ),
// ),
// ),
// ]),
// );
// },
// );
// },
// child: Text(
// "login".i18n,
// style: const TextStyle(
// fontFamily: 'Montserrat',
// fontSize: 20,
// fontWeight: FontWeight.w700),
// )),
// ),
// ),
// const SizedBox(height: 8),
// ],
// ),
// ),
// ),
// ],
// ),
// if (_loginState == LoginState.missingFields ||
// _loginState == LoginState.invalidGrant ||
// _loginState == LoginState.failed)
// Padding(
// padding: const EdgeInsets.only(
// top: 8.0, left: 12.0, right: 12.0),
// child: Text(
// [
// "missing_fields",
// "invalid_grant",
// "error"
// ][_loginState.index]
// .i18n,
// style: const TextStyle(
// color: Colors.red,
// fontWeight: FontWeight.w500,
// ),
// textAlign: TextAlign.center,
// ),
// ),
// // privacy policy
// GestureDetector(
// onTap: () => PrivacyView.show(context),
// child: Text(
// 'privacy'.i18n,
// style: TextStyle(
// color: AppColors.of(context).loginSecondary,
// fontWeight: FontWeight.w500,
// fontSize: 14.0,
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
// );
// }
// void _loginAPI({required BuildContext context}) {
// String username = usernameController.text;
// String password = passwordController.text;
// tempUsername = username;
// if (username == "" ||
// password == "" ||
// schoolController.selectedSchool == null) {
// return setState(() => _loginState = LoginState.missingFields);
// }
// // ignore: no_leading_underscores_for_local_identifiers
// void _callAPI() {
// loginAPI(
// username: username,
// password: password,
// instituteCode: schoolController.selectedSchool!.instituteCode,
// context: context,
// onLogin: (user) {
// ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
// context: context,
// brightness: Brightness.light,
// content: Text("welcome".i18n.fill([user.name]),
// overflow: TextOverflow.ellipsis),
// ));
// },
// onSuccess: () {
// ScaffoldMessenger.of(context).hideCurrentSnackBar();
// setSystemChrome(context);
// Navigator.of(context).pushReplacementNamed("login_to_navigation");
// }).then(
// (res) => setState(() {
// // if (res == LoginState.invalidGrant &&
// // tempUsername.replaceAll(username, '').length <= 3) {
// // tempUsername = username + ' ';
// // Timer(
// // const Duration(milliseconds: 500),
// // () => _loginAPI(context: context),
// // );
// // // _loginAPI(context: context);
// // } else {
// _loginState = res;
// // }
// }),
// );
// }
// setState(() => _loginState = LoginState.inProgress);
// _callAPI();
// }
// }

View File

@ -751,7 +751,7 @@ class _BellDelaySettingState extends State<BellDelaySetting>
Provider.of<SettingsProvider>(context, listen: false) Provider.of<SettingsProvider>(context, listen: false)
.update(bellDelay: currentDelay.inSeconds); .update(bellDelay: currentDelay.inSeconds);
_tabController.index = currentDelay.inSeconds > 0 ? 1 : 0; _tabController.index = currentDelay.inSeconds > 0 ? 1 : 0;
if(Platform.isIOS){ if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true; LiveCardProvider.hasActivitySettingsChanged = true;
} }
setState(() {}); setState(() {});
@ -764,7 +764,7 @@ class _BellDelaySettingState extends State<BellDelaySetting>
//Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt()); //Provider.of<SettingsProvider>(context, listen: false).update(context, rounding: (r * 10).toInt());
Provider.of<SettingsProvider>(context, listen: false) Provider.of<SettingsProvider>(context, listen: false)
.update(bellDelay: currentDelay.inSeconds); .update(bellDelay: currentDelay.inSeconds);
if(Platform.isIOS){ if (Platform.isIOS) {
LiveCardProvider.hasActivitySettingsChanged = true; LiveCardProvider.hasActivitySettingsChanged = true;
} }
Navigator.of(context).maybePop(); Navigator.of(context).maybePop();

@ -1 +1 @@
Subproject commit 574d3ab0aca1bb68d21607c2b9df1046aa46fc55 Subproject commit 1f5cca7b8e2ac896155a6c494e79fb057628379e