[new look] first draft finished
This commit is contained in:
		
							parent
							
								
									ac803d3e71
								
							
						
					
					
						commit
						c716de3e02
					
				
					 32 changed files with 856 additions and 987 deletions
				
			
		
							
								
								
									
										48
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								Dockerfile
									
									
									
									
									
								
							| 
						 | 
					@ -1,45 +1,13 @@
 | 
				
			||||||
FROM debian:stable-slim AS build-env
 | 
					# BUILD
 | 
				
			||||||
 | 
					FROM node:16.14-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# install all needed stuff
 | 
					COPY ./build/web /app
 | 
				
			||||||
RUN apt-get update
 | 
					 | 
				
			||||||
RUN apt-get install -y curl git unzip
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# define variables
 | 
					WORKDIR /app/
 | 
				
			||||||
ARG FLUTTER_SDK=/usr/local/flutter
 | 
					 | 
				
			||||||
ARG FLUTTER_VERSION=3.10.5
 | 
					 | 
				
			||||||
ARG APP=/app/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#clone flutter
 | 
					RUN apk --no-cache add curl
 | 
				
			||||||
RUN git clone https://github.com/flutter/flutter.git $FLUTTER_SDK
 | 
					RUN npm install --global http-server
 | 
				
			||||||
# change dir to current flutter folder and make a checkout to the specific version
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# setup the flutter path as an enviromental variable
 | 
					 | 
				
			||||||
ENV PATH="$FLUTTER_SDK/bin:$FLUTTER_SDK/bin/cache/dart-sdk/bin:${PATH}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Start to run Flutter commands
 | 
					 | 
				
			||||||
# doctor to see if all was installes ok
 | 
					 | 
				
			||||||
RUN flutter doctor -v
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# create folder to copy source code
 | 
					 | 
				
			||||||
RUN mkdir $APP
 | 
					 | 
				
			||||||
# copy source code to folder
 | 
					 | 
				
			||||||
COPY . $APP
 | 
					 | 
				
			||||||
# stup new folder as the working directory
 | 
					 | 
				
			||||||
WORKDIR $APP
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Run build: 1 - clean, 2 - pub get, 3 - build web
 | 
					 | 
				
			||||||
RUN flutter clean
 | 
					 | 
				
			||||||
RUN flutter pub get
 | 
					 | 
				
			||||||
RUN flutter build web
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# once heare the app will be compiled and ready to deploy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# use nginx to deploy
 | 
					 | 
				
			||||||
FROM nginx:1.25.2-alpine
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# copy the info of the builded web app to nginx
 | 
					 | 
				
			||||||
COPY --from=build-env /app/build/web /usr/share/nginx/html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Expose and run nginx
 | 
					 | 
				
			||||||
EXPOSE 80
 | 
					EXPOSE 80
 | 
				
			||||||
CMD ["nginx", "-g", "daemon off;"]
 | 
					
 | 
				
			||||||
 | 
					CMD ["npx", "http-server", "-p", "80"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
					@ -9,6 +9,7 @@ endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: build
 | 
					.PHONY: build
 | 
				
			||||||
build:
 | 
					build:
 | 
				
			||||||
 | 
						flutter build web
 | 
				
			||||||
	$(DOCKER_BUILD) -t registry.domandoman.xyz/fooder/app -f Dockerfile .
 | 
						$(DOCKER_BUILD) -t registry.domandoman.xyz/fooder/app -f Dockerfile .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: push
 | 
					.PHONY: push
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,8 @@ class FAppBar extends StatelessWidget implements PreferredSizeWidget {
 | 
				
			||||||
        padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
					        padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
				
			||||||
        child: AppBar(
 | 
					        child: AppBar(
 | 
				
			||||||
          backgroundColor: Colors.transparent,
 | 
					          backgroundColor: Colors.transparent,
 | 
				
			||||||
 | 
					          shadowColor: Colors.transparent,
 | 
				
			||||||
 | 
					          surfaceTintColor: Colors.transparent,
 | 
				
			||||||
          elevation: 0,
 | 
					          elevation: 0,
 | 
				
			||||||
          actions: actions,
 | 
					          actions: actions,
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								lib/components/blur_container.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/components/blur_container.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:blur/blur.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BlurContainer extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Widget? child;
 | 
				
			||||||
 | 
					  final double? height;
 | 
				
			||||||
 | 
					  final double? width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const BlurContainer({super.key, this.height, this.width, this.child});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    var theme = Theme.of(context);
 | 
				
			||||||
 | 
					    var colorScheme = theme.colorScheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var blured = Blur(
 | 
				
			||||||
 | 
					      blur: 10,
 | 
				
			||||||
 | 
					      blurColor: colorScheme.surface.withOpacity(0.1),
 | 
				
			||||||
 | 
					      child: Container(
 | 
				
			||||||
 | 
					        height: height,
 | 
				
			||||||
 | 
					        width: width,
 | 
				
			||||||
 | 
					        color: colorScheme.surface.withOpacity(0.1),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (child == null) {
 | 
				
			||||||
 | 
					      return blured;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Stack(
 | 
				
			||||||
 | 
					      children: [
 | 
				
			||||||
 | 
					        blured,
 | 
				
			||||||
 | 
					        child!,
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -27,20 +27,8 @@ class FButton extends StatelessWidget {
 | 
				
			||||||
          child: Container(
 | 
					          child: Container(
 | 
				
			||||||
            padding: EdgeInsets.symmetric(vertical: insidePadding),
 | 
					            padding: EdgeInsets.symmetric(vertical: insidePadding),
 | 
				
			||||||
            decoration: BoxDecoration(
 | 
					            decoration: BoxDecoration(
 | 
				
			||||||
              gradient: LinearGradient(
 | 
					 | 
				
			||||||
                colors: [
 | 
					 | 
				
			||||||
                  colorScheme.primary.withOpacity(0.5),
 | 
					 | 
				
			||||||
                  colorScheme.secondary.withOpacity(0.5),
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              borderRadius: BorderRadius.circular(4),
 | 
					              borderRadius: BorderRadius.circular(4),
 | 
				
			||||||
              boxShadow: [
 | 
					              color: colorScheme.surfaceTint.withOpacity(0.85),
 | 
				
			||||||
                BoxShadow(
 | 
					 | 
				
			||||||
                  color: colorScheme.primary.withOpacity(0.3),
 | 
					 | 
				
			||||||
                  blurRadius: 5,
 | 
					 | 
				
			||||||
                  offset: const Offset(0, 5),
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
              ],
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            child: Center(
 | 
					            child: Center(
 | 
				
			||||||
              child: Text(
 | 
					              child: Text(
 | 
				
			||||||
| 
						 | 
					@ -48,6 +36,7 @@ class FButton extends StatelessWidget {
 | 
				
			||||||
                style: theme.textTheme.labelLarge!.copyWith(
 | 
					                style: theme.textTheme.labelLarge!.copyWith(
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
                  fontSize: fontSize,
 | 
					                  fontSize: fontSize,
 | 
				
			||||||
 | 
					                  color: colorScheme.onPrimary,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ class FDateItemWidget extends StatelessWidget {
 | 
				
			||||||
            width: 2,
 | 
					            width: 2,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          color: picked
 | 
					          color: picked
 | 
				
			||||||
              ? colorScheme.onPrimary.withOpacity(0.25)
 | 
					              ? colorScheme.onSurfaceVariant.withOpacity(0.25)
 | 
				
			||||||
              : Colors.transparent,
 | 
					              : Colors.transparent,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        child: Column(
 | 
					        child: Column(
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ class FDateItemWidget extends StatelessWidget {
 | 
				
			||||||
            Text(
 | 
					            Text(
 | 
				
			||||||
              dayOfTheWeekMap[date.weekday]!,
 | 
					              dayOfTheWeekMap[date.weekday]!,
 | 
				
			||||||
              style: TextStyle(
 | 
					              style: TextStyle(
 | 
				
			||||||
                color: colorScheme.onPrimary,
 | 
					                color: colorScheme.onSurfaceVariant,
 | 
				
			||||||
                fontSize: picked ? 24 : 12,
 | 
					                fontSize: picked ? 24 : 12,
 | 
				
			||||||
                fontWeight: FontWeight.bold,
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ class FDateItemWidget extends StatelessWidget {
 | 
				
			||||||
            Text(
 | 
					            Text(
 | 
				
			||||||
              '${date.day}.${date.month}',
 | 
					              '${date.day}.${date.month}',
 | 
				
			||||||
              style: TextStyle(
 | 
					              style: TextStyle(
 | 
				
			||||||
                color: colorScheme.onPrimary,
 | 
					                color: colorScheme.onSurfaceVariant,
 | 
				
			||||||
                fontSize: picked ? 24 : 12,
 | 
					                fontSize: picked ? 24 : 12,
 | 
				
			||||||
                fontWeight: FontWeight.bold,
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ class _FDatePickerWidgetState extends State<FDatePickerWidget> {
 | 
				
			||||||
              child: IconButton(
 | 
					              child: IconButton(
 | 
				
			||||||
                icon: Icon(
 | 
					                icon: Icon(
 | 
				
			||||||
                  Icons.calendar_month,
 | 
					                  Icons.calendar_month,
 | 
				
			||||||
                  color: colorScheme.onPrimary,
 | 
					                  color: colorScheme.onSurfaceVariant,
 | 
				
			||||||
                  size: 20,
 | 
					                  size: 20,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                onPressed: () {
 | 
					                onPressed: () {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								lib/components/dropdown.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								lib/components/dropdown.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FDropdown<T> extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String labelText;
 | 
				
			||||||
 | 
					  final List<DropdownMenuItem<T>> items;
 | 
				
			||||||
 | 
					  final Function(T?) onChanged;
 | 
				
			||||||
 | 
					  final T? value;
 | 
				
			||||||
 | 
					  final double padding;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const FDropdown(
 | 
				
			||||||
 | 
					      {super.key,
 | 
				
			||||||
 | 
					      required this.labelText,
 | 
				
			||||||
 | 
					      this.padding = 8,
 | 
				
			||||||
 | 
					      required this.items,
 | 
				
			||||||
 | 
					      required this.onChanged,
 | 
				
			||||||
 | 
					      this.value});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    var theme = Theme.of(context);
 | 
				
			||||||
 | 
					    var colorScheme = theme.colorScheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
 | 
				
			||||||
 | 
					      child: DropdownButtonFormField<T>(
 | 
				
			||||||
 | 
					        onChanged: onChanged,
 | 
				
			||||||
 | 
					        items: items,
 | 
				
			||||||
 | 
					        value: value,
 | 
				
			||||||
 | 
					        decoration: InputDecoration(
 | 
				
			||||||
 | 
					          labelText: labelText,
 | 
				
			||||||
 | 
					          floatingLabelStyle:
 | 
				
			||||||
 | 
					              theme.textTheme.bodyLarge!.copyWith(color: colorScheme.onSurface),
 | 
				
			||||||
 | 
					          enabledBorder: OutlineInputBorder(
 | 
				
			||||||
 | 
					            borderSide: BorderSide(color: colorScheme.primary),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          focusedBorder: OutlineInputBorder(
 | 
				
			||||||
 | 
					            borderSide: BorderSide(color: colorScheme.onPrimary),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								lib/components/floating_action_button.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lib/components/floating_action_button.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/blur_container.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FActionButton extends StatelessWidget {
 | 
				
			||||||
 | 
					  final IconData icon;
 | 
				
			||||||
 | 
					  final Function() onPressed;
 | 
				
			||||||
 | 
					  final String tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const FActionButton(
 | 
				
			||||||
 | 
					      {super.key,
 | 
				
			||||||
 | 
					      required this.icon,
 | 
				
			||||||
 | 
					      required this.onPressed,
 | 
				
			||||||
 | 
					      this.tag = 'fap'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    var theme = Theme.of(context);
 | 
				
			||||||
 | 
					    var colorScheme = theme.colorScheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Container(
 | 
				
			||||||
 | 
					      height: 64,
 | 
				
			||||||
 | 
					      width: 64,
 | 
				
			||||||
 | 
					      decoration: BoxDecoration(
 | 
				
			||||||
 | 
					        borderRadius: BorderRadius.circular(32),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      child: ClipRRect(
 | 
				
			||||||
 | 
					        borderRadius: BorderRadius.circular(32),
 | 
				
			||||||
 | 
					        child: BlurContainer(
 | 
				
			||||||
 | 
					          height: 64,
 | 
				
			||||||
 | 
					          width: 64,
 | 
				
			||||||
 | 
					          child: SizedBox(
 | 
				
			||||||
 | 
					            height: 64,
 | 
				
			||||||
 | 
					            width: 64,
 | 
				
			||||||
 | 
					            child: FloatingActionButton(
 | 
				
			||||||
 | 
					              elevation: 0,
 | 
				
			||||||
 | 
					              onPressed: onPressed,
 | 
				
			||||||
 | 
					              heroTag: tag,
 | 
				
			||||||
 | 
					              backgroundColor: Colors.transparent,
 | 
				
			||||||
 | 
					              child: Icon(
 | 
				
			||||||
 | 
					                icon,
 | 
				
			||||||
 | 
					                color: colorScheme.onSurface,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:blur/blur.dart';
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/blur_container.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FNavBar extends StatelessWidget {
 | 
					class FNavBar extends StatelessWidget {
 | 
				
			||||||
  static const maxWidth = 920.0;
 | 
					  static const maxWidth = 920.0;
 | 
				
			||||||
| 
						 | 
					@ -7,61 +8,25 @@ class FNavBar extends StatelessWidget {
 | 
				
			||||||
  final List<Widget> children;
 | 
					  final List<Widget> children;
 | 
				
			||||||
  final double height;
 | 
					  final double height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const FNavBar({super.key, required this.children, this.height = 56});
 | 
					  const FNavBar({super.key, required this.children, this.height = 78});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    var theme = Theme.of(context);
 | 
					 | 
				
			||||||
    var colorScheme = theme.colorScheme;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var widthAvail = MediaQuery.of(context).size.width;
 | 
					    var widthAvail = MediaQuery.of(context).size.width;
 | 
				
			||||||
    // var width = widthAvail > maxWidth ? maxWidth : widthAvail;
 | 
					    // var width = widthAvail > maxWidth ? maxWidth : widthAvail;
 | 
				
			||||||
 | 
					    return SizedBox(
 | 
				
			||||||
    return SafeArea(
 | 
					      width: widthAvail,
 | 
				
			||||||
      child: Padding(
 | 
					      height: height * children.length,
 | 
				
			||||||
        padding: const EdgeInsets.all(12),
 | 
					      child: BlurContainer(
 | 
				
			||||||
        child: Container(
 | 
					        width: widthAvail,
 | 
				
			||||||
          decoration: BoxDecoration(
 | 
					        height: height * children.length,
 | 
				
			||||||
            borderRadius: BorderRadius.circular(24),
 | 
					        child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
 | 
				
			||||||
            boxShadow: [
 | 
					          ...children,
 | 
				
			||||||
              BoxShadow(
 | 
					          Container(
 | 
				
			||||||
                color: colorScheme.primary.withOpacity(0.3),
 | 
					            height: height / 3,
 | 
				
			||||||
                blurRadius: 5,
 | 
					            color: Colors.transparent,
 | 
				
			||||||
                offset: const Offset(0, 5),
 | 
					 | 
				
			||||||
              )
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          child: ClipRRect(
 | 
					        ]),
 | 
				
			||||||
              borderRadius: BorderRadius.circular(24),
 | 
					 | 
				
			||||||
              child: Stack(
 | 
					 | 
				
			||||||
                children: [
 | 
					 | 
				
			||||||
                  Blur(
 | 
					 | 
				
			||||||
                    blur: 10,
 | 
					 | 
				
			||||||
                    blurColor: colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                    child: Container(
 | 
					 | 
				
			||||||
                      width: widthAvail,
 | 
					 | 
				
			||||||
                      height: height * children.length,
 | 
					 | 
				
			||||||
                      decoration: BoxDecoration(
 | 
					 | 
				
			||||||
                        gradient: LinearGradient(
 | 
					 | 
				
			||||||
                          colors: [
 | 
					 | 
				
			||||||
                            colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                            colorScheme.secondary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                          ],
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  SizedBox(
 | 
					 | 
				
			||||||
                    width: widthAvail,
 | 
					 | 
				
			||||||
                    height: height * children.length,
 | 
					 | 
				
			||||||
                    child: Column(
 | 
					 | 
				
			||||||
                      mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                      children: children,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
              )),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:blur/blur.dart';
 | 
					import 'package:fooder/components/blur_container.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClipShadowPath extends StatelessWidget {
 | 
					class ClipShadowPath extends StatelessWidget {
 | 
				
			||||||
  final Shadow shadow;
 | 
					  final Shadow shadow;
 | 
				
			||||||
| 
						 | 
					@ -56,28 +56,11 @@ class BackgroundWave extends StatelessWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return SizedBox(
 | 
					    return SizedBox(
 | 
				
			||||||
      height: height,
 | 
					      height: height,
 | 
				
			||||||
      child: ClipShadowPath(
 | 
					      child: ClipPath(
 | 
				
			||||||
        clipper: BackgroundWaveClipper(),
 | 
					        clipper: BackgroundWaveClipper(),
 | 
				
			||||||
        shadow: BoxShadow(
 | 
					        child: BlurContainer(
 | 
				
			||||||
          blurRadius: 5,
 | 
					          width: MediaQuery.of(context).size.width,
 | 
				
			||||||
          color: colorScheme.primary.withOpacity(0.3),
 | 
					          height: height,
 | 
				
			||||||
          offset: const Offset(0, 5),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        child: Blur(
 | 
					 | 
				
			||||||
          blur: 10,
 | 
					 | 
				
			||||||
          blurColor: colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
          child: Container(
 | 
					 | 
				
			||||||
            width: MediaQuery.of(context).size.width,
 | 
					 | 
				
			||||||
            height: height,
 | 
					 | 
				
			||||||
            decoration: BoxDecoration(
 | 
					 | 
				
			||||||
              gradient: LinearGradient(
 | 
					 | 
				
			||||||
                colors: [
 | 
					 | 
				
			||||||
                  colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                  colorScheme.secondary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -131,8 +114,9 @@ class BackgroundWaveClipper extends CustomClipper<Path> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FSliverAppBar extends SliverPersistentHeaderDelegate {
 | 
					class FSliverAppBar extends SliverPersistentHeaderDelegate {
 | 
				
			||||||
 | 
					  final double preferredHeight;
 | 
				
			||||||
  final Widget child;
 | 
					  final Widget child;
 | 
				
			||||||
  const FSliverAppBar({required this.child});
 | 
					  const FSliverAppBar({required this.child, this.preferredHeight = 220});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(
 | 
					  Widget build(
 | 
				
			||||||
| 
						 | 
					@ -147,8 +131,11 @@ class FSliverAppBar extends SliverPersistentHeaderDelegate {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Stack(
 | 
					    return Stack(
 | 
				
			||||||
      children: [
 | 
					      children: [
 | 
				
			||||||
        const BackgroundWave(
 | 
					        // const BackgroundWave(
 | 
				
			||||||
          height: 280,
 | 
					        //   height: preferredHeight,
 | 
				
			||||||
 | 
					        // ),
 | 
				
			||||||
 | 
					        BlurContainer(
 | 
				
			||||||
 | 
					          height: preferredHeight,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        Positioned(
 | 
					        Positioned(
 | 
				
			||||||
          top: offset,
 | 
					          top: offset,
 | 
				
			||||||
| 
						 | 
					@ -161,10 +148,10 @@ class FSliverAppBar extends SliverPersistentHeaderDelegate {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  double get maxExtent => 280;
 | 
					  double get maxExtent => preferredHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  double get minExtent => 140;
 | 
					  double get minExtent => preferredHeight / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
 | 
					  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FTextInput extends StatelessWidget {
 | 
					class FTextInput extends StatelessWidget {
 | 
				
			||||||
  final String labelText;
 | 
					  final String labelText;
 | 
				
			||||||
| 
						 | 
					@ -8,6 +9,9 @@ class FTextInput extends StatelessWidget {
 | 
				
			||||||
  final bool autofocus;
 | 
					  final bool autofocus;
 | 
				
			||||||
  final bool obscureText;
 | 
					  final bool obscureText;
 | 
				
			||||||
  final Function(String)? onFieldSubmitted;
 | 
					  final Function(String)? onFieldSubmitted;
 | 
				
			||||||
 | 
					  final TextInputType? keyboardType;
 | 
				
			||||||
 | 
					  final List<TextInputFormatter>? inputFormatters;
 | 
				
			||||||
 | 
					  final Function(String)? onChanged;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const FTextInput(
 | 
					  const FTextInput(
 | 
				
			||||||
      {super.key,
 | 
					      {super.key,
 | 
				
			||||||
| 
						 | 
					@ -17,7 +21,10 @@ class FTextInput extends StatelessWidget {
 | 
				
			||||||
      this.autofillHints,
 | 
					      this.autofillHints,
 | 
				
			||||||
      this.autofocus = false,
 | 
					      this.autofocus = false,
 | 
				
			||||||
      this.onFieldSubmitted,
 | 
					      this.onFieldSubmitted,
 | 
				
			||||||
      this.obscureText = false});
 | 
					      this.obscureText = false,
 | 
				
			||||||
 | 
					      this.keyboardType,
 | 
				
			||||||
 | 
					      this.inputFormatters,
 | 
				
			||||||
 | 
					      this.onChanged});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
| 
						 | 
					@ -30,6 +37,8 @@ class FTextInput extends StatelessWidget {
 | 
				
			||||||
        obscureText: obscureText,
 | 
					        obscureText: obscureText,
 | 
				
			||||||
        decoration: InputDecoration(
 | 
					        decoration: InputDecoration(
 | 
				
			||||||
          labelText: labelText,
 | 
					          labelText: labelText,
 | 
				
			||||||
 | 
					          floatingLabelStyle:
 | 
				
			||||||
 | 
					              theme.textTheme.bodyLarge!.copyWith(color: colorScheme.onSurface),
 | 
				
			||||||
          enabledBorder: OutlineInputBorder(
 | 
					          enabledBorder: OutlineInputBorder(
 | 
				
			||||||
            borderSide: BorderSide(color: colorScheme.primary),
 | 
					            borderSide: BorderSide(color: colorScheme.primary),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
| 
						 | 
					@ -41,6 +50,9 @@ class FTextInput extends StatelessWidget {
 | 
				
			||||||
        autofillHints: autofillHints,
 | 
					        autofillHints: autofillHints,
 | 
				
			||||||
        autofocus: autofocus,
 | 
					        autofocus: autofocus,
 | 
				
			||||||
        onFieldSubmitted: onFieldSubmitted,
 | 
					        onFieldSubmitted: onFieldSubmitted,
 | 
				
			||||||
 | 
					        keyboardType: keyboardType,
 | 
				
			||||||
 | 
					        inputFormatters: inputFormatters,
 | 
				
			||||||
 | 
					        onChanged: onChanged,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:fooder/screens/login.dart';
 | 
					import 'package:fooder/screens/login.dart';
 | 
				
			||||||
import 'package:fooder/client.dart';
 | 
					import 'package:fooder/client.dart';
 | 
				
			||||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
 | 
					import 'package:fooder/theme.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MyApp extends StatelessWidget {
 | 
					class MyApp extends StatelessWidget {
 | 
				
			||||||
  const MyApp({super.key});
 | 
					  const MyApp({super.key});
 | 
				
			||||||
| 
						 | 
					@ -10,8 +10,8 @@ class MyApp extends StatelessWidget {
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return MaterialApp(
 | 
					    return MaterialApp(
 | 
				
			||||||
      title: 'FOODER',
 | 
					      title: 'FOODER',
 | 
				
			||||||
      theme: FlexThemeData.light(scheme: FlexScheme.brandBlue),
 | 
					      theme: MainTheme.light(),
 | 
				
			||||||
      darkTheme: FlexThemeData.dark(scheme: FlexScheme.brandBlue),
 | 
					      darkTheme: MainTheme.dark(),
 | 
				
			||||||
      themeMode: ThemeMode.system,
 | 
					      themeMode: ThemeMode.system,
 | 
				
			||||||
      debugShowCheckedModeBanner: false,
 | 
					      debugShowCheckedModeBanner: false,
 | 
				
			||||||
      home: LoginScreen(
 | 
					      home: LoginScreen(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,9 @@ import 'package:fooder/models/product.dart';
 | 
				
			||||||
import 'package:fooder/models/diary.dart';
 | 
					import 'package:fooder/models/diary.dart';
 | 
				
			||||||
import 'package:fooder/models/meal.dart';
 | 
					import 'package:fooder/models/meal.dart';
 | 
				
			||||||
import 'package:fooder/widgets/product.dart';
 | 
					import 'package:fooder/widgets/product.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/text.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/dropdown.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/floating_action_button.dart';
 | 
				
			||||||
import 'package:fooder/screens/add_product.dart';
 | 
					import 'package:fooder/screens/add_product.dart';
 | 
				
			||||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
 | 
					import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +135,8 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
 | 
				
			||||||
            constraints: const BoxConstraints(maxWidth: 720),
 | 
					            constraints: const BoxConstraints(maxWidth: 720),
 | 
				
			||||||
            padding: const EdgeInsets.all(10),
 | 
					            padding: const EdgeInsets.all(10),
 | 
				
			||||||
            child: ListView(children: <Widget>[
 | 
					            child: ListView(children: <Widget>[
 | 
				
			||||||
              DropdownButton<Meal>(
 | 
					              FDropdown<Meal>(
 | 
				
			||||||
 | 
					                labelText: 'Meal',
 | 
				
			||||||
                value: meal,
 | 
					                value: meal,
 | 
				
			||||||
                // Callback that sets the selected popup menu item.
 | 
					                // Callback that sets the selected popup menu item.
 | 
				
			||||||
                onChanged: (Meal? meal) {
 | 
					                onChanged: (Meal? meal) {
 | 
				
			||||||
| 
						 | 
					@ -151,19 +155,15 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Product name',
 | 
				
			||||||
                  labelText: 'Product name',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                controller: productNameController,
 | 
					                controller: productNameController,
 | 
				
			||||||
                onChanged: (_) => _getProducts(),
 | 
					                onChanged: (_) => _getProducts(),
 | 
				
			||||||
                onFieldSubmitted: (_) => _addEntry(),
 | 
					                onFieldSubmitted: (_) => _addEntry(),
 | 
				
			||||||
                autofocus: true,
 | 
					                autofocus: true,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Grams',
 | 
				
			||||||
                  labelText: 'Grams',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -212,14 +212,15 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
 | 
				
			||||||
      floatingActionButton: Row(
 | 
					      floatingActionButton: Row(
 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.end,
 | 
					        mainAxisAlignment: MainAxisAlignment.end,
 | 
				
			||||||
        children: <Widget>[
 | 
					        children: <Widget>[
 | 
				
			||||||
          FloatingActionButton(
 | 
					          FActionButton(
 | 
				
			||||||
            onPressed: _findProductByBarCode,
 | 
					            onPressed: _findProductByBarCode,
 | 
				
			||||||
            heroTag: null,
 | 
					            icon: Icons.photo_camera,
 | 
				
			||||||
            child: const Icon(Icons.photo_camera),
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          FloatingActionButton(
 | 
					          const SizedBox(width: 10),
 | 
				
			||||||
 | 
					          FActionButton(
 | 
				
			||||||
            onPressed: _addEntry,
 | 
					            onPressed: _addEntry,
 | 
				
			||||||
            child: const Icon(Icons.add),
 | 
					            icon: Icons.library_add,
 | 
				
			||||||
 | 
					            tag: "fap2",
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,8 @@ import 'package:fooder/screens/based.dart';
 | 
				
			||||||
import 'package:fooder/models/diary.dart';
 | 
					import 'package:fooder/models/diary.dart';
 | 
				
			||||||
import 'package:fooder/models/preset.dart';
 | 
					import 'package:fooder/models/preset.dart';
 | 
				
			||||||
import 'package:fooder/widgets/preset.dart';
 | 
					import 'package:fooder/widgets/preset.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/text.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/floating_action_button.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddMealScreen extends BasedScreen {
 | 
					class AddMealScreen extends BasedScreen {
 | 
				
			||||||
  final Diary diary;
 | 
					  final Diary diary;
 | 
				
			||||||
| 
						 | 
					@ -14,7 +16,7 @@ class AddMealScreen extends BasedScreen {
 | 
				
			||||||
  State<AddMealScreen> createState() => _AddMealScreen();
 | 
					  State<AddMealScreen> createState() => _AddMealScreen();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _AddMealScreen extends State<AddMealScreen> {
 | 
					class _AddMealScreen extends BasedState<AddMealScreen> {
 | 
				
			||||||
  final nameController = TextEditingController();
 | 
					  final nameController = TextEditingController();
 | 
				
			||||||
  final presetNameController = TextEditingController();
 | 
					  final presetNameController = TextEditingController();
 | 
				
			||||||
  bool nameChanged = false;
 | 
					  bool nameChanged = false;
 | 
				
			||||||
| 
						 | 
					@ -37,7 +39,7 @@ class _AddMealScreen extends State<AddMealScreen> {
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
    super.initState();
 | 
					    super.initState();
 | 
				
			||||||
    setState(() {
 | 
					    setState(() {
 | 
				
			||||||
      nameController.text = "Meal ${widget.diary.meals.length}";
 | 
					      nameController.text = "Meal ${widget.diary.meals.length + 1}";
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    _getPresets();
 | 
					    _getPresets();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -54,15 +56,6 @@ class _AddMealScreen extends State<AddMealScreen> {
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void showError(String message) {
 | 
					 | 
				
			||||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
					 | 
				
			||||||
      SnackBar(
 | 
					 | 
				
			||||||
        content: Text(message, textAlign: TextAlign.center),
 | 
					 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<void> _addMeal() async {
 | 
					  Future<void> _addMeal() async {
 | 
				
			||||||
    await widget.apiClient.addMeal(
 | 
					    await widget.apiClient.addMeal(
 | 
				
			||||||
      name: nameController.text,
 | 
					      name: nameController.text,
 | 
				
			||||||
| 
						 | 
					@ -121,28 +114,21 @@ class _AddMealScreen extends State<AddMealScreen> {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      appBar: AppBar(
 | 
					      appBar: appBar(),
 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
					 | 
				
			||||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      body: Center(
 | 
					      body: Center(
 | 
				
			||||||
        child: Container(
 | 
					        child: Container(
 | 
				
			||||||
          constraints: const BoxConstraints(maxWidth: 720),
 | 
					          constraints: const BoxConstraints(maxWidth: 720),
 | 
				
			||||||
          padding: const EdgeInsets.all(10),
 | 
					          padding: const EdgeInsets.all(10),
 | 
				
			||||||
          child: ListView(children: <Widget>[
 | 
					          child: ListView(children: <Widget>[
 | 
				
			||||||
            TextFormField(
 | 
					            FTextInput(
 | 
				
			||||||
              decoration: const InputDecoration(
 | 
					              labelText: 'Meal name',
 | 
				
			||||||
                labelText: 'Meal name',
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              controller: nameController,
 | 
					              controller: nameController,
 | 
				
			||||||
              onChanged: (_) => setState(() {
 | 
					              onChanged: (_) => setState(() {
 | 
				
			||||||
                nameChanged = true;
 | 
					                nameChanged = true;
 | 
				
			||||||
              }),
 | 
					              }),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            TextFormField(
 | 
					            FTextInput(
 | 
				
			||||||
              decoration: const InputDecoration(
 | 
					              labelText: 'Search presets',
 | 
				
			||||||
                hintText: 'Search presets',
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              controller: presetNameController,
 | 
					              controller: presetNameController,
 | 
				
			||||||
              onChanged: (_) => _getPresets(),
 | 
					              onChanged: (_) => _getPresets(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
| 
						 | 
					@ -166,9 +152,9 @@ class _AddMealScreen extends State<AddMealScreen> {
 | 
				
			||||||
          ]),
 | 
					          ]),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      floatingActionButton: FloatingActionButton(
 | 
					      floatingActionButton: FActionButton(
 | 
				
			||||||
        onPressed: _addMealFromPreset,
 | 
					        onPressed: _addMealFromPreset,
 | 
				
			||||||
        child: const Icon(Icons.add),
 | 
					        icon: Icons.playlist_add_rounded,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter/services.dart';
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
import 'package:fooder/screens/based.dart';
 | 
					import 'package:fooder/screens/based.dart';
 | 
				
			||||||
import 'package:fooder/models/product.dart';
 | 
					import 'package:fooder/models/product.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/widgets/product.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/text.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/floating_action_button.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddProductScreen extends BasedScreen {
 | 
					class AddProductScreen extends BasedScreen {
 | 
				
			||||||
  const AddProductScreen({super.key, required super.apiClient});
 | 
					  const AddProductScreen({super.key, required super.apiClient});
 | 
				
			||||||
| 
						 | 
					@ -10,7 +13,7 @@ class AddProductScreen extends BasedScreen {
 | 
				
			||||||
  State<AddProductScreen> createState() => _AddProductScreen();
 | 
					  State<AddProductScreen> createState() => _AddProductScreen();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _AddProductScreen extends State<AddProductScreen> {
 | 
					class _AddProductScreen extends BasedState<AddProductScreen> {
 | 
				
			||||||
  final nameController = TextEditingController();
 | 
					  final nameController = TextEditingController();
 | 
				
			||||||
  final carbController = TextEditingController();
 | 
					  final carbController = TextEditingController();
 | 
				
			||||||
  final fatController = TextEditingController();
 | 
					  final fatController = TextEditingController();
 | 
				
			||||||
| 
						 | 
					@ -34,15 +37,6 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void showError(String message) {
 | 
					 | 
				
			||||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
					 | 
				
			||||||
      SnackBar(
 | 
					 | 
				
			||||||
        content: Text(message, textAlign: TextAlign.center),
 | 
					 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<double?> _parseDouble(String text, String name,
 | 
					  Future<double?> _parseDouble(String text, String name,
 | 
				
			||||||
      {bool silent = false}) async {
 | 
					      {bool silent = false}) async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
| 
						 | 
					@ -113,25 +107,21 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      appBar: AppBar(
 | 
					      appBar: appBar(),
 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
					 | 
				
			||||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      body: Center(
 | 
					      body: Center(
 | 
				
			||||||
        child: Container(
 | 
					        child: Container(
 | 
				
			||||||
            constraints: const BoxConstraints(maxWidth: 720),
 | 
					            constraints: const BoxConstraints(maxWidth: 720),
 | 
				
			||||||
            padding: const EdgeInsets.all(10),
 | 
					            padding: const EdgeInsets.all(10),
 | 
				
			||||||
            child: Column(children: <Widget>[
 | 
					            child: Column(children: <Widget>[
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Product name',
 | 
				
			||||||
                  labelText: 'Product name',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                controller: nameController,
 | 
					                controller: nameController,
 | 
				
			||||||
 | 
					                onChanged: (String value) {
 | 
				
			||||||
 | 
					                  setState(() {});
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Carbs',
 | 
				
			||||||
                  labelText: 'Carbs',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -143,10 +133,8 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
                  setState(() {});
 | 
					                  setState(() {});
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Fat',
 | 
				
			||||||
                  labelText: 'Fat',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -158,10 +146,8 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
                  setState(() {});
 | 
					                  setState(() {});
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Protein',
 | 
				
			||||||
                  labelText: 'Protein',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -173,10 +159,8 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
                  setState(() {});
 | 
					                  setState(() {});
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Fiber',
 | 
				
			||||||
                  labelText: 'Fiber',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -188,15 +172,30 @@ class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
                  setState(() {});
 | 
					                  setState(() {});
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              Text(
 | 
					              ProductWidget(
 | 
				
			||||||
                "${calculateCalories().toStringAsFixed(2)} kcal",
 | 
					                product: Product(
 | 
				
			||||||
                textAlign: TextAlign.right,
 | 
					                  id: 0,
 | 
				
			||||||
              ),
 | 
					                  name: nameController.text,
 | 
				
			||||||
 | 
					                  carb: double.tryParse(
 | 
				
			||||||
 | 
					                          carbController.text.replaceAll(",", ".")) ??
 | 
				
			||||||
 | 
					                      0.0,
 | 
				
			||||||
 | 
					                  fat: double.tryParse(
 | 
				
			||||||
 | 
					                          fatController.text.replaceAll(",", ".")) ??
 | 
				
			||||||
 | 
					                      0.0,
 | 
				
			||||||
 | 
					                  protein: double.tryParse(
 | 
				
			||||||
 | 
					                          proteinController.text.replaceAll(",", ".")) ??
 | 
				
			||||||
 | 
					                      0.0,
 | 
				
			||||||
 | 
					                  fiber: double.tryParse(
 | 
				
			||||||
 | 
					                          fiberController.text.replaceAll(",", ".")) ??
 | 
				
			||||||
 | 
					                      0.0,
 | 
				
			||||||
 | 
					                  calories: calculateCalories(),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
            ])),
 | 
					            ])),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      floatingActionButton: FloatingActionButton(
 | 
					      floatingActionButton: FActionButton(
 | 
				
			||||||
        onPressed: _addProduct,
 | 
					        onPressed: _addProduct,
 | 
				
			||||||
        child: const Icon(Icons.add),
 | 
					        icon: Icons.save,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ abstract class BasedState<T extends BasedScreen> extends State<T> {
 | 
				
			||||||
        IconButton(
 | 
					        IconButton(
 | 
				
			||||||
          icon: Icon(
 | 
					          icon: Icon(
 | 
				
			||||||
            Icons.logout,
 | 
					            Icons.logout,
 | 
				
			||||||
            color: Theme.of(context).colorScheme.onPrimary,
 | 
					            color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          onPressed: _logout,
 | 
					          onPressed: _logout,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
| 
						 | 
					@ -60,28 +60,28 @@ abstract class BasedState<T extends BasedScreen> extends State<T> {
 | 
				
			||||||
            IconButton(
 | 
					            IconButton(
 | 
				
			||||||
              icon: Icon(
 | 
					              icon: Icon(
 | 
				
			||||||
                Icons.menu_book,
 | 
					                Icons.menu_book,
 | 
				
			||||||
                color: Theme.of(context).colorScheme.onPrimary,
 | 
					                color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onPressed: backToDiary,
 | 
					              onPressed: backToDiary,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            IconButton(
 | 
					            IconButton(
 | 
				
			||||||
              icon: Icon(
 | 
					              icon: Icon(
 | 
				
			||||||
                Icons.dinner_dining,
 | 
					                Icons.dinner_dining,
 | 
				
			||||||
                color: Theme.of(context).colorScheme.onPrimary,
 | 
					                color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onPressed: () {},
 | 
					              onPressed: () {},
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            IconButton(
 | 
					            IconButton(
 | 
				
			||||||
              icon: Icon(
 | 
					              icon: Icon(
 | 
				
			||||||
                Icons.lunch_dining,
 | 
					                Icons.lunch_dining,
 | 
				
			||||||
                color: Theme.of(context).colorScheme.onPrimary,
 | 
					                color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onPressed: () {},
 | 
					              onPressed: () {},
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            IconButton(
 | 
					            IconButton(
 | 
				
			||||||
              icon: Icon(
 | 
					              icon: Icon(
 | 
				
			||||||
                Icons.person,
 | 
					                Icons.person,
 | 
				
			||||||
                color: Theme.of(context).colorScheme.onPrimary,
 | 
					                color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onPressed: () {},
 | 
					              onPressed: () {},
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,8 @@ import 'package:fooder/models/product.dart';
 | 
				
			||||||
import 'package:fooder/models/entry.dart';
 | 
					import 'package:fooder/models/entry.dart';
 | 
				
			||||||
import 'package:fooder/widgets/product.dart';
 | 
					import 'package:fooder/widgets/product.dart';
 | 
				
			||||||
import 'package:fooder/screens/add_product.dart';
 | 
					import 'package:fooder/screens/add_product.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/text.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/components/floating_action_button.dart';
 | 
				
			||||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
 | 
					import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EditEntryScreen extends BasedScreen {
 | 
					class EditEntryScreen extends BasedScreen {
 | 
				
			||||||
| 
						 | 
					@ -17,7 +19,7 @@ class EditEntryScreen extends BasedScreen {
 | 
				
			||||||
  State<EditEntryScreen> createState() => _EditEntryScreen();
 | 
					  State<EditEntryScreen> createState() => _EditEntryScreen();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _EditEntryScreen extends State<EditEntryScreen> {
 | 
					class _EditEntryScreen extends BasedState<EditEntryScreen> {
 | 
				
			||||||
  final gramsController = TextEditingController();
 | 
					  final gramsController = TextEditingController();
 | 
				
			||||||
  final productNameController = TextEditingController();
 | 
					  final productNameController = TextEditingController();
 | 
				
			||||||
  List<Product> products = [];
 | 
					  List<Product> products = [];
 | 
				
			||||||
| 
						 | 
					@ -53,15 +55,6 @@ class _EditEntryScreen extends State<EditEntryScreen> {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void showError(String message) {
 | 
					 | 
				
			||||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
					 | 
				
			||||||
      SnackBar(
 | 
					 | 
				
			||||||
        content: Text(message, textAlign: TextAlign.center),
 | 
					 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<double?> _parseDouble(String text, String name) async {
 | 
					  Future<double?> _parseDouble(String text, String name) async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      return double.parse(text.replaceAll(",", "."));
 | 
					      return double.parse(text.replaceAll(",", "."));
 | 
				
			||||||
| 
						 | 
					@ -123,27 +116,20 @@ class _EditEntryScreen extends State<EditEntryScreen> {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      appBar: AppBar(
 | 
					      appBar: appBar(),
 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
					 | 
				
			||||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      body: Center(
 | 
					      body: Center(
 | 
				
			||||||
        child: Container(
 | 
					        child: Container(
 | 
				
			||||||
            constraints: const BoxConstraints(maxWidth: 720),
 | 
					            constraints: const BoxConstraints(maxWidth: 720),
 | 
				
			||||||
            padding: const EdgeInsets.all(10),
 | 
					            padding: const EdgeInsets.all(10),
 | 
				
			||||||
            child: ListView(children: <Widget>[
 | 
					            child: ListView(children: <Widget>[
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Product name',
 | 
				
			||||||
                  labelText: 'Product name',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                controller: productNameController,
 | 
					                controller: productNameController,
 | 
				
			||||||
                onChanged: (_) => _getProducts(),
 | 
					                onChanged: (_) => _getProducts(),
 | 
				
			||||||
                autofocus: true,
 | 
					                autofocus: true,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              TextFormField(
 | 
					              FTextInput(
 | 
				
			||||||
                decoration: const InputDecoration(
 | 
					                labelText: 'Grams',
 | 
				
			||||||
                  labelText: 'Grams',
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                keyboardType:
 | 
					                keyboardType:
 | 
				
			||||||
                    const TextInputType.numberWithOptions(decimal: true),
 | 
					                    const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
                inputFormatters: <TextInputFormatter>[
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
| 
						 | 
					@ -190,20 +176,21 @@ class _EditEntryScreen extends State<EditEntryScreen> {
 | 
				
			||||||
      floatingActionButton: Row(
 | 
					      floatingActionButton: Row(
 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.end,
 | 
					        mainAxisAlignment: MainAxisAlignment.end,
 | 
				
			||||||
        children: <Widget>[
 | 
					        children: <Widget>[
 | 
				
			||||||
          FloatingActionButton(
 | 
					          FActionButton(
 | 
				
			||||||
            onPressed: _findProductByBarCode,
 | 
					            onPressed: _findProductByBarCode,
 | 
				
			||||||
            heroTag: null,
 | 
					            icon: Icons.photo_camera,
 | 
				
			||||||
            child: const Icon(Icons.photo_camera),
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          FloatingActionButton(
 | 
					          const SizedBox(width: 10),
 | 
				
			||||||
 | 
					          FActionButton(
 | 
				
			||||||
            onPressed: _deleteEntry,
 | 
					            onPressed: _deleteEntry,
 | 
				
			||||||
            heroTag: null,
 | 
					            tag: "fap1",
 | 
				
			||||||
            child: const Icon(Icons.delete),
 | 
					            icon: Icons.delete,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          FloatingActionButton(
 | 
					          const SizedBox(width: 10),
 | 
				
			||||||
 | 
					          FActionButton(
 | 
				
			||||||
            onPressed: _saveEntry,
 | 
					            onPressed: _saveEntry,
 | 
				
			||||||
            heroTag: null,
 | 
					            tag: "fap2",
 | 
				
			||||||
            child: const Icon(Icons.save),
 | 
					            icon: Icons.save,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:fooder/screens/based.dart';
 | 
					import 'package:fooder/screens/based.dart';
 | 
				
			||||||
import 'package:fooder/screens/add_entry.dart';
 | 
					import 'package:fooder/screens/add_entry.dart';
 | 
				
			||||||
 | 
					import 'package:fooder/screens/add_meal.dart';
 | 
				
			||||||
import 'package:fooder/models/diary.dart';
 | 
					import 'package:fooder/models/diary.dart';
 | 
				
			||||||
import 'package:fooder/widgets/summary.dart';
 | 
					import 'package:fooder/widgets/summary.dart';
 | 
				
			||||||
import 'package:fooder/widgets/meal.dart';
 | 
					import 'package:fooder/widgets/meal.dart';
 | 
				
			||||||
import 'package:fooder/components/sliver.dart';
 | 
					import 'package:fooder/components/sliver.dart';
 | 
				
			||||||
import 'package:fooder/components/date_picker.dart';
 | 
					import 'package:fooder/components/date_picker.dart';
 | 
				
			||||||
import 'package:blur/blur.dart';
 | 
					import 'package:fooder/components/floating_action_button.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MainScreen extends BasedScreen {
 | 
					class MainScreen extends BasedScreen {
 | 
				
			||||||
  const MainScreen({super.key, required super.apiClient});
 | 
					  const MainScreen({super.key, required super.apiClient});
 | 
				
			||||||
| 
						 | 
					@ -43,6 +44,10 @@ class _MainScreen extends BasedState<MainScreen> {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> _addEntry() async {
 | 
					  Future<void> _addEntry() async {
 | 
				
			||||||
 | 
					    if (diary == null) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await Navigator.push(
 | 
					    await Navigator.push(
 | 
				
			||||||
      context,
 | 
					      context,
 | 
				
			||||||
      MaterialPageRoute(
 | 
					      MaterialPageRoute(
 | 
				
			||||||
| 
						 | 
					@ -52,60 +57,20 @@ class _MainScreen extends BasedState<MainScreen> {
 | 
				
			||||||
    ).then((_) => _asyncInitState());
 | 
					    ).then((_) => _asyncInitState());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Widget floatingActionButton(BuildContext context) {
 | 
					  Future<void> _addMeal(context) async {
 | 
				
			||||||
    var theme = Theme.of(context);
 | 
					    if (diary == null) {
 | 
				
			||||||
    var colorScheme = theme.colorScheme;
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Container(
 | 
					    await Navigator.push(
 | 
				
			||||||
      height: 64,
 | 
					      context,
 | 
				
			||||||
      width: 64,
 | 
					      MaterialPageRoute(
 | 
				
			||||||
      decoration: BoxDecoration(
 | 
					        builder: (context) => AddMealScreen(
 | 
				
			||||||
        borderRadius: BorderRadius.circular(32),
 | 
					          apiClient: widget.apiClient,
 | 
				
			||||||
        boxShadow: [
 | 
					          diary: diary!,
 | 
				
			||||||
          BoxShadow(
 | 
					 | 
				
			||||||
            color: colorScheme.primary.withOpacity(0.3),
 | 
					 | 
				
			||||||
            blurRadius: 5,
 | 
					 | 
				
			||||||
            offset: const Offset(0, 5),
 | 
					 | 
				
			||||||
          )
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      child: ClipRRect(
 | 
					 | 
				
			||||||
        borderRadius: BorderRadius.circular(32),
 | 
					 | 
				
			||||||
        child: Stack(
 | 
					 | 
				
			||||||
          children: [
 | 
					 | 
				
			||||||
            Blur(
 | 
					 | 
				
			||||||
              blur: 10,
 | 
					 | 
				
			||||||
              blurColor: colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
              child: Container(
 | 
					 | 
				
			||||||
                height: 64,
 | 
					 | 
				
			||||||
                width: 64,
 | 
					 | 
				
			||||||
                decoration: BoxDecoration(
 | 
					 | 
				
			||||||
                  gradient: LinearGradient(
 | 
					 | 
				
			||||||
                    colors: [
 | 
					 | 
				
			||||||
                      colorScheme.primary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                      colorScheme.secondary.withOpacity(0.1),
 | 
					 | 
				
			||||||
                    ],
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            SizedBox(
 | 
					 | 
				
			||||||
              height: 64,
 | 
					 | 
				
			||||||
              width: 64,
 | 
					 | 
				
			||||||
              child: FloatingActionButton(
 | 
					 | 
				
			||||||
                elevation: 0,
 | 
					 | 
				
			||||||
                onPressed: _addEntry,
 | 
					 | 
				
			||||||
                backgroundColor: Colors.transparent,
 | 
					 | 
				
			||||||
                child: Icon(
 | 
					 | 
				
			||||||
                  Icons.library_add,
 | 
					 | 
				
			||||||
                  color: colorScheme.onPrimary,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    ).then((_) => _asyncInitState());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
| 
						 | 
					@ -133,7 +98,9 @@ class _MainScreen extends BasedState<MainScreen> {
 | 
				
			||||||
                  apiClient: widget.apiClient,
 | 
					                  apiClient: widget.apiClient,
 | 
				
			||||||
                  refreshParent: _asyncInitState,
 | 
					                  refreshParent: _asyncInitState,
 | 
				
			||||||
                  initiallyExpanded: i == 0,
 | 
					                  initiallyExpanded: i == 0,
 | 
				
			||||||
 | 
					                  showText: showText,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					              const SizedBox(height: 200),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
| 
						 | 
					@ -149,7 +116,18 @@ class _MainScreen extends BasedState<MainScreen> {
 | 
				
			||||||
      appBar: appBar(),
 | 
					      appBar: appBar(),
 | 
				
			||||||
      bottomNavigationBar: navBar(),
 | 
					      bottomNavigationBar: navBar(),
 | 
				
			||||||
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
 | 
					      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
 | 
				
			||||||
      floatingActionButton: floatingActionButton(context),
 | 
					      floatingActionButton: Row(
 | 
				
			||||||
 | 
					        mainAxisAlignment: MainAxisAlignment.end,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          FActionButton(
 | 
				
			||||||
 | 
					            icon: Icons.playlist_add,
 | 
				
			||||||
 | 
					            onPressed: () => _addMeal(context),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          const SizedBox(width: 10),
 | 
				
			||||||
 | 
					          FActionButton(
 | 
				
			||||||
 | 
					              icon: Icons.library_add, onPressed: _addEntry, tag: "fap2"),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,181 +0,0 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/screens/based.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/models/meal.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/widgets/macro.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MealScreen extends BasedScreen {
 | 
					 | 
				
			||||||
  final Meal meal;
 | 
					 | 
				
			||||||
  final Function() refresh;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const MealScreen(
 | 
					 | 
				
			||||||
      {super.key,
 | 
					 | 
				
			||||||
      required super.apiClient,
 | 
					 | 
				
			||||||
      required this.refresh,
 | 
					 | 
				
			||||||
      required this.meal});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  State<MealScreen> createState() => _AddMealScreen();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class _AddMealScreen extends State<MealScreen> {
 | 
					 | 
				
			||||||
  Future<void> saveMeal(context) async {
 | 
					 | 
				
			||||||
    TextEditingController textFieldController = TextEditingController();
 | 
					 | 
				
			||||||
    textFieldController.text = widget.meal.name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    showDialog(
 | 
					 | 
				
			||||||
      context: context,
 | 
					 | 
				
			||||||
      builder: (context) {
 | 
					 | 
				
			||||||
        return AlertDialog(
 | 
					 | 
				
			||||||
          title: const Text('Save Meal'),
 | 
					 | 
				
			||||||
          content: TextField(
 | 
					 | 
				
			||||||
            controller: textFieldController,
 | 
					 | 
				
			||||||
            decoration: const InputDecoration(hintText: "Meal template name"),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          actions: <Widget>[
 | 
					 | 
				
			||||||
            IconButton(
 | 
					 | 
				
			||||||
              icon: const Icon(Icons.cancel),
 | 
					 | 
				
			||||||
              onPressed: () {
 | 
					 | 
				
			||||||
                Navigator.pop(context);
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            IconButton(
 | 
					 | 
				
			||||||
              icon: const Icon(Icons.save),
 | 
					 | 
				
			||||||
              onPressed: () {
 | 
					 | 
				
			||||||
                widget.apiClient
 | 
					 | 
				
			||||||
                    .saveMeal(widget.meal, textFieldController.text);
 | 
					 | 
				
			||||||
                Navigator.pop(context);
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<void> _deleteMeal(Meal meal) async {
 | 
					 | 
				
			||||||
    await widget.apiClient.deleteMeal(meal.id);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<void> deleteMeal(context) async {
 | 
					 | 
				
			||||||
    showDialog(
 | 
					 | 
				
			||||||
      context: context,
 | 
					 | 
				
			||||||
      builder: (context) {
 | 
					 | 
				
			||||||
        return AlertDialog(
 | 
					 | 
				
			||||||
          title: const Text('Confirm deletion of the meal'),
 | 
					 | 
				
			||||||
          actions: <Widget>[
 | 
					 | 
				
			||||||
            IconButton(
 | 
					 | 
				
			||||||
              icon: const Icon(Icons.cancel),
 | 
					 | 
				
			||||||
              onPressed: () {
 | 
					 | 
				
			||||||
                Navigator.pop(context);
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            IconButton(
 | 
					 | 
				
			||||||
              icon: const Icon(Icons.delete),
 | 
					 | 
				
			||||||
              onPressed: () {
 | 
					 | 
				
			||||||
                _deleteMeal(widget.meal);
 | 
					 | 
				
			||||||
                Navigator.pop(context);
 | 
					 | 
				
			||||||
                Navigator.pop(context);
 | 
					 | 
				
			||||||
                widget.refresh();
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Widget buildButton(Icon icon, String text, Function() onPressed) {
 | 
					 | 
				
			||||||
    return Card(
 | 
					 | 
				
			||||||
      child: ListTile(
 | 
					 | 
				
			||||||
        onTap: onPressed,
 | 
					 | 
				
			||||||
        title: Container(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.all(8),
 | 
					 | 
				
			||||||
          child: Row(
 | 
					 | 
				
			||||||
            children: <Widget>[
 | 
					 | 
				
			||||||
              IconButton(
 | 
					 | 
				
			||||||
                icon: icon,
 | 
					 | 
				
			||||||
                onPressed: onPressed,
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              const Spacer(),
 | 
					 | 
				
			||||||
              Text(text),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Scaffold(
 | 
					 | 
				
			||||||
      appBar: AppBar(
 | 
					 | 
				
			||||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
					 | 
				
			||||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      body: Center(
 | 
					 | 
				
			||||||
        child: Container(
 | 
					 | 
				
			||||||
          constraints: const BoxConstraints(maxWidth: 720),
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.all(10),
 | 
					 | 
				
			||||||
          child: CustomScrollView(slivers: <Widget>[
 | 
					 | 
				
			||||||
            SliverAppBar(
 | 
					 | 
				
			||||||
                title: Row(
 | 
					 | 
				
			||||||
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					 | 
				
			||||||
                    children: <Widget>[
 | 
					 | 
				
			||||||
                      Text(
 | 
					 | 
				
			||||||
                        widget.meal.name,
 | 
					 | 
				
			||||||
                        style: Theme.of(context)
 | 
					 | 
				
			||||||
                            .textTheme
 | 
					 | 
				
			||||||
                            .headlineLarge!
 | 
					 | 
				
			||||||
                            .copyWith(
 | 
					 | 
				
			||||||
                              color: Theme.of(context).colorScheme.onSecondary,
 | 
					 | 
				
			||||||
                              fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                      const Spacer(),
 | 
					 | 
				
			||||||
                      Text(
 | 
					 | 
				
			||||||
                        "${widget.meal.calories.toStringAsFixed(1)} kcal",
 | 
					 | 
				
			||||||
                        style: Theme.of(context)
 | 
					 | 
				
			||||||
                            .textTheme
 | 
					 | 
				
			||||||
                            .headlineLarge!
 | 
					 | 
				
			||||||
                            .copyWith(
 | 
					 | 
				
			||||||
                              color: Theme.of(context).colorScheme.onSecondary,
 | 
					 | 
				
			||||||
                              fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ]),
 | 
					 | 
				
			||||||
                expandedHeight: 150,
 | 
					 | 
				
			||||||
                backgroundColor: Theme.of(context).colorScheme.secondary,
 | 
					 | 
				
			||||||
                shape: RoundedRectangleBorder(
 | 
					 | 
				
			||||||
                  borderRadius: BorderRadius.circular(8),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                floating: true,
 | 
					 | 
				
			||||||
                flexibleSpace: FlexibleSpaceBar(
 | 
					 | 
				
			||||||
                  title: MacroWidget(
 | 
					 | 
				
			||||||
                    protein: widget.meal.protein,
 | 
					 | 
				
			||||||
                    carb: widget.meal.carb,
 | 
					 | 
				
			||||||
                    fat: widget.meal.fat,
 | 
					 | 
				
			||||||
                    style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
					 | 
				
			||||||
                          color: Theme.of(context).colorScheme.onSecondary,
 | 
					 | 
				
			||||||
                          fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                )),
 | 
					 | 
				
			||||||
            SliverList(
 | 
					 | 
				
			||||||
                delegate: SliverChildListDelegate([
 | 
					 | 
				
			||||||
              buildButton(
 | 
					 | 
				
			||||||
                const Icon(Icons.save),
 | 
					 | 
				
			||||||
                "Save as preset",
 | 
					 | 
				
			||||||
                () => saveMeal(context),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              buildButton(
 | 
					 | 
				
			||||||
                const Icon(Icons.delete),
 | 
					 | 
				
			||||||
                "Delete",
 | 
					 | 
				
			||||||
                () => deleteMeal(context),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ]))
 | 
					 | 
				
			||||||
          ]),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										51
									
								
								lib/theme.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								lib/theme.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,51 @@
 | 
				
			||||||
 | 
					import 'package:flex_color_scheme/flex_color_scheme.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:google_fonts/google_fonts.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MainTheme {
 | 
				
			||||||
 | 
					  static ThemeData light() {
 | 
				
			||||||
 | 
					    return FlexThemeData.light(
 | 
				
			||||||
 | 
					      scheme: FlexScheme.brandBlue,
 | 
				
			||||||
 | 
					      surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold,
 | 
				
			||||||
 | 
					      blendLevel: 40,
 | 
				
			||||||
 | 
					      subThemesData: const FlexSubThemesData(
 | 
				
			||||||
 | 
					        blendOnLevel: 40,
 | 
				
			||||||
 | 
					        useTextTheme: true,
 | 
				
			||||||
 | 
					        useM2StyleDividerInM3: true,
 | 
				
			||||||
 | 
					        alignedDropdown: true,
 | 
				
			||||||
 | 
					        useInputDecoratorThemeInDialogs: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      keyColors: const FlexKeyColors(
 | 
				
			||||||
 | 
					        useSecondary: true,
 | 
				
			||||||
 | 
					        useTertiary: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      visualDensity: FlexColorScheme.comfortablePlatformDensity,
 | 
				
			||||||
 | 
					      useMaterial3: true,
 | 
				
			||||||
 | 
					      swapLegacyOnMaterial3: true,
 | 
				
			||||||
 | 
					      fontFamily: GoogleFonts.notoSans().fontFamily,
 | 
				
			||||||
 | 
					    ).copyWith(
 | 
				
			||||||
 | 
					      dividerColor: Colors.transparent,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static ThemeData dark() {
 | 
				
			||||||
 | 
					    return FlexThemeData.dark(
 | 
				
			||||||
 | 
					      scheme: FlexScheme.brandBlue,
 | 
				
			||||||
 | 
					      surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold,
 | 
				
			||||||
 | 
					      blendLevel: 40,
 | 
				
			||||||
 | 
					      subThemesData: const FlexSubThemesData(
 | 
				
			||||||
 | 
					        blendOnLevel: 20,
 | 
				
			||||||
 | 
					        useTextTheme: true,
 | 
				
			||||||
 | 
					        useM2StyleDividerInM3: true,
 | 
				
			||||||
 | 
					        alignedDropdown: true,
 | 
				
			||||||
 | 
					        useInputDecoratorThemeInDialogs: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      visualDensity: FlexColorScheme.comfortablePlatformDensity,
 | 
				
			||||||
 | 
					      useMaterial3: true,
 | 
				
			||||||
 | 
					      swapLegacyOnMaterial3: true,
 | 
				
			||||||
 | 
					      fontFamily: GoogleFonts.notoSans().fontFamily,
 | 
				
			||||||
 | 
					    ).copyWith(
 | 
				
			||||||
 | 
					      dividerColor: Colors.transparent,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,97 +0,0 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/models/diary.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/widgets/meal.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/widgets/macro.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/client.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/screens/add_meal.dart';
 | 
					 | 
				
			||||||
import 'dart:core';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class DiaryWidget extends StatelessWidget {
 | 
					 | 
				
			||||||
  final Diary diary;
 | 
					 | 
				
			||||||
  final ApiClient apiClient;
 | 
					 | 
				
			||||||
  final Function() refreshParent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const DiaryWidget(
 | 
					 | 
				
			||||||
      {super.key,
 | 
					 | 
				
			||||||
      required this.diary,
 | 
					 | 
				
			||||||
      required this.apiClient,
 | 
					 | 
				
			||||||
      required this.refreshParent});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Container(
 | 
					 | 
				
			||||||
      padding: const EdgeInsets.all(8),
 | 
					 | 
				
			||||||
      child: CustomScrollView(
 | 
					 | 
				
			||||||
        slivers: <Widget>[
 | 
					 | 
				
			||||||
          SliverAppBar(
 | 
					 | 
				
			||||||
              title: Row(
 | 
					 | 
				
			||||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					 | 
				
			||||||
                  children: <Widget>[
 | 
					 | 
				
			||||||
                    const Spacer(),
 | 
					 | 
				
			||||||
                    Text(
 | 
					 | 
				
			||||||
                      "${diary.calories.toStringAsFixed(1)} kcal",
 | 
					 | 
				
			||||||
                      style: Theme.of(context)
 | 
					 | 
				
			||||||
                          .textTheme
 | 
					 | 
				
			||||||
                          .headlineLarge!
 | 
					 | 
				
			||||||
                          .copyWith(
 | 
					 | 
				
			||||||
                            color: Theme.of(context).colorScheme.onSecondary,
 | 
					 | 
				
			||||||
                            fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ]),
 | 
					 | 
				
			||||||
              expandedHeight: 150,
 | 
					 | 
				
			||||||
              backgroundColor: Theme.of(context).colorScheme.secondary,
 | 
					 | 
				
			||||||
              shape: RoundedRectangleBorder(
 | 
					 | 
				
			||||||
                borderRadius: BorderRadius.circular(8),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              floating: true,
 | 
					 | 
				
			||||||
              flexibleSpace: FlexibleSpaceBar(
 | 
					 | 
				
			||||||
                title: MacroWidget(
 | 
					 | 
				
			||||||
                  protein: diary.protein,
 | 
					 | 
				
			||||||
                  carb: diary.carb,
 | 
					 | 
				
			||||||
                  fat: diary.fat,
 | 
					 | 
				
			||||||
                  style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
					 | 
				
			||||||
                        color: Theme.of(context).colorScheme.onSecondary,
 | 
					 | 
				
			||||||
                        fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              )),
 | 
					 | 
				
			||||||
          SliverToBoxAdapter(
 | 
					 | 
				
			||||||
            child: Container(
 | 
					 | 
				
			||||||
              padding: const EdgeInsets.all(8),
 | 
					 | 
				
			||||||
              child: TextButton(
 | 
					 | 
				
			||||||
                onPressed: () {
 | 
					 | 
				
			||||||
                  Navigator.push(
 | 
					 | 
				
			||||||
                    context,
 | 
					 | 
				
			||||||
                    MaterialPageRoute(
 | 
					 | 
				
			||||||
                      builder: (context) => AddMealScreen(
 | 
					 | 
				
			||||||
                        apiClient: apiClient,
 | 
					 | 
				
			||||||
                        diary: diary,
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ).then((_) {
 | 
					 | 
				
			||||||
                    refreshParent();
 | 
					 | 
				
			||||||
                  });
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                child: const Text("Add Meal"),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          SliverList(
 | 
					 | 
				
			||||||
            delegate: SliverChildListDelegate(
 | 
					 | 
				
			||||||
              [
 | 
					 | 
				
			||||||
                for (var (i, meal) in diary.meals.indexed)
 | 
					 | 
				
			||||||
                  MealWidget(
 | 
					 | 
				
			||||||
                    meal: meal,
 | 
					 | 
				
			||||||
                    apiClient: apiClient,
 | 
					 | 
				
			||||||
                    refreshParent: refreshParent,
 | 
					 | 
				
			||||||
                    initiallyExpanded: i == 0,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
              ],
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:fooder/models/entry.dart';
 | 
					import 'package:fooder/models/entry.dart';
 | 
				
			||||||
import 'package:fooder/widgets/macroEntry.dart';
 | 
					import 'package:fooder/widgets/macro.dart';
 | 
				
			||||||
import 'dart:core';
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EntryHeader extends StatelessWidget {
 | 
					class EntryHeader extends StatelessWidget {
 | 
				
			||||||
| 
						 | 
					@ -12,14 +12,17 @@ class EntryHeader extends StatelessWidget {
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Row(
 | 
					    return Row(
 | 
				
			||||||
      children: <Widget>[
 | 
					      children: <Widget>[
 | 
				
			||||||
        Padding(
 | 
					        Expanded(
 | 
				
			||||||
          padding: const EdgeInsets.all(8),
 | 
					          child: Padding(
 | 
				
			||||||
          child: Text(
 | 
					            padding: const EdgeInsets.all(8),
 | 
				
			||||||
            entry.product.name,
 | 
					            child: Text(
 | 
				
			||||||
            style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
					              entry.product.name,
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.onPrimary,
 | 
					              overflow: TextOverflow.fade,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
				
			||||||
                ),
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        const Spacer(),
 | 
					        const Spacer(),
 | 
				
			||||||
| 
						 | 
					@ -28,7 +31,7 @@ class EntryHeader extends StatelessWidget {
 | 
				
			||||||
          child: Text(
 | 
					          child: Text(
 | 
				
			||||||
            "${entry.grams.toStringAsFixed(0)} g",
 | 
					            "${entry.grams.toStringAsFixed(0)} g",
 | 
				
			||||||
            style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
					            style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.onPrimary,
 | 
					                  color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,122 +1,163 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MacroWidget extends StatelessWidget {
 | 
					class MacroHeaderWidget extends StatelessWidget {
 | 
				
			||||||
  final double? amount;
 | 
					  static const double padY = 4;
 | 
				
			||||||
  final double? calories;
 | 
					  static const double padX = 8;
 | 
				
			||||||
  final double? fiber;
 | 
					 | 
				
			||||||
  final double protein;
 | 
					 | 
				
			||||||
  final double carb;
 | 
					 | 
				
			||||||
  final double fat;
 | 
					 | 
				
			||||||
  final TextStyle style;
 | 
					 | 
				
			||||||
  final Widget? child;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MacroWidget({
 | 
					  final bool? fiber;
 | 
				
			||||||
 | 
					  final bool? calories;
 | 
				
			||||||
 | 
					  final Alignment alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MacroHeaderWidget({
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    this.calories,
 | 
					    this.fiber = false,
 | 
				
			||||||
    this.amount,
 | 
					    this.calories = false,
 | 
				
			||||||
    this.child,
 | 
					    this.alignment = Alignment.centerLeft,
 | 
				
			||||||
    this.fiber,
 | 
					 | 
				
			||||||
    required this.protein,
 | 
					 | 
				
			||||||
    required this.carb,
 | 
					 | 
				
			||||||
    required this.fat,
 | 
					 | 
				
			||||||
    required this.style,
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    var elements = <Widget>[
 | 
					    var elements = <String>[
 | 
				
			||||||
      Expanded(
 | 
					      "C(g)",
 | 
				
			||||||
        flex: 1,
 | 
					      "F(g)",
 | 
				
			||||||
        child: Text(
 | 
					      "P(g)",
 | 
				
			||||||
          "C: ${carb.toStringAsFixed(1)}g",
 | 
					    ];
 | 
				
			||||||
          style: style,
 | 
					
 | 
				
			||||||
          textAlign: TextAlign.center,
 | 
					    if (fiber == true) {
 | 
				
			||||||
 | 
					      elements.add(
 | 
				
			||||||
 | 
					        "f(g)",
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (calories == true) {
 | 
				
			||||||
 | 
					      elements.add(
 | 
				
			||||||
 | 
					        "kcal",
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var children = <Widget>[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (alignment == Alignment.centerRight) {
 | 
				
			||||||
 | 
					      children.add(const Spacer());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (var element in elements) {
 | 
				
			||||||
 | 
					      children.add(
 | 
				
			||||||
 | 
					        Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.symmetric(
 | 
				
			||||||
 | 
					            horizontal: 2,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          child: SizedBox(
 | 
				
			||||||
 | 
					            width: 55,
 | 
				
			||||||
 | 
					            child: Text(
 | 
				
			||||||
 | 
					              element,
 | 
				
			||||||
 | 
					              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
				
			||||||
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					              textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (alignment == Alignment.centerLeft) {
 | 
				
			||||||
 | 
					      children.add(const Spacer());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.symmetric(
 | 
				
			||||||
 | 
					        vertical: padY,
 | 
				
			||||||
 | 
					        horizontal: padX,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      Expanded(
 | 
					      child: Row(
 | 
				
			||||||
        flex: 1,
 | 
					        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | 
				
			||||||
        child: Text(
 | 
					        children: children,
 | 
				
			||||||
          "F: ${fat.toStringAsFixed(1)}g",
 | 
					 | 
				
			||||||
          style: style,
 | 
					 | 
				
			||||||
          textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      Expanded(
 | 
					 | 
				
			||||||
        flex: 1,
 | 
					 | 
				
			||||||
        child: Text(
 | 
					 | 
				
			||||||
          "P: ${protein.toStringAsFixed(1)}g",
 | 
					 | 
				
			||||||
          style: style,
 | 
					 | 
				
			||||||
          textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MacroEntryWidget extends StatelessWidget {
 | 
				
			||||||
 | 
					  static const double padY = 4;
 | 
				
			||||||
 | 
					  static const double padX = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final double protein;
 | 
				
			||||||
 | 
					  final double carb;
 | 
				
			||||||
 | 
					  final double fat;
 | 
				
			||||||
 | 
					  final double? fiber;
 | 
				
			||||||
 | 
					  final double? calories;
 | 
				
			||||||
 | 
					  final Alignment alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MacroEntryWidget({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.protein,
 | 
				
			||||||
 | 
					    required this.carb,
 | 
				
			||||||
 | 
					    required this.fat,
 | 
				
			||||||
 | 
					    this.fiber,
 | 
				
			||||||
 | 
					    this.calories,
 | 
				
			||||||
 | 
					    this.alignment = Alignment.centerLeft,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    var elements = <String>[
 | 
				
			||||||
 | 
					      (carb.toStringAsFixed(1)),
 | 
				
			||||||
 | 
					      (fat.toStringAsFixed(1)),
 | 
				
			||||||
 | 
					      (protein.toStringAsFixed(1)),
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (fiber != null) {
 | 
					    if (fiber != null) {
 | 
				
			||||||
      elements.add(
 | 
					      elements.add(
 | 
				
			||||||
        Expanded(
 | 
					        fiber!.toStringAsFixed(1),
 | 
				
			||||||
          flex: 1,
 | 
					 | 
				
			||||||
          child: Text(
 | 
					 | 
				
			||||||
            "f: ${fiber!.toStringAsFixed(1)}g",
 | 
					 | 
				
			||||||
            style: style,
 | 
					 | 
				
			||||||
            textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (calories != null) {
 | 
					    if (calories != null) {
 | 
				
			||||||
      elements.add(
 | 
					      elements.add(
 | 
				
			||||||
        Expanded(
 | 
					        calories!.toStringAsFixed(0),
 | 
				
			||||||
          flex: 1,
 | 
					      );
 | 
				
			||||||
          child: Text(
 | 
					    }
 | 
				
			||||||
            "${calories!.toStringAsFixed(1)} kcal",
 | 
					
 | 
				
			||||||
            style: style,
 | 
					    var children = <Widget>[];
 | 
				
			||||||
            textAlign: TextAlign.center,
 | 
					
 | 
				
			||||||
 | 
					    if (alignment == Alignment.centerRight) {
 | 
				
			||||||
 | 
					      children.add(const Spacer());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (var element in elements) {
 | 
				
			||||||
 | 
					      children.add(
 | 
				
			||||||
 | 
					        Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.symmetric(
 | 
				
			||||||
 | 
					            horizontal: 2,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          child: SizedBox(
 | 
				
			||||||
 | 
					            width: 55,
 | 
				
			||||||
 | 
					            child: Text(
 | 
				
			||||||
 | 
					              element,
 | 
				
			||||||
 | 
					              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
				
			||||||
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					              textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (amount != null) {
 | 
					    if (alignment == Alignment.centerLeft) {
 | 
				
			||||||
      elements.add(
 | 
					      children.add(const Spacer());
 | 
				
			||||||
        Expanded(
 | 
					 | 
				
			||||||
          flex: 1,
 | 
					 | 
				
			||||||
          child: Text(
 | 
					 | 
				
			||||||
            "${amount!.toStringAsFixed(1)}g",
 | 
					 | 
				
			||||||
            style: style,
 | 
					 | 
				
			||||||
            textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (child != null) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        Expanded(
 | 
					 | 
				
			||||||
          flex: 1,
 | 
					 | 
				
			||||||
          child: child!,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (elements.length < 4) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        const Expanded(
 | 
					 | 
				
			||||||
          flex: 1,
 | 
					 | 
				
			||||||
          child: Text(""),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Padding(
 | 
					    return Padding(
 | 
				
			||||||
      padding: const EdgeInsets.only(
 | 
					      padding: const EdgeInsets.symmetric(
 | 
				
			||||||
        top: 4.0,
 | 
					        vertical: padY,
 | 
				
			||||||
        bottom: 4.0,
 | 
					        horizontal: padX,
 | 
				
			||||||
        left: 8.0,
 | 
					 | 
				
			||||||
        right: 8.0,
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      child: Row(
 | 
					      child: Row(
 | 
				
			||||||
        children: elements,
 | 
					        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | 
				
			||||||
 | 
					        children: children,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,148 +0,0 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'dart:core';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MacroHeaderWidget extends StatelessWidget {
 | 
					 | 
				
			||||||
  static const double PAD_Y = 4;
 | 
					 | 
				
			||||||
  static const double PAD_X = 8;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  final bool? fiber;
 | 
					 | 
				
			||||||
  final bool? calories;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const MacroHeaderWidget({
 | 
					 | 
				
			||||||
    super.key,
 | 
					 | 
				
			||||||
    this.fiber = false,
 | 
					 | 
				
			||||||
    this.calories = false,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    var elements = <String>[
 | 
					 | 
				
			||||||
      "C(g)",
 | 
					 | 
				
			||||||
      "F(g)",
 | 
					 | 
				
			||||||
      "P(g)",
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (fiber == true) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        "F(g)",
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (calories == true) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        "kcal",
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var children = <Widget>[];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (var element in elements) {
 | 
					 | 
				
			||||||
      children.add(
 | 
					 | 
				
			||||||
        Padding(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.symmetric(
 | 
					 | 
				
			||||||
            horizontal: 2,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          child: SizedBox(
 | 
					 | 
				
			||||||
            width: 55,
 | 
					 | 
				
			||||||
            child: Text(
 | 
					 | 
				
			||||||
              element,
 | 
					 | 
				
			||||||
              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
					 | 
				
			||||||
                    color: Theme.of(context).colorScheme.onPrimary,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
              textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    children.add(const Spacer());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Padding(
 | 
					 | 
				
			||||||
      padding: const EdgeInsets.symmetric(
 | 
					 | 
				
			||||||
        vertical: PAD_Y,
 | 
					 | 
				
			||||||
        horizontal: PAD_X,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      child: Row(
 | 
					 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | 
					 | 
				
			||||||
        children: children,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MacroEntryWidget extends StatelessWidget {
 | 
					 | 
				
			||||||
  static const double PAD_Y = 4;
 | 
					 | 
				
			||||||
  static const double PAD_X = 8;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  final double protein;
 | 
					 | 
				
			||||||
  final double carb;
 | 
					 | 
				
			||||||
  final double fat;
 | 
					 | 
				
			||||||
  final double? fiber;
 | 
					 | 
				
			||||||
  final double? calories;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const MacroEntryWidget({
 | 
					 | 
				
			||||||
    super.key,
 | 
					 | 
				
			||||||
    required this.protein,
 | 
					 | 
				
			||||||
    required this.carb,
 | 
					 | 
				
			||||||
    required this.fat,
 | 
					 | 
				
			||||||
    this.fiber,
 | 
					 | 
				
			||||||
    this.calories,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    var elements = <String>[
 | 
					 | 
				
			||||||
      (carb.toStringAsFixed(1)),
 | 
					 | 
				
			||||||
      (fat.toStringAsFixed(1)),
 | 
					 | 
				
			||||||
      (protein.toStringAsFixed(1)),
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (fiber != null) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        fiber!.toStringAsFixed(1),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (calories != null) {
 | 
					 | 
				
			||||||
      elements.add(
 | 
					 | 
				
			||||||
        calories!.toStringAsFixed(0),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var children = <Widget>[];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (var element in elements) {
 | 
					 | 
				
			||||||
      children.add(
 | 
					 | 
				
			||||||
        Padding(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.symmetric(
 | 
					 | 
				
			||||||
            horizontal: 2,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          child: SizedBox(
 | 
					 | 
				
			||||||
            width: 55,
 | 
					 | 
				
			||||||
            child: Text(
 | 
					 | 
				
			||||||
              element,
 | 
					 | 
				
			||||||
              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
					 | 
				
			||||||
                    color: Theme.of(context).colorScheme.onPrimary,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
              textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    children.add(const Spacer());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Padding(
 | 
					 | 
				
			||||||
      padding: const EdgeInsets.symmetric(
 | 
					 | 
				
			||||||
        vertical: PAD_Y,
 | 
					 | 
				
			||||||
        horizontal: PAD_X,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      child: Row(
 | 
					 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | 
					 | 
				
			||||||
        children: children,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,8 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:fooder/models/meal.dart';
 | 
					import 'package:fooder/models/meal.dart';
 | 
				
			||||||
import 'package:fooder/widgets/entry.dart';
 | 
					import 'package:fooder/widgets/entry.dart';
 | 
				
			||||||
import 'package:fooder/widgets/macroEntry.dart';
 | 
					import 'package:fooder/widgets/macro.dart';
 | 
				
			||||||
import 'package:fooder/screens/edit_entry.dart';
 | 
					import 'package:fooder/screens/edit_entry.dart';
 | 
				
			||||||
import 'package:fooder/screens/meal.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/client.dart';
 | 
					import 'package:fooder/client.dart';
 | 
				
			||||||
import 'dart:core';
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,14 +15,17 @@ class MealHeader extends StatelessWidget {
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Row(
 | 
					    return Row(
 | 
				
			||||||
      children: <Widget>[
 | 
					      children: <Widget>[
 | 
				
			||||||
        Padding(
 | 
					        Expanded(
 | 
				
			||||||
          padding: const EdgeInsets.all(8),
 | 
					          child: Padding(
 | 
				
			||||||
          child: Text(
 | 
					            padding: const EdgeInsets.all(8),
 | 
				
			||||||
            meal.name,
 | 
					            child: Text(
 | 
				
			||||||
            style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
					              meal.name,
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.onPrimary,
 | 
					              overflow: TextOverflow.fade,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					              style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
				
			||||||
                ),
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
| 
						 | 
					@ -37,6 +39,7 @@ class MealWidget extends StatelessWidget {
 | 
				
			||||||
  final Meal meal;
 | 
					  final Meal meal;
 | 
				
			||||||
  final ApiClient apiClient;
 | 
					  final ApiClient apiClient;
 | 
				
			||||||
  final Function() refreshParent;
 | 
					  final Function() refreshParent;
 | 
				
			||||||
 | 
					  final Function(String) showText;
 | 
				
			||||||
  final bool initiallyExpanded;
 | 
					  final bool initiallyExpanded;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MealWidget({
 | 
					  const MealWidget({
 | 
				
			||||||
| 
						 | 
					@ -45,19 +48,73 @@ class MealWidget extends StatelessWidget {
 | 
				
			||||||
    required this.apiClient,
 | 
					    required this.apiClient,
 | 
				
			||||||
    required this.refreshParent,
 | 
					    required this.refreshParent,
 | 
				
			||||||
    required this.initiallyExpanded,
 | 
					    required this.initiallyExpanded,
 | 
				
			||||||
 | 
					    required this.showText,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> _editMeal(context) async {
 | 
					  Future<void> saveMeal(context) async {
 | 
				
			||||||
    await Navigator.push(
 | 
					    TextEditingController textFieldController = TextEditingController();
 | 
				
			||||||
      context,
 | 
					    textFieldController.text = meal.name;
 | 
				
			||||||
      MaterialPageRoute(
 | 
					
 | 
				
			||||||
        builder: (context) => MealScreen(
 | 
					    showDialog(
 | 
				
			||||||
          apiClient: apiClient,
 | 
					      context: context,
 | 
				
			||||||
          meal: meal,
 | 
					      builder: (context) {
 | 
				
			||||||
          refresh: refreshParent,
 | 
					        return AlertDialog(
 | 
				
			||||||
        ),
 | 
					          title: const Text('Save Meal'),
 | 
				
			||||||
      ),
 | 
					          content: TextField(
 | 
				
			||||||
    ).then((_) => refreshParent());
 | 
					            controller: textFieldController,
 | 
				
			||||||
 | 
					            decoration: const InputDecoration(hintText: "Meal template name"),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          actions: <Widget>[
 | 
				
			||||||
 | 
					            IconButton(
 | 
				
			||||||
 | 
					              icon: const Icon(Icons.cancel),
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                Navigator.pop(context);
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            IconButton(
 | 
				
			||||||
 | 
					              icon: const Icon(Icons.save),
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                apiClient.saveMeal(meal, textFieldController.text);
 | 
				
			||||||
 | 
					                Navigator.pop(context);
 | 
				
			||||||
 | 
					                showText("Meal saved");
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> _deleteMeal(Meal meal) async {
 | 
				
			||||||
 | 
					    await apiClient.deleteMeal(meal.id);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> deleteMeal(context) async {
 | 
				
			||||||
 | 
					    showDialog(
 | 
				
			||||||
 | 
					      context: context,
 | 
				
			||||||
 | 
					      barrierDismissible: false,
 | 
				
			||||||
 | 
					      builder: (context) {
 | 
				
			||||||
 | 
					        return AlertDialog(
 | 
				
			||||||
 | 
					          title: const Text('Confirm deletion of the meal'),
 | 
				
			||||||
 | 
					          actions: <Widget>[
 | 
				
			||||||
 | 
					            IconButton(
 | 
				
			||||||
 | 
					              icon: const Icon(Icons.cancel),
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                Navigator.pop(context);
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            IconButton(
 | 
				
			||||||
 | 
					              icon: const Icon(Icons.delete),
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                _deleteMeal(meal).then((_) => refreshParent());
 | 
				
			||||||
 | 
					                Navigator.pop(context);
 | 
				
			||||||
 | 
					                showText("Meal deleted");
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> _editEntry(context, entry) async {
 | 
					  Future<void> _editEntry(context, entry) async {
 | 
				
			||||||
| 
						 | 
					@ -84,61 +141,61 @@ class MealWidget extends StatelessWidget {
 | 
				
			||||||
      child: Padding(
 | 
					      child: Padding(
 | 
				
			||||||
        padding: const EdgeInsets.all(8),
 | 
					        padding: const EdgeInsets.all(8),
 | 
				
			||||||
        child: Card(
 | 
					        child: Card(
 | 
				
			||||||
          elevation: 4,
 | 
					 | 
				
			||||||
          clipBehavior: Clip.antiAlias,
 | 
					          clipBehavior: Clip.antiAlias,
 | 
				
			||||||
          shadowColor: colorScheme.primary.withOpacity(1.0),
 | 
					 | 
				
			||||||
          shape: RoundedRectangleBorder(
 | 
					          shape: RoundedRectangleBorder(
 | 
				
			||||||
            borderRadius: BorderRadius.circular(24),
 | 
					            borderRadius: BorderRadius.circular(24),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          child: SizedBox(
 | 
					          child: Container(
 | 
				
			||||||
            width: width,
 | 
					            constraints: BoxConstraints(maxWidth: width),
 | 
				
			||||||
            child: Container(
 | 
					            color: colorScheme.surface.withOpacity(0.2),
 | 
				
			||||||
              decoration: BoxDecoration(
 | 
					            child: ExpansionTile(
 | 
				
			||||||
                gradient: LinearGradient(
 | 
					              iconColor: colorScheme.onSurface,
 | 
				
			||||||
                  colors: [
 | 
					              collapsedIconColor: colorScheme.onSurface,
 | 
				
			||||||
                    colorScheme.primary.withOpacity(0.6),
 | 
					              initiallyExpanded: initiallyExpanded,
 | 
				
			||||||
                    colorScheme.secondary.withOpacity(0.5),
 | 
					              enableFeedback: true,
 | 
				
			||||||
                  ],
 | 
					              title: Padding(
 | 
				
			||||||
                ),
 | 
					                padding: const EdgeInsets.all(8),
 | 
				
			||||||
              ),
 | 
					                child: Column(
 | 
				
			||||||
              child: InkWell(
 | 
					 | 
				
			||||||
                splashColor: Colors.blue.withAlpha(30),
 | 
					 | 
				
			||||||
                onLongPress: () => _editMeal(context),
 | 
					 | 
				
			||||||
                child: ExpansionTile(
 | 
					 | 
				
			||||||
                  iconColor: colorScheme.onPrimary,
 | 
					 | 
				
			||||||
                  collapsedIconColor: colorScheme.onPrimary,
 | 
					 | 
				
			||||||
                  initiallyExpanded: initiallyExpanded,
 | 
					 | 
				
			||||||
                  title: Padding(
 | 
					 | 
				
			||||||
                    padding: const EdgeInsets.all(8),
 | 
					 | 
				
			||||||
                    child: Column(
 | 
					 | 
				
			||||||
                      children: <Widget>[
 | 
					 | 
				
			||||||
                        MealHeader(meal: meal),
 | 
					 | 
				
			||||||
                        const MacroHeaderWidget(
 | 
					 | 
				
			||||||
                          calories: true,
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        MacroEntryWidget(
 | 
					 | 
				
			||||||
                          protein: meal.protein,
 | 
					 | 
				
			||||||
                          carb: meal.carb,
 | 
					 | 
				
			||||||
                          fat: meal.fat,
 | 
					 | 
				
			||||||
                          calories: meal.calories,
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      ],
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  children: <Widget>[
 | 
					                  children: <Widget>[
 | 
				
			||||||
                    for (var (i, entry) in meal.entries.indexed)
 | 
					                    MealHeader(meal: meal),
 | 
				
			||||||
                      ListTile(
 | 
					                    const MacroHeaderWidget(
 | 
				
			||||||
                        title: EntryWidget(
 | 
					                      calories: true,
 | 
				
			||||||
                          entry: entry,
 | 
					                    ),
 | 
				
			||||||
                        ),
 | 
					                    MacroEntryWidget(
 | 
				
			||||||
                        tileColor: i % 2 == 0
 | 
					                      protein: meal.protein,
 | 
				
			||||||
                            ? colorScheme.secondary.withOpacity(0.1)
 | 
					                      carb: meal.carb,
 | 
				
			||||||
                            : Colors.transparent,
 | 
					                      fat: meal.fat,
 | 
				
			||||||
                        onTap: () => _editEntry(context, entry),
 | 
					                      calories: meal.calories,
 | 
				
			||||||
                      )
 | 
					                    ),
 | 
				
			||||||
                  ],
 | 
					                  ],
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 | 
					              children: <Widget>[
 | 
				
			||||||
 | 
					                for (var (i, entry) in meal.entries.indexed)
 | 
				
			||||||
 | 
					                  ListTile(
 | 
				
			||||||
 | 
					                    title: EntryWidget(
 | 
				
			||||||
 | 
					                      entry: entry,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    tileColor: i % 2 == 0
 | 
				
			||||||
 | 
					                        ? colorScheme.surfaceVariant.withOpacity(0.1)
 | 
				
			||||||
 | 
					                        : Colors.transparent,
 | 
				
			||||||
 | 
					                    onTap: () => _editEntry(context, entry),
 | 
				
			||||||
 | 
					                    enableFeedback: true,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                Row(
 | 
				
			||||||
 | 
					                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | 
				
			||||||
 | 
					                  children: <Widget>[
 | 
				
			||||||
 | 
					                    IconButton(
 | 
				
			||||||
 | 
					                      icon: const Icon(Icons.save),
 | 
				
			||||||
 | 
					                      onPressed: () => saveMeal(context),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    IconButton(
 | 
				
			||||||
 | 
					                      icon: const Icon(Icons.delete),
 | 
				
			||||||
 | 
					                      onPressed: () => deleteMeal(context),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,33 @@ import 'package:fooder/models/preset.dart';
 | 
				
			||||||
import 'package:fooder/widgets/macro.dart';
 | 
					import 'package:fooder/widgets/macro.dart';
 | 
				
			||||||
import 'dart:core';
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PresetHeader extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const PresetHeader({super.key, required this.title});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Row(
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Expanded(
 | 
				
			||||||
 | 
					          child: Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
				
			||||||
 | 
					            child: Text(
 | 
				
			||||||
 | 
					              title,
 | 
				
			||||||
 | 
					              overflow: TextOverflow.fade,
 | 
				
			||||||
 | 
					              style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
				
			||||||
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PresetWidget extends StatelessWidget {
 | 
					class PresetWidget extends StatelessWidget {
 | 
				
			||||||
  final Preset preset;
 | 
					  final Preset preset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,24 +41,21 @@ class PresetWidget extends StatelessWidget {
 | 
				
			||||||
      padding: const EdgeInsets.all(8),
 | 
					      padding: const EdgeInsets.all(8),
 | 
				
			||||||
      child: Column(
 | 
					      child: Column(
 | 
				
			||||||
        children: <Widget>[
 | 
					        children: <Widget>[
 | 
				
			||||||
          Row(
 | 
					          PresetHeader(
 | 
				
			||||||
            children: <Widget>[
 | 
					            title: preset.name,
 | 
				
			||||||
              Expanded(
 | 
					 | 
				
			||||||
                child: Text(
 | 
					 | 
				
			||||||
                  preset.name,
 | 
					 | 
				
			||||||
                  style: Theme.of(context).textTheme.titleLarge,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              Text("${preset.calories.toStringAsFixed(1)} kcal"),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          MacroWidget(
 | 
					          const MacroHeaderWidget(
 | 
				
			||||||
 | 
					            fiber: true,
 | 
				
			||||||
 | 
					            calories: true,
 | 
				
			||||||
 | 
					            alignment: Alignment.center,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          MacroEntryWidget(
 | 
				
			||||||
            protein: preset.protein,
 | 
					            protein: preset.protein,
 | 
				
			||||||
            carb: preset.carb,
 | 
					            carb: preset.carb,
 | 
				
			||||||
            fat: preset.fat,
 | 
					            fat: preset.fat,
 | 
				
			||||||
            style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
					            fiber: preset.fiber,
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.secondary,
 | 
					            calories: preset.calories,
 | 
				
			||||||
                ),
 | 
					            alignment: Alignment.center,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,33 @@ import 'package:fooder/models/product.dart';
 | 
				
			||||||
import 'package:fooder/widgets/macro.dart';
 | 
					import 'package:fooder/widgets/macro.dart';
 | 
				
			||||||
import 'dart:core';
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProductHeader extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ProductHeader({super.key, required this.title});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Row(
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Expanded(
 | 
				
			||||||
 | 
					          child: Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
				
			||||||
 | 
					            child: Text(
 | 
				
			||||||
 | 
					              title,
 | 
				
			||||||
 | 
					              overflow: TextOverflow.fade,
 | 
				
			||||||
 | 
					              style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
				
			||||||
 | 
					                    color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProductWidget extends StatelessWidget {
 | 
					class ProductWidget extends StatelessWidget {
 | 
				
			||||||
  final Product product;
 | 
					  final Product product;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,26 +41,21 @@ class ProductWidget extends StatelessWidget {
 | 
				
			||||||
      padding: const EdgeInsets.all(8),
 | 
					      padding: const EdgeInsets.all(8),
 | 
				
			||||||
      child: Column(
 | 
					      child: Column(
 | 
				
			||||||
        children: <Widget>[
 | 
					        children: <Widget>[
 | 
				
			||||||
          Row(
 | 
					          ProductHeader(
 | 
				
			||||||
            children: <Widget>[
 | 
					            title: product.name,
 | 
				
			||||||
              Expanded(
 | 
					 | 
				
			||||||
                child: Text(
 | 
					 | 
				
			||||||
                  product.name,
 | 
					 | 
				
			||||||
                  style: Theme.of(context).textTheme.titleLarge,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              Text("${product.calories.toStringAsFixed(1)} kcal"),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          MacroWidget(
 | 
					          const MacroHeaderWidget(
 | 
				
			||||||
 | 
					            fiber: true,
 | 
				
			||||||
 | 
					            calories: true,
 | 
				
			||||||
 | 
					            alignment: Alignment.center,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          MacroEntryWidget(
 | 
				
			||||||
            protein: product.protein,
 | 
					            protein: product.protein,
 | 
				
			||||||
            carb: product.carb,
 | 
					            carb: product.carb,
 | 
				
			||||||
            fat: product.fat,
 | 
					            fat: product.fat,
 | 
				
			||||||
            fiber: product.fiber,
 | 
					            fiber: product.fiber,
 | 
				
			||||||
            style: Theme.of(context).textTheme.bodyMedium!.copyWith(
 | 
					            calories: product.calories,
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.secondary,
 | 
					            alignment: Alignment.center,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,13 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:fooder/models/diary.dart';
 | 
					import 'package:fooder/models/diary.dart';
 | 
				
			||||||
import 'package:fooder/widgets/macroEntry.dart';
 | 
					import 'package:fooder/widgets/macro.dart';
 | 
				
			||||||
import 'package:fooder/screens/add_meal.dart';
 | 
					 | 
				
			||||||
import 'package:fooder/client.dart';
 | 
					import 'package:fooder/client.dart';
 | 
				
			||||||
import 'dart:core';
 | 
					import 'dart:core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SummaryHeader extends StatelessWidget {
 | 
					class SummaryHeader extends StatelessWidget {
 | 
				
			||||||
  final Diary diary;
 | 
					  final Diary diary;
 | 
				
			||||||
  final Function addMeal;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const SummaryHeader({super.key, required this.addMeal, required this.diary});
 | 
					  const SummaryHeader({super.key, required this.diary});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
| 
						 | 
					@ -20,21 +18,12 @@ class SummaryHeader extends StatelessWidget {
 | 
				
			||||||
          child: Text(
 | 
					          child: Text(
 | 
				
			||||||
            "Summary",
 | 
					            "Summary",
 | 
				
			||||||
            style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
					            style: Theme.of(context).textTheme.headlineSmall!.copyWith(
 | 
				
			||||||
                  color: Theme.of(context).colorScheme.onPrimary,
 | 
					                  color: Theme.of(context).colorScheme.onSurface,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        const Spacer(),
 | 
					        const Spacer(),
 | 
				
			||||||
        Padding(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.symmetric(horizontal: 8),
 | 
					 | 
				
			||||||
          child: IconButton(
 | 
					 | 
				
			||||||
            icon: const Icon(Icons.playlist_add_rounded),
 | 
					 | 
				
			||||||
            iconSize: 32,
 | 
					 | 
				
			||||||
            color: Theme.of(context).colorScheme.onPrimary,
 | 
					 | 
				
			||||||
            onPressed: () => addMeal(context),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -53,18 +42,6 @@ class SummaryWidget extends StatelessWidget {
 | 
				
			||||||
      required this.apiClient,
 | 
					      required this.apiClient,
 | 
				
			||||||
      required this.refreshParent});
 | 
					      required this.refreshParent});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> _addMeal(context) async {
 | 
					 | 
				
			||||||
    await Navigator.push(
 | 
					 | 
				
			||||||
      context,
 | 
					 | 
				
			||||||
      MaterialPageRoute(
 | 
					 | 
				
			||||||
        builder: (context) => AddMealScreen(
 | 
					 | 
				
			||||||
          apiClient: apiClient,
 | 
					 | 
				
			||||||
          diary: diary,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((_) => refreshParent());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    var theme = Theme.of(context);
 | 
					    var theme = Theme.of(context);
 | 
				
			||||||
| 
						 | 
					@ -77,40 +54,28 @@ class SummaryWidget extends StatelessWidget {
 | 
				
			||||||
      child: Padding(
 | 
					      child: Padding(
 | 
				
			||||||
        padding: const EdgeInsets.all(8),
 | 
					        padding: const EdgeInsets.all(8),
 | 
				
			||||||
        child: Card(
 | 
					        child: Card(
 | 
				
			||||||
          elevation: 4,
 | 
					 | 
				
			||||||
          clipBehavior: Clip.antiAlias,
 | 
					          clipBehavior: Clip.antiAlias,
 | 
				
			||||||
          shadowColor: colorScheme.primary.withOpacity(1.0),
 | 
					 | 
				
			||||||
          shape: RoundedRectangleBorder(
 | 
					          shape: RoundedRectangleBorder(
 | 
				
			||||||
            borderRadius: BorderRadius.circular(24),
 | 
					            borderRadius: BorderRadius.circular(24),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          child: SizedBox(
 | 
					          child: Container(
 | 
				
			||||||
            width: width,
 | 
					            constraints: BoxConstraints(maxWidth: width),
 | 
				
			||||||
            child: Container(
 | 
					            color: colorScheme.surface.withOpacity(0.2),
 | 
				
			||||||
              decoration: BoxDecoration(
 | 
					            child: Padding(
 | 
				
			||||||
                gradient: LinearGradient(
 | 
					              padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
 | 
				
			||||||
                  colors: [
 | 
					              child: Column(
 | 
				
			||||||
                    colorScheme.primary.withOpacity(0.6),
 | 
					                children: <Widget>[
 | 
				
			||||||
                    colorScheme.secondary.withOpacity(0.5),
 | 
					                  SummaryHeader(diary: diary),
 | 
				
			||||||
                  ],
 | 
					                  const MacroHeaderWidget(
 | 
				
			||||||
                ),
 | 
					                    calories: true,
 | 
				
			||||||
              ),
 | 
					                  ),
 | 
				
			||||||
              child: Padding(
 | 
					                  MacroEntryWidget(
 | 
				
			||||||
                padding:
 | 
					                    protein: diary.protein,
 | 
				
			||||||
                    const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
 | 
					                    carb: diary.carb,
 | 
				
			||||||
                child: Column(
 | 
					                    fat: diary.fat,
 | 
				
			||||||
                  children: <Widget>[
 | 
					                    calories: diary.calories,
 | 
				
			||||||
                    SummaryHeader(diary: diary, addMeal: _addMeal),
 | 
					                  ),
 | 
				
			||||||
                    const MacroHeaderWidget(
 | 
					                ],
 | 
				
			||||||
                      calories: true,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                    MacroEntryWidget(
 | 
					 | 
				
			||||||
                      protein: diary.protein,
 | 
					 | 
				
			||||||
                      carb: diary.carb,
 | 
					 | 
				
			||||||
                      fat: diary.fat,
 | 
					 | 
				
			||||||
                      calories: diary.calories,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ],
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								macos/Podfile.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								macos/Podfile.lock
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					PODS:
 | 
				
			||||||
 | 
					  - flutter_secure_storage_macos (6.1.1):
 | 
				
			||||||
 | 
					    - FlutterMacOS
 | 
				
			||||||
 | 
					  - FlutterMacOS (1.0.0)
 | 
				
			||||||
 | 
					  - path_provider_foundation (0.0.1):
 | 
				
			||||||
 | 
					    - Flutter
 | 
				
			||||||
 | 
					    - FlutterMacOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEPENDENCIES:
 | 
				
			||||||
 | 
					  - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
 | 
				
			||||||
 | 
					  - FlutterMacOS (from `Flutter/ephemeral`)
 | 
				
			||||||
 | 
					  - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTERNAL SOURCES:
 | 
				
			||||||
 | 
					  flutter_secure_storage_macos:
 | 
				
			||||||
 | 
					    :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
 | 
				
			||||||
 | 
					  FlutterMacOS:
 | 
				
			||||||
 | 
					    :path: Flutter/ephemeral
 | 
				
			||||||
 | 
					  path_provider_foundation:
 | 
				
			||||||
 | 
					    :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPEC CHECKSUMS:
 | 
				
			||||||
 | 
					  flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
 | 
				
			||||||
 | 
					  FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
 | 
				
			||||||
 | 
					  path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COCOAPODS: 1.15.2
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,8 @@
 | 
				
			||||||
		33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
 | 
							33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
 | 
				
			||||||
		33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
 | 
							33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
 | 
				
			||||||
		33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
 | 
							33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
 | 
				
			||||||
 | 
							47A87A2D935C9FD21BC18BA6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BEB3BB725731AD7E5B80B1 /* Pods_Runner.framework */; };
 | 
				
			||||||
 | 
							DC768C2964C710CDD24D0DB4 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 465D02A290608CA511C1F4CA /* Pods_RunnerTests.framework */; };
 | 
				
			||||||
/* End PBXBuildFile section */
 | 
					/* End PBXBuildFile section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXContainerItemProxy section */
 | 
					/* Begin PBXContainerItemProxy section */
 | 
				
			||||||
| 
						 | 
					@ -60,11 +62,14 @@
 | 
				
			||||||
/* End PBXCopyFilesBuildPhase section */
 | 
					/* End PBXCopyFilesBuildPhase section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXFileReference section */
 | 
					/* Begin PBXFileReference section */
 | 
				
			||||||
 | 
							0834B9429B6D5467EDC30594 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							17BEB3BB725731AD7E5B80B1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
				
			||||||
 | 
							19DEDDAC7F8C48D43A9E76CF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
		331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
							331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
				
			||||||
		331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
 | 
							331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
 | 
				
			||||||
		333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
 | 
							333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
 | 
				
			||||||
		335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
 | 
							335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
 | 
				
			||||||
		33CC10ED2044A3C60003C045 /* fooder_web.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "fooder_web.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
							33CC10ED2044A3C60003C045 /* fooder_web.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fooder_web.app; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
				
			||||||
		33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 | 
							33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 | 
				
			||||||
		33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
 | 
							33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
 | 
				
			||||||
		33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
 | 
							33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
 | 
				
			||||||
| 
						 | 
					@ -76,8 +81,13 @@
 | 
				
			||||||
		33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
 | 
							33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
 | 
				
			||||||
		33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
 | 
							33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
 | 
				
			||||||
		33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
 | 
							33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							465D02A290608CA511C1F4CA /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
				
			||||||
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
 | 
							7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
 | 
				
			||||||
		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
 | 
							9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							A4E1FEE05E55FE57D150055B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							A7C614E4C8DC6AE860A60034 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							D32BEBE6FA5B351434300418 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
 | 
							F971A3061D014BCFE5A477A9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
 | 
				
			||||||
/* End PBXFileReference section */
 | 
					/* End PBXFileReference section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXFrameworksBuildPhase section */
 | 
					/* Begin PBXFrameworksBuildPhase section */
 | 
				
			||||||
| 
						 | 
					@ -85,6 +95,7 @@
 | 
				
			||||||
			isa = PBXFrameworksBuildPhase;
 | 
								isa = PBXFrameworksBuildPhase;
 | 
				
			||||||
			buildActionMask = 2147483647;
 | 
								buildActionMask = 2147483647;
 | 
				
			||||||
			files = (
 | 
								files = (
 | 
				
			||||||
 | 
									DC768C2964C710CDD24D0DB4 /* Pods_RunnerTests.framework in Frameworks */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
| 
						 | 
					@ -92,12 +103,27 @@
 | 
				
			||||||
			isa = PBXFrameworksBuildPhase;
 | 
								isa = PBXFrameworksBuildPhase;
 | 
				
			||||||
			buildActionMask = 2147483647;
 | 
								buildActionMask = 2147483647;
 | 
				
			||||||
			files = (
 | 
								files = (
 | 
				
			||||||
 | 
									47A87A2D935C9FD21BC18BA6 /* Pods_Runner.framework in Frameworks */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			runOnlyForDeploymentPostprocessing = 0;
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
/* End PBXFrameworksBuildPhase section */
 | 
					/* End PBXFrameworksBuildPhase section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXGroup section */
 | 
					/* Begin PBXGroup section */
 | 
				
			||||||
 | 
							076AC79CB527EDDF03C6C1BF /* Pods */ = {
 | 
				
			||||||
 | 
								isa = PBXGroup;
 | 
				
			||||||
 | 
								children = (
 | 
				
			||||||
 | 
									0834B9429B6D5467EDC30594 /* Pods-Runner.debug.xcconfig */,
 | 
				
			||||||
 | 
									A7C614E4C8DC6AE860A60034 /* Pods-Runner.release.xcconfig */,
 | 
				
			||||||
 | 
									A4E1FEE05E55FE57D150055B /* Pods-Runner.profile.xcconfig */,
 | 
				
			||||||
 | 
									F971A3061D014BCFE5A477A9 /* Pods-RunnerTests.debug.xcconfig */,
 | 
				
			||||||
 | 
									D32BEBE6FA5B351434300418 /* Pods-RunnerTests.release.xcconfig */,
 | 
				
			||||||
 | 
									19DEDDAC7F8C48D43A9E76CF /* Pods-RunnerTests.profile.xcconfig */,
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								name = Pods;
 | 
				
			||||||
 | 
								path = Pods;
 | 
				
			||||||
 | 
								sourceTree = "<group>";
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
		331C80D6294CF71000263BE5 /* RunnerTests */ = {
 | 
							331C80D6294CF71000263BE5 /* RunnerTests */ = {
 | 
				
			||||||
			isa = PBXGroup;
 | 
								isa = PBXGroup;
 | 
				
			||||||
			children = (
 | 
								children = (
 | 
				
			||||||
| 
						 | 
					@ -125,6 +151,7 @@
 | 
				
			||||||
				331C80D6294CF71000263BE5 /* RunnerTests */,
 | 
									331C80D6294CF71000263BE5 /* RunnerTests */,
 | 
				
			||||||
				33CC10EE2044A3C60003C045 /* Products */,
 | 
									33CC10EE2044A3C60003C045 /* Products */,
 | 
				
			||||||
				D73912EC22F37F3D000D13A0 /* Frameworks */,
 | 
									D73912EC22F37F3D000D13A0 /* Frameworks */,
 | 
				
			||||||
 | 
									076AC79CB527EDDF03C6C1BF /* Pods */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			sourceTree = "<group>";
 | 
								sourceTree = "<group>";
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
| 
						 | 
					@ -175,6 +202,8 @@
 | 
				
			||||||
		D73912EC22F37F3D000D13A0 /* Frameworks */ = {
 | 
							D73912EC22F37F3D000D13A0 /* Frameworks */ = {
 | 
				
			||||||
			isa = PBXGroup;
 | 
								isa = PBXGroup;
 | 
				
			||||||
			children = (
 | 
								children = (
 | 
				
			||||||
 | 
									17BEB3BB725731AD7E5B80B1 /* Pods_Runner.framework */,
 | 
				
			||||||
 | 
									465D02A290608CA511C1F4CA /* Pods_RunnerTests.framework */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			name = Frameworks;
 | 
								name = Frameworks;
 | 
				
			||||||
			sourceTree = "<group>";
 | 
								sourceTree = "<group>";
 | 
				
			||||||
| 
						 | 
					@ -186,6 +215,7 @@
 | 
				
			||||||
			isa = PBXNativeTarget;
 | 
								isa = PBXNativeTarget;
 | 
				
			||||||
			buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
 | 
								buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
 | 
				
			||||||
			buildPhases = (
 | 
								buildPhases = (
 | 
				
			||||||
 | 
									EBBB44C74E6664565AAD7743 /* [CP] Check Pods Manifest.lock */,
 | 
				
			||||||
				331C80D1294CF70F00263BE5 /* Sources */,
 | 
									331C80D1294CF70F00263BE5 /* Sources */,
 | 
				
			||||||
				331C80D2294CF70F00263BE5 /* Frameworks */,
 | 
									331C80D2294CF70F00263BE5 /* Frameworks */,
 | 
				
			||||||
				331C80D3294CF70F00263BE5 /* Resources */,
 | 
									331C80D3294CF70F00263BE5 /* Resources */,
 | 
				
			||||||
| 
						 | 
					@ -204,11 +234,13 @@
 | 
				
			||||||
			isa = PBXNativeTarget;
 | 
								isa = PBXNativeTarget;
 | 
				
			||||||
			buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
 | 
								buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
 | 
				
			||||||
			buildPhases = (
 | 
								buildPhases = (
 | 
				
			||||||
 | 
									DD4A3E0D06F0EB3D92595679 /* [CP] Check Pods Manifest.lock */,
 | 
				
			||||||
				33CC10E92044A3C60003C045 /* Sources */,
 | 
									33CC10E92044A3C60003C045 /* Sources */,
 | 
				
			||||||
				33CC10EA2044A3C60003C045 /* Frameworks */,
 | 
									33CC10EA2044A3C60003C045 /* Frameworks */,
 | 
				
			||||||
				33CC10EB2044A3C60003C045 /* Resources */,
 | 
									33CC10EB2044A3C60003C045 /* Resources */,
 | 
				
			||||||
				33CC110E2044A8840003C045 /* Bundle Framework */,
 | 
									33CC110E2044A8840003C045 /* Bundle Framework */,
 | 
				
			||||||
				3399D490228B24CF009A79C7 /* ShellScript */,
 | 
									3399D490228B24CF009A79C7 /* ShellScript */,
 | 
				
			||||||
 | 
									3020AFE6AB38B106E5D2E587 /* [CP] Embed Pods Frameworks */,
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
			buildRules = (
 | 
								buildRules = (
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
| 
						 | 
					@ -227,7 +259,7 @@
 | 
				
			||||||
			isa = PBXProject;
 | 
								isa = PBXProject;
 | 
				
			||||||
			attributes = {
 | 
								attributes = {
 | 
				
			||||||
				LastSwiftUpdateCheck = 0920;
 | 
									LastSwiftUpdateCheck = 0920;
 | 
				
			||||||
				LastUpgradeCheck = 1430;
 | 
									LastUpgradeCheck = 1510;
 | 
				
			||||||
				ORGANIZATIONNAME = "";
 | 
									ORGANIZATIONNAME = "";
 | 
				
			||||||
				TargetAttributes = {
 | 
									TargetAttributes = {
 | 
				
			||||||
					331C80D4294CF70F00263BE5 = {
 | 
										331C80D4294CF70F00263BE5 = {
 | 
				
			||||||
| 
						 | 
					@ -290,6 +322,23 @@
 | 
				
			||||||
/* End PBXResourcesBuildPhase section */
 | 
					/* End PBXResourcesBuildPhase section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXShellScriptBuildPhase section */
 | 
					/* Begin PBXShellScriptBuildPhase section */
 | 
				
			||||||
 | 
							3020AFE6AB38B106E5D2E587 /* [CP] Embed Pods Frameworks */ = {
 | 
				
			||||||
 | 
								isa = PBXShellScriptBuildPhase;
 | 
				
			||||||
 | 
								buildActionMask = 2147483647;
 | 
				
			||||||
 | 
								files = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								inputFileListPaths = (
 | 
				
			||||||
 | 
									"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								name = "[CP] Embed Pods Frameworks";
 | 
				
			||||||
 | 
								outputFileListPaths = (
 | 
				
			||||||
 | 
									"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
 | 
								shellPath = /bin/sh;
 | 
				
			||||||
 | 
								shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
 | 
				
			||||||
 | 
								showEnvVarsInLog = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
		3399D490228B24CF009A79C7 /* ShellScript */ = {
 | 
							3399D490228B24CF009A79C7 /* ShellScript */ = {
 | 
				
			||||||
			isa = PBXShellScriptBuildPhase;
 | 
								isa = PBXShellScriptBuildPhase;
 | 
				
			||||||
			alwaysOutOfDate = 1;
 | 
								alwaysOutOfDate = 1;
 | 
				
			||||||
| 
						 | 
					@ -328,6 +377,50 @@
 | 
				
			||||||
			shellPath = /bin/sh;
 | 
								shellPath = /bin/sh;
 | 
				
			||||||
			shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
 | 
								shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
							DD4A3E0D06F0EB3D92595679 /* [CP] Check Pods Manifest.lock */ = {
 | 
				
			||||||
 | 
								isa = PBXShellScriptBuildPhase;
 | 
				
			||||||
 | 
								buildActionMask = 2147483647;
 | 
				
			||||||
 | 
								files = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								inputFileListPaths = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								inputPaths = (
 | 
				
			||||||
 | 
									"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
 | 
				
			||||||
 | 
									"${PODS_ROOT}/Manifest.lock",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								name = "[CP] Check Pods Manifest.lock";
 | 
				
			||||||
 | 
								outputFileListPaths = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								outputPaths = (
 | 
				
			||||||
 | 
									"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
 | 
								shellPath = /bin/sh;
 | 
				
			||||||
 | 
								shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 | 
				
			||||||
 | 
								showEnvVarsInLog = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							EBBB44C74E6664565AAD7743 /* [CP] Check Pods Manifest.lock */ = {
 | 
				
			||||||
 | 
								isa = PBXShellScriptBuildPhase;
 | 
				
			||||||
 | 
								buildActionMask = 2147483647;
 | 
				
			||||||
 | 
								files = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								inputFileListPaths = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								inputPaths = (
 | 
				
			||||||
 | 
									"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
 | 
				
			||||||
 | 
									"${PODS_ROOT}/Manifest.lock",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								name = "[CP] Check Pods Manifest.lock";
 | 
				
			||||||
 | 
								outputFileListPaths = (
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								outputPaths = (
 | 
				
			||||||
 | 
									"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								runOnlyForDeploymentPostprocessing = 0;
 | 
				
			||||||
 | 
								shellPath = /bin/sh;
 | 
				
			||||||
 | 
								shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 | 
				
			||||||
 | 
								showEnvVarsInLog = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
/* End PBXShellScriptBuildPhase section */
 | 
					/* End PBXShellScriptBuildPhase section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Begin PBXSourcesBuildPhase section */
 | 
					/* Begin PBXSourcesBuildPhase section */
 | 
				
			||||||
| 
						 | 
					@ -379,6 +472,7 @@
 | 
				
			||||||
/* Begin XCBuildConfiguration section */
 | 
					/* Begin XCBuildConfiguration section */
 | 
				
			||||||
		331C80DB294CF71000263BE5 /* Debug */ = {
 | 
							331C80DB294CF71000263BE5 /* Debug */ = {
 | 
				
			||||||
			isa = XCBuildConfiguration;
 | 
								isa = XCBuildConfiguration;
 | 
				
			||||||
 | 
								baseConfigurationReference = F971A3061D014BCFE5A477A9 /* Pods-RunnerTests.debug.xcconfig */;
 | 
				
			||||||
			buildSettings = {
 | 
								buildSettings = {
 | 
				
			||||||
				BUNDLE_LOADER = "$(TEST_HOST)";
 | 
									BUNDLE_LOADER = "$(TEST_HOST)";
 | 
				
			||||||
				CURRENT_PROJECT_VERSION = 1;
 | 
									CURRENT_PROJECT_VERSION = 1;
 | 
				
			||||||
| 
						 | 
					@ -393,6 +487,7 @@
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		331C80DC294CF71000263BE5 /* Release */ = {
 | 
							331C80DC294CF71000263BE5 /* Release */ = {
 | 
				
			||||||
			isa = XCBuildConfiguration;
 | 
								isa = XCBuildConfiguration;
 | 
				
			||||||
 | 
								baseConfigurationReference = D32BEBE6FA5B351434300418 /* Pods-RunnerTests.release.xcconfig */;
 | 
				
			||||||
			buildSettings = {
 | 
								buildSettings = {
 | 
				
			||||||
				BUNDLE_LOADER = "$(TEST_HOST)";
 | 
									BUNDLE_LOADER = "$(TEST_HOST)";
 | 
				
			||||||
				CURRENT_PROJECT_VERSION = 1;
 | 
									CURRENT_PROJECT_VERSION = 1;
 | 
				
			||||||
| 
						 | 
					@ -407,6 +502,7 @@
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		331C80DD294CF71000263BE5 /* Profile */ = {
 | 
							331C80DD294CF71000263BE5 /* Profile */ = {
 | 
				
			||||||
			isa = XCBuildConfiguration;
 | 
								isa = XCBuildConfiguration;
 | 
				
			||||||
 | 
								baseConfigurationReference = 19DEDDAC7F8C48D43A9E76CF /* Pods-RunnerTests.profile.xcconfig */;
 | 
				
			||||||
			buildSettings = {
 | 
								buildSettings = {
 | 
				
			||||||
				BUNDLE_LOADER = "$(TEST_HOST)";
 | 
									BUNDLE_LOADER = "$(TEST_HOST)";
 | 
				
			||||||
				CURRENT_PROJECT_VERSION = 1;
 | 
									CURRENT_PROJECT_VERSION = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<Scheme
 | 
					<Scheme
 | 
				
			||||||
   LastUpgradeVersion = "1430"
 | 
					   LastUpgradeVersion = "1510"
 | 
				
			||||||
   version = "1.3">
 | 
					   version = "1.3">
 | 
				
			||||||
   <BuildAction
 | 
					   <BuildAction
 | 
				
			||||||
      parallelizeBuildables = "YES"
 | 
					      parallelizeBuildables = "YES"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,4 +4,7 @@
 | 
				
			||||||
   <FileRef
 | 
					   <FileRef
 | 
				
			||||||
      location = "group:Runner.xcodeproj">
 | 
					      location = "group:Runner.xcodeproj">
 | 
				
			||||||
   </FileRef>
 | 
					   </FileRef>
 | 
				
			||||||
 | 
					   <FileRef
 | 
				
			||||||
 | 
					      location = "group:Pods/Pods.xcodeproj">
 | 
				
			||||||
 | 
					   </FileRef>
 | 
				
			||||||
</Workspace>
 | 
					</Workspace>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue