init refilc-plus

This commit is contained in:
skidoodle 2024-10-03 18:47:25 +02:00
commit 6edc2029bd
Signed by: albert
GPG key ID: A06E3070D7D55BF2
37 changed files with 6988 additions and 0 deletions

View file

@ -0,0 +1,242 @@
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart';
// import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_plus/helpers/app_icon_helper.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 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'app_icon_screen.i18n.dart';
class PremiumCustomAppIconMenu extends StatelessWidget {
const PremiumCustomAppIconMenu({super.key, required this.settings});
final SettingsProvider settings;
@override
Widget build(BuildContext context) {
// return PanelButton(
// onPressed: () {
// if (!Provider.of<PlusProvider>(context, listen: false)
// .hasScope(PremiumScopes.changeAppIcon)) {
// PlusLockedFeaturePopup.show(
// context: context, feature: PremiumFeature.appiconchange);
// return;
// }
// Navigator.of(context, rootNavigator: true).push(
// CupertinoPageRoute(builder: (context) => const ModifyAppIcon()),
// );
// },
// title: Text('custom_app_icon'.i18n),
// leading: const Icon(FeatherIcons.edit),
// );
return const SizedBox(
width: 0,
height: 0,
);
}
}
class ModifyAppIcon extends StatefulWidget {
const ModifyAppIcon({super.key});
@override
State<ModifyAppIcon> createState() => _ModifyAppIconState();
}
class _ModifyAppIconState extends State<ModifyAppIcon> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
late SettingsProvider settings;
@override
Widget build(BuildContext context) {
settings = Provider.of<SettingsProvider>(context);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text),
title: Text(
"app_icons".i18n,
style: TextStyle(color: AppColors.of(context).text),
),
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Panel(
title: Text("basic".i18n),
child: Column(
children: [
AppIconItem(
iconName: 'refilc_default',
iconPath: 'assets/launch_icons/refilc_default.png',
displayName: 'reFilc Default',
description: 'Az alapértelmezett ikon.',
selected: settings.appIcon == 'refilc_default',
selectCallback: () async {
await AppIconHelper.setAppIcon('refilc_default');
settings.update(appIcon: 'refilc_default');
},
),
],
),
),
// const SizedBox(height: 16.0),
// Panel(
// title: Text("seasonal".i18n),
// child: Column(
// children: [
// // AppIconItem(
// // iconName: 'refilc_default',
// // iconPath: 'assets/launch_icons/refilc_default.png',
// // displayName: 'reFilc Default',
// // description: 'Az alapértelmezett ikon.',
// // selected: true,
// // selectCallback: () {},
// // ),
// ],
// ),
// ),
const SizedBox(height: 16.0),
Panel(
title: Text("special".i18n),
child: Column(
children: [
AppIconItem(
iconName: 'refilc_overcomplicated',
iconPath:
'assets/launch_icons/refilc_overcomplicated.png',
displayName: 'Overcomplicated',
// description: 'Egy túlkomplikált ikon.',
selected: settings.appIcon == 'refilc_overcomplicated',
selectCallback: () async {
await AppIconHelper.setAppIcon(
'refilc_overcomplicated');
settings.update(appIcon: 'refilc_overcomplicated');
},
),
AppIconItem(
iconName: 'refilc_concept',
iconPath: 'assets/launch_icons/refilc_concept.png',
displayName: 'Modern Concept',
// description: 'Egy modernebb, letisztultabb ikon.',
selected: settings.appIcon == 'refilc_concept',
selectCallback: () async {
await AppIconHelper.setAppIcon('refilc_concept');
settings.update(appIcon: 'refilc_concept');
},
),
],
),
),
const SizedBox(height: 16.0),
Panel(
title: Text("other".i18n),
child: Column(
children: [
AppIconItem(
iconName: 'refilc_pride',
iconPath: 'assets/launch_icons/refilc_pride.png',
displayName: 'Pride',
// description: '',
selected: settings.appIcon == 'refilc_pride',
selectCallback: () async {
await AppIconHelper.setAppIcon('refilc_pride');
settings.update(appIcon: 'refilc_pride');
},
),
],
),
),
],
),
),
));
}
}
class AppIconItem extends StatelessWidget {
const AppIconItem({
super.key,
required this.iconName,
required this.iconPath,
required this.displayName,
this.description,
required this.selected,
required this.selectCallback,
});
final String iconName;
final String iconPath;
final String displayName;
final String? description;
final bool selected;
final void Function() selectCallback;
@override
Widget build(BuildContext context) {
return ListTile(
minLeadingWidth: 32.0,
dense: true,
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
visualDensity: VisualDensity.compact,
onTap: () {},
leading: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
image: DecorationImage(
image: AssetImage(iconPath),
fit: BoxFit.contain,
),
),
),
title: InkWell(
onTap: selectCallback,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
displayName,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
height: description == null ? 3.2 : 1.8,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
if (description != null)
Text(
description!,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
color: AppColors.of(context).text.withOpacity(.75),
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
trailing: selected
? Icon(
FeatherIcons.checkCircle,
color: Theme.of(context).colorScheme.primary,
)
: const SizedBox(),
);
}
}

View file

@ -0,0 +1,36 @@
import 'package:i18n_extension/i18n_extension.dart';
extension Localization on String {
static final _t = Translations.byLocale("hu_hu") +
{
"en_en": {
"custom_app_icon": "Custom App Icon",
"app_icons": "App Icons",
"basic": "Basic",
"seasonal": "Seasonal",
"special": "Special",
"other": "Other",
},
"hu_hu": {
"custom_app_icon": "Alkalmazásikon",
"app_icons": "Alkalmazásikonok",
"basic": "Egyszerű",
"seasonal": "Szezonális",
"special": "Különleges",
"other": "Egyéb",
},
"de_de": {
"custom_app_icon": "App-Symbol",
"app_icons": "App-Symbole",
"basic": "Basic",
"seasonal": "Saisonal",
"special": "Besonders",
"other": "Andere",
},
};
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,452 @@
// import 'package:dropdown_button2/dropdown_button2.dart';
// import 'package:refilc/api/providers/database_provider.dart';
// import 'package:refilc/api/providers/user_provider.dart';
// import 'package:refilc/models/settings.dart';
// import 'package:refilc/theme/colors/colors.dart';
// import 'package:refilc/utils/format.dart';
// import 'package:refilc_kreta_api/models/teacher.dart';
// import 'package:refilc_kreta_api/providers/absence_provider.dart';
// import 'package:refilc_kreta_api/providers/grade_provider.dart';
// import 'package:refilc_kreta_api/providers/timetable_provider.dart';
// import 'package:refilc_mobile_ui/common/panel/panel.dart';
// import 'package:refilc_mobile_ui/common/panel/panel_button.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 '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_mobile_ui/screens/settings/modify_names.i18n.dart';
// class MenuRenamedTeachers extends StatelessWidget {
// const MenuRenamedTeachers({Key? key, required this.settings})
// : super(key: key);
// final SettingsProvider settings;
// @override
// Widget build(BuildContext context) {
// return PanelButton(
// padding: const EdgeInsets.only(left: 14.0),
// onPressed: () {
// // if (!Provider.of<PlusProvider>(context, listen: false)
// // .hasScope(PremiumScopes.renameTeachers)) {
// // PlusLockedFeaturePopup.show(
// // context: context, feature: PremiumFeature.teacherrename);
// // return;
// // }
// Navigator.of(context, rootNavigator: true).push(
// CupertinoPageRoute(builder: (context) => const ModifyTeacherNames()),
// );
// },
// title: Text(
// "rename_teachers".i18n,
// style: TextStyle(
// color: AppColors.of(context)
// .text
// .withOpacity(settings.renamedTeachersEnabled ? 1.0 : .5)),
// ),
// leading: settings.renamedTeachersEnabled
// ? const Icon(FeatherIcons.users)
// : Icon(FeatherIcons.users,
// color: AppColors.of(context).text.withOpacity(.25)),
// trailingDivider: true,
// trailing: Switch(
// onChanged: (v) async {
// // if (!Provider.of<PlusProvider>(context, listen: false)
// // .hasScope(PremiumScopes.renameTeachers)) {
// // PlusLockedFeaturePopup.show(
// // context: context, feature: PremiumFeature.teacherrename);
// // return;
// // }
// settings.update(renamedTeachersEnabled: v);
// await Provider.of<GradeProvider>(context, listen: false)
// .convertBySettings();
// await Provider.of<TimetableProvider>(context, listen: false)
// .convertBySettings();
// await Provider.of<AbsenceProvider>(context, listen: false)
// .convertBySettings();
// },
// value: settings.renamedTeachersEnabled,
// activeColor: Theme.of(context).colorScheme.secondary,
// ),
// );
// }
// }
// class ModifyTeacherNames extends StatefulWidget {
// const ModifyTeacherNames({Key? key}) : super(key: key);
// @override
// State<ModifyTeacherNames> createState() => _ModifyTeacherNamesState();
// }
// class _ModifyTeacherNamesState extends State<ModifyTeacherNames> {
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
// final _teacherName = TextEditingController();
// String? selectedTeacherId;
// late List<Teacher> teachers;
// late UserProvider user;
// late DatabaseProvider dbProvider;
// late SettingsProvider settings;
// @override
// void initState() {
// super.initState();
// teachers = (Provider.of<GradeProvider>(context, listen: false)
// .grades
// .map((e) => e.teacher)
// .toSet()
// .toList()
// ..sort((a, b) => a.name.compareTo(b.name)));
// user = Provider.of<UserProvider>(context, listen: false);
// dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
// }
// Future<Map<String, String>> fetchRenamedTeachers() async {
// return await dbProvider.userQuery.renamedTeachers(userId: user.id!);
// }
// void showRenameDialog() {
// showDialog(
// context: context,
// builder: (context) => StatefulBuilder(builder: (context, setS) {
// return AlertDialog(
// shape: const RoundedRectangleBorder(
// borderRadius: BorderRadius.all(Radius.circular(14.0))),
// title: Text("rename_teacher".i18n),
// content: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// DropdownButton2(
// items: teachers
// .map((item) => DropdownMenuItem<String>(
// value: item.id,
// child: Text(
// item.name,
// style: TextStyle(
// fontSize: 14,
// fontWeight: FontWeight.bold,
// color: AppColors.of(context).text,
// ),
// overflow: TextOverflow.ellipsis,
// ),
// ))
// .toList(),
// onChanged: (String? v) async {
// final renamedSubs = await fetchRenamedTeachers();
// setS(() {
// selectedTeacherId = v;
// if (renamedSubs.containsKey(selectedTeacherId)) {
// _teacherName.text = renamedSubs[selectedTeacherId]!;
// } else {
// _teacherName.text = "";
// }
// });
// },
// iconStyleData: IconStyleData(
// iconSize: 14,
// iconEnabledColor: AppColors.of(context).text,
// iconDisabledColor: AppColors.of(context).text,
// ),
// underline: const SizedBox(),
// menuItemStyleData: MenuItemStyleData(height: 40,),
// itemHeight: 40,
// itemPadding: const EdgeInsets.only(left: 14, right: 14),
// buttonWidth: 50,
// dropdownWidth: 300,
// dropdownPadding: null,
// buttonDecoration: BoxDecoration(
// borderRadius: BorderRadius.circular(8),
// ),
// dropdownDecoration: BoxDecoration(
// borderRadius: BorderRadius.circular(14),
// ),
// dropdownElevation: 8,
// scrollbarRadius: const Radius.circular(40),
// scrollbarThickness: 6,
// scrollbarAlwaysShow: true,
// offset: const Offset(-10, -10),
// buttonSplashColor: Colors.transparent,
// customButton: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// border: Border.all(color: Colors.grey, width: 2),
// borderRadius: BorderRadius.circular(12.0),
// ),
// padding: const EdgeInsets.symmetric(
// vertical: 12.0, horizontal: 8.0),
// child: Text(
// selectedTeacherId == null
// ? "select_teacher".i18n
// : teachers
// .firstWhere(
// (element) => element.id == selectedTeacherId,
// orElse: () => Teacher(
// id: 'noid', name: "select_teacher".i18n),
// )
// .name,
// style: Theme.of(context).textTheme.titleSmall!.copyWith(
// fontWeight: FontWeight.w700,
// color: AppColors.of(context).text.withOpacity(0.75)),
// overflow: TextOverflow.ellipsis,
// maxLines: 2,
// textAlign: TextAlign.center,
// ),
// ),
// ),
// const Padding(
// padding: EdgeInsets.symmetric(vertical: 8.0),
// child: Icon(FeatherIcons.arrowDown, size: 32),
// ),
// TextField(
// controller: _teacherName,
// 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: "modified_name".i18n,
// suffixIcon: IconButton(
// icon: const Icon(
// FeatherIcons.x,
// color: Colors.grey,
// ),
// onPressed: () {
// setState(() {
// _teacherName.text = "";
// });
// },
// ),
// ),
// ),
// ],
// ),
// actions: [
// TextButton(
// child: Text(
// "cancel".i18n,
// style: const TextStyle(fontWeight: FontWeight.w500),
// ),
// onPressed: () {
// Navigator.of(context).maybePop();
// },
// ),
// TextButton(
// child: Text(
// "done".i18n,
// style: const TextStyle(fontWeight: FontWeight.w500),
// ),
// onPressed: () async {
// if (selectedTeacherId != null) {
// final renamedSubs = await fetchRenamedTeachers();
// renamedSubs[selectedTeacherId!] = _teacherName.text;
// await dbProvider.userStore
// .storeRenamedTeachers(renamedSubs, userId: user.id!);
// await Provider.of<GradeProvider>(context, listen: false)
// .convertBySettings();
// await Provider.of<TimetableProvider>(context, listen: false)
// .convertBySettings();
// await Provider.of<AbsenceProvider>(context, listen: false)
// .convertBySettings();
// }
// Navigator.of(context).pop(true);
// setState(() {});
// },
// ),
// ],
// );
// }),
// ).then((val) {
// _teacherName.text = "";
// selectedTeacherId = null;
// });
// }
// @override
// Widget build(BuildContext context) {
// settings = Provider.of<SettingsProvider>(context);
// return Scaffold(
// key: _scaffoldKey,
// appBar: AppBar(
// surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
// leading: BackButton(color: AppColors.of(context).text),
// title: Text(
// "modify_teachers".i18n,
// style: TextStyle(color: AppColors.of(context).text),
// ),
// ),
// body: Padding(
// padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
// child: SingleChildScrollView(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// // Panel(
// // child: SwitchListTile(
// // title: Text("italics_toggle".i18n),
// // onChanged: (value) =>
// // settings.update(renamedTeachersItalics: value),
// // value: settings.renamedTeachersItalics,
// // ),
// // ),
// // const SizedBox(
// // height: 20,
// // ),
// InkWell(
// onTap: showRenameDialog,
// borderRadius: BorderRadius.circular(12.0),
// child: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// border: Border.all(color: Colors.grey, width: 2),
// borderRadius: BorderRadius.circular(12.0),
// ),
// padding: const EdgeInsets.symmetric(
// vertical: 18.0, horizontal: 12.0),
// child: Center(
// child: Text(
// "rename_new_teacher".i18n,
// style: TextStyle(
// fontWeight: FontWeight.w600,
// fontSize: 18,
// color: AppColors.of(context).text.withOpacity(.85),
// ),
// ),
// ),
// ),
// ),
// const SizedBox(
// height: 30,
// ),
// FutureBuilder<Map<String, String>>(
// future: fetchRenamedTeachers(),
// builder: (context, snapshot) {
// if (!snapshot.hasData || snapshot.data!.isEmpty) {
// return Container();
// }
// return Panel(
// title: Text("renamed_teachers".i18n),
// child: Column(
// children: snapshot.data!.keys.map(
// (key) {
// Teacher? teacher = teachers.firstWhere(
// (element) => key == element.id,
// orElse: () => Teacher(id: 'noid', name: 'noname'),
// );
// if (teacher.id == 'noid') {
// return const SizedBox(
// width: 0,
// height: 0,
// );
// }
// String renameTo = snapshot.data![key]!;
// return RenamedTeacherItem(
// teacher: teacher,
// renamedTo: renameTo,
// modifyCallback: () {
// setState(() {
// selectedTeacherId = teacher.id;
// _teacherName.text = renameTo;
// });
// showRenameDialog();
// },
// removeCallback: () {
// setState(() {
// Map<String, String> subs =
// Map.from(snapshot.data!);
// subs.remove(key);
// dbProvider.userStore.storeRenamedTeachers(
// subs,
// userId: user.id!);
// });
// },
// );
// },
// ).toList(),
// ),
// );
// },
// ),
// ],
// ),
// ),
// ));
// }
// }
// class RenamedTeacherItem extends StatelessWidget {
// const RenamedTeacherItem({
// Key? key,
// required this.teacher,
// required this.renamedTo,
// required this.modifyCallback,
// required this.removeCallback,
// }) : super(key: key);
// final Teacher teacher;
// final String renamedTo;
// final void Function() modifyCallback;
// final void Function() removeCallback;
// @override
// Widget build(BuildContext context) {
// return ListTile(
// minLeadingWidth: 32.0,
// dense: true,
// contentPadding:
// const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0),
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
// visualDensity: VisualDensity.compact,
// onTap: () {},
// leading: Icon(FeatherIcons.user,
// color: AppColors.of(context).text.withOpacity(.75)),
// title: InkWell(
// onTap: modifyCallback,
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// teacher.name.capital(),
// style: TextStyle(
// fontWeight: FontWeight.w500,
// fontSize: 14,
// color: AppColors.of(context).text.withOpacity(.75)),
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// ),
// Text(
// renamedTo,
// style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
// maxLines: 2,
// overflow: TextOverflow.ellipsis,
// ),
// ],
// ),
// ),
// trailing: InkWell(
// onTap: removeCallback,
// child: Icon(FeatherIcons.trash,
// color: AppColors.of(context).red.withOpacity(.75)),
// ),
// );
// }
// }

View file

@ -0,0 +1,143 @@
import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
import 'package:refilc_kreta_api/models/grade.dart';
class GradeRarityTextSetting extends StatefulWidget {
const GradeRarityTextSetting({
super.key,
required this.title,
required this.cancel,
required this.done,
required this.defaultRarities,
});
final String title;
final String cancel;
final String done;
final List<String> defaultRarities;
@override
GradeRarityTextSettingState createState() => GradeRarityTextSettingState();
}
class GradeRarityTextSettingState extends State<GradeRarityTextSetting> {
late SettingsProvider settings;
late DatabaseProvider db;
late UserProvider user;
final _rarityText = TextEditingController();
@override
void initState() {
super.initState();
settings = Provider.of<SettingsProvider>(context, listen: false);
db = Provider.of<DatabaseProvider>(context, listen: false);
user = Provider.of<UserProvider>(context, listen: false);
}
@override
Widget build(BuildContext context) {
return Column(children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(5, (index) {
return ClipOval(
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () async {
showRenameDialog(
title: widget.title,
cancel: widget.cancel,
done: widget.done,
rarities:
await db.userQuery.getGradeRarities(userId: user.id!),
gradeIndex: (index + 1).toString(),
defaultRarities: widget.defaultRarities,
);
},
child: GradeValueWidget(GradeValue(index + 1, "", "", 0),
fill: true, size: 36.0),
),
),
);
}),
),
),
]);
}
void showRenameDialog(
{required String title,
required String cancel,
required String done,
required Map<String, String> rarities,
required String gradeIndex,
required List<String> defaultRarities,
required}) {
showDialog(
context: context,
builder: (context) => StatefulBuilder(builder: (context, setS) {
String? rr = rarities[gradeIndex];
rr ??= '';
_rarityText.text = rr;
return AlertDialog(
title: Text(title),
content: TextField(
controller: _rarityText,
autofocus: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text(defaultRarities[int.parse(gradeIndex) - 1]),
suffixIcon: IconButton(
icon: const Icon(FeatherIcons.x),
onPressed: () {
setState(() {
_rarityText.clear();
});
},
),
),
),
actions: [
TextButton(
child: Text(
cancel,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).maybePop();
},
),
TextButton(
child: Text(
done,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
rarities[gradeIndex] = _rarityText.text;
Provider.of<DatabaseProvider>(context, listen: false)
.userStore
.storeGradeRarities(rarities, userId: user.id!);
Navigator.of(context).pop(true);
},
),
],
);
}),
).then((val) {
_rarityText.clear();
});
}
}

View file

@ -0,0 +1,26 @@
import 'package:refilc/models/settings.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class PremiumShareTheme extends StatefulWidget {
const PremiumShareTheme({super.key});
@override
State<PremiumShareTheme> createState() => _PremiumShareThemeState();
}
class _PremiumShareThemeState extends State<PremiumShareTheme>
with TickerProviderStateMixin {
late final SettingsProvider settingsProvider;
@override
void initState() {
super.initState();
settingsProvider = Provider.of<SettingsProvider>(context, listen: false);
}
@override
Widget build(BuildContext context) {
return const Scaffold();
}
}

View file

@ -0,0 +1,660 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:io';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/models/linked_account.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/providers/third_party_provider.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_kreta_api/providers/share_provider.dart';
import 'package:refilc_mobile_ui/common/dot.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.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_mobile_ui/common/widgets/custom_segmented_control.dart';
import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.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';
class MenuCalendarSync extends StatelessWidget {
const MenuCalendarSync({
super.key,
this.borderRadius = const BorderRadius.vertical(
top: Radius.circular(4.0), bottom: Radius.circular(4.0)),
});
final BorderRadius borderRadius;
@override
Widget build(BuildContext context) {
return PanelButton(
onPressed: () async {
// if (!Provider.of<PlusProvider>(context, listen: false)
// .hasScope(PremiumScopes.calendarSync)) {
// return PlusLockedFeaturePopup.show(
// context: context, feature: PremiumFeature.calendarSync);
// }
// Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(
// builder: (context) => const CalendarSyncScreen()));
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Figyelem!"),
content: const Text(
"A naptár szinkronizálás csak azután fog működni, hogy a Google elfogadja az OAuth kérelmünket, addig is szíves türelmeteket kérjük! Amint ez megtörténik, értesíteni fogunk titeket Discord-on, valamint alkalmazáson belüli hírekben is."),
actions: [
TextButton(
child: const Text(
"Vissza",
style: TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text(
"Tovább",
style: TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).pop();
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.calendarSync)) {
return PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.calendarSync);
}
Navigator.of(context, rootNavigator: true).push(
CupertinoPageRoute(
builder: (context) => const CalendarSyncScreen()));
},
),
],
),
);
},
title: Text(
"calendar_sync".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.95),
),
),
leading: Icon(
FeatherIcons.calendar,
size: 22.0,
color: AppColors.of(context).text.withOpacity(.95),
),
trailing: Icon(
FeatherIcons.chevronRight,
size: 22.0,
color: AppColors.of(context).text.withOpacity(0.95),
),
borderRadius: borderRadius,
);
}
}
class CalendarSyncScreen extends StatefulWidget {
const CalendarSyncScreen({super.key});
@override
CalendarSyncScreenState createState() => CalendarSyncScreenState();
}
class CalendarSyncScreenState extends State<CalendarSyncScreen>
with SingleTickerProviderStateMixin {
late SettingsProvider settingsProvider;
late UserProvider user;
late ShareProvider shareProvider;
late ThirdPartyProvider thirdPartyProvider;
late AnimationController _hideContainersController;
@override
void initState() {
super.initState();
shareProvider = Provider.of<ShareProvider>(context, listen: false);
_hideContainersController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
}
@override
Widget build(BuildContext context) {
settingsProvider = Provider.of<SettingsProvider>(context);
user = Provider.of<UserProvider>(context);
thirdPartyProvider = Provider.of<ThirdPartyProvider>(context);
return AnimatedBuilder(
animation: _hideContainersController,
builder: (context, child) => Opacity(
opacity: 1 - _hideContainersController.value,
child: Scaffold(
appBar: AppBar(
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text),
title: Text(
"calendar_sync".i18n,
style: TextStyle(color: AppColors.of(context).text),
),
),
body: SingleChildScrollView(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Column(
children: [
// banner
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
image: const DecorationImage(
image: AssetImage(
'assets/images/banner_texture.png',
),
fit: BoxFit.cover,
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 40,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 4.0,
spreadRadius: 0.01,
),
],
),
height: 64,
width: 64,
child: const Icon(
Icons.calendar_month,
color: Colors.black,
size: 38.0,
),
),
const SizedBox(width: 10),
Icon(
Icons.sync_alt_outlined,
color: Colors.black.withOpacity(
thirdPartyProvider.linkedAccounts.isEmpty
? 0.2
: 0.5),
size: 20.0,
),
const SizedBox(width: 10),
Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(16.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 4.0,
spreadRadius: 0.01,
),
],
),
child: Image.asset(
'assets/icons/ic_rounded.png',
width: 64,
height: 64,
),
),
],
),
),
),
),
const SizedBox(
height: 18.0,
),
// choose account if not logged in
if (thirdPartyProvider.linkedAccounts.isEmpty)
Column(
children: [
if (Platform.isAndroid)
SplittedPanel(
title: Text('choose_account'.i18n),
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
children: [
PanelButton(
onPressed: () async {
await Provider.of<ThirdPartyProvider>(context,
listen: false)
.googleSignIn();
setState(() {});
},
title: Text(
'Google',
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(.95),
),
),
leading: Image.asset(
'assets/images/ext_logo/google.png',
width: 24.0,
height: 24.0,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
],
),
// const SizedBox(
// height: 9.0,
// ),
if (Platform.isIOS)
SplittedPanel(
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
children: [
PanelButton(
onPressed: null,
title: Text(
'Apple',
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(.55),
decoration: TextDecoration.lineThrough,
),
),
leading: Image.asset(
'assets/images/ext_logo/apple.png',
width: 24.0,
height: 24.0,
),
trailing: Text(
'soon'.i18n,
style: const TextStyle(
fontStyle: FontStyle.italic,
fontSize: 14.0),
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
],
),
const SizedBox(
height: 10.0,
),
const Text(
"A naptár szinkronizálás csak azután fog működni, hogy a Google elfogadja az OAuth kérelmünket, addig is szíves türelmeteket kérjük! Amint ez megtörténik, értesíteni fogunk titeket Discord-on, valamint alkalmazáson belüli hírekben is."),
],
),
// show options if logged in
if (thirdPartyProvider.linkedAccounts.isNotEmpty)
Column(
children: [
SplittedPanel(
title: Text('your_account'.i18n),
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
children: [
PanelButton(
onPressed: null,
title: Text(
thirdPartyProvider
.linkedAccounts.first.username,
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(.95),
),
),
leading: Image.asset(
'assets/images/ext_logo/${thirdPartyProvider.linkedAccounts.first.type == AccountType.google ? "google" : "apple"}.png',
width: 24.0,
height: 24.0,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
PanelButton(
onPressed: () async {
await thirdPartyProvider.signOutAll();
setState(() {});
},
title: Text(
'change_account'.i18n,
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(.95),
),
),
trailing: Icon(
FeatherIcons.chevronRight,
size: 22.0,
color: AppColors.of(context)
.text
.withOpacity(0.95),
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
],
),
const SizedBox(
height: 18.0,
),
SplittedPanel(
title: Text('choose_calendar'.i18n),
padding: EdgeInsets.zero,
cardPadding: EdgeInsets.zero,
isTransparent: true,
children: getCalendarList(),
),
const SizedBox(
height: 18.0,
),
SplittedPanel(
title: Text('room_num_location'.i18n),
padding: EdgeInsets.zero,
cardPadding: EdgeInsets.zero,
isTransparent: true,
children: [
CustomSegmentedControl(
onChanged: (v) {
settingsProvider.update(
calSyncRoomLocation:
v == 0 ? 'location' : 'description');
},
value: settingsProvider.calSyncRoomLocation ==
'location'
? 0
: 1,
height: 45,
children: [
Text(
'location'.i18n,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16.0,
),
),
Text(
'description'.i18n,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16.0,
),
),
],
),
],
),
const SizedBox(
height: 18.0,
),
SplittedPanel(
title: Text('options'.i18n),
padding: EdgeInsets.zero,
cardPadding: EdgeInsets.zero,
isTransparent: true,
isSeparated: true,
children: [
SplittedPanel(
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
children: [
PanelButton(
padding: const EdgeInsets.only(
left: 14.0, right: 6.0),
onPressed: () async {
settingsProvider.update(
calSyncShowExams:
!settingsProvider.calSyncShowExams);
setState(() {});
},
title: Text(
"show_exams".i18n,
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(
settingsProvider.calSyncShowExams
? .95
: .25),
),
),
trailing: Switch(
onChanged: (v) async {
settingsProvider.update(
calSyncShowExams: v);
setState(() {});
},
value: settingsProvider.calSyncShowExams,
activeColor:
Theme.of(context).colorScheme.secondary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(12.0),
),
),
],
),
SplittedPanel(
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
children: [
PanelButton(
padding: const EdgeInsets.only(
left: 14.0, right: 6.0),
onPressed: () async {
settingsProvider.update(
calSyncShowTeacher: !settingsProvider
.calSyncShowTeacher);
setState(() {});
},
title: Text(
"show_teacher".i18n,
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(settingsProvider
.calSyncShowTeacher
? .95
: .25),
),
),
trailing: Switch(
onChanged: (v) async {
settingsProvider.update(
calSyncShowTeacher: v);
setState(() {});
},
value: settingsProvider.calSyncShowTeacher,
activeColor:
Theme.of(context).colorScheme.secondary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(12.0),
),
),
],
),
SplittedPanel(
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
children: [
PanelButton(
padding: const EdgeInsets.only(
left: 14.0, right: 6.0),
onPressed: () async {
settingsProvider.update(
calSyncRenamed:
!settingsProvider.calSyncRenamed);
setState(() {});
},
title: Text(
"show_renamed".i18n,
style: TextStyle(
color: AppColors.of(context)
.text
.withOpacity(
settingsProvider.calSyncRenamed
? .95
: .25),
),
),
trailing: Switch(
onChanged: (v) async {
settingsProvider.update(
calSyncRenamed: v);
setState(() {});
},
value: settingsProvider.calSyncRenamed,
activeColor:
Theme.of(context).colorScheme.secondary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(12.0),
),
),
],
),
],
),
],
),
],
),
),
),
),
),
);
}
List<Widget> getCalendarList() {
// List<Widget> widgets = thirdPartyProvider.googleCalendars
// .map(
// (e) => Container(
// margin: const EdgeInsets.only(bottom: 3.0),
// decoration: BoxDecoration(
// border: Border.all(
// color: Theme.of(context).colorScheme.primary.withOpacity(.25),
// width: 1.0,
// ),
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: PanelButton(
// onPressed: () async {
// print((e.backgroundColor ?? '#000000').replaceAll('#', '0x'));
// setState(() {});
// },
// title: Text(
// e.summary ?? 'no_title'.i18n,
// style: TextStyle(
// color: AppColors.of(context).text.withOpacity(.95),
// ),
// ),
// leading: Dot(
// color: colorFromHex(
// e.backgroundColor ?? '#000',
// ) ??
// Colors.black,
// ),
// borderRadius: const BorderRadius.vertical(
// top: Radius.circular(12),
// bottom: Radius.circular(12),
// ),
// ),
// ),
// )
// .toList();
List<Widget> widgets = [];
widgets.add(
Container(
margin: const EdgeInsets.only(bottom: 3.0),
decoration: BoxDecoration(
// border: Border.all(
// color: Theme.of(context).colorScheme.primary.withOpacity(.25),
// width: 1.0,
// ),
color: AppColors.of(context).highlight,
borderRadius: BorderRadius.circular(16.0),
),
child: PanelButton(
onPressed: null,
// onPressed: () async {
// // thirdPartyProvider.pushTimetable(context, timetable);
// setState(() {});
// },
title: Text(
'reFilc - Órarend',
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.95),
),
),
// leading: Icon(
// FeatherIcons.plus,
// size: 20.0,
// color: AppColors.of(context).text.withOpacity(0.75),
// ),
leading: Dot(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
),
);
return widgets;
}
}

View file

@ -0,0 +1,363 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:convert';
import 'dart:io';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/providers/third_party_provider.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_kreta_api/models/grade.dart';
import 'package:refilc_kreta_api/providers/grade_provider.dart';
import 'package:refilc_kreta_api/providers/share_provider.dart';
import 'package:refilc_mobile_ui/common/dot.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.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_mobile_ui/screens/settings/settings_screen.i18n.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 'package:share_plus/share_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:refilc_mobile_ui/common/chips/new_chip.dart';
class MenuGradeExporting extends StatelessWidget {
const MenuGradeExporting({
super.key,
this.borderRadius = const BorderRadius.vertical(
top: Radius.circular(4.0), bottom: Radius.circular(4.0)),
});
final BorderRadius borderRadius;
@override
Widget build(BuildContext context) {
return PanelButton(
onPressed: () async {
// if (!Provider.of<PlusProvider>(context, listen: false)
// .hasScope(PremiumScopes.calendarSync)) {
// return PlusLockedFeaturePopup.show(
// context: context, feature: PremiumFeature.calendarSync);
// }
// Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(
// builder: (context) => const CalendarSyncScreen()));
// showDialog(
// context: context,
// builder: (context) => AlertDialog(
// title: const Text("Figyelem!"),
// content: const Text(
// "Az exportált jegyek jelenleg még nem megtekinthetők a reFilc-ben, csak te magad tudod átnézni őket JSON formátumban. A jövőben ez a funkció bővülni fog, és a jegyeket meg is tekintheted majd a reFilc felületén."),
// actions: [
// // TextButton(
// // child: const Text(
// // "Vissza",
// // style: TextStyle(fontWeight: FontWeight.w500),
// // ),
// // onPressed: () {
// // Navigator.of(context).pop();
// // },
// // ),
// TextButton(
// child: const Text(
// "Tovább",
// style: TextStyle(fontWeight: FontWeight.w500),
// ),
// onPressed: () {
// Navigator.of(context).pop();
Provider.of<SettingsProvider>(context, listen: false).update(
unseenNewFeatures: List.from(
Provider.of<SettingsProvider>(context, listen: false)
.unseenNewFeatures
..remove('grade_exporting'),
),
);
// Provider.of<SettingsProvider>(context, listen: false).update(
// unseenNewFeatures: ['grade_exporting'],
// );
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.gradeExporting)) {
return PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.gradeExporting);
}
Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(
builder: (context) => const GradeExportingScreen()));
// },
// ),
// ],
// ),
// );
},
title: Text(
"grade_exporting".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.95),
),
),
leading: Icon(
Icons.toll_rounded,
size: 22.0,
color: AppColors.of(context).text.withOpacity(.95),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (Provider.of<SettingsProvider>(context)
.unseenNewFeatures
.contains('grade_exporting'))
const NewChip(),
Icon(
FeatherIcons.chevronRight,
size: 22.0,
color: AppColors.of(context).text.withOpacity(0.95),
)
],
),
borderRadius: borderRadius,
);
}
}
class GradeExportingScreen extends StatefulWidget {
const GradeExportingScreen({super.key});
@override
CalendarSyncScreenState createState() => CalendarSyncScreenState();
}
class CalendarSyncScreenState extends State<GradeExportingScreen>
with SingleTickerProviderStateMixin {
late SettingsProvider settingsProvider;
late UserProvider user;
late ShareProvider shareProvider;
late ThirdPartyProvider thirdPartyProvider;
late AnimationController _hideContainersController;
@override
void initState() {
super.initState();
shareProvider = Provider.of<ShareProvider>(context, listen: false);
_hideContainersController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 200));
}
@override
Widget build(BuildContext context) {
settingsProvider = Provider.of<SettingsProvider>(context);
user = Provider.of<UserProvider>(context);
thirdPartyProvider = Provider.of<ThirdPartyProvider>(context);
return AnimatedBuilder(
animation: _hideContainersController,
builder: (context, child) => Opacity(
opacity: 1 - _hideContainersController.value,
child: Scaffold(
appBar: AppBar(
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(color: AppColors.of(context).text),
title: Text(
"grade_exporting".i18n,
style: TextStyle(color: AppColors.of(context).text),
),
),
body: SingleChildScrollView(
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Column(
children: [
// choose export method
Column(
children: [
SplittedPanel(
title: Text('export_method'.i18n),
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
children: [
PanelButton(
onPressed: () async {
// get all grades
List<Grade> grades = Provider.of<GradeProvider>(
context,
listen: false)
.grades;
// gmake a list of grades in json format
List<Map<dynamic, dynamic>> gradesList = [
for (Grade grade in grades)
// {
// '"subject"': '"${grade.subject.name}"',
// '"value"': grade.value.value,
// '"value_name"':
// '"${grade.value.valueName}"',
// '"date"':
// '"${grade.date.toIso8601String()}"',
// '"weight"': grade.value.weight,
// '"type"': '"${grade.type.name}"',
// '"description"': '"${grade.description}"',
// '"teacher"': '"${grade.teacher.name}"',
// }
grade.json ?? {},
];
// convert list to json file
final directory = await getTemporaryDirectory();
File file = File('${directory.path}/grades.json');
file.writeAsStringSync(
jsonEncode(gradesList),
);
// convert json to bytes
final jsonBytes = file.readAsBytesSync();
// get current study year
final now = DateTime.now();
String studyYearStr = '';
if (now.month <= 8) {
studyYearStr = '${now.year - 1}_${now.year}';
} else {
studyYearStr = '${now.year}_${now.year + 1}';
}
// open the share popup with the json file
Share.shareXFiles(
[
XFile.fromData(
jsonBytes,
name: 'refilc_grades_$studyYearStr',
mimeType: 'application/json',
),
],
subject:
'reFilc Jegyek - ${studyYearStr.replaceAll('_', '/')}',
);
},
title: Text(
'JSON',
style: TextStyle(
color:
AppColors.of(context).text.withOpacity(.95),
),
),
// leading: Image.asset(
// 'assets/images/ext_logo/google.png',
// width: 24.0,
// height: 24.0,
// ),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
],
),
// const SizedBox(
// height: 10.0,
// ),
// const Text(
// "Az exportált jegyek jelenleg még nem megtekinthetők a reFilc-ben, csak te magad tudod átnézni őket JSON formátumban. A jövőben ez a funkció bővülni fog, és a jegyeket meg is tekintheted majd a reFilc felületén."),
],
),
],
),
),
),
),
),
);
}
List<Widget> getCalendarList() {
// List<Widget> widgets = thirdPartyProvider.googleCalendars
// .map(
// (e) => Container(
// margin: const EdgeInsets.only(bottom: 3.0),
// decoration: BoxDecoration(
// border: Border.all(
// color: Theme.of(context).colorScheme.primary.withOpacity(.25),
// width: 1.0,
// ),
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: PanelButton(
// onPressed: () async {
// print((e.backgroundColor ?? '#000000').replaceAll('#', '0x'));
// setState(() {});
// },
// title: Text(
// e.summary ?? 'no_title'.i18n,
// style: TextStyle(
// color: AppColors.of(context).text.withOpacity(.95),
// ),
// ),
// leading: Dot(
// color: colorFromHex(
// e.backgroundColor ?? '#000',
// ) ??
// Colors.black,
// ),
// borderRadius: const BorderRadius.vertical(
// top: Radius.circular(12),
// bottom: Radius.circular(12),
// ),
// ),
// ),
// )
// .toList();
List<Widget> widgets = [];
widgets.add(
Container(
margin: const EdgeInsets.only(bottom: 3.0),
decoration: BoxDecoration(
// border: Border.all(
// color: Theme.of(context).colorScheme.primary.withOpacity(.25),
// width: 1.0,
// ),
color: AppColors.of(context).highlight,
borderRadius: BorderRadius.circular(16.0),
),
child: PanelButton(
onPressed: null,
// onPressed: () async {
// // thirdPartyProvider.pushTimetable(context, timetable);
// setState(() {});
// },
title: Text(
'reFilc - Órarend',
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.95),
),
),
// leading: Icon(
// FeatherIcons.plus,
// size: 20.0,
// color: AppColors.of(context).text.withOpacity(0.75),
// ),
leading: Dot(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12),
bottom: Radius.circular(12),
),
),
),
);
return widgets;
}
}

View file

@ -0,0 +1,157 @@
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.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 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:refilc_mobile_ui/screens/settings/settings_screen.i18n.dart';
import 'package:provider/provider.dart';
import 'package:i18n_extension/i18n_extension.dart';
// ignore: must_be_immutable
class WelcomeMessagePanelButton extends StatelessWidget {
late SettingsProvider settingsProvider;
late UserProvider user;
WelcomeMessagePanelButton(this.settingsProvider, this.user, {super.key});
@override
Widget build(BuildContext context) {
String finalName = ((user.nickname ?? '') != ''
? user.nickname
: (user.displayName ?? '') != ''
? user.displayName
: 'János') ??
'János';
return PanelButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => WelcomeMessageEditor(settingsProvider));
},
title: Text(
"welcome_msg".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(.95),
),
),
leading: Icon(
FeatherIcons.smile,
size: 22.0,
color: AppColors.of(context).text.withOpacity(.95),
),
trailing: Container(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
settingsProvider.welcomeMessage.replaceAll(' ', '') != ''
? localizeFill(
settingsProvider.welcomeMessage,
[finalName],
)
: 'default'.i18n,
style: const TextStyle(fontSize: 14.0),
textAlign: TextAlign.end,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
),
);
}
}
// ignore: must_be_immutable
class WelcomeMessageEditor extends StatefulWidget {
late SettingsProvider settingsProvider;
WelcomeMessageEditor(this.settingsProvider, {super.key});
@override
State<WelcomeMessageEditor> createState() => _WelcomeMessageEditorState();
}
class _WelcomeMessageEditorState extends State<WelcomeMessageEditor> {
final _welcomeMsg = TextEditingController();
@override
void initState() {
super.initState();
_welcomeMsg.text =
widget.settingsProvider.welcomeMessage.replaceAll('%s', '%name%');
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text("edit_welcome_msg".i18n),
content: TextField(
controller: _welcomeMsg,
autofocus: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text('welcome_msg'.i18n),
suffixIcon: IconButton(
icon: const Icon(FeatherIcons.x),
onPressed: () {
setState(() {
_welcomeMsg.text = "";
});
},
),
),
),
actions: [
TextButton(
child: Text(
"cancel".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).maybePop();
},
),
TextButton(
child: Text(
"done".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
// var trimmed = _welcomeMsg.text.trim();
// var defLen = trimmed.length;
// var replacedLen = trimmed.replaceAll('%s', '').length;
// if (defLen - 2 > replacedLen) {
// print('fuck yourself rn');
// }
var finalText = _welcomeMsg.text
.trim()
.replaceFirst('%name%', '\$s')
.replaceFirst('%user%', '\$s')
.replaceFirst('%username%', '\$s')
.replaceFirst('%me%', '\$s')
.replaceFirst('%profile%', '\$s')
.replaceAll('%', '')
.replaceFirst('\$s', '%s');
// .replaceAll('\$s', 's');
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.welcomeMessage) &&
finalText.replaceAll(' ', '') != '') {
PlusLockedFeaturePopup.show(
context: context, feature: PremiumFeature.welcomeMessage);
return;
}
widget.settingsProvider
.update(welcomeMessage: finalText, store: true);
Navigator.of(context).pop(true);
},
),
],
);
}
}