diff --git a/assets/data/nollning_26/nolleguide/studentlife/building_blocks/wall_edge.png b/assets/data/nollning_26/nolleguide/studentlife/building_blocks/wall_edge.png index 329c3fa8..d8fb7b1e 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/building_blocks/wall_edge.png and b/assets/data/nollning_26/nolleguide/studentlife/building_blocks/wall_edge.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_en.png deleted file mode 100644 index 061727ce..00000000 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_en.png and /dev/null differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_sv.png deleted file mode 100644 index 0c4d0cdd..00000000 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_boardmember_sv.png and /dev/null differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_en.png index 0996f701..157834c6 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_sv.png index 0de9c970..a771fd1d 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_bookfos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_en.png index f4c5742c..676e8968 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_sv.png index ab03648b..31422948 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_eventfos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_en.png index f4d79a6b..af0d55d2 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_sv.png index f100e38d..e8714def 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_fadderfos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_en.png index a688e7b3..243b7da1 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_sv.png index c5719552..f2a25b63 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_infofos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_en.png index b92aa8b5..834b15aa 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_sv.png index ba782716..384c577b 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_overfos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_en.png index 68b8df2f..226c2300 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_sv.png index 7142ece4..7954de8f 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sigmafos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_en.png index e80e1e6e..e8992cd8 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_en.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_sv.png index 15c8479b..5d304667 100644 Binary files a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_sv.png and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_sponsfos_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_en.png new file mode 100644 index 00000000..b8c1f48b Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_sv.png new file mode 100644 index 00000000..371afbe6 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse1_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_en.png new file mode 100644 index 00000000..3a577b77 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_sv.png new file mode 100644 index 00000000..963622d0 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse2_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_en.png new file mode 100644 index 00000000..46163801 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_sv.png new file mode 100644 index 00000000..6929e4e9 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse3_sv.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_en.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_en.png new file mode 100644 index 00000000..7efd9c69 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_en.png differ diff --git a/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_sv.png b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_sv.png new file mode 100644 index 00000000..ee735f47 Binary files /dev/null and b/assets/data/nollning_26/nolleguide/studentlife/guild/portrait_styrelse4_sv.png differ diff --git a/lib/content_wrapper.dart b/lib/content_wrapper.dart index 645c7b54..ae36f911 100644 --- a/lib/content_wrapper.dart +++ b/lib/content_wrapper.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'models/destination.dart'; import 'models/user/user.dart'; import 'widgets/bottom_app_bar.dart'; +import 'widgets/verification_banner.dart'; import 'package:fsek_mobile/l10n/app_localizations.dart'; import 'package:audioplayers/audioplayers.dart'; @@ -201,6 +202,7 @@ class _ContentWrapperState extends State view); //move offstage to ensure they aren't painted when not visible } }).toList())), + VerificationBanner(), ])), bottomNavigationBar: BottomAppBar( shape: CircularNotchedRectangle(), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 261aa78c..eb36009d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -14,6 +14,12 @@ "other" : "Other", "introduction" : "Introduction", + "verifyEmailBanner": "Your account is not verified. Verify your email to get full access.", + "verifyEmailAction": "Send email", + "verifyEmailSent": "A verification email has been sent.", + "verifyEmailSentShort": "Sent", + "verifyEmailFailed": "Could not send verification email, please try again later.", + "loginRequiredField": "Required field", "loginEmail": "Email", "loginPassword": "Password", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 1de7f910..1409eef9 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -164,6 +164,36 @@ abstract class AppLocalizations { /// **'Nollning'** String get introduction; + /// No description provided for @verifyEmailBanner. + /// + /// In sv, this message translates to: + /// **'Ditt konto är inte verifierat. Verifiera din e-post för att få full åtkomst.'** + String get verifyEmailBanner; + + /// No description provided for @verifyEmailAction. + /// + /// In sv, this message translates to: + /// **'Skicka mejl'** + String get verifyEmailAction; + + /// No description provided for @verifyEmailSent. + /// + /// In sv, this message translates to: + /// **'Ett verifieringsmejl har skickats.'** + String get verifyEmailSent; + + /// No description provided for @verifyEmailSentShort. + /// + /// In sv, this message translates to: + /// **'Skickat'** + String get verifyEmailSentShort; + + /// No description provided for @verifyEmailFailed. + /// + /// In sv, this message translates to: + /// **'Kunde inte skicka verifieringsmejl, försök igen senare.'** + String get verifyEmailFailed; + /// No description provided for @loginRequiredField. /// /// In sv, this message translates to: diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index fc814a4d..374ca121 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -41,6 +41,23 @@ class AppLocalizationsEn extends AppLocalizations { @override String get introduction => 'Introduction'; + @override + String get verifyEmailBanner => + 'Your account is not verified. Verify your email to get full access.'; + + @override + String get verifyEmailAction => 'Send email'; + + @override + String get verifyEmailSent => 'A verification email has been sent.'; + + @override + String get verifyEmailSentShort => 'Sent'; + + @override + String get verifyEmailFailed => + 'Could not send verification email, please try again later.'; + @override String get loginRequiredField => 'Required field'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index feb09ede..1f85faf0 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -41,6 +41,23 @@ class AppLocalizationsSv extends AppLocalizations { @override String get introduction => 'Nollning'; + @override + String get verifyEmailBanner => + 'Ditt konto är inte verifierat. Verifiera din e-post för att få full åtkomst.'; + + @override + String get verifyEmailAction => 'Skicka mejl'; + + @override + String get verifyEmailSent => 'Ett verifieringsmejl har skickats.'; + + @override + String get verifyEmailSentShort => 'Skickat'; + + @override + String get verifyEmailFailed => + 'Kunde inte skicka verifieringsmejl, försök igen senare.'; + @override String get loginRequiredField => 'Obligatoriskt fält'; diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index f67986e4..540b735a 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -14,6 +14,12 @@ "other" : "Övrigt", "introduction" : "Nollning", + "verifyEmailBanner": "Ditt konto är inte verifierat. Verifiera din e-post för att få full åtkomst.", + "verifyEmailAction": "Skicka mejl", + "verifyEmailSent": "Ett verifieringsmejl har skickats.", + "verifyEmailSentShort": "Skickat", + "verifyEmailFailed": "Kunde inte skicka verifieringsmejl, försök igen senare.", + "loginRequiredField": "Obligatoriskt fält", "loginEmail": "E-postadress", "loginPassword": "Lösenord", diff --git a/lib/screens/nollning/nolleguide_26/guild.dart b/lib/screens/nollning/nolleguide_26/guild.dart index 487ad46e..d8efc43c 100644 --- a/lib/screens/nollning/nolleguide_26/guild.dart +++ b/lib/screens/nollning/nolleguide_26/guild.dart @@ -97,7 +97,6 @@ class _GuildPageState extends State { } final String boardPortrait = portrait("board"); - final String boardmemberPortrait = portrait("boardmember"); final String bookPortrait = portrait("book"); final String bookfosPortrait = portrait("bookfos"); final String cafePortrait = portrait("cafe"); @@ -123,6 +122,10 @@ class _GuildPageState extends State { final String spiderPortrait = portrait("spider"); final String sponsfosPortrait = portrait("sponsfos"); final String sportPortrait = portrait("sport"); + final String styrelse1Portrait = portrait("styrelse1"); + final String styrelse2Portrait = portrait("styrelse2"); + final String styrelse3Portrait = portrait("styrelse3"); + final String styrelse4Portrait = portrait("styrelse4"); final String tavernPortrait = portrait("tavern"); final String treasurerPortrait = portrait("treasurer"); final String truthPortrait = portrait("truth"); @@ -176,8 +179,16 @@ class _GuildPageState extends State { onTap: () => pushNavigator(index: 9, imagePath: boardPortrait)), ]), PortraitRow(portraits: [ - PortraitData(imagePath: boardmemberPortrait, flex: smallPortraitFlex, - onTap: () => pushNavigator(index: 10, imagePath: boardmemberPortrait)), + PortraitData(imagePath: styrelse1Portrait, flex: doublePortraitFlex, + onTap: () => pushNavigator(index: 10, imagePath: styrelse1Portrait)), + PortraitData(imagePath: styrelse2Portrait, flex: doublePortraitFlex, + onTap: () => pushNavigator(index: 10, imagePath: styrelse2Portrait)), + ]), + PortraitRow(portraits: [ + PortraitData(imagePath: styrelse3Portrait, flex: doublePortraitFlex, + onTap: () => pushNavigator(index: 10, imagePath: styrelse3Portrait)), + PortraitData(imagePath: styrelse4Portrait, flex: doublePortraitFlex, + onTap: () => pushNavigator(index: 10, imagePath: styrelse4Portrait)), ]), Image.asset(studentcouncilTitle), PortraitRow(portraits: [ diff --git a/lib/widgets/verification_banner.dart b/lib/widgets/verification_banner.dart new file mode 100644 index 00000000..92ceb95b --- /dev/null +++ b/lib/widgets/verification_banner.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:fsek_mobile/api_client/lib/api_client.dart'; +import 'package:fsek_mobile/services/api.service.dart'; +import 'package:fsek_mobile/l10n/app_localizations.dart'; + +// Banner shown above the navbar when the user has not verified their email. +class VerificationBanner extends StatefulWidget { + const VerificationBanner({Key? key}) : super(key: key); + + @override + _VerificationBannerState createState() => _VerificationBannerState(); +} + +class _VerificationBannerState extends State + with WidgetsBindingObserver { + AdminUserRead? user; + bool sending = false; + bool sent = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + _loadUser(); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // Re-check when coming back to the app + if (state == AppLifecycleState.resumed) { + _loadUser(); + } + } + + Future _loadUser() async { + try { + final response = await ApiService.apiClient.getUsersApi().usersGetMe(); + if (!mounted) return; + setState(() { + user = response.data; + }); + } catch (error) { + // If we can't fetch the user we simply don't show the banner + } + } + + Future _requestVerification() async { + final email = user?.email; + if (email == null || sending) return; + setState(() { + sending = true; + }); + var t = AppLocalizations.of(context)!; + try { + await ApiService.apiClient.getAuthApi().authVerifyRequestToken( + bodyAuthVerifyRequestToken: BodyAuthVerifyRequestToken( + (b) => b..email = email, + ), + ); + if (!mounted) return; + setState(() { + sending = false; + sent = true; + }); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(t.verifyEmailSent))); + } catch (error) { + if (!mounted) return; + setState(() { + sending = false; + }); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(t.verifyEmailFailed))); + } + } + + @override + Widget build(BuildContext context) { + // Only show the banner once we know the user isn't verified + if (user == null || user!.isVerified != false) { + return SizedBox.shrink(); + } + + var t = AppLocalizations.of(context)!; + ColorScheme colors = Theme.of(context).colorScheme; + + return Material( + color: colors.errorContainer, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( + children: [ + Icon( + Icons.warning_amber_rounded, + color: colors.onErrorContainer, + size: 22, + ), + SizedBox(width: 10), + Expanded( + child: Text( + t.verifyEmailBanner, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: colors.onErrorContainer, + ), + ), + ), + SizedBox(width: 8), + TextButton( + onPressed: (sending || sent) ? null : _requestVerification, + style: TextButton.styleFrom( + foregroundColor: colors.onPrimary, + padding: EdgeInsets.symmetric(horizontal: 8), + minimumSize: Size(0, 32), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + child: sending + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: colors.onErrorContainer, + ), + ) + : Text(sent ? t.verifyEmailSentShort : t.verifyEmailAction), + ), + ], + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 12e577de..243d9aff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ description: Mobile application for the F-guild # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # -version: 1.29.6122+1 +version: 1.30.6122+1 environment: sdk: '>=3.10.0 <4.0.0'