Merge branch 'master' of github.com:refilc/naplo

This commit is contained in:
zypherift
2024-06-14 14:09:28 +02:00
72 changed files with 2854 additions and 609 deletions

View File

@@ -0,0 +1,179 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:refilc_kreta_api/client/api.dart';
import 'package:refilc_kreta_api/client/client.dart';
import 'package:webview_flutter/webview_flutter.dart';
class KretenLoginScreen extends StatefulWidget {
const KretenLoginScreen({super.key});
@override
State<KretenLoginScreen> createState() => _KretenLoginScreenState();
}
class _KretenLoginScreenState extends State<KretenLoginScreen> {
late final WebViewController controller;
var loadingPercentage = 0;
var currentUrl = '';
@override
void initState() {
super.initState();
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) async {
setState(() {
loadingPercentage = 0;
currentUrl = url;
});
List<String> requiredThings = url
.replaceAll(
'https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect?code=',
'')
.replaceAll(
'&scope=openid email offline_access kreta-ellenorzo-webapi.public kreta-eugyintezes-webapi.public kreta-fileservice-webapi.public kreta-mobile-global-webapi.public kreta-dkt-webapi.public kreta-ier-webapi.public&state=refilc_student_mobile&session_state=',
':')
.split(':');
String code = requiredThings[0];
// String sessionState = requiredThings[1];
debugPrint('url: $url');
// actual login (token grant) logic
Map<String, String> headers = {
"content-type": "application/x-www-form-urlencoded",
"accept": "*/*",
"user-agent":
"eKretaStudent/264745 CFNetwork/1494.0.7 Darwin/23.4.0",
"code_verifier": "THDUSddKOOndwCkqBtVHvRjh2LK0V2kMyLP2QirqVWQ",
};
Map? res = await Provider.of<KretaClient>(context, listen: false)
.postAPI(KretaAPI.login, headers: headers, body: {
"code": code,
"redirect_uri":
"https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect",
"client_id": "kreta-ellenorzo-student-mobile-ios",
"grant_type": "authorization_code",
});
if (res != null) {
print(res);
// if (res.containsKey("error")) {
// if (res["error"] == "invalid_grant") {
// print("ERROR: invalid_grant");
// return;
// }
// } else {
// if (res.containsKey("access_token")) {
// try {
// Provider.of<KretaClient>(context, listen: false).accessToken =
// res["access_token"];
// Map? studentJson =
// await Provider.of<KretaClient>(context, listen: false)
// .getAPI(KretaAPI.student(instituteCode));
// Student student = Student.fromJson(studentJson!);
// var user = User(
// username: username,
// password: password,
// instituteCode: instituteCode,
// name: student.name,
// student: student,
// role: JwtUtils.getRoleFromJWT(res["access_token"])!,
// );
// if (onLogin != null) onLogin(user);
// // Store User in the database
// await Provider.of<DatabaseProvider>(context, listen: false)
// .store
// .storeUser(user);
// Provider.of<UserProvider>(context, listen: false)
// .addUser(user);
// Provider.of<UserProvider>(context, listen: false)
// .setUser(user.id);
// // Get user data
// try {
// await Future.wait([
// Provider.of<GradeProvider>(context, listen: false)
// .fetch(),
// Provider.of<TimetableProvider>(context, listen: false)
// .fetch(week: Week.current()),
// Provider.of<ExamProvider>(context, listen: false).fetch(),
// Provider.of<HomeworkProvider>(context, listen: false)
// .fetch(),
// Provider.of<MessageProvider>(context, listen: false)
// .fetchAll(),
// Provider.of<MessageProvider>(context, listen: false)
// .fetchAllRecipients(),
// Provider.of<NoteProvider>(context, listen: false).fetch(),
// Provider.of<EventProvider>(context, listen: false)
// .fetch(),
// Provider.of<AbsenceProvider>(context, listen: false)
// .fetch(),
// ]);
// } catch (error) {
// print("WARNING: failed to fetch user data: $error");
// }
// if (onSuccess != null) onSuccess();
// return LoginState.success;
// } catch (error) {
// print("ERROR: loginAPI: $error");
// // maybe check debug mode
// // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("ERROR: $error")));
// return LoginState.failed;
// }
// }
// }
}
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
))
..loadRequest(
Uri.parse(
'https://idp.e-kreta.hu/connect/authorize?prompt=login&nonce=refilc&response_type=code&code_challenge_method=S256&scope=openid%20email%20offline_access%20kreta-ellenorzo-webapi.public%20kreta-eugyintezes-webapi.public%20kreta-fileservice-webapi.public%20kreta-mobile-global-webapi.public%20kreta-dkt-webapi.public%20kreta-ier-webapi.public&code_challenge=Oj_aVMRJHYsv00mrtGJY72NJa7HY54lVnU2Cb4CWbWw&redirect_uri=https://mobil.e-kreta.hu/ellenorzo-student/prod/oauthredirect&client_id=kreta-ellenorzo-student-mobile-ios&state=refilc_student_mobile'),
);
}
// Future<void> loadLoginUrl() async {
// String nonceStr = await Provider.of<KretaClient>(context, listen: false)
// .getAPI(KretaAPI.nonce, json: false);
// Nonce nonce = getNonce(nonceStr, );
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: const BackButton(),
title: const Text('e-KRÉTA Bejelentkezés'),
),
body: Stack(
children: [
WebViewWidget(
controller: controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
),
);
}
}

View File

@@ -56,6 +56,13 @@ class AccountView extends StatelessWidget {
Detail(
title: "parents".plural(user.student.parents.length),
description: user.student.parents.join(", ")),
const SizedBox(
height: 10.0,
),
// Detail(
// title: "parents".i18n,
// description: user.student.parents.join(", ")),
Detail(title: "school".i18n, description: user.student.school.name),
],
),
);

View File

@@ -9,6 +9,7 @@ extension Localization on String {
"class": "Class",
"address": "Home address",
"parents": "Parents".one("Parent"),
"parents_phone": "Parents' phone number: ".one("Parent"),
},
"hu_hu": {
"birthdate": "Születési dátum",

View File

@@ -37,6 +37,9 @@ import 'package:flutter_material_color_picker/flutter_material_color_picker.dart
import 'package:refilc/models/icon_pack.dart';
import 'package:refilc/utils/format.dart';
import 'package:refilc_mobile_ui/screens/settings/theme_screen.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:refilc_plus/models/premium_scopes.dart';
// import 'package:refilc_plus/providers/plus_provider.dart';
// import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
@@ -900,6 +903,15 @@ class _LiveActivityColorSettingState extends State<LiveActivityColorSetting> {
allowShades: false,
selectedColor: settings.liveActivityColor,
onMainColorChange: (k) {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.liveActivityColor)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.liveActivity,
);
return;
}
setState(() {
currentColor = k as Color;
settings.update(

View File

@@ -27,6 +27,7 @@ import 'package:refilc_mobile_ui/common/bottom_sheet_menu/bottom_sheet_menu.dart
import 'package:refilc_mobile_ui/common/panel/panel.dart';
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
import 'package:refilc_mobile_ui/common/profile_image/profile_image.dart';
import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
// import 'package:refilc_mobile_ui/common/soon_alert/soon_alert.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
// import 'package:refilc_mobile_ui/common/system_chrome.dart';
@@ -320,6 +321,7 @@ class SettingsScreenState extends State<SettingsScreen>
badge: updateProvider.available,
role: user.role,
profilePictureString: user.picture,
gradeStreak: (user.gradeStreak ?? 0) > 1,
backgroundColor: Theme.of(context)
.colorScheme
.tertiary, //!settings.presentationMode
@@ -702,6 +704,46 @@ class SettingsScreenState extends State<SettingsScreen>
],
),
if ((user.gradeStreak ?? 0) > 1)
SplittedPanel(
padding: const EdgeInsets.only(
bottom: 12.0, left: 24.0, right: 24.0),
children: [
GestureDetector(
onTap: () {
SoonAlert.show(context: context);
},
child: ListTile(
title: Text(
"grade_streak".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.95),
fontWeight: FontWeight.w500,
),
),
subtitle: Text(
"grade_streak_subtitle".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.75),
),
),
leading: const Text(
"🔥",
style: TextStyle(fontSize: 22.0),
),
trailing: Text(
"${user.gradeStreak}",
style: TextStyle(
color: AppColors.of(context).text.withOpacity(0.95),
fontWeight: FontWeight.w500,
fontSize: 18.0,
),
),
),
),
],
),
// plus subscribe inline
const PlusSettingsInline(),

View File

@@ -116,6 +116,14 @@ extension SettingsLocalization on String {
"exp_settings": "Export Settings",
"manage_subs": "Manage Subscription",
"copy_plus_id": "Copy reFilc+ ID",
// grade streak
"grade_streak": "Grade 5 Streak",
"grade_streak_subtitle": "So many 5s in a row?!",
// other
"only_ch_title_font": "Font Only for Titles",
"new_popups": "New Popups",
"export_method": "Export Method",
"grade_exporting": "Grade Exporting",
},
"hu_hu": {
"personal_details": "Személyes információk",
@@ -230,6 +238,14 @@ extension SettingsLocalization on String {
"exp_settings": "Beállítások exportálása",
"manage_subs": "Előfizetés kezelése",
"copy_plus_id": "reFilc+ ID másolása",
// grade streak
"grade_streak": "5-ös sorozat",
"grade_streak_subtitle": "Egymás után ennyi 5-ös?!",
// other
"only_ch_title_font": "Betűtípus csak címekre",
"new_popups": "Új felugró ablakok",
"export_method": "Exportálási mód",
"grade_exporting": "Jegy exportálás",
},
"de_de": {
"personal_details": "Persönliche Angaben",
@@ -344,6 +360,14 @@ extension SettingsLocalization on String {
"exp_settings": "Einstellungen exportieren",
"manage_subs": "Abonnement verwalten",
"copy_plus_id": "reFilc+ ID kopieren",
// grade streak
"grade_streak": "5er-Streak",
"grade_streak_subtitle": "So viele 5er in Folge?!",
// other
"only_ch_title_font": "Schriftart nur für Titel",
"new_popups": "Neue Popups",
"export_method": "Exportmethode",
"grade_exporting": "Noten exportieren",
},
};

View File

@@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'package:refilc_plus/ui/mobile/settings/submenu/calendar_sync.dart';
import 'package:refilc_plus/ui/mobile/settings/submenu/grade_exporting.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';
@@ -158,6 +159,16 @@ class ExtrasSettingsScreenState extends State<ExtrasSettingsScreen> {
),
],
),
SplittedPanel(
padding: const EdgeInsets.only(top: 9.0),
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
children: [
MenuGradeExporting(
borderRadius: BorderRadius.circular(12.0),
),
],
),
SplittedPanel(
padding: const EdgeInsets.only(top: 9.0),
cardPadding: const EdgeInsets.all(4.0),

View File

@@ -0,0 +1,381 @@
import 'package:refilc/models/settings.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:refilc/ui/flutter_colorpicker/colorpicker.dart';
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
import 'package:refilc_kreta_api/models/grade.dart';
import 'package:refilc_mobile_ui/screens/settings/theme_screen.dart';
import 'submenu_screen.i18n.dart';
enum SelectedGrade { one, two, three, four, five }
class GradeColorsSettingsScreen extends StatefulWidget {
const GradeColorsSettingsScreen({super.key});
@override
GradeColorsSettingsScreenState createState() =>
GradeColorsSettingsScreenState();
}
class GradeColorsSettingsScreenState extends State<GradeColorsSettingsScreen> {
late SettingsProvider settingsProvider;
SelectedGrade currentEditGrade = SelectedGrade.one;
@override
Widget build(BuildContext context) {
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
return Scaffold(
appBar: AppBar(
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
leading: BackButton(
color: AppColors.of(context).text,
onPressed: () {
setState(() {
// made this cuz else it will be ugly
currentEditGrade = SelectedGrade.one;
});
Navigator.of(context).pop();
},
),
title: Text(
"grade_colors".i18n,
style: TextStyle(color: AppColors.of(context).text),
),
actions: [
IconButton(
onPressed: () {
List<Color> colors = List.castFrom(settingsProvider.gradeColors);
var defaultColors =
SettingsProvider.defaultSettings().gradeColors;
colors[currentEditGrade.index] =
defaultColors[currentEditGrade.index];
settingsProvider.update(gradeColors: colors);
},
icon: const Icon(
Icons.restore,
size: 26.0,
),
),
const SizedBox(
width: 10.0,
),
],
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.14,
),
Stack(
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(75.0),
boxShadow: [
BoxShadow(
color: Theme.of(context)
.colorScheme
.shadow
.withOpacity(.1),
blurRadius: 10.0,
offset: const Offset(0, 5),
),
],
),
padding: const EdgeInsets.all(6.0),
child: GradeValueWidget(
GradeValue(currentEditGrade.index + 1, '', '', 100),
fill: true,
size: 75.0,
// color:
// settingsProvider.gradeColors[currentEditGrade.index],
),
),
// before grades
if (currentEditGrade.index > 0)
Transform.translate(
offset: const Offset(-110, 16.5),
child: GradeValueWidget(
GradeValue(currentEditGrade.index, '', '', 100),
fill: true,
size: 60.0,
// color:
// settingsProvider.gradeColors[currentEditGrade.index],
),
),
if (currentEditGrade.index > 1)
Transform.translate(
offset: const Offset(-200, 23),
child: GradeValueWidget(
GradeValue(currentEditGrade.index - 1, '', '', 100),
fill: true,
size: 50.0,
// color:
// settingsProvider.gradeColors[currentEditGrade.index],
),
),
// after grades
if (currentEditGrade.index < 4)
Transform.translate(
offset: const Offset(142, 16.5),
child: GradeValueWidget(
GradeValue(currentEditGrade.index + 2, '', '', 100),
fill: true,
size: 60.0,
// color:
// settingsProvider.gradeColors[currentEditGrade.index],
),
),
if (currentEditGrade.index < 3)
Transform.translate(
offset: const Offset(245, 23),
child: GradeValueWidget(
GradeValue(currentEditGrade.index + 3, '', '', 100),
fill: true,
size: 50.0,
// color:
// settingsProvider.gradeColors[currentEditGrade.index],
),
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.14,
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: SafeArea(
child: FilcColorPicker(
colorMode: CustomColorMode.grade,
pickerColor:
settingsProvider.gradeColors[currentEditGrade.index],
onColorChanged: (c) {
setState(() {
// update grade color
settingsProvider.update(
gradeColors: settingsProvider.gradeColors
..[currentEditGrade.index] = c);
});
},
onColorChangeEnd: (c, {adaptive}) {
// update grade color
},
onThemeIdProvided: (t) {},
),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 20.0, top: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () => setState(() {
currentEditGrade = SelectedGrade.one;
}),
child: Container(
width: 45.0,
height: 45.0,
decoration: BoxDecoration(
border: Border.all(
color: currentEditGrade == SelectedGrade.one
? Theme.of(context).colorScheme.secondary
: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.2),
width: 1.0,
),
borderRadius: BorderRadius.circular(50.0),
color: currentEditGrade == SelectedGrade.one
? Theme.of(context).colorScheme.secondary
: null,
),
child: Center(
child: Text(
'1',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: currentEditGrade == SelectedGrade.one
? Colors.white
: null,
),
),
),
),
),
const SizedBox(width: 10.0),
GestureDetector(
onTap: () => setState(() {
currentEditGrade = SelectedGrade.two;
}),
child: Container(
width: 45.0,
height: 45.0,
decoration: BoxDecoration(
border: Border.all(
color: currentEditGrade == SelectedGrade.two
? Theme.of(context).colorScheme.secondary
: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.2),
width: 1.0,
),
borderRadius: BorderRadius.circular(50.0),
color: currentEditGrade == SelectedGrade.two
? Theme.of(context).colorScheme.secondary
: null,
),
child: Center(
child: Text(
'2',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: currentEditGrade == SelectedGrade.two
? Colors.white
: null,
),
),
),
),
),
const SizedBox(width: 10.0),
GestureDetector(
onTap: () => setState(() {
currentEditGrade = SelectedGrade.three;
}),
child: Container(
width: 45.0,
height: 45.0,
decoration: BoxDecoration(
border: Border.all(
color: currentEditGrade == SelectedGrade.three
? Theme.of(context).colorScheme.secondary
: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.2),
width: 1.0,
),
borderRadius: BorderRadius.circular(50.0),
color: currentEditGrade == SelectedGrade.three
? Theme.of(context).colorScheme.secondary
: null,
),
child: Center(
child: Text(
'3',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: currentEditGrade == SelectedGrade.three
? Colors.white
: null,
),
),
),
),
),
const SizedBox(width: 10.0),
GestureDetector(
onTap: () => setState(() {
currentEditGrade = SelectedGrade.four;
}),
child: Container(
width: 45.0,
height: 45.0,
decoration: BoxDecoration(
border: Border.all(
color: currentEditGrade == SelectedGrade.four
? Theme.of(context).colorScheme.secondary
: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.2),
width: 1.0,
),
borderRadius: BorderRadius.circular(50.0),
color: currentEditGrade == SelectedGrade.four
? Theme.of(context).colorScheme.secondary
: null,
),
child: Center(
child: Text(
'4',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: currentEditGrade == SelectedGrade.four
? Colors.white
: null,
),
),
),
),
),
const SizedBox(width: 10.0),
GestureDetector(
onTap: () => setState(() {
currentEditGrade = SelectedGrade.five;
}),
child: Container(
width: 45.0,
height: 45.0,
decoration: BoxDecoration(
border: Border.all(
color: currentEditGrade == SelectedGrade.five
? Theme.of(context).colorScheme.secondary
: Theme.of(context)
.colorScheme
.secondary
.withOpacity(.2),
width: 1.0,
),
borderRadius: BorderRadius.circular(50.0),
color: currentEditGrade == SelectedGrade.five
? Theme.of(context).colorScheme.secondary
: null,
),
child: Center(
child: Text(
'5',
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w600,
color: currentEditGrade == SelectedGrade.five
? Colors.white
: null,
),
),
),
),
),
],
),
),
],
),
],
),
),
);
}
}

View File

@@ -16,6 +16,7 @@ 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_mobile_ui/screens/settings/submenu/share_theme_popup.dart';
import 'package:share_plus/share_plus.dart';
class MenuPaintList extends StatelessWidget {
@@ -251,18 +252,7 @@ class PaintListScreenState extends State<PaintListScreen>
subject: 'share_subj_theme'.i18n,
);
} else {
SharedGradeColors gradeColors = await shareProvider
.shareCurrentGradeColors(context);
SharedTheme theme =
await shareProvider.shareCurrentTheme(
context,
gradeColors: gradeColors,
);
Share.share(
theme.id,
subject: 'share_subj_theme'.i18n,
);
ShareThemeDialog.show(context);
}
},
longPressInstead: true,

View File

@@ -30,6 +30,8 @@ import 'package:refilc_plus/providers/plus_provider.dart';
import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
import 'package:google_fonts/google_fonts.dart';
import 'grade_colors.dart';
class MenuPersonalizeSettings extends StatelessWidget {
const MenuPersonalizeSettings({
super.key,
@@ -459,6 +461,49 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
),
],
),
// new popup toggle
SplittedPanel(
padding: const EdgeInsets.only(top: 9.0),
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
children: [
PanelButton(
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
onPressed: () async {
settingsProvider.update(
newPopups: !settingsProvider.newPopups);
setState(() {});
},
title: Text(
"new_popups".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(
settingsProvider.newPopups ? .95 : .25),
),
),
leading: Icon(
FeatherIcons.alertOctagon,
size: 22.0,
color: AppColors.of(context).text.withOpacity(
settingsProvider.newPopups ? .95 : .25),
),
trailing: Switch(
onChanged: (v) async {
settingsProvider.update(newPopups: v);
setState(() {});
},
value: settingsProvider.newPopups,
activeColor: Theme.of(context).colorScheme.secondary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(12.0),
),
),
],
),
// change subject icons
// SplittedPanel(
// padding: const EdgeInsets.only(top: 9.0),
@@ -499,8 +544,14 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
children: [
PanelButton(
onPressed: () {
SettingsHelper.gradeColors(context);
setState(() {});
// SettingsHelper.gradeColors(context);
// setState(() {});
Navigator.of(context, rootNavigator: true).push(
CupertinoPageRoute(
builder: (context) =>
const GradeColorsSettingsScreen(),
),
);
},
title: Text(
"grade_colors".i18n,
@@ -670,16 +721,6 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
children: [
PanelButton(
onPressed: () {
if (!Provider.of<PlusProvider>(context,
listen: false)
.hasScope(PremiumScopes.liveActivityColor)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.liveActivity,
);
return;
}
SettingsHelper.liveActivityColor(context);
setState(() {});
},
@@ -882,7 +923,7 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
title: Text('fonts'.i18n),
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.all(4.0),
isSeparated: true,
isSeparated: false,
children: [
PanelButton(
onPressed: () {
@@ -920,11 +961,72 @@ class PersonalizeSettingsScreenState extends State<PersonalizeSettingsScreen>
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(12.0),
bottom: Radius.circular(6.0),
),
),
PanelButton(
padding: const EdgeInsets.only(left: 14.0, right: 6.0),
onPressed: () async {
if (!Provider.of<PlusProvider>(context, listen: false)
.hasScope(PremiumScopes.customFont)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.fontChange);
return;
}
settingsProvider.update(
titleOnlyFont: !settingsProvider.titleOnlyFont);
Provider.of<ThemeModeObserver>(context, listen: false)
.changeTheme(settingsProvider.theme,
updateNavbarColor: false);
setState(() {});
},
title: Text(
"only_ch_title_font".i18n,
style: TextStyle(
color: AppColors.of(context).text.withOpacity(
settingsProvider.titleOnlyFont ? .95 : .25),
),
),
leading: Icon(
Icons.text_increase_rounded,
size: 22.0,
color: AppColors.of(context).text.withOpacity(
settingsProvider.titleOnlyFont ? .95 : .25),
),
trailing: Switch(
onChanged: (v) async {
if (!Provider.of<PlusProvider>(context,
listen: false)
.hasScope(PremiumScopes.customFont)) {
PlusLockedFeaturePopup.show(
context: context,
feature: PremiumFeature.fontChange);
return;
}
settingsProvider.update(titleOnlyFont: v);
Provider.of<ThemeModeObserver>(context,
listen: false)
.changeTheme(settingsProvider.theme,
updateNavbarColor: false);
setState(() {});
},
value: settingsProvider.titleOnlyFont,
activeColor: Theme.of(context).colorScheme.secondary,
),
borderRadius: const BorderRadius.vertical(
top: Radius.circular(4.0),
bottom: Radius.circular(12.0),
),
),
],
),
// bottom padding
const SizedBox(
height: 20.0,
),
],
),
),

View File

@@ -0,0 +1,160 @@
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
// import 'package:refilc/models/settings.dart';
import 'package:refilc/models/shared_theme.dart';
import 'package:refilc_kreta_api/providers/share_provider.dart';
import 'package:refilc_mobile_ui/common/action_button.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
import 'package:share_plus/share_plus.dart';
import 'submenu_screen.i18n.dart';
class ShareThemeDialog extends StatefulWidget {
const ShareThemeDialog({super.key});
static void show(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
title: Text("attention".i18n),
content: Text("share_disclaimer".i18n),
actions: [
ActionButton(
label: "understand".i18n,
onTap: () async {
Navigator.of(context).pop();
showDialog(
context: context,
builder: (context) => const ShareThemeDialog());
},
),
],
),
);
}
@override
ShareThemeDialogState createState() => ShareThemeDialogState();
}
class ShareThemeDialogState extends State<ShareThemeDialog> {
final _title = TextEditingController();
bool isPublic = false;
late ShareProvider shareProvider;
@override
void initState() {
super.initState();
shareProvider = Provider.of<ShareProvider>(context, listen: false);
}
@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("share_theme".i18n),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
child: TextField(
controller: _title,
onEditingComplete: () async {},
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: 'paint_title'.i18n,
suffixIcon: IconButton(
icon: const Icon(
FeatherIcons.x,
color: Colors.grey,
),
onPressed: () {
setState(() {
_title.text = '';
});
},
),
),
),
),
SplittedPanel(
children: [
SwitchListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
value: isPublic,
onChanged: (value) {
setState(() {
isPublic = value;
});
},
title: Text("is_public".i18n),
contentPadding: const EdgeInsets.only(left: 15.0, right: 10.0),
),
],
),
],
),
actions: [
TextButton(
child: Text(
"cancel".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () {
Navigator.of(context).maybePop();
},
),
TextButton(
child: Text(
"share_it".i18n,
style: const TextStyle(fontWeight: FontWeight.w500),
),
onPressed: () async {
// share the fucking theme
SharedGradeColors gradeColors =
await shareProvider.shareCurrentGradeColors(context);
SharedTheme theme = await shareProvider.shareCurrentTheme(
context,
gradeColors: gradeColors,
isPublic: isPublic,
displayName: _title.text,
);
// save theme id in settings
// Provider.of<SettingsProvider>(context, listen: false)
// .update(currentThemeId: theme.id);
// close this popup shit
Navigator.of(context).pop(true);
// show the share popup
Share.share(
theme.id,
subject: 'share_subj_theme'.i18n,
);
},
),
],
);
}
}

View File

@@ -17,6 +17,17 @@ extension SettingsLocalization on String {
"rare": "Rare",
"epic": "Epic",
"legendary": "Legendary",
// grade colors
"grade_colors": "Grade Colors",
// theme share popup
"share_theme": "Share Paint",
"paint_title": "Paint title...",
"share_it": "Share it!",
"is_public": "Public Paint",
"attention": "Attention!",
"share_disclaimer":
"By sharing the theme, you agree that the nickname you set and all settings of the theme will be shared publicly.",
"understand": "I understand",
},
"hu_hu": {
"general": "Általános",
@@ -32,6 +43,17 @@ extension SettingsLocalization on String {
"rare": "Ritka",
"epic": "Epikus",
"legendary": "Legendás",
// grade colors
"grade_colors": "Jegyek színei",
// theme share popup
"share_theme": "Téma megosztása",
"paint_title": "Téma neve...",
"share_it": "Megosztás!",
"is_public": "Nyilvános téma",
"attention": "Figyelem!",
"share_disclaimer":
"A téma megosztásával elfogadod, hogy az általad beállított becenév és a téma minden beállítása nyilvánosan megosztásra kerüljön.",
"understand": "Értem",
},
"de_de": {
"general": "Allgemeine",
@@ -47,6 +69,17 @@ extension SettingsLocalization on String {
"rare": "Selten",
"epic": "Episch",
"legendary": "Legendär",
// grade colors
"grade_colors": "Notenfarben",
// theme share popup
"share_theme": "Thema teilen",
"paint_title": "Thema Titel...",
"share_it": "Teilen!",
"is_public": "Öffentliches Thema",
"attention": "Achtung!",
"share_disclaimer":
"Durch das Teilen des Themes erklären Sie sich damit einverstanden, dass der von Ihnen festgelegte Spitzname und alle Einstellungen des Themes öffentlich geteilt werden.",
"understand": "Ich verstehe",
},
};

View File

@@ -1,7 +1,7 @@
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
import 'package:refilc/models/settings.dart';
import 'package:refilc/models/shared_theme.dart';
// import 'package:refilc/models/shared_theme.dart';
import 'package:refilc/theme/colors/accent.dart';
import 'package:refilc/theme/colors/colors.dart';
import 'package:refilc/theme/observer.dart';
@@ -10,7 +10,7 @@ import 'package:refilc/ui/widgets/message/message_tile.dart';
import 'package:refilc_kreta_api/models/grade.dart';
import 'package:refilc_kreta_api/models/homework.dart';
import 'package:refilc_kreta_api/models/message.dart';
import 'package:refilc_mobile_ui/common/action_button.dart';
// import 'package:refilc_mobile_ui/common/action_button.dart';
import 'package:refilc_mobile_ui/common/filter_bar.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart';
import 'package:refilc_mobile_ui/common/widgets/grade/new_grades.dart';
@@ -24,6 +24,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'package:refilc_mobile_ui/screens/settings/submenu/share_theme_popup.dart';
import 'theme_screen.i18n.dart';
import 'package:share_plus/share_plus.dart';
@@ -44,6 +45,7 @@ enum CustomColorMode {
text,
icon,
enterId,
grade,
}
class _PremiumCustomAccentColorSettingState
@@ -158,6 +160,9 @@ class _PremiumCustomAccentColorSettingState
case CustomColorMode.enterId:
// do nothing here lol
break;
case CustomColorMode.grade:
// do nothing here as well
break;
}
}
@@ -218,6 +223,9 @@ class _PremiumCustomAccentColorSettingState
settings.update(customAccentColor: accent, store: store);
settings.update(customIconColor: icon, store: store);
break;
case CustomColorMode.grade:
// do nothing
break;
}
}
@@ -297,40 +305,48 @@ class _PremiumCustomAccentColorSettingState
// ),
// ),
// );
showDialog(
context: context,
builder: (context) => WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
title: Text("attention".i18n),
content: Text("share_disclaimer".i18n),
actions: [
ActionButton(
label: "understand".i18n,
onTap: () async {
Navigator.of(context).pop();
// showDialog(
// context: context,
// builder: (context) => WillPopScope(
// onWillPop: () async => false,
// child: AlertDialog(
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(12.0)),
// title: Text("attention".i18n),
// content: Text("share_disclaimer".i18n),
// actions: [
// ActionButton(
// label: "understand".i18n,
// onTap: () async {
// Navigator.of(context).pop();
SharedGradeColors gradeColors =
await shareProvider
.shareCurrentGradeColors(context);
SharedTheme theme =
await shareProvider.shareCurrentTheme(
context,
gradeColors: gradeColors,
);
// SharedGradeColors gradeColors =
// await shareProvider
// .shareCurrentGradeColors(context);
// SharedTheme theme =
// await shareProvider.shareCurrentTheme(
// context,
// gradeColors: gradeColors,
// );
Share.share(
theme.id,
subject: 'share_subj_theme'.i18n,
);
},
),
],
),
),
);
// Share.share(
// theme.id,
// subject: 'share_subj_theme'.i18n,
// );
// },
// ),
// ],
// ),
// ),
// );
if (settings.currentThemeId != '') {
Share.share(
settings.currentThemeId,
subject: 'share_subj_theme'.i18n,
);
} else {
ShareThemeDialog.show(context);
}
},
icon: const Icon(
FeatherIcons.share2,