fixed lot of ui things

This commit is contained in:
Kima
2023-07-31 23:20:30 +02:00
parent d79045e47f
commit 5523a2a919
22 changed files with 1812 additions and 750 deletions

View File

@@ -1,7 +1,7 @@
import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/ui/date_widget.dart';
import 'package:filcnaplo_desktop_ui/common/filter_bar.dart';
import 'package:filcnaplo_mobile_ui/common/filter_bar.dart';
import 'package:flutter/material.dart';
import 'package:animated_list_plus/animated_list_plus.dart';
import 'package:provider/provider.dart';
@@ -16,7 +16,8 @@ class HomePage extends StatefulWidget {
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late UserProvider user;
late SettingsProvider settings;
@@ -41,11 +42,15 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
user = Provider.of<UserProvider>(context, listen: false);
DateTime now = DateTime.now();
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) && now.isAfter(DateTime(now.year, DateTime.june, 14))) {
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
greeting = "goodrest";
} else if (now.month == user.student?.birth.month && now.day == user.student?.birth.day) {
} else if (now.month == user.student?.birth.month &&
now.day == user.student?.birth.day) {
greeting = "happybirthday";
} else if (now.month == DateTime.december && now.day >= 24 && now.day <= 26) {
} else if (now.month == DateTime.december &&
now.day >= 24 &&
now.day <= 26) {
greeting = "merryxmas";
} else if (now.month == DateTime.january && now.day == 1) {
greeting = "happynewyear";
@@ -81,7 +86,8 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
children: [
// Greeting
Padding(
padding: const EdgeInsets.only(left: 32.0, top: 24.0, bottom: 12.0),
padding: const EdgeInsets.only(
left: 32.0, top: 24.0, bottom: 12.0),
child: Text(
greeting.i18n.fill([firstName]),
overflow: TextOverflow.fade,
@@ -107,8 +113,10 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
int selectedPage = _pageController.page!.round();
if (i == selectedPage) return;
if (_pageController.page?.roundToDouble() != _pageController.page) {
_pageController.animateToPage(i, curve: Curves.easeIn, duration: kTabScrollDuration);
if (_pageController.page?.roundToDouble() !=
_pageController.page) {
_pageController.animateToPage(i,
curve: Curves.easeIn, duration: kTabScrollDuration);
return;
}
@@ -132,27 +140,34 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
(BuildContext context, int index) {
return FutureBuilder<List<DateWidget>>(
key: ValueKey<String>(listOrder[index]),
future: getFilterWidgets(homeFilters[index], context: context),
builder: (context, dateWidgets) => dateWidgets.data != null
future: getFilterWidgets(homeFilters[index],
context: context),
builder: (context, dateWidgets) => dateWidgets.data !=
null
? ImplicitlyAnimatedList<Widget>(
items: sortDateWidgets(context, dateWidgets: dateWidgets.data!),
items: sortDateWidgets(context,
dateWidgets: dateWidgets.data!),
itemBuilder: filterItemBuilder,
spawnIsolate: false,
areItemsTheSame: (a, b) => a.key == b.key,
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
padding: const EdgeInsets.symmetric(horizontal: 24.0),
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
padding: const EdgeInsets.symmetric(
horizontal: 24.0),
)
: Container(),
);
},
childCount: 4,
findChildIndexCallback: (Key key) {
final ValueKey<String> valueKey = key as ValueKey<String>;
final ValueKey<String> valueKey =
key as ValueKey<String>;
final String data = valueKey.value;
return listOrder.indexOf(data);
},
),
physics: const PageScrollPhysics().applyTo(const BouncingScrollPhysics()),
physics: const PageScrollPhysics()
.applyTo(const BouncingScrollPhysics()),
),
),
],

View File

@@ -23,12 +23,14 @@ import 'timetable_page.i18n.dart';
// todo: "fix" overflow (priority: -1)
class TimetablePage extends StatefulWidget {
const TimetablePage({Key? key, this.initialDay, this.initialWeek}) : super(key: key);
const TimetablePage({Key? key, this.initialDay, this.initialWeek})
: super(key: key);
final DateTime? initialDay;
final Week? initialWeek;
static void jump(BuildContext context, {Week? week, DateTime? day, Lesson? lesson}) {
static void jump(BuildContext context,
{Week? week, DateTime? day, Lesson? lesson}) {
// Go to timetable page with arguments
// NavigationScreen.of(context)?.customRoute(navigationPageRoute((context) => TimetablePage(
// initialDay: lesson?.date ?? day,
@@ -49,7 +51,8 @@ class TimetablePage extends StatefulWidget {
_TimetablePageState createState() => _TimetablePageState();
}
class _TimetablePageState extends State<TimetablePage> with TickerProviderStateMixin {
class _TimetablePageState extends State<TimetablePage>
with TickerProviderStateMixin {
late UserProvider user;
late TimetableProvider timetableProvider;
late UpdateProvider updateProvider;
@@ -60,7 +63,9 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
int _getDayIndex(DateTime date) {
int index = 0;
if (_controller.days == null || (_controller.days?.isEmpty ?? true)) return index;
if (_controller.days == null || (_controller.days?.isEmpty ?? true)) {
return index;
}
// find the first day with upcoming lessons
index = _controller.days!.indexWhere((day) => day.last.end.isAfter(date));
@@ -94,11 +99,14 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
_tabController = TabController(
length: _controller.days!.length,
vsync: this,
initialIndex: min(_tabController.index, max(_controller.days!.length - 1, 0)),
initialIndex:
min(_tabController.index, max(_controller.days!.length - 1, 0)),
);
if (initial || _controller.previousWeekId != _controller.currentWeekId) {
_tabController.animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
if (initial ||
_controller.previousWeekId != _controller.currentWeekId) {
_tabController
.animateTo(_getDayIndex(widget.initialDay ?? DateTime.now()));
}
initial = false;
@@ -111,7 +119,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
if (widget.initialWeek != null) {
_controller.jump(widget.initialWeek!, context: context, initial: true);
} else {
_controller.jump(_controller.currentWeek, context: context, initial: true, skip: true);
_controller.jump(_controller.currentWeek,
context: context, initial: true, skip: true);
}
}
// Listen for user changes
@@ -131,7 +140,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
// Sometimes when changing weeks really fast,
// controller.days might be null or won't include index
try {
return DateFormat("EEEE", I18n.of(context).locale.languageCode).format(_controller.days![index].first.date);
return DateFormat("EEEE", I18n.of(context).locale.languageCode)
.format(_controller.days![index].first.date);
} catch (e) {
return "timetable".i18n;
}
@@ -181,9 +191,14 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
children: [
// Day Title
Padding(
padding: const EdgeInsets.only(left: 24.0, right: 28.0, top: 18.0, bottom: 8.0),
padding: const EdgeInsets.only(
left: 24.0,
right: 28.0,
top: 18.0,
bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
dayTitle(tab).capital(),
@@ -193,9 +208,13 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
),
),
Text(
"${_controller.days![tab].first.date.day}".padLeft(2, '0') + ".",
"${_controller.days![tab].first.date.day}"
.padLeft(2, '0') +
".",
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.5),
color: AppColors.of(context)
.text
.withOpacity(.5),
fontWeight: FontWeight.w500,
),
),
@@ -208,35 +227,59 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
child: ListView.builder(
padding: EdgeInsets.zero,
physics: const BouncingScrollPhysics(),
itemCount: _controller.days![tab].length + 2,
itemCount:
_controller.days![tab].length + 2,
itemBuilder: (context, index) {
if (_controller.days == null) return Container();
if (_controller.days == null) {
return Container();
}
// Header
if (index == 0) {
return const Padding(
padding: EdgeInsets.only(top: 8.0, left: 24.0, right: 24.0),
child: PanelHeader(padding: EdgeInsets.only(top: 12.0)),
padding: EdgeInsets.only(
top: 8.0,
left: 24.0,
right: 24.0),
child: PanelHeader(
padding: EdgeInsets.only(
top: 12.0)),
);
}
// Footer
if (index == _controller.days![tab].length + 1) {
if (index ==
_controller.days![tab].length +
1) {
return const Padding(
padding: EdgeInsets.only(bottom: 8.0, left: 24.0, right: 24.0),
child: PanelFooter(padding: EdgeInsets.only(top: 12.0)),
padding: EdgeInsets.only(
bottom: 8.0,
left: 24.0,
right: 24.0),
child: PanelFooter(
padding: EdgeInsets.only(
top: 12.0)),
);
}
// Body
final Lesson lesson = _controller.days![tab][index - 1];
final bool swapDescDay = _controller.days![tab].map((l) => l.swapDesc ? 1 : 0).reduce((a, b) => a + b) >=
_controller.days![tab].length * .5;
final Lesson lesson =
_controller.days![tab][index - 1];
final bool swapDescDay = _controller
.days![tab]
.map(
(l) => l.swapDesc ? 1 : 0)
.reduce((a, b) => a + b) >=
_controller.days![tab].length *
.5;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
padding: const EdgeInsets.symmetric(
horizontal: 24.0),
child: PanelBody(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
padding:
const EdgeInsets.symmetric(
horizontal: 10.0),
child: LessonViewable(
lesson,
swapDesc: swapDescDay,
@@ -264,7 +307,8 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
padding:
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -285,7 +329,10 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
onTap: () => setState(() {
_controller.current();
if (mounted) {
_controller.jump(_controller.currentWeek, context: context, loader: _controller.currentWeekId != _controller.previousWeekId);
_controller.jump(_controller.currentWeek,
context: context,
loader: _controller.currentWeekId !=
_controller.previousWeekId);
}
}),
child: Padding(
@@ -295,12 +342,22 @@ class _TimetablePageState extends State<TimetablePage> with TickerProviderStateM
"week".i18n +
" (" +
// Week start
DateFormat((_controller.currentWeek.start.year != DateTime.now().year ? "yy. " : "") + "MMM d.",
DateFormat(
(_controller.currentWeek.start.year !=
DateTime.now().year
? "yy. "
: "") +
"MMM d.",
I18n.of(context).locale.languageCode)
.format(_controller.currentWeek.start) +
" - " +
// Week end
DateFormat((_controller.currentWeek.start.year != DateTime.now().year ? "yy. " : "") + "MMM d.",
DateFormat(
(_controller.currentWeek.start.year !=
DateTime.now().year
? "yy. "
: "") +
"MMM d.",
I18n.of(context).locale.languageCode)
.format(_controller.currentWeek.end) +
")",

View File

@@ -6,6 +6,7 @@ import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/utils/color.dart';
import 'package:filcnaplo_desktop_ui/common/panel_button.dart';
import 'package:filcnaplo_desktop_ui/common/profile_image.dart';
import 'package:filcnaplo_desktop_ui/screens/navigation/sidebar.i18n.dart';
import 'package:filcnaplo_desktop_ui/screens/navigation/sidebar_action.dart';
import 'package:filcnaplo_desktop_ui/screens/settings/settings_screen.dart';
import 'package:filcnaplo_mobile_ui/screens/settings/accounts/account_tile.dart';
@@ -25,7 +26,12 @@ import 'package:provider/provider.dart';
import 'package:filcnaplo/theme/colors/colors.dart';
class Sidebar extends StatefulWidget {
const Sidebar({Key? key, required this.navigator, required this.onRouteChange, this.selected = "home"}) : super(key: key);
const Sidebar(
{Key? key,
required this.navigator,
required this.onRouteChange,
this.selected = "home"})
: super(key: key);
final NavigatorState navigator;
final String selected;
@@ -71,12 +77,12 @@ class _SidebarState extends State<Sidebar> {
if (!settings.presentationMode) {
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
} else {
firstName = "Béla";
firstName = "János";
}
List<Widget> pageWidgets = [
SidebarAction(
title: const Text("Home"),
title: Text("Home".i18n),
icon: const Icon(FilcIcons.home),
selected: widget.selected == "home",
onTap: () {
@@ -87,7 +93,7 @@ class _SidebarState extends State<Sidebar> {
},
),
SidebarAction(
title: const Text("Grades"),
title: Text("Grades".i18n),
icon: const Icon(FeatherIcons.bookmark),
selected: widget.selected == "grades",
onTap: () {
@@ -98,7 +104,7 @@ class _SidebarState extends State<Sidebar> {
},
),
SidebarAction(
title: const Text("Timetable"),
title: Text("Timetable".i18n),
icon: const Icon(FeatherIcons.calendar),
selected: widget.selected == "timetable",
onTap: () {
@@ -109,7 +115,7 @@ class _SidebarState extends State<Sidebar> {
},
),
SidebarAction(
title: const Text("Messages"),
title: Text("Messages".i18n),
icon: const Icon(FeatherIcons.messageSquare),
selected: widget.selected == "messages",
onTap: () {
@@ -120,7 +126,7 @@ class _SidebarState extends State<Sidebar> {
},
),
SidebarAction(
title: const Text("Absences"),
title: Text("Absences".i18n),
icon: const Icon(FeatherIcons.clock),
selected: widget.selected == "absences",
onTap: () {
@@ -134,12 +140,15 @@ class _SidebarState extends State<Sidebar> {
List<Widget> bottomActions = [
SidebarAction(
title: const Text("Settings"),
title: Text("Settings".i18n),
selected: true,
icon: const Icon(FeatherIcons.settings),
onTap: () {
if (topNav != "settings") {
widget.navigator.push(CupertinoPageRoute(builder: (context) => const SettingsScreen())).then((value) => topNav = "");
widget.navigator
.push(CupertinoPageRoute(
builder: (context) => const SettingsScreen()))
.then((value) => topNav = "");
topNav = "settings";
}
},
@@ -159,7 +168,7 @@ class _SidebarState extends State<Sidebar> {
onPressed: () {
Navigator.of(context).pushNamed("login_back");
},
title: const Text("Add User"),
title: Text("adduser".i18n),
leading: const Icon(FeatherIcons.userPlus),
),
PanelButton(
@@ -169,17 +178,20 @@ class _SidebarState extends State<Sidebar> {
// Delete User
user.removeUser(userId);
await Provider.of<DatabaseProvider>(context, listen: false).store.removeUser(userId);
await Provider.of<DatabaseProvider>(context, listen: false)
.store
.removeUser(userId);
// If no other Users left, go back to LoginScreen
if (user.getUsers().isNotEmpty) {
user.setUser(user.getUsers().first.id);
restore().then((_) => user.setUser(user.getUsers().first.id));
} else {
Navigator.of(context).pushNamedAndRemoveUntil("login", (_) => false);
Navigator.of(context)
.pushNamedAndRemoveUntil("login", (_) => false);
}
},
title: const Text("Log Out"),
title: Text("logout".i18n),
leading: Icon(FeatherIcons.logOut, color: AppColors.of(context).red),
),
];
@@ -190,49 +202,77 @@ class _SidebarState extends State<Sidebar> {
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 18.0, top: 18.0, bottom: 24.0, right: 8.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 12.0),
child: ProfileImage(
name: firstName,
radius: 18.0,
backgroundColor:
!settings.presentationMode ? ColorUtils.stringToColor(user.name ?? "?") : Theme.of(context).colorScheme.secondary,
),
),
Expanded(
child: Text(
firstName,
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
padding: const EdgeInsets.only(
left: 12.0,
top: 18.0,
bottom: 24.0,
right: 12.0,
),
child: InkWell(
customBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
onTap: () {
setState(() {
expandAccount = !expandAccount;
});
},
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(
right: 12.0,
left: 5.0,
top: 5.0,
bottom: 5.0,
),
child: ProfileImage(
name: firstName,
radius: 18.0,
backgroundColor: Theme.of(context)
.colorScheme
.primary, //!settings.presentationMode
// ? ColorUtils.stringToColor(user.name ?? "?")
// : Theme.of(context).colorScheme.secondary,
),
),
),
PageTransitionSwitcher(
transitionBuilder: (child, primaryAnimation, secondaryAnimation) {
return FadeThroughTransition(
fillColor: Colors.transparent,
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
child: IconButton(
key: Key(expandAccount ? "accounts" : "pages"),
icon: Icon(expandAccount ? FeatherIcons.chevronDown : FeatherIcons.chevronRight),
padding: EdgeInsets.zero,
splashRadius: 20.0,
onPressed: () {
setState(() {
expandAccount = !expandAccount;
});
},
Expanded(
child: Text(
firstName,
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
),
),
],
PageTransitionSwitcher(
transitionBuilder:
(child, primaryAnimation, secondaryAnimation) {
return FadeThroughTransition(
fillColor: Colors.transparent,
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
child: IconButton(
key: Key(expandAccount ? "accounts" : "pages"),
icon: Icon(expandAccount
? FeatherIcons.chevronDown
: FeatherIcons.chevronRight),
padding: EdgeInsets.zero,
onPressed: () {
setState(() {
expandAccount = !expandAccount;
});
},
splashColor: const Color(0x00000000),
focusColor: const Color(0x00000000),
hoverColor: const Color(0x00000000),
highlightColor: const Color(0x00000000),
),
),
],
),
),
),
@@ -282,15 +322,19 @@ class _SidebarState extends State<Sidebar> {
if (!settings.presentationMode) {
_firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
} else {
_firstName = "Béla";
_firstName = "János";
}
accountTiles.add(AccountTile(
name: Text(!settings.presentationMode ? account.name : "Béla", style: const TextStyle(fontWeight: FontWeight.w500)),
username: Text(!settings.presentationMode ? account.username : "72469696969"),
name: Text(!settings.presentationMode ? account.name : "János",
style: const TextStyle(fontWeight: FontWeight.w500)),
username:
Text(!settings.presentationMode ? account.username : "72469696969"),
profileImage: ProfileImage(
name: _firstName,
backgroundColor: !settings.presentationMode ? ColorUtils.stringToColor(account.name) : Theme.of(context).colorScheme.secondary,
backgroundColor: !settings.presentationMode
? ColorUtils.stringToColor(account.name)
: Theme.of(context).colorScheme.secondary,
role: account.role,
),
onTap: () {

View File

@@ -0,0 +1,42 @@
import 'package:i18n_extension/i18n_extension.dart';
extension SettingsLocalization on String {
static final _t = Translations.byLocale("hu_hu") +
{
"en_en": {
"Home": "Home",
"Grades": "Grades",
"Timetable": "Timetable",
"Messages": "Messages",
"Absences": "Absences",
"Settings": "Settings",
"adduser": "Add User",
"logout": "Log Out",
},
"hu_hu": {
"Home": "Kezdőlap",
"Grades": "Jegyek",
"Timetable": "Órarend",
"Messages": "Üzenetek",
"Absences": "Hiányzások",
"Settings": "Beállítások",
"adduser": "Fiók hozzáadása",
"logout": "Kilépés",
},
"de_de": {
"Home": "Zuhause",
"Grades": "Noten",
"Timetable": "Zeitplan",
"Messages": "Mitteilungen",
"Absences": "Fehlen",
"Settings": "Einstellungen",
"adduser": "Benutzer hinzufügen",
"logout": "Abmelden",
},
};
String get i18n => localize(this, _t);
String fill(List<Object> params) => localizeFill(this, params);
String plural(int value) => localizePlural(value, this, _t);
String version(Object modifier) => localizeVersion(modifier, this, _t);
}

File diff suppressed because it is too large Load Diff