changed everything from filcnaplo to refilc finally

This commit is contained in:
Kima
2024-02-24 20:12:25 +01:00
parent 0d1c7b7143
commit 1171e3aaaf
655 changed files with 38728 additions and 44967 deletions

View File

@@ -0,0 +1,25 @@
class NavigationRoute {
late String _name;
late int _index;
final List<String> _internalPageMap = [
"home",
"grades",
"timetable",
"messages",
"absences",
];
String get name => _name;
int get index => _index;
set name(String n) {
_name = n;
_index = _internalPageMap.indexOf(n);
}
set index(int i) {
_index = i;
_name = _internalPageMap.elementAt(i);
}
}

View File

@@ -0,0 +1,37 @@
import 'package:animations/animations.dart';
import 'package:refilc_desktop_ui/pages/absences/absences_page.dart';
import 'package:refilc_desktop_ui/pages/grades/grades_page.dart';
import 'package:refilc_desktop_ui/pages/home/home_page.dart';
import 'package:refilc_desktop_ui/pages/messages/messages_page.dart';
import 'package:refilc_desktop_ui/pages/timetable/timetable_page.dart';
import 'package:flutter/material.dart';
Route navigationRouteHandler(RouteSettings settings) {
switch (settings.name) {
case "grades":
return navigationPageRoute((context) => const GradesPage());
case "timetable":
return navigationPageRoute((context) => const TimetablePage());
case "messages":
return navigationPageRoute((context) => const MessagesPage());
case "absences":
return navigationPageRoute((context) => const AbsencesPage());
case "home":
default:
return navigationPageRoute((context) => const HomePage());
}
}
Route navigationPageRoute(Widget Function(BuildContext) builder) {
return PageRouteBuilder(
pageBuilder: (context, _, __) => builder(context),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeThroughTransition(
fillColor: Theme.of(context).scaffoldBackgroundColor,
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
);
},
);
}

View File

@@ -0,0 +1,167 @@
import 'dart:io';
import 'package:refilc/api/providers/news_provider.dart';
import 'package:refilc/api/providers/sync.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/observer.dart';
import 'package:refilc_desktop_ui/screens/navigation/navigation_route.dart';
import 'package:refilc_desktop_ui/screens/navigation/navigation_route_handler.dart';
import 'package:refilc_desktop_ui/screens/navigation/sidebar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart';
import 'package:provider/provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc_kreta_api/client/client.dart';
import 'package:refilc_plus/providers/goal_provider.dart';
class NavigationScreen extends StatefulWidget {
const NavigationScreen({Key? key}) : super(key: key);
static NavigationScreenState? of(BuildContext context) =>
context.findAncestorStateOfType<NavigationScreenState>();
@override
State<NavigationScreen> createState() => NavigationScreenState();
}
class NavigationScreenState extends State<NavigationScreen>
with WidgetsBindingObserver {
final _navigatorState = GlobalKey<NavigatorState>();
late NavigationRoute selected;
late SettingsProvider settings;
late NewsProvider newsProvider;
late GoalProvider goalProvider;
double topInset = 0.0;
@override
void initState() {
super.initState();
settings = Provider.of<SettingsProvider>(context, listen: false);
selected = NavigationRoute();
selected.index = 0;
// add brightness observer
WidgetsBinding.instance.addObserver(this);
// set client User-Agent
Provider.of<KretaClient>(context, listen: false).userAgent =
settings.config.userAgent;
// get news
newsProvider = Provider.of<NewsProvider>(context, listen: false);
newsProvider.restore().then((value) => newsProvider.fetch());
// get goals
// goalProvider = Provider.of<GoalProvider>(context, listen: false);
// goalProvider.fetchDone();
// Initial sync
syncAll(context);
() async {
try {
await Window.initialize();
} catch (_) {}
// Transparent sidebar
if (Platform.isLinux) return;
await Window.setEffect(
effect: Platform.isLinux
? WindowEffect.transparent
: WindowEffect.acrylic,
color: Platform.isMacOS
? Colors.transparent
: const Color.fromARGB(27, 27, 27, 27));
// todo: do for windows
if (Platform.isMacOS) {
topInset = await Window.getTitlebarHeight();
await Window.enableFullSizeContentView();
await Window.hideTitle();
await Window.makeTitlebarTransparent();
}
}();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangePlatformBrightness() {
if (settings.theme == ThemeMode.system) {
// ignore: deprecated_member_use
Brightness? brightness =
// ignore: deprecated_member_use
WidgetsBinding.instance.window.platformBrightness;
Provider.of<ThemeModeObserver>(context, listen: false).changeTheme(
brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark);
}
super.didChangePlatformBrightness();
}
void setPage(String page) => setState(() => selected.name = page);
@override
Widget build(BuildContext context) {
settings = Provider.of<SettingsProvider>(context);
newsProvider = Provider.of<NewsProvider>(context);
goalProvider = Provider.of<GoalProvider>(context);
// show news / complete goals
WidgetsBinding.instance.addPostFrameCallback((_) {
if (newsProvider.show) {
newsProvider.lock();
// NewsView.show(newsProvider.news[newsProvider.state], context: context).then((value) => newsProvider.release());
}
if (goalProvider.hasDoneGoals) {
// to-do
}
});
return Scaffold(
backgroundColor: Colors.transparent,
body: Row(
children: [
if (_navigatorState.currentState != null)
Container(
decoration: BoxDecoration(
color:
Theme.of(context).scaffoldBackgroundColor.withOpacity(.5),
border: Border(
right: BorderSide(
color: AppColors.of(context).shadow.withOpacity(.7),
width: 1.0)),
),
child: Padding(
padding: EdgeInsets.only(top: topInset),
child: Sidebar(
navigator: _navigatorState.currentState!,
selected: selected.name,
onRouteChange: (name) => setPage(name),
),
),
),
Expanded(
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: MediaQuery(
data: MediaQuery.of(context).copyWith(
padding: EdgeInsets.only(top: topInset),
),
child: Navigator(
key: _navigatorState,
initialRoute: selected.name,
onGenerateRoute: (settings) =>
navigationRouteHandler(settings),
),
),
),
),
],
),
);
}
}

View File

@@ -0,0 +1,353 @@
import 'package:animations/animations.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/icons/filc_icons.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/utils/color.dart';
import 'package:refilc_desktop_ui/common/panel_button.dart';
import 'package:refilc_desktop_ui/common/profile_image.dart';
import 'package:refilc_desktop_ui/screens/navigation/sidebar.i18n.dart';
import 'package:refilc_desktop_ui/screens/navigation/sidebar_action.dart';
import 'package:refilc_desktop_ui/screens/settings/settings_screen.dart';
import 'package:refilc_mobile_ui/screens/settings/accounts/account_tile.dart';
import 'package:refilc_kreta_api/client/client.dart';
import 'package:refilc_kreta_api/providers/absence_provider.dart';
import 'package:refilc_kreta_api/providers/event_provider.dart';
import 'package:refilc_kreta_api/providers/exam_provider.dart';
import 'package:refilc_kreta_api/providers/grade_provider.dart';
import 'package:refilc_kreta_api/providers/homework_provider.dart';
import 'package:refilc_kreta_api/providers/message_provider.dart';
import 'package:refilc_kreta_api/providers/note_provider.dart';
import 'package:refilc_kreta_api/providers/timetable_provider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'package:refilc/theme/colors/colors.dart';
class Sidebar extends StatefulWidget {
const Sidebar(
{Key? key,
required this.navigator,
required this.onRouteChange,
this.selected = "home"})
: super(key: key);
final NavigatorState navigator;
final String selected;
final Function(String) onRouteChange;
@override
State<Sidebar> createState() => _SidebarState();
}
class _SidebarState extends State<Sidebar> {
late UserProvider user;
late SettingsProvider settings;
late String firstName;
String topNav = "";
bool expandAccount = false;
List<Widget> accountTiles = [];
@override
void initState() {
super.initState();
user = Provider.of<UserProvider>(context, listen: false);
}
Future<void> restore() => Future.wait([
Provider.of<GradeProvider>(context, listen: false).restore(),
Provider.of<TimetableProvider>(context, listen: false).restoreUser(),
Provider.of<ExamProvider>(context, listen: false).restore(),
Provider.of<HomeworkProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false).restore(),
Provider.of<MessageProvider>(context, listen: false)
.restoreRecipients(),
Provider.of<NoteProvider>(context, listen: false).restore(),
Provider.of<EventProvider>(context, listen: false).restore(),
Provider.of<AbsenceProvider>(context, listen: false).restore(),
Provider.of<KretaClient>(context, listen: false).refreshLogin(),
]);
@override
Widget build(BuildContext context) {
user = Provider.of<UserProvider>(context);
settings = Provider.of<SettingsProvider>(context);
List<String> nameParts = user.name?.split(" ") ?? ["?"];
if (!settings.presentationMode) {
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
} else {
firstName = "János";
}
List<Widget> pageWidgets = [
SidebarAction(
title: Text("Home".i18n),
icon: const Icon(FilcIcons.home),
selected: widget.selected == "home",
onTap: () {
if (widget.selected != "home") {
widget.navigator.pushReplacementNamed("home");
widget.onRouteChange("home");
}
},
),
SidebarAction(
title: Text("Grades".i18n),
icon: const Icon(FeatherIcons.bookmark),
selected: widget.selected == "grades",
onTap: () {
if (widget.selected != "grades") {
widget.navigator.pushReplacementNamed("grades");
widget.onRouteChange("grades");
}
},
),
SidebarAction(
title: Text("Timetable".i18n),
icon: const Icon(FeatherIcons.calendar),
selected: widget.selected == "timetable",
onTap: () {
if (widget.selected != "timetable") {
widget.navigator.pushReplacementNamed("timetable");
widget.onRouteChange("timetable");
}
},
),
SidebarAction(
title: Text("Messages".i18n),
icon: const Icon(FeatherIcons.messageSquare),
selected: widget.selected == "messages",
onTap: () {
if (widget.selected != "messages") {
widget.navigator.pushReplacementNamed("messages");
widget.onRouteChange("messages");
}
},
),
SidebarAction(
title: Text("Absences".i18n),
icon: const Icon(FeatherIcons.clock),
selected: widget.selected == "absences",
onTap: () {
if (widget.selected != "absences") {
widget.navigator.pushReplacementNamed("absences");
widget.onRouteChange("absences");
}
},
),
];
List<Widget> bottomActions = [
SidebarAction(
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 = "");
topNav = "settings";
}
},
),
];
buildAccountTiles();
List<Widget> accountWidgets = [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Column(children: accountTiles),
),
// Account settings
PanelButton(
onPressed: () {
Navigator.of(context).pushNamed("login_back");
},
title: Text("adduser".i18n),
leading: const Icon(FeatherIcons.userPlus),
),
PanelButton(
onPressed: () async {
String? userId = user.id;
if (userId == null) return;
// revoke refresh token
await Provider.of<KretaClient>(context, listen: false).logout();
// delete user from app
user.removeUser(userId);
await Provider.of<DatabaseProvider>(context, listen: false)
.store
.removeUser(userId);
// if no other users left, go back to login screen
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);
}
},
title: Text("logout".i18n),
leading: Icon(FeatherIcons.logOut, color: AppColors.of(context).red),
),
];
return SizedBox(
height: double.infinity,
width: 250.0,
child: Column(
children: [
Padding(
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,
),
),
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),
),
),
],
),
),
),
// Pages
Expanded(
child: PageTransitionSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (child, primaryAnimation, secondaryAnimation) {
return SharedAxisTransition(
fillColor: Colors.transparent,
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.scaled,
child: child,
);
},
child: !expandAccount
? Column(
key: const Key("pages"),
children: pageWidgets,
)
: Column(
key: const Key("accounts"),
children: accountWidgets,
),
),
),
// Settings
...bottomActions,
// Bottom padding
const SizedBox(height: 12.0),
],
),
);
}
void buildAccountTiles() {
accountTiles = [];
user.getUsers().forEach((account) {
if (account.id == user.id) return;
String _firstName;
List<String> _nameParts = user.name?.split(" ") ?? ["?"];
if (!settings.presentationMode) {
_firstName = _nameParts.length > 1 ? _nameParts[1] : _nameParts[0];
} else {
_firstName = "János";
}
accountTiles.add(AccountTile(
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,
role: account.role,
),
onTap: () {
user.setUser(account.id);
restore().then((_) => user.setUser(account.id));
},
// onTapMenu: () => _showBottomSheet(account),
));
});
}
}

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);
}

View File

@@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
import 'package:refilc/theme/colors/colors.dart';
class SidebarAction extends StatelessWidget {
const SidebarAction(
{Key? key, this.title, this.icon, this.onTap, this.selected = false})
: super(key: key);
final bool selected;
final Widget? icon;
final Widget? title;
final Function()? onTap;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 12.0),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12.0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
if (icon != null)
IconTheme(
data: IconThemeData(
color: AppColors.of(context)
.text
.withOpacity(selected ? 1.0 : .3),
),
child: icon!,
),
if (title != null)
Padding(
padding: const EdgeInsets.only(left: 24.0),
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 500),
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(selected ? 1.0 : .8),
fontWeight: FontWeight.w500,
fontFamily: "Montserrat",
),
child: title!,
),
),
],
),
),
),
);
}
}