Compare commits

..

No commits in common. "ebd001e6ce735f79904ddac082b198115e8a4cae" and "985ed670e474487754e59b4d1e82048437a5c301" have entirely different histories.

94 changed files with 931 additions and 2576 deletions

View file

@ -1,7 +1,32 @@
# BUILD # BUILD
FROM debian:stable-slim AS build-env
RUN apt-get update && apt-get install -yq curl file git unzip xz-utils zip && rm -rf /var/lib/apt/lists/*
RUN useradd -m flutter
RUN groupadd flutterusers
RUN usermod -aG flutterusers flutter
RUN mkdir /opt/flutter && chown -R flutter:flutter /opt/flutter
USER flutter
WORKDIR /home/flutter
RUN git clone https://github.com/flutter/flutter.git /opt/flutter
ENV PATH $PATH:/opt/flutter/bin
RUN flutter config --no-analytics --enable-web --no-enable-android --no-enable-ios
RUN flutter precache --web
RUN flutter create --platforms web dummy && rm -rf dummy
COPY . /home/flutter
USER root
RUN chown -R flutter:flutter /home/flutter
USER flutter
WORKDIR /home/flutter
RUN flutter build web
# DEPLOY
FROM node:16.14-alpine FROM node:16.14-alpine
COPY ./build/web /app COPY --from=build-env /home/flutter/build/web /app/
WORKDIR /app/ WORKDIR /app/

View file

@ -1,17 +0,0 @@
VERSION=0.`git rev-list --count HEAD`
.PHONY: black
DOCKER_BUILD=docker build
ifeq ($(shell uname -m), arm64)
DOCKER_BUILD=docker buildx build --platform linux/amd64
endif
.PHONY: build
build:
flutter build web
$(DOCKER_BUILD) -t registry.domandoman.xyz/fooder/app -f Dockerfile .
.PHONY: push
push:
docker push registry.domandoman.xyz/fooder/app

View file

@ -1,3 +1,3 @@
# Fooder web app # Fooder web app
Very simple diary project that uses [fooder_api](https://gitea.domandoman.xyz/doman/fooder-api). Very simple diary project that uses [fooder_api](https://github.com/ickyicky/fooder-api).

View file

@ -1,69 +0,0 @@
{
"name": "Doman",
"subtitle": "Doman source!",
"description": "For now it's just the fooder app",
"iconURL": "https://fooder.domandoman.xyz/assets/logo.png",
"headerURL": "https://fooder.domandoman.xyz/assets/logo.png",
"website": "https://fooder.domandoman.xyz",
"tintColor": "#FF8B9DC3",
"featuredApps": [
"com.example.fooderWeb",
],
"apps": [
{
"name": "Fooder",
"bundleIdentifier": "com.example.fooderWeb",
"developerName": "Doman",
"subtitle": "Count your calories",
"localizedDescription": "Awesome app to count your calories",
"iconURL": "https://fooder.domandoman.xyz/assets/logo.png",
"tintColor": "#FF8B9DC3",
"screenshots": [
"https://fooder.domandoman.xyz/assets/screenshot1.png",
"https://fooder.domandoman.xyz/assets/screenshot2.png",
],
"versions": [
{
"version": "1.0.0+1",
"date": "2024-05-10T07:00:00-08:00",
"size": 10000000,
"downloadURL": "https://example.com/myapp_v1.0.ipa",
"localizedDescription": "Initial release."
}
],
"appPermissions": {
"entitlements": [
"com.apple.security.application-groups",
"com.apple.developer.siri"
],
"privacy": {
"NSPhotoLibraryUsageDescription": "App saves photos to your Photo Library.",
"NSCameraUsageDescription": "App uses camera to take photos.",
"NSMicrophoneUsageDescription": "App uses microphone to record video."
}
}
},
],
"news": [
{
"title": "New Feature Announcement",
"identifier": "new_feature",
"caption": "Introducing a new feature in AltStore!",
"date": "2023-03-15",
"tintColor": "#5CA399",
"imageURL": "https://example.com/new_feature_image.png",
"notify": true,
"url": "https://example.com/new_feature_details"
},
{
"title": "App Update Available",
"identifier": "app_update",
"caption": "An update is available for My Example App.",
"date": "2023-03-10T10:00:00-07:00",
"tintColor": "#3660A2",
"imageURL": "https://example.com/app_update_image.png",
"notify": false,
"appID": "com.example.myapp"
}
]
}

View file

@ -1,14 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
<application <application
android:label="Fooder" android:label="fooder_web"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/launcher_icon"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>12.0</string> <string>11.0</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, '12.0' # platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View file

@ -1,41 +0,0 @@
PODS:
- Flutter (1.0.0)
- flutter_barcode_scanner (2.0.0):
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_barcode_scanner (from `.symlinks/plugins/flutter_barcode_scanner/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_barcode_scanner:
:path: ".symlinks/plugins/flutter_barcode_scanner/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_barcode_scanner: 7a1144744c28dc0c57a8de7218ffe5ec59a9e4bf
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
COCOAPODS: 1.15.2

View file

@ -8,14 +8,12 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
29C8E8B714ED94E557D46BFB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5E968578F4C69854CF864C0 /* Pods_Runner.framework */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
E7AAC4F7DD7928627B2E33CF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C30D6B3DD05EBC43545DEB8A /* Pods_RunnerTests.framework */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -42,16 +40,11 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0F1A42FF524A7E0FAE56F82F /* 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>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
17C2E4C7353DD17838B2B616 /* 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>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
76F6F6B11AE95BFC7130779E /* 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>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
@ -60,64 +53,21 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B51F7AB59BCC9B009252D2EA /* 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>"; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
C30D6B3DD05EBC43545DEB8A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
CE784006A2AE02B13BFDBF63 /* 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>"; };
F084D738B0611C829C6F2BBF /* 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>"; };
F5E968578F4C69854CF864C0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
08A8547522D611B14F2528AB /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E7AAC4F7DD7928627B2E33CF /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = { 97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
29C8E8B714ED94E557D46BFB /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
3B7F475446216C505E738298 /* Pods */ = {
isa = PBXGroup;
children = (
17C2E4C7353DD17838B2B616 /* Pods-Runner.debug.xcconfig */,
CE784006A2AE02B13BFDBF63 /* Pods-Runner.release.xcconfig */,
0F1A42FF524A7E0FAE56F82F /* Pods-Runner.profile.xcconfig */,
76F6F6B11AE95BFC7130779E /* Pods-RunnerTests.debug.xcconfig */,
F084D738B0611C829C6F2BBF /* Pods-RunnerTests.release.xcconfig */,
B51F7AB59BCC9B009252D2EA /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
74C2F6500218C186F355BF0F /* Frameworks */ = {
isa = PBXGroup;
children = (
F5E968578F4C69854CF864C0 /* Pods_Runner.framework */,
C30D6B3DD05EBC43545DEB8A /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -129,6 +79,14 @@
name = Flutter; name = Flutter;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = { 97C146E51CF9000F007C117D = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -136,8 +94,6 @@
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */, 331C8082294A63A400263BE5 /* RunnerTests */,
3B7F475446216C505E738298 /* Pods */,
74C2F6500218C186F355BF0F /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -172,10 +128,9 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = ( buildPhases = (
BD433A59F73EC51680792A1B /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */, 331C807D294A63A400263BE5 /* Sources */,
331C807E294A63A400263BE5 /* Frameworks */,
331C807F294A63A400263BE5 /* Resources */, 331C807F294A63A400263BE5 /* Resources */,
08A8547522D611B14F2528AB /* Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -191,15 +146,12 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
009EAABCB5CD7F8DB81D5667 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
32E2CACC130A6F356B3006E8 /* [CP] Embed Pods Frameworks */,
2126B9461F451C94849B0573 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@ -216,7 +168,7 @@
97C146E61CF9000F007C117D /* Project object */ = { 97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1510; LastUpgradeCheck = 1300;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
331C8080294A63A400263BE5 = { 331C8080294A63A400263BE5 = {
@ -270,62 +222,6 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
009EAABCB5CD7F8DB81D5667 /* [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;
};
2126B9461F451C94849B0573 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
32E2CACC130A6F356B3006E8 /* [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;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1; alwaysOutOfDate = 1;
@ -357,28 +253,6 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
}; };
BD433A59F73EC51680792A1B /* [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 */
@ -470,7 +344,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -486,7 +360,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = SPB5V9QPZG;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -503,7 +376,7 @@
}; };
331C8088294A63A400263BE5 /* Debug */ = { 331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 76F6F6B11AE95BFC7130779E /* Pods-RunnerTests.debug.xcconfig */; baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -521,7 +394,7 @@
}; };
331C8089294A63A400263BE5 /* Release */ = { 331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = F084D738B0611C829C6F2BBF /* Pods-RunnerTests.release.xcconfig */; baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -537,7 +410,7 @@
}; };
331C808A294A63A400263BE5 /* Profile */ = { 331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = B51F7AB59BCC9B009252D2EA /* Pods-RunnerTests.profile.xcconfig */; baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -598,7 +471,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -647,7 +520,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -665,7 +538,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = SPB5V9QPZG;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -688,7 +560,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = SPB5V9QPZG;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1510" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View file

@ -4,7 +4,4 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 B

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 964 B

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Flutter View Controller--> <!--Flutter View Controller-->
@ -16,14 +14,13 @@
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/> <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="102" y="-34"/>
</scene> </scene>
</scenes> </scenes>
</document> </document>

View file

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Fooder</string> <string>Fooder Web</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -47,9 +47,5 @@
<true/> <true/>
<key>UIApplicationSupportsIndirectInputEvents</key> <key>UIApplicationSupportsIndirectInputEvents</key>
<true/> <true/>
<key>NSPhotoLibraryUsageDescription</key>
<string>App needs access to photo lib for profile images</string>
<key>NSCameraUsageDescription</key>
<string>To capture profile photo please grant camera access</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,33 +1,23 @@
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import 'dart:html';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:fooder/models/meal.dart'; import 'package:fooder/models/meal.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ApiClient { class ApiClient {
final String baseUrl; final String baseUrl;
String? token; String? token;
String? refreshToken; String? refreshToken;
http.Client httpClient = http.Client(); http.Client httpClient = http.Client();
final FlutterSecureStorage storage = const FlutterSecureStorage();
ApiClient({ ApiClient({
required this.baseUrl, required this.baseUrl,
}) { }) {
() async { if (window.localStorage.containsKey('token')) {
await loadToken(); token = window.localStorage['token'];
}();
} }
if (window.localStorage.containsKey('refreshToken')) {
Future<void> loadToken() async { refreshToken = window.localStorage['refreshToken'];
Map<String, String> allValues = await storage.readAll();
if (allValues.containsKey('token')) {
token = allValues['token'];
}
if (allValues.containsKey('refreshToken')) {
refreshToken = allValues['refreshToken'];
} }
} }
@ -172,11 +162,11 @@ class ApiClient {
final token = _jsonDecode(response)['access_token']; final token = _jsonDecode(response)['access_token'];
this.token = token; this.token = token;
await storage.write(key: 'token', value: token); window.localStorage['token'] = token;
final refreshToken = _jsonDecode(response)['refresh_token']; final refreshToken = _jsonDecode(response)['refresh_token'];
this.refreshToken = refreshToken; this.refreshToken = refreshToken;
await storage.write(key: 'refreshToken', value: refreshToken); window.localStorage['refreshToken'] = refreshToken;
} }
Future<void> refresh() async { Future<void> refresh() async {
@ -189,10 +179,9 @@ class ApiClient {
}); });
token = response['access_token'] as String; token = response['access_token'] as String;
await storage.write(key: 'token', value: token); window.localStorage['token'] = token!;
refreshToken = response['refresh_token'] as String; refreshToken = response['refresh_token'] as String;
await storage.write(key: 'refreshToken', value: refreshToken); window.localStorage['refreshToken'] = refreshToken!;
} }
Future<Map<String, dynamic>> getDiary({required DateTime date}) async { Future<Map<String, dynamic>> getDiary({required DateTime date}) async {
@ -204,11 +193,11 @@ class ApiClient {
return response; return response;
} }
Future<void> logout() async { void logout() {
token = null; token = null;
refreshToken = null; refreshToken = null;
window.localStorage.remove('token');
await storage.deleteAll(); window.localStorage.remove('refreshToken');
} }
Future<Map<String, dynamic>> getProducts(String q) async { Future<Map<String, dynamic>> getProducts(String q) async {
@ -217,13 +206,6 @@ class ApiClient {
return response; return response;
} }
Future<Map<String, dynamic>> getProductByBarcode(String barcode) async {
var response = await get("/product/by_barcode?${Uri(queryParameters: {
"barcode": barcode
}).query}");
return response;
}
Future<Map<String, dynamic>> getPresets(String? q) async { Future<Map<String, dynamic>> getPresets(String? q) async {
var response = await get("/preset?${Uri(queryParameters: {"q": q}).query}"); var response = await get("/preset?${Uri(queryParameters: {"q": q}).query}");
return response; return response;
@ -283,20 +265,21 @@ class ApiClient {
} }
} }
Future<void> addMeal({required String name, required int diaryId}) async { Future<void> addMeal(
{required String name, required int diaryId, required int order}) async {
await post("/meal", { await post("/meal", {
"name": name, "name": name,
"diary_id": diaryId, "diary_id": diaryId,
"order": order,
}); });
} }
Future<void> addMealFromPreset( Future<void> addMealFromPreset(
{required String name, {required String name, required int diaryId, required int order, required int presetId}) async {
required int diaryId,
required int presetId}) async {
await post("/meal/from_preset", { await post("/meal/from_preset", {
"name": name, "name": name,
"diary_id": diaryId, "diary_id": diaryId,
"order": order,
"preset_id": presetId, "preset_id": presetId,
}); });
} }

View file

@ -1,23 +0,0 @@
import 'package:flutter/material.dart';
class FAppBar extends StatelessWidget implements PreferredSizeWidget {
final List<Widget> actions;
const FAppBar({super.key, required this.actions});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: AppBar(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
elevation: 0,
actions: actions,
));
}
@override
Size get preferredSize => const Size.fromHeight(56);
}

View file

@ -1,37 +0,0 @@
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!,
],
);
}
}

View file

@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
class FButton extends StatelessWidget {
final String labelText;
final double padding;
final double insidePadding;
final double fontSize;
final Function()? onPressed;
const FButton(
{super.key,
required this.labelText,
this.padding = 8,
this.insidePadding = 24,
this.fontSize = 20,
this.onPressed});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return GestureDetector(
onTap: onPressed,
child: Padding(
padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
child: Container(
padding: EdgeInsets.symmetric(vertical: insidePadding),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: colorScheme.surfaceTint.withOpacity(0.85),
),
child: Center(
child: Text(
labelText,
style: theme.textTheme.labelLarge!.copyWith(
fontWeight: FontWeight.bold,
fontSize: fontSize,
color: colorScheme.onPrimary,
),
),
),
),
));
}
}

View file

@ -1,154 +0,0 @@
import 'package:flutter/material.dart';
class FDateItemWidget extends StatelessWidget {
final DateTime date;
final bool picked;
final Function(DateTime) onDatePicked;
const FDateItemWidget(
{super.key,
required this.date,
required this.onDatePicked,
this.picked = false});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
var dayOfTheWeekMap = {
1: 'Mon',
2: 'Tue',
3: 'Wed',
4: 'Thu',
5: 'Fri',
6: 'Sat',
7: 'Sun',
};
return GestureDetector(
onTap: () {
onDatePicked(date);
},
child: Container(
width: picked ? 100 : 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
border: Border.all(
// color: picked ? colorScheme.onPrimary : Colors.transparent,
color: Colors.transparent,
width: 2,
),
color: picked
? colorScheme.onSurfaceVariant.withOpacity(0.25)
: Colors.transparent,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
dayOfTheWeekMap[date.weekday]!,
style: TextStyle(
color: colorScheme.onSurfaceVariant,
fontSize: picked ? 24 : 12,
fontWeight: FontWeight.bold,
),
),
Text(
'${date.day}.${date.month}',
style: TextStyle(
color: colorScheme.onSurfaceVariant,
fontSize: picked ? 24 : 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
}
class FDatePickerWidget extends StatefulWidget {
final DateTime date;
final Function(DateTime) onDatePicked;
const FDatePickerWidget(
{super.key, required this.date, required this.onDatePicked});
@override
State<FDatePickerWidget> createState() => _FDatePickerWidgetState();
}
class _FDatePickerWidgetState extends State<FDatePickerWidget> {
DateTime date = DateTime.now();
@override
void initState() {
super.initState();
setState(() {
date = widget.date;
});
}
Future<void> onDatePicked(DateTime date) async {
setState(() {
this.date = date;
});
await widget.onDatePicked(date);
}
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return SizedBox(
height: 100,
child: Center(
child: ListView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 20),
shrinkWrap: true,
children: <Widget>[
FDateItemWidget(
date: date.add(const Duration(days: -2)),
onDatePicked: onDatePicked),
FDateItemWidget(
date: date.add(const Duration(days: -1)),
onDatePicked: onDatePicked),
FDateItemWidget(
date: date, onDatePicked: onDatePicked, picked: true),
FDateItemWidget(
date: date.add(const Duration(days: 1)),
onDatePicked: onDatePicked),
SizedBox(
width: 50,
child: IconButton(
icon: Icon(
Icons.calendar_month,
color: colorScheme.onSurfaceVariant,
size: 20,
),
onPressed: () {
// open date picker
showDatePicker(
context: context,
initialDate: date,
firstDate: date.add(const Duration(days: -365)),
lastDate: date.add(const Duration(days: 365)),
).then((value) {
if (value != null) {
onDatePicked(value);
}
});
},
),
),
],
),
),
);
}
}

View file

@ -1,43 +0,0 @@
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),
),
),
),
);
}
}

View file

@ -1,49 +0,0 @@
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,
),
),
),
),
),
);
}
}

View file

@ -1,33 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fooder/components/blur_container.dart';
class FNavBar extends StatelessWidget {
static const maxWidth = 920.0;
final List<Widget> children;
final double height;
const FNavBar({super.key, required this.children, this.height = 78});
@override
Widget build(BuildContext context) {
var widthAvail = MediaQuery.of(context).size.width;
// var width = widthAvail > maxWidth ? maxWidth : widthAvail;
return SizedBox(
width: widthAvail,
height: height * children.length,
child: BlurContainer(
width: widthAvail,
height: height * children.length,
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
...children,
Container(
height: height / 3,
color: Colors.transparent,
),
]),
),
);
}
}

View file

@ -1,159 +0,0 @@
import 'package:flutter/material.dart';
import 'package:fooder/components/blur_container.dart';
class ClipShadowPath extends StatelessWidget {
final Shadow shadow;
final CustomClipper<Path> clipper;
final Widget child;
const ClipShadowPath({
super.key,
required this.shadow,
required this.clipper,
required this.child,
});
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _ClipShadowShadowPainter(
clipper: clipper,
shadow: shadow,
),
child: ClipPath(clipper: clipper, child: child),
);
}
}
class _ClipShadowShadowPainter extends CustomPainter {
final Shadow shadow;
final CustomClipper<Path> clipper;
_ClipShadowShadowPainter({required this.shadow, required this.clipper});
@override
void paint(Canvas canvas, Size size) {
var paint = shadow.toPaint();
var clipPath = clipper.getClip(size).shift(shadow.offset);
canvas.drawPath(clipPath, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class BackgroundWave extends StatelessWidget {
final double height;
const BackgroundWave({super.key, required this.height});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return SizedBox(
height: height,
child: ClipPath(
clipper: BackgroundWaveClipper(),
child: BlurContainer(
width: MediaQuery.of(context).size.width,
height: height,
),
),
);
}
}
class BackgroundWaveClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height);
var firstCurve = Offset(0, size.height - 20);
var lastCurve = Offset(40, size.height - 20);
path.quadraticBezierTo(
firstCurve.dx,
firstCurve.dy,
lastCurve.dx,
lastCurve.dy,
);
firstCurve = Offset(0, size.height - 20);
lastCurve = Offset(size.width - 40, size.height - 20);
path.quadraticBezierTo(
firstCurve.dx,
firstCurve.dy,
lastCurve.dx,
lastCurve.dy,
);
firstCurve = Offset(size.width, size.height - 20);
lastCurve = Offset(size.width, size.height);
path.quadraticBezierTo(
firstCurve.dx,
firstCurve.dy,
lastCurve.dx,
lastCurve.dy,
);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
@override
bool shouldReclip(BackgroundWaveClipper oldClipper) => oldClipper != this;
}
class FSliverAppBar extends SliverPersistentHeaderDelegate {
final double preferredHeight;
final Widget child;
const FSliverAppBar({required this.child, this.preferredHeight = 220});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
var adjustedShrinkOffset =
shrinkOffset > minExtent ? minExtent : shrinkOffset;
double offset = (minExtent - adjustedShrinkOffset);
if (offset < 4) {
offset = 4;
}
return Stack(
children: [
// const BackgroundWave(
// height: preferredHeight,
// ),
BlurContainer(
height: preferredHeight,
),
Positioned(
top: offset,
left: 16,
right: 16,
child: child,
)
],
);
}
@override
double get maxExtent => preferredHeight;
@override
double get minExtent => preferredHeight / 2;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
oldDelegate.maxExtent != maxExtent || oldDelegate.minExtent != minExtent;
}

View file

@ -1,59 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FTextInput extends StatelessWidget {
final String labelText;
final double padding;
final TextEditingController controller;
final List<String>? autofillHints;
final bool autofocus;
final bool obscureText;
final Function(String)? onFieldSubmitted;
final TextInputType? keyboardType;
final List<TextInputFormatter>? inputFormatters;
final Function(String)? onChanged;
const FTextInput(
{super.key,
required this.labelText,
this.padding = 8,
required this.controller,
this.autofillHints,
this.autofocus = false,
this.onFieldSubmitted,
this.obscureText = false,
this.keyboardType,
this.inputFormatters,
this.onChanged});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return Padding(
padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
child: TextFormField(
obscureText: obscureText,
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),
),
),
controller: controller,
autofillHints: autofillHints,
autofocus: autofocus,
onFieldSubmitted: onFieldSubmitted,
keyboardType: keyboardType,
inputFormatters: inputFormatters,
onChanged: onChanged,
),
);
}
}

View file

@ -1,7 +1,6 @@
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:fooder/theme.dart';
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
const MyApp({super.key}); const MyApp({super.key});
@ -10,10 +9,13 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: 'FOODER', title: 'FOODER',
theme: MainTheme.light(), theme: ThemeData(
darkTheme: MainTheme.dark(), colorScheme: ColorScheme.fromSeed(
themeMode: ThemeMode.system, seedColor: Colors.blueGrey,
debugShowCheckedModeBanner: false, brightness: Brightness.dark,
),
useMaterial3: true,
),
home: LoginScreen( home: LoginScreen(
apiClient: ApiClient( apiClient: ApiClient(
baseUrl: 'https://fooderapi.domandoman.xyz/api', baseUrl: 'https://fooderapi.domandoman.xyz/api',

View file

@ -5,11 +5,7 @@ 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';
class AddEntryScreen extends BasedScreen { class AddEntryScreen extends BasedScreen {
final Diary diary; final Diary diary;
@ -21,7 +17,7 @@ class AddEntryScreen extends BasedScreen {
State<AddEntryScreen> createState() => _AddEntryScreen(); State<AddEntryScreen> createState() => _AddEntryScreen();
} }
class _AddEntryScreen extends BasedState<AddEntryScreen> { class _AddEntryScreen extends State<AddEntryScreen> {
final gramsController = TextEditingController(); final gramsController = TextEditingController();
final productNameController = TextEditingController(); final productNameController = TextEditingController();
Meal? meal; Meal? meal;
@ -59,7 +55,6 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
}); });
} }
@override
void showError(String message) { void showError(String message) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
@ -101,42 +96,19 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
popMeDaddy(); popMeDaddy();
} }
Future<void> _findProductByBarCode() async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SimpleBarcodeScannerPage(),
),
);
if (res is String) {
try {
var productMap = await widget.apiClient.getProductByBarcode(res);
var product = Product.fromJson(productMap);
setState(() {
products = [product];
productNameController.text = product.name;
});
} catch (e) {
showError("Product not found");
}
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, 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>[
FDropdown<Meal>( DropdownButton<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) {
@ -155,15 +127,19 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
), ),
], ],
), ),
FTextInput( TextFormField(
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,
), ),
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Grams', labelText: 'Grams',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -209,20 +185,9 @@ class _AddEntryScreen extends BasedState<AddEntryScreen> {
), ),
])), ])),
), ),
floatingActionButton: Row( floatingActionButton: FloatingActionButton(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FActionButton(
onPressed: _findProductByBarCode,
icon: Icons.photo_camera,
),
const SizedBox(width: 10),
FActionButton(
onPressed: _addEntry, onPressed: _addEntry,
icon: Icons.library_add, child: const Icon(Icons.add),
tag: "fap2",
),
],
), ),
); );
} }

View file

@ -3,8 +3,6 @@ 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;
@ -16,7 +14,7 @@ class AddMealScreen extends BasedScreen {
State<AddMealScreen> createState() => _AddMealScreen(); State<AddMealScreen> createState() => _AddMealScreen();
} }
class _AddMealScreen extends BasedState<AddMealScreen> { class _AddMealScreen extends State<AddMealScreen> {
final nameController = TextEditingController(); final nameController = TextEditingController();
final presetNameController = TextEditingController(); final presetNameController = TextEditingController();
bool nameChanged = false; bool nameChanged = false;
@ -39,7 +37,7 @@ class _AddMealScreen extends BasedState<AddMealScreen> {
void initState() { void initState() {
super.initState(); super.initState();
setState(() { setState(() {
nameController.text = "Meal ${widget.diary.meals.length + 1}"; nameController.text = "Meal ${widget.diary.meals.length}";
}); });
_getPresets(); _getPresets();
} }
@ -56,10 +54,20 @@ class _AddMealScreen extends BasedState<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,
diaryId: widget.diary.id, diaryId: widget.diary.id,
order: widget.diary.meals.length,
); );
popMeDaddy(); popMeDaddy();
} }
@ -106,6 +114,7 @@ class _AddMealScreen extends BasedState<AddMealScreen> {
await widget.apiClient.addMealFromPreset( await widget.apiClient.addMealFromPreset(
name: nameChanged ? nameController.text : selectedPreset!.name, name: nameChanged ? nameController.text : selectedPreset!.name,
diaryId: widget.diary.id, diaryId: widget.diary.id,
order: widget.diary.meals.length,
presetId: selectedPreset!.id, presetId: selectedPreset!.id,
); );
popMeDaddy(); popMeDaddy();
@ -114,21 +123,28 @@ class _AddMealScreen extends BasedState<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>[
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Meal name', labelText: 'Meal name',
),
controller: nameController, controller: nameController,
onChanged: (_) => setState(() { onChanged: (_) => setState(() {
nameChanged = true; nameChanged = true;
}), }),
), ),
FTextInput( TextFormField(
labelText: 'Search presets', decoration: const InputDecoration(
hintText: 'Search presets',
),
controller: presetNameController, controller: presetNameController,
onChanged: (_) => _getPresets(), onChanged: (_) => _getPresets(),
), ),
@ -152,9 +168,9 @@ class _AddMealScreen extends BasedState<AddMealScreen> {
]), ]),
), ),
), ),
floatingActionButton: FActionButton( floatingActionButton: FloatingActionButton(
onPressed: _addMealFromPreset, onPressed: _addMealFromPreset,
icon: Icons.playlist_add_rounded, child: const Icon(Icons.add),
), ),
); );
} }

View file

@ -2,9 +2,6 @@ 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});
@ -13,7 +10,7 @@ class AddProductScreen extends BasedScreen {
State<AddProductScreen> createState() => _AddProductScreen(); State<AddProductScreen> createState() => _AddProductScreen();
} }
class _AddProductScreen extends BasedState<AddProductScreen> { class _AddProductScreen extends State<AddProductScreen> {
final nameController = TextEditingController(); final nameController = TextEditingController();
final carbController = TextEditingController(); final carbController = TextEditingController();
final fatController = TextEditingController(); final fatController = TextEditingController();
@ -37,8 +34,16 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
); );
} }
Future<double?> _parseDouble(String text, String name, void showError(String message) {
{bool silent = false}) async { ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
}
Future<double?> _parseDouble(String text, String name, {bool silent = false}) async {
try { try {
return double.parse(text.replaceAll(",", ".")); return double.parse(text.replaceAll(",", "."));
} catch (e) { } catch (e) {
@ -53,8 +58,7 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
var carb = await _parseDouble(carbController.text, "Carbs"); var carb = await _parseDouble(carbController.text, "Carbs");
var fat = await _parseDouble(fatController.text, "Fat"); var fat = await _parseDouble(fatController.text, "Fat");
var protein = await _parseDouble(proteinController.text, "Protein"); var protein = await _parseDouble(proteinController.text, "Protein");
var fiber = var fiber = await _parseDouble(fiberController.text, "Fiber", silent: true) ?? 0;
await _parseDouble(fiberController.text, "Fiber", silent: true) ?? 0;
if (carb == null || fat == null || protein == null) { if (carb == null || fat == null || protein == null) {
return; return;
@ -107,21 +111,25 @@ class _AddProductScreen extends BasedState<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>[
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Product name', labelText: 'Product name',
controller: nameController,
onChanged: (String value) {
setState(() {});
},
), ),
FTextInput( controller: nameController,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Carbs', labelText: 'Carbs',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -133,8 +141,10 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
setState(() {}); setState(() {});
}, },
), ),
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Fat', labelText: 'Fat',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -146,8 +156,10 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
setState(() {}); setState(() {});
}, },
), ),
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Protein', labelText: 'Protein',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -159,8 +171,10 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
setState(() {}); setState(() {});
}, },
), ),
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Fiber', labelText: 'Fiber',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -172,30 +186,15 @@ class _AddProductScreen extends BasedState<AddProductScreen> {
setState(() {}); setState(() {});
}, },
), ),
ProductWidget( Text(
product: Product( "${calculateCalories().toStringAsFixed(2)} kcal",
id: 0, textAlign: TextAlign.right,
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: FActionButton( floatingActionButton: FloatingActionButton(
onPressed: _addProduct, onPressed: _addProduct,
icon: Icons.save, child: const Icon(Icons.add),
), ),
); );
} }

View file

@ -1,9 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fooder/client.dart'; import 'package:fooder/client.dart';
import 'package:fooder/components/app_bar.dart';
import 'package:fooder/components/navigation_bar.dart';
import 'package:fooder/screens/login.dart';
import 'package:fooder/screens/main.dart';
TextStyle logoStyle(context) { TextStyle logoStyle(context) {
return Theme.of(context).textTheme.labelLarge!.copyWith( return Theme.of(context).textTheme.labelLarge!.copyWith(
@ -15,111 +11,5 @@ abstract class BasedScreen extends StatefulWidget {
final ApiClient apiClient; final ApiClient apiClient;
const BasedScreen({super.key, required this.apiClient}); const BasedScreen({super.key, required this.apiClient});
}
abstract class BasedState<T extends BasedScreen> extends State<T> {
void _logout() async {
await widget.apiClient.logout();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(apiClient: widget.apiClient),
),
);
}
void backToDiary() {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MainScreen(apiClient: widget.apiClient),
),
);
}
FAppBar appBar() {
return FAppBar(
actions: [
IconButton(
icon: Icon(
Icons.logout,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: _logout,
),
],
);
}
FNavBar navBar() {
return FNavBar(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
icon: Icon(
Icons.menu_book,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: backToDiary,
),
IconButton(
icon: Icon(
Icons.dinner_dining,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.lunch_dining,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.person,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
onPressed: () {},
),
],
),
],
);
}
void showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
message,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.onError,
),
),
backgroundColor: Theme.of(context).colorScheme.error.withOpacity(0.8),
),
);
}
void showText(String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
text,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.onPrimary,
),
),
backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.8),
),
);
}
} }

View file

@ -5,9 +5,6 @@ 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';
class EditEntryScreen extends BasedScreen { class EditEntryScreen extends BasedScreen {
final Entry entry; final Entry entry;
@ -19,7 +16,7 @@ class EditEntryScreen extends BasedScreen {
State<EditEntryScreen> createState() => _EditEntryScreen(); State<EditEntryScreen> createState() => _EditEntryScreen();
} }
class _EditEntryScreen extends BasedState<EditEntryScreen> { class _EditEntryScreen extends State<EditEntryScreen> {
final gramsController = TextEditingController(); final gramsController = TextEditingController();
final productNameController = TextEditingController(); final productNameController = TextEditingController();
List<Product> products = []; List<Product> products = [];
@ -55,6 +52,15 @@ class _EditEntryScreen extends BasedState<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(",", "."));
@ -89,47 +95,30 @@ class _EditEntryScreen extends BasedState<EditEntryScreen> {
popMeDaddy(); popMeDaddy();
} }
Future<void> _findProductByBarCode() async {
var res = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SimpleBarcodeScannerPage(),
),
);
if (res is String) {
try {
var productMap = await widget.apiClient.getProductByBarcode(res);
var product = Product.fromJson(productMap);
setState(() {
products = [product];
productNameController.text = product.name;
});
} catch (e) {
showError("Product not found");
}
}
}
@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>[
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Product name', labelText: 'Product name',
),
controller: productNameController, controller: productNameController,
onChanged: (_) => _getProducts(), onChanged: (_) => _getProducts(),
autofocus: true, autofocus: true,
), ),
FTextInput( TextFormField(
decoration: const InputDecoration(
labelText: 'Grams', labelText: 'Grams',
),
keyboardType: keyboardType:
const TextInputType.numberWithOptions(decimal: true), const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[ inputFormatters: <TextInputFormatter>[
@ -176,21 +165,15 @@ class _EditEntryScreen extends BasedState<EditEntryScreen> {
floatingActionButton: Row( floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ children: <Widget>[
FActionButton( FloatingActionButton(
onPressed: _findProductByBarCode,
icon: Icons.photo_camera,
),
const SizedBox(width: 10),
FActionButton(
onPressed: _deleteEntry, onPressed: _deleteEntry,
tag: "fap1", heroTag: null,
icon: Icons.delete, child: const Icon(Icons.delete),
), ),
const SizedBox(width: 10), FloatingActionButton(
FActionButton(
onPressed: _saveEntry, onPressed: _saveEntry,
tag: "fap2", heroTag: null,
icon: Icons.save, child: const Icon(Icons.save),
), ),
], ],
), ),

View file

@ -3,8 +3,6 @@ import 'package:flutter/services.dart';
import 'package:fooder/screens/based.dart'; import 'package:fooder/screens/based.dart';
import 'package:fooder/screens/main.dart'; import 'package:fooder/screens/main.dart';
import 'package:fooder/screens/register.dart'; import 'package:fooder/screens/register.dart';
import 'package:fooder/components/text.dart';
import 'package:fooder/components/button.dart';
class LoginScreen extends BasedScreen { class LoginScreen extends BasedScreen {
const LoginScreen({super.key, required super.apiClient}); const LoginScreen({super.key, required super.apiClient});
@ -13,7 +11,7 @@ class LoginScreen extends BasedScreen {
State<LoginScreen> createState() => _LoginScreen(); State<LoginScreen> createState() => _LoginScreen();
} }
class _LoginScreen extends BasedState<LoginScreen> { class _LoginScreen extends State<LoginScreen> {
final usernameController = TextEditingController(); final usernameController = TextEditingController();
final passwordController = TextEditingController(); final passwordController = TextEditingController();
@ -24,6 +22,24 @@ class _LoginScreen extends BasedState<LoginScreen> {
super.dispose(); super.dispose();
} }
void showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
}
void showText(String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(text, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.primary,
),
);
}
void popMeDaddy() { void popMeDaddy() {
Navigator.pushReplacement( Navigator.pushReplacement(
context, context,
@ -62,8 +78,6 @@ class _LoginScreen extends BasedState<LoginScreen> {
} }
Future<void> _asyncInitState() async { Future<void> _asyncInitState() async {
await widget.apiClient.loadToken();
if (widget.apiClient.refreshToken == null) { if (widget.apiClient.refreshToken == null) {
return; return;
} }
@ -79,10 +93,11 @@ class _LoginScreen extends BasedState<LoginScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return Scaffold( return Scaffold(
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: 600), constraints: const BoxConstraints(maxWidth: 600),
@ -91,30 +106,32 @@ class _LoginScreen extends BasedState<LoginScreen> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Icon( TextFormField(
Icons.lock, decoration: const InputDecoration(
size: 100,
color: colorScheme.primary.withOpacity(0.85),
),
FTextInput(
labelText: 'Username', labelText: 'Username',
),
controller: usernameController, controller: usernameController,
autofillHints: const [AutofillHints.username], autofillHints: const [AutofillHints.username],
autofocus: true, autofocus: true,
), ),
FTextInput( TextFormField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Password', labelText: 'Password',
),
controller: passwordController, controller: passwordController,
onFieldSubmitted: (_) => _login(), onFieldSubmitted: (_) => _login(),
autofillHints: const [AutofillHints.password], autofillHints: const [AutofillHints.password],
obscureText: true,
),
FButton(
labelText: 'Sign In',
onPressed: _login,
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 10),
child: FilledButton(
onPressed: _login,
child: const Text('Login'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: TextButton( child: TextButton(
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(

View file

@ -1,13 +1,9 @@
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/login.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/diary.dart';
import 'package:fooder/widgets/meal.dart';
import 'package:fooder/components/sliver.dart';
import 'package:fooder/components/date_picker.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});
@ -16,7 +12,7 @@ class MainScreen extends BasedScreen {
State<MainScreen> createState() => _MainScreen(); State<MainScreen> createState() => _MainScreen();
} }
class _MainScreen extends BasedState<MainScreen> { class _MainScreen extends State<MainScreen> {
Diary? diary; Diary? diary;
DateTime date = DateTime.now(); DateTime date = DateTime.now();
@ -28,26 +24,33 @@ class _MainScreen extends BasedState<MainScreen> {
Future<void> _asyncInitState() async { Future<void> _asyncInitState() async {
var diaryMap = await widget.apiClient.getDiary(date: date); var diaryMap = await widget.apiClient.getDiary(date: date);
setState(() { setState(() {
diary = Diary.fromJson(diaryMap); diary = Diary.fromJson(diaryMap);
date = date; date = date;
}); });
} }
Future<void> _pickDate(DateTime date) async { Future<void> _pickDate() async {
setState(() { date = (await showDatePicker(
this.date = date; context: context,
}); initialDate: date,
firstDate: DateTime(2020),
lastDate: DateTime(DateTime.now().year + 1),
))!;
await _asyncInitState(); await _asyncInitState();
} }
Future<void> _addEntry() async { void _logout() async {
if (diary == null) { widget.apiClient.logout();
return; Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => LoginScreen(apiClient: widget.apiClient),
),
);
} }
Future<void> _addEntry() async {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
@ -57,76 +60,69 @@ class _MainScreen extends BasedState<MainScreen> {
).then((_) => _asyncInitState()); ).then((_) => _asyncInitState());
} }
Future<void> _addMeal(context) async {
if (diary == null) {
return;
}
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddMealScreen(
apiClient: widget.apiClient,
diary: diary!,
),
),
).then((_) => _asyncInitState());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget content; Widget content;
Widget title;
if (diary != null) { if (diary != null) {
content = CustomScrollView(slivers: <Widget>[ content = Container(
SliverPersistentHeader( constraints: const BoxConstraints(maxWidth: 720),
delegate: FSliverAppBar( padding: const EdgeInsets.all(10),
child: FDatePickerWidget(date: date, onDatePicked: _pickDate)), child: DiaryWidget(
pinned: true,
),
SliverList(
delegate: SliverChildListDelegate(
[
SummaryWidget(
diary: diary!, diary: diary!,
apiClient: widget.apiClient, apiClient: widget.apiClient,
refreshParent: _asyncInitState, refreshParent: _asyncInitState),
);
title = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
child: Text(
"🅵🅾🅾🅳🅴🆁",
style: logoStyle(context),
), ),
for (var (i, meal) in diary!.meals.indexed) onPressed: () {
MealWidget( Navigator.pushReplacement(
meal: meal, context,
apiClient: widget.apiClient, MaterialPageRoute(
refreshParent: _asyncInitState, builder: (context) =>
initiallyExpanded: i == 0, MainScreen(apiClient: widget.apiClient)),
showText: showText, ).then((_) => _asyncInitState());
},
),
const Spacer(),
Text(
"${date.year}-${date.month}-${date.day}",
style: const TextStyle(fontSize: 20),
),
IconButton(
icon: const Icon(Icons.calendar_month),
onPressed: _pickDate,
),
const Spacer(),
IconButton(
icon: const Icon(Icons.logout),
onPressed: _logout,
), ),
const SizedBox(height: 200),
], ],
), );
),
]);
} else { } else {
content = const Center(child: CircularProgressIndicator()); content = const CircularProgressIndicator();
title = Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context));
} }
return Scaffold( return Scaffold(
body: content, appBar: AppBar(
extendBodyBehindAppBar: true, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
extendBody: true, title: title,
appBar: appBar(),
bottomNavigationBar: navBar(),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FActionButton(
icon: Icons.playlist_add,
onPressed: () => _addMeal(context),
), ),
const SizedBox(width: 10), body: Center(
FActionButton( child: content,
icon: Icons.library_add, onPressed: _addEntry, tag: "fap2"), ),
], floatingActionButton: FloatingActionButton(
onPressed: _addEntry,
child: const Icon(Icons.add),
), ),
); );
} }

174
lib/screens/meal.dart Normal file
View file

@ -0,0 +1,174 @@
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;
const MealScreen({super.key, required super.apiClient, 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);
},
),
],
);
},
);
}
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),
),
]))
]),
),
),
);
}
}

View file

@ -1,8 +1,6 @@
import 'package:flutter/material.dart'; 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/components/text.dart';
import 'package:fooder/components/button.dart';
class RegisterScreen extends BasedScreen { class RegisterScreen extends BasedScreen {
const RegisterScreen({super.key, required super.apiClient}); const RegisterScreen({super.key, required super.apiClient});
@ -11,7 +9,7 @@ class RegisterScreen extends BasedScreen {
State<RegisterScreen> createState() => _RegisterScreen(); State<RegisterScreen> createState() => _RegisterScreen();
} }
class _RegisterScreen extends BasedState<RegisterScreen> { class _RegisterScreen extends State<RegisterScreen> {
final usernameController = TextEditingController(); final usernameController = TextEditingController();
final passwordController = TextEditingController(); final passwordController = TextEditingController();
final passwordConfirmController = TextEditingController(); final passwordConfirmController = TextEditingController();
@ -37,6 +35,24 @@ class _RegisterScreen extends BasedState<RegisterScreen> {
}); });
} }
void showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
}
void showText(String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(text, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.primary,
),
);
}
void popMeDaddy() { void popMeDaddy() {
Navigator.pop(context); Navigator.pop(context);
} }
@ -62,10 +78,11 @@ class _RegisterScreen extends BasedState<RegisterScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
return Scaffold( return Scaffold(
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: 600), constraints: const BoxConstraints(maxWidth: 600),
@ -74,34 +91,35 @@ class _RegisterScreen extends BasedState<RegisterScreen> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Icon( TextFormField(
Icons.group_add, decoration: const InputDecoration(
size: 100,
color: colorScheme.primary.withOpacity(0.85),
),
FTextInput(
labelText: 'Username', labelText: 'Username',
),
controller: usernameController, controller: usernameController,
autofillHints: const [AutofillHints.username], autofillHints: const [AutofillHints.username],
autofocus: true,
), ),
FTextInput( TextFormField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Password', labelText: 'Password',
),
controller: passwordController, controller: passwordController,
autofillHints: const [AutofillHints.password], autofillHints: const [AutofillHints.password],
obscureText: true,
), ),
FTextInput( TextFormField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Confirm password', labelText: 'Confirm password',
),
controller: passwordConfirmController, controller: passwordConfirmController,
autofillHints: const [AutofillHints.password], autofillHints: const [AutofillHints.password],
onFieldSubmitted: (_) => _register(), onFieldSubmitted: (_) => _register()),
obscureText: true, Padding(
), padding: const EdgeInsets.symmetric(vertical: 10),
FButton( child: FilledButton(
labelText: 'Register account',
onPressed: _register, onPressed: _register,
), child: const Text('Register'),
)),
], ],
), ),
), ),

View file

@ -1,51 +0,0 @@
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,
);
}
}

96
lib/widgets/diary.dart Normal file
View file

@ -0,0 +1,96 @@
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: SizedBox(
height: 30,
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 meal in diary.meals)
MealWidget(
meal: meal,
apiClient: apiClient,
refreshParent: refreshParent,
),
],
),
),
],
),
);
}
}

View file

@ -3,43 +3,6 @@ import 'package:fooder/models/entry.dart';
import 'package:fooder/widgets/macro.dart'; import 'package:fooder/widgets/macro.dart';
import 'dart:core'; import 'dart:core';
class EntryHeader extends StatelessWidget {
final Entry entry;
const EntryHeader({super.key, required this.entry});
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
entry.product.name,
overflow: TextOverflow.fade,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
"${entry.grams.toStringAsFixed(0)} g",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
),
),
],
);
}
}
class EntryWidget extends StatelessWidget { class EntryWidget extends StatelessWidget {
final Entry entry; final Entry entry;
@ -51,12 +14,25 @@ class EntryWidget extends StatelessWidget {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
EntryHeader(entry: entry), Row(
MacroEntryWidget( children: <Widget>[
Expanded(
child: Text(
entry.product.name,
style: Theme.of(context).textTheme.titleLarge,
),
),
Text("${entry.calories.toStringAsFixed(1)} kcal"),
],
),
MacroWidget(
protein: entry.protein, protein: entry.protein,
carb: entry.carb, carb: entry.carb,
fat: entry.fat, fat: entry.fat,
calories: entry.calories, amount: entry.grams,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.secondary,
),
), ),
], ],
), ),

View file

@ -1,163 +1,122 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:core';
class MacroHeaderWidget extends StatelessWidget {
static const double padY = 4;
static const double padX = 8;
final bool? fiber;
final bool? calories;
final Alignment alignment;
const MacroHeaderWidget({
super.key,
this.fiber = false,
this.calories = false,
this.alignment = Alignment.centerLeft,
});
@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>[];
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,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: children,
),
);
}
}
class MacroEntryWidget extends StatelessWidget {
static const double padY = 4;
static const double padX = 8;
class MacroWidget extends StatelessWidget {
final double? amount;
final double? calories;
final double? fiber;
final double protein; final double protein;
final double carb; final double carb;
final double fat; final double fat;
final double? fiber; final TextStyle style;
final double? calories; final Widget? child;
final Alignment alignment;
const MacroEntryWidget({ const MacroWidget({
super.key, Key? key,
this.calories,
this.amount,
this.child,
this.fiber,
required this.protein, required this.protein,
required this.carb, required this.carb,
required this.fat, required this.fat,
this.fiber, required this.style,
this.calories, }) : super(key: key);
this.alignment = Alignment.centerLeft,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var elements = <String>[ var elements = <Widget>[
(carb.toStringAsFixed(1)), Expanded(
(fat.toStringAsFixed(1)), flex: 1,
(protein.toStringAsFixed(1)), child: Text(
"C: ${carb.toStringAsFixed(1)}g",
style: style,
textAlign: TextAlign.center,
),
),
Expanded(
flex: 1,
child: Text(
"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,
),
),
]; ];
if (fiber != null) { if (fiber != null) {
elements.add( elements.add(
fiber!.toStringAsFixed(1), Expanded(
flex: 1,
child: Text(
"f: ${fiber!.toStringAsFixed(1)}g",
style: style,
textAlign: TextAlign.center,
),
),
); );
} }
if (calories != null) { if (calories != null) {
elements.add( elements.add(
calories!.toStringAsFixed(0), Expanded(
); flex: 1,
}
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( child: Text(
element, "${calories!.toStringAsFixed(1)} kcal",
style: Theme.of(context).textTheme.bodyLarge!.copyWith( style: style,
color: Theme.of(context).colorScheme.onSurface,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
);
}
if (amount != null) {
elements.add(
Expanded(
flex: 1,
child: Text(
"${amount!.toStringAsFixed(1)}g",
style: style,
textAlign: TextAlign.center,
),
), ),
); );
} }
if (alignment == Alignment.centerLeft) { if (child != null) {
children.add(const Spacer()); 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.symmetric( padding: const EdgeInsets.only(
vertical: padY, top: 4.0,
horizontal: padX, bottom: 4.0,
left: 8.0,
right: 8.0,
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: elements,
children: children,
), ),
); );
} }

View file

@ -3,122 +3,75 @@ import 'package:fooder/models/meal.dart';
import 'package:fooder/widgets/entry.dart'; import 'package:fooder/widgets/entry.dart';
import 'package:fooder/widgets/macro.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';
class MealHeader extends StatelessWidget {
final Meal meal;
const MealHeader({super.key, required this.meal});
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
meal.name,
overflow: TextOverflow.fade,
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
),
),
],
);
}
}
class MealWidget extends StatelessWidget { class MealWidget extends StatelessWidget {
static const maxWidth = 920.0;
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;
const MealWidget({ const MealWidget(
super.key, {super.key,
required this.meal, required this.meal,
required this.apiClient, required this.apiClient,
required this.refreshParent, required this.refreshParent});
required this.initiallyExpanded,
required this.showText, @override
Widget build(BuildContext context) {
return Card(
child: GestureDetector(
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MealScreen(
apiClient: apiClient,
meal: meal,
),
),
).then((_) {
refreshParent();
}); });
Future<void> saveMeal(context) async {
TextEditingController textFieldController = TextEditingController();
textFieldController.text = 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);
}, },
child: Padding(
padding: const EdgeInsets.only(
top: 36.0, left: 6.0, right: 6.0, bottom: 6.0),
child: ExpansionTile(
title: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text(
meal.name,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
),
Text("${meal.calories.toStringAsFixed(1)} kcal"),
],
),
MacroWidget(
protein: meal.protein,
carb: meal.carb,
fat: meal.fat,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.secondary,
), ),
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( children: <Widget>[
icon: const Icon(Icons.delete), for (var entry in meal.entries)
onPressed: () { ListTile(
_deleteMeal(meal).then((_) => refreshParent()); title: EntryWidget(
Navigator.pop(context); entry: entry,
showText("Meal deleted");
},
), ),
], onTap: () {
); Navigator.push(
},
);
}
Future<void> _editEntry(context, entry) async {
await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => EditEntryScreen( builder: (context) => EditEntryScreen(
@ -126,80 +79,14 @@ class MealWidget extends StatelessWidget {
entry: entry, entry: entry,
), ),
), ),
).then((_) => refreshParent()); ).then((_) {
} refreshParent();
});
@override },
Widget build(BuildContext context) { )
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
var widthAvail = MediaQuery.of(context).size.width;
var width = widthAvail > maxWidth ? maxWidth : widthAvail;
return Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
child: Container(
constraints: BoxConstraints(maxWidth: width),
color: colorScheme.surface.withOpacity(0.2),
child: ExpansionTile(
iconColor: colorScheme.onSurface,
collapsedIconColor: colorScheme.onSurface,
initiallyExpanded: initiallyExpanded,
enableFeedback: true,
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>[ ));
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),
),
],
),
],
),
),
),
),
);
} }
} }

View file

@ -3,33 +3,6 @@ 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;
@ -41,21 +14,24 @@ class PresetWidget extends StatelessWidget {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
PresetHeader( Row(
title: preset.name, children: <Widget>[
Expanded(
child: Text(
preset.name,
style: Theme.of(context).textTheme.titleLarge,
), ),
const MacroHeaderWidget(
fiber: true,
calories: true,
alignment: Alignment.center,
), ),
MacroEntryWidget( Text("${preset.calories.toStringAsFixed(1)} kcal"),
],
),
MacroWidget(
protein: preset.protein, protein: preset.protein,
carb: preset.carb, carb: preset.carb,
fat: preset.fat, fat: preset.fat,
fiber: preset.fiber, style: Theme.of(context).textTheme.bodyMedium!.copyWith(
calories: preset.calories, color: Theme.of(context).colorScheme.secondary,
alignment: Alignment.center, ),
), ),
], ],
), ),

View file

@ -3,33 +3,6 @@ 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;
@ -41,21 +14,26 @@ class ProductWidget extends StatelessWidget {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
ProductHeader( Row(
title: product.name, children: <Widget>[
Expanded(
child: Text(
product.name,
style: Theme.of(context).textTheme.titleLarge,
), ),
const MacroHeaderWidget(
fiber: true,
calories: true,
alignment: Alignment.center,
), ),
MacroEntryWidget( Text("${product.calories.toStringAsFixed(1)} kcal"),
],
),
MacroWidget(
protein: product.protein, protein: product.protein,
carb: product.carb, carb: product.carb,
fat: product.fat, fat: product.fat,
fiber: product.fiber, fiber: product.fiber,
calories: product.calories, style: Theme.of(context).textTheme.bodyMedium!.copyWith(
alignment: Alignment.center, color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
), ),
], ],
), ),

View file

@ -1,86 +0,0 @@
import 'package:flutter/material.dart';
import 'package:fooder/models/diary.dart';
import 'package:fooder/widgets/macro.dart';
import 'package:fooder/client.dart';
import 'dart:core';
class SummaryHeader extends StatelessWidget {
final Diary diary;
const SummaryHeader({super.key, required this.diary});
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(
"Summary",
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
),
const Spacer(),
],
);
}
}
class SummaryWidget extends StatelessWidget {
static const maxWidth = 920.0;
final Diary diary;
final ApiClient apiClient;
final Function() refreshParent;
const SummaryWidget(
{super.key,
required this.diary,
required this.apiClient,
required this.refreshParent});
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
var widthAvail = MediaQuery.of(context).size.width;
var width = widthAvail > maxWidth ? maxWidth : widthAvail;
return Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
child: Container(
constraints: BoxConstraints(maxWidth: width),
color: colorScheme.surface.withOpacity(0.2),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
child: Column(
children: <Widget>[
SummaryHeader(diary: diary),
const MacroHeaderWidget(
calories: true,
),
MacroEntryWidget(
protein: diary.protein,
carb: diary.carb,
fat: diary.fat,
calories: diary.calories,
),
],
),
),
),
),
),
);
}
}

View file

@ -6,10 +6,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
} }

View file

@ -3,7 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

View file

@ -5,10 +5,6 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import flutter_secure_storage_macos
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
} }

View file

@ -1,29 +0,0 @@
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

View file

@ -27,8 +27,6 @@
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 */
@ -62,14 +60,11 @@
/* 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>"; };
@ -81,13 +76,8 @@
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 */
@ -95,7 +85,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
DC768C2964C710CDD24D0DB4 /* Pods_RunnerTests.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -103,27 +92,12 @@
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 = (
@ -151,7 +125,6 @@
331C80D6294CF71000263BE5 /* RunnerTests */, 331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */, 33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */, D73912EC22F37F3D000D13A0 /* Frameworks */,
076AC79CB527EDDF03C6C1BF /* Pods */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -202,8 +175,6 @@
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>";
@ -215,7 +186,6 @@
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 */,
@ -234,13 +204,11 @@
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 = (
); );
@ -259,7 +227,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1510; LastUpgradeCheck = 1430;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
331C80D4294CF70F00263BE5 = { 331C80D4294CF70F00263BE5 = {
@ -322,23 +290,6 @@
/* 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;
@ -377,50 +328,6 @@
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 */
@ -472,7 +379,6 @@
/* 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;
@ -487,7 +393,6 @@
}; };
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;
@ -502,7 +407,6 @@
}; };
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;

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1510" LastUpgradeVersion = "1430"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View file

@ -4,7 +4,4 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

View file

@ -1,8 +1,4 @@
{ {
"info": {
"version": 1,
"author": "xcode"
},
"images" : [ "images" : [
{ {
"size" : "16x16", "size" : "16x16",
@ -64,5 +60,9 @@
"filename" : "app_icon_1024.png", "filename" : "app_icon_1024.png",
"scale" : "2x" "scale" : "2x"
} }
] ],
"info" : {
"version" : 1,
"author" : "xcode"
}
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,22 +1,6 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
archive:
dependency: transitive
description:
name: archive
sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265
url: "https://pub.dev"
source: hosted
version: "3.5.1"
args:
dependency: transitive
description:
name: args
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
version: "2.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -25,14 +9,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
blur:
dependency: "direct main"
description:
name: blur
sha256: fd23f1247faee4a7d1a3efb6b7c3cea134f3b939d72e5f8d45233deb0776259f
url: "https://pub.dev"
source: hosted
version: "3.1.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -49,22 +25,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
cli_util:
dependency: transitive
description:
name: cli_util
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
url: "https://pub.dev"
source: hosted
version: "0.4.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -77,34 +37,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.17.2"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.5"
fading_edge_scrollview:
dependency: transitive
description:
name: fading_edge_scrollview
sha256: c25c2231652ce774cc31824d0112f11f653881f43d7f5302c05af11942052031
url: "https://pub.dev"
source: hosted
version: "3.0.0"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -113,141 +57,32 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
flex_color_scheme:
dependency: "direct main"
description:
name: flex_color_scheme
sha256: "32914024a4f404d90ff449f58d279191675b28e7c08824046baf06826e99d984"
url: "https://pub.dev"
source: hosted
version: "7.3.1"
flex_seed_scheme:
dependency: transitive
description:
name: flex_seed_scheme
sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_barcode_scanner:
dependency: transitive
description:
name: flutter_barcode_scanner
sha256: a4ba37daf9933f451a5e812c753ddd045d6354e4a3280342d895b07fecaab3fa
url: "https://pub.dev"
source: hosted
version: "2.0.0"
flutter_launcher_icons:
dependency: "direct main"
description:
name: flutter_launcher_icons
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
url: "https://pub.dev"
source: hosted
version: "0.13.1"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "2.0.2"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f"
url: "https://pub.dev"
source: hosted
version: "2.0.19"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: c0f402067fb0498934faa6bddd670de0a3db45222e2ca9a068c6177c9a2360a4
url: "https://pub.dev"
source: hosted
version: "9.1.1"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
sha256: "8cfa53010a294ff095d7be8fa5bb15f2252c50018d69c5104851303f3ff92510"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
sha256: "301f67ee9b87f04aef227f57f13f126fa7b13543c8e7a93f25c5d2d534c28a4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
url: "https://pub.dev"
source: hosted
version: "1.2.1"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
url: "https://pub.dev"
source: hosted
version: "6.2.1"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.1.0"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -256,238 +91,54 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
url: "https://pub.dev"
source: hosted
version: "4.1.7"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.0" version: "0.18.1"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
url: "https://pub.dev"
source: hosted
version: "2.0.1"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
url: "https://pub.dev"
source: hosted
version: "2.0.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "2.1.1"
marquee:
dependency: "direct main"
description:
name: marquee
sha256: "4b5243d2804373bdc25fc93d42c3b402d6ec1f4ee8d0bb72276edd04ae7addb8"
url: "https://pub.dev"
source: hosted
version: "2.2.3"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16+1" version: "0.12.16"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.0" version: "0.5.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.0" version: "1.9.1"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" version: "1.8.3"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
url: "https://pub.dev"
source: hosted
version: "2.1.3"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
url: "https://pub.dev"
source: hosted
version: "2.2.4"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev"
source: hosted
version: "2.4.0"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
permission_handler:
dependency: transitive
description:
name: permission_handler
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5"
url: "https://pub.dev"
source: hosted
version: "12.0.6"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
url: "https://pub.dev"
source: hosted
version: "9.4.4"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
url: "https://pub.dev"
source: hosted
version: "4.2.1"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
name: platform
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
simple_barcode_scanner:
dependency: "direct main"
description:
name: simple_barcode_scanner
sha256: e14c0b302ffe76f0b61004aa47c36365b5d884fcd745494309e21042667902d3
url: "https://pub.dev"
source: hosted
version: "0.1.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -505,18 +156,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.1" version: "1.11.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.1"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@ -537,10 +188,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.1" version: "0.6.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -557,62 +208,13 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
url: "https://pub.dev"
source: hosted
version: "13.0.0"
web: web:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.1.4-beta"
webview_windows:
dependency: transitive
description:
name: webview_windows
sha256: "7572089e5d6fe09e790093c499fcb6d76a552250187dbcb89790987b1fb723db"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
win32:
dependency: transitive
description:
name: win32
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
url: "https://pub.dev"
source: hosted
version: "5.5.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
url: "https://pub.dev"
source: hosted
version: "1.0.4"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks: sdks:
dart: ">=3.3.0 <4.0.0" dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.19.2"

View file

@ -36,17 +36,9 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
http: ^1.1.0 http: ^1.1.0
intl: ^0.19.0 intl: ^0.18.1
flutter_secure_storage: ^9.0.0
simple_barcode_scanner: ^0.1.1
google_fonts: ^6.2.1
flex_color_scheme: ^7.3.1
blur: ^3.1.0
marquee: ^2.2.3
flutter_launcher_icons: ^0.13.1
dev_dependencies: dev_dependencies:
flutter_launcher_icons: ^0.13.1
flutter_test: flutter_test:
sdk: flutter sdk: flutter
@ -55,28 +47,10 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^4.0.0 flutter_lints: ^2.0.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
#
flutter_launcher_icons:
android: "launcher_icon"
ios: true
image_path: "assets/logo.png"
min_sdk_android: 21 # android min sdk min:16, default 21
web:
generate: true
image_path: "assets/logo.png"
background_color: "#FF8B9DC3"
theme_color: "#FF8B9DC3"
windows:
generate: true
image_path: "assets/logo.png"
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: "assets/logo.png"
# The following section is specific to Flutter packages. # The following section is specific to Flutter packages.
flutter: flutter:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 B

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -3,8 +3,8 @@
"short_name": "fooder_web", "short_name": "fooder_web",
"start_url": ".", "start_url": ".",
"display": "standalone", "display": "standalone",
"background_color": "#FF8B9DC3", "background_color": "#0175C2",
"theme_color": "#FF8B9DC3", "theme_color": "#0175C2",
"description": "A new Flutter project.", "description": "A new Flutter project.",
"orientation": "portrait-primary", "orientation": "portrait-primary",
"prefer_related_applications": false, "prefer_related_applications": false,

View file

@ -6,15 +6,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <webview_windows/webview_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
WebviewWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WebviewWindowsPlugin"));
} }

View file

@ -3,9 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_windows
permission_handler_windows
webview_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 33 KiB