Skip to content

Commit

Permalink
Refactor common widgets (#903)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdmendes authored Jan 26, 2024
2 parents cb6bcec + 720e61e commit c497f79
Show file tree
Hide file tree
Showing 21 changed files with 425 additions and 173 deletions.
1 change: 0 additions & 1 deletion uni/lib/controller/local_storage/file_offline_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:http/http.dart' as http;
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:uni/controller/networking/network_router.dart';

import 'package:uni/model/entities/session.dart';

/// The offline image storage location on the device.
Expand Down
6 changes: 3 additions & 3 deletions uni/lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ class MessageLookup extends MessageLookupByLibrary {
"edit_on": MessageLookupByLibrary.simpleMessage("Finish editing"),
"empty_text":
MessageLookupByLibrary.simpleMessage("Please fill in this field"),
"exam_of": MessageLookupByLibrary.simpleMessage("of"),
"exams_filter":
MessageLookupByLibrary.simpleMessage("Exams Filter Settings"),
"exit_confirm":
Expand Down Expand Up @@ -187,10 +186,10 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("No favorite restaurants"),
"no_info": MessageLookupByLibrary.simpleMessage(
"There is no information to display"),
"no_link":
MessageLookupByLibrary.simpleMessage("We couldn\'t open the link"),
"no_library_info": MessageLookupByLibrary.simpleMessage(
"No library occupation information available"),
"no_link":
MessageLookupByLibrary.simpleMessage("We couldn\'t open the link"),
"no_menu_info": MessageLookupByLibrary.simpleMessage(
"There is no information available about meals"),
"no_menus": MessageLookupByLibrary.simpleMessage(
Expand All @@ -211,6 +210,7 @@ class MessageLookup extends MessageLookupByLibrary {
"notifications": MessageLookupByLibrary.simpleMessage("Notifications"),
"occurrence_type":
MessageLookupByLibrary.simpleMessage("Type of occurrence"),
"of_month": MessageLookupByLibrary.simpleMessage("of"),
"other_links": MessageLookupByLibrary.simpleMessage("Other links"),
"pass_change_request": MessageLookupByLibrary.simpleMessage(
"For security reasons, passwords must be changed periodically."),
Expand Down
6 changes: 3 additions & 3 deletions uni/lib/generated/intl/messages_pt_PT.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ class MessageLookup extends MessageLookupByLibrary {
"edit_on": MessageLookupByLibrary.simpleMessage("Concluir edição"),
"empty_text": MessageLookupByLibrary.simpleMessage(
"Por favor preenche este campo"),
"of_month": MessageLookupByLibrary.simpleMessage("de"),
"exams_filter":
MessageLookupByLibrary.simpleMessage("Definições Filtro de Exames"),
"exit_confirm": MessageLookupByLibrary.simpleMessage(
Expand Down Expand Up @@ -188,10 +187,10 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Sem restaurantes favoritos"),
"no_info": MessageLookupByLibrary.simpleMessage(
"Não existem informações para apresentar"),
"no_link": MessageLookupByLibrary.simpleMessage(
"Não conseguimos abrir o link"),
"no_library_info":
MessageLookupByLibrary.simpleMessage("Sem informação de ocupação"),
"no_link": MessageLookupByLibrary.simpleMessage(
"Não conseguimos abrir o link"),
"no_menu_info": MessageLookupByLibrary.simpleMessage(
"Não há informação disponível sobre refeições"),
"no_menus": MessageLookupByLibrary.simpleMessage(
Expand All @@ -212,6 +211,7 @@ class MessageLookup extends MessageLookupByLibrary {
"notifications": MessageLookupByLibrary.simpleMessage("Notificações"),
"occurrence_type":
MessageLookupByLibrary.simpleMessage("Tipo de ocorrência"),
"of_month": MessageLookupByLibrary.simpleMessage("de"),
"other_links": MessageLookupByLibrary.simpleMessage("Outros links"),
"pass_change_request": MessageLookupByLibrary.simpleMessage(
"Por razões de segurança, as palavras-passe têm de ser alteradas periodicamente."),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';

import 'package:uni/model/entities/location.dart';

class SpecialRoomLocation implements Location {
Expand Down
1 change: 0 additions & 1 deletion uni/lib/model/entities/locations/store_location.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';

import 'package:uni/model/entities/location.dart';

class StoreLocation implements Location {
Expand Down
1 change: 0 additions & 1 deletion uni/lib/model/entities/locations/unknown_location.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';

import 'package:uni/model/entities/location.dart';

class UnknownLocation implements Location {
Expand Down
88 changes: 41 additions & 47 deletions uni/lib/view/common_widgets/generic_card.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:uni/model/entities/time_utilities.dart';
import 'package:uni/view/common_widgets/widgets/delete_icon.dart';
import 'package:uni/view/common_widgets/widgets/move_icon.dart';

/// App default card
abstract class GenericCard extends StatefulWidget {
abstract class GenericCard extends StatelessWidget {
GenericCard({Key? key})
: this.customStyle(key: key, editingMode: false, onDelete: () {});

Expand All @@ -23,17 +26,16 @@ abstract class GenericCard extends StatefulWidget {
this.margin = const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
this.hasSmallTitle = false,
});

static const double borderRadius = 10;
static const double padding = 12;

final EdgeInsetsGeometry margin;
final Widget cardAction;
final bool hasSmallTitle;
final bool editingMode;
final void Function()? onDelete;

@override
State<StatefulWidget> createState() {
return GenericCardState();
}

Widget buildCardContent(BuildContext context);

String getTitle(BuildContext context);
Expand All @@ -49,29 +51,43 @@ abstract class GenericCard extends StatefulWidget {
style: Theme.of(context).textTheme.titleLarge,
);
}
}

class GenericCardState extends State<GenericCard> {
final double borderRadius = 10;
final double padding = 12;
StatelessWidget showLastRefreshedTime(String? time, BuildContext context) {
if (time == null) {
return const Text('N/A');
}

final parsedTime = DateTime.tryParse(time);
if (parsedTime == null) {
return const Text('N/A');
}

return Container(
alignment: Alignment.center,
child: Text(
'última atualização às ${parsedTime.toTimeHourMinString()}',
style: Theme.of(context).textTheme.bodySmall,
),
);
}

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (!widget.editingMode) {
widget.onClick(context);
if (!editingMode) {
onClick(context);
}
},
child: Card(
margin: widget.margin,
margin: margin,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadius),
),
child: DecoratedBox(
decoration: BoxDecoration(
boxShadow: const [
decoration: const BoxDecoration(
boxShadow: [
BoxShadow(
color: Color.fromARGB(0x1c, 0, 0, 0),
blurRadius: 7,
Expand All @@ -87,7 +103,8 @@ class GenericCardState extends State<GenericCard> {
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
borderRadius:
const BorderRadius.all(Radius.circular(borderRadius)),
),
width: double.infinity,
child: Column(
Expand All @@ -103,8 +120,8 @@ class GenericCardState extends State<GenericCard> {
padding: const EdgeInsets.symmetric(horizontal: 15),
margin: const EdgeInsets.only(top: 15, bottom: 10),
child: Text(
widget.getTitle(context),
style: (widget.hasSmallTitle
getTitle(context),
style: (hasSmallTitle
? Theme.of(context).textTheme.titleLarge!
: Theme.of(context)
.textTheme
Expand All @@ -115,23 +132,23 @@ class GenericCardState extends State<GenericCard> {
),
),
),
widget.cardAction,
if (widget.editingMode)
cardAction,
if (editingMode)
Container(
alignment: Alignment.center,
margin: const EdgeInsets.only(top: 8),
child: getMoveIcon(context),
child: const MoveIcon(),
),
if (widget.editingMode) getDeleteIcon(context),
if (editingMode) DeleteIcon(onDelete: onDelete),
],
),
Container(
padding: EdgeInsets.only(
padding: const EdgeInsets.only(
left: padding,
right: padding,
bottom: padding,
),
child: widget.buildCardContent(context),
child: buildCardContent(context),
),
],
),
Expand All @@ -141,27 +158,4 @@ class GenericCardState extends State<GenericCard> {
),
);
}

Widget getDeleteIcon(BuildContext context) {
return Flexible(
child: Container(
alignment: Alignment.centerRight,
height: 32,
child: IconButton(
iconSize: 22,
icon: const Icon(Icons.delete),
tooltip: 'Remover',
onPressed: widget.onDelete,
),
),
);
}

Widget getMoveIcon(BuildContext context) {
return Icon(
Icons.drag_handle_rounded,
color: Colors.grey.shade500,
size: 22,
);
}
}
98 changes: 11 additions & 87 deletions uni/lib/view/common_widgets/pages_layouts/general/general.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:logger/logger.dart';
import 'package:provider/provider.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:uni/model/providers/startup/profile_provider.dart';
import 'package:uni/model/providers/startup/session_provider.dart';
import 'package:uni/utils/drawer_items.dart';
import 'package:uni/view/common_widgets/pages_layouts/general/widgets/app_bar.dart';
import 'package:uni/view/common_widgets/pages_layouts/general/widgets/navigation_drawer.dart';
import 'package:uni/view/profile/profile.dart';
import 'package:uni/view/common_widgets/pages_layouts/general/widgets/profile_button.dart';
import 'package:uni/view/common_widgets/pages_layouts/general/widgets/refresh_state.dart';

/// Page with a hamburger menu and the user profile picture
abstract class GeneralPageViewState<T extends StatefulWidget> extends State<T> {
final double borderMargin = 18;
bool _loadedOnce = false;
bool _loading = true;
static ImageProvider? profileImageProvider;

Future<void> onRefresh(BuildContext context);

Expand Down Expand Up @@ -116,92 +117,15 @@ abstract class GeneralPageViewState<T extends StatefulWidget> extends State<T> {

Widget getScaffold(BuildContext context, Widget body) {
return Scaffold(
appBar: buildAppBar(context),
drawer: AppNavigationDrawer(parentContext: context),
body: refreshState(context, body),
);
}

/// Builds the upper bar of the app.
///
/// This method returns an instance of `AppBar` containing the app's logo,
/// an option button and a button with the user's picture.
AppBar buildAppBar(BuildContext context) {
final queryData = MediaQuery.of(context);

return AppBar(
bottom: PreferredSize(
preferredSize: Size.zero,
child: Container(
color: Theme.of(context).dividerColor,
margin: EdgeInsets.only(left: borderMargin, right: borderMargin),
height: 1.5,
),
appBar: CustomAppBar(getTopRightButton: getTopRightButton),
drawer: AppNavigationDrawer(
parentContext: context,
),
elevation: 0,
iconTheme: Theme.of(context).iconTheme,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
titleSpacing: 0,
title: ButtonTheme(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: const RoundedRectangleBorder(),
child: Builder(
builder: (context) => TextButton(
onPressed: () {
final currentRouteName = ModalRoute.of(context)!.settings.name;
if (currentRouteName != '/${DrawerItem.navPersonalArea.title}') {
Navigator.pushNamed(
context,
'/${DrawerItem.navPersonalArea.title}',
);
} else {
Scaffold.of(context).openDrawer();
}
},
child: SvgPicture.asset(
colorFilter: ColorFilter.mode(
Theme.of(context).primaryColor,
BlendMode.srcIn,
),
'assets/images/logo_dark.svg',
height: queryData.size.height / 25,
),
),
),
),
actions: <Widget>[
getTopRightButton(context),
],
body: RefreshState(onRefresh: onRefresh, child: body),
);
}

// Gets a round shaped button with the photo of the current user.
Widget getTopRightButton(BuildContext context) {
return FutureBuilder(
future: buildProfileDecorationImage(context),
builder: (
BuildContext context,
AsyncSnapshot<DecorationImage> decorationImage,
) {
return TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute<ProfilePageView>(
builder: (__) => const ProfilePageView(),
),
),
},
child: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: decorationImage.data,
),
),
);
},
);
}
/// Gets a round shaped button with the photo of the current user.
Widget getTopRightButton(BuildContext context) =>
ProfileButton(getProfileDecorationImage: getProfileDecorationImage);
}
Loading

0 comments on commit c497f79

Please sign in to comment.