made app cupertino compatible; improvements; bugfixes

This commit is contained in:
Myzel394 2022-08-17 19:57:55 +02:00
parent cee08c080f
commit 0b0c2ce15f
24 changed files with 696 additions and 365 deletions

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

View File

@ -13,6 +13,7 @@
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 */; };
F2449A063F9DD54E63262023 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D38127B4F5788EF3381B2B4C /* Pods_Runner.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -32,9 +33,11 @@
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>"; };
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>"; };
6B64EB075DA14AE8EEB89C89 /* 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>"; };
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>"; };
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>"; };
8B5ED7BEA3FBEF103E66F847 /* 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>"; };
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>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -42,6 +45,8 @@
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>"; };
D3486A5CDDD946E1FF3C0592 /* 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>"; };
D38127B4F5788EF3381B2B4C /* 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 */
@ -49,12 +54,24 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
F2449A063F9DD54E63262023 /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
928A05FA6D1D23BECAA39FAE /* Pods */ = {
isa = PBXGroup;
children = (
6B64EB075DA14AE8EEB89C89 /* Pods-Runner.debug.xcconfig */,
8B5ED7BEA3FBEF103E66F847 /* Pods-Runner.release.xcconfig */,
D3486A5CDDD946E1FF3C0592 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -72,6 +89,8 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
928A05FA6D1D23BECAA39FAE /* Pods */,
A5CF9B62B23D4F71C0785FAA /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -98,6 +117,14 @@
path = Runner; path = Runner;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A5CF9B62B23D4F71C0785FAA /* Frameworks */ = {
isa = PBXGroup;
children = (
D38127B4F5788EF3381B2B4C /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -105,12 +132,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
6BF4497D0DD8B6C4E3A61453 /* [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 */,
8C74D292913673DDB09B3D1F /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -183,6 +212,45 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
6BF4497D0DD8B6C4E3A61453 /* [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;
};
8C74D292913673DDB09B3D1F /* [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;
};
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -272,7 +340,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 = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 15.5;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -288,6 +356,7 @@
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 = 6FJFK7645A;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -349,7 +418,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 = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 15.5;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -398,7 +467,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 = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 15.5;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -416,6 +485,7 @@
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 = 6FJFK7645A;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -438,6 +508,7 @@
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 = 6FJFK7645A;
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

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

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
final LIGHT_THEME = ThemeData( final LIGHT_THEME_MATERIAL = ThemeData(
textTheme: ThemeData().textTheme.copyWith( textTheme: ThemeData().textTheme.copyWith(
headline1: const TextStyle( headline1: const TextStyle(
fontSize: 32, fontSize: 32,
@ -17,7 +18,7 @@ final LIGHT_THEME = ThemeData(
), ),
); );
final DARK_THEME = ThemeData.dark().copyWith( final DARK_THEME_MATERIAL = ThemeData.dark().copyWith(
textTheme: ThemeData.dark().textTheme.copyWith( textTheme: ThemeData.dark().textTheme.copyWith(
headline1: const TextStyle( headline1: const TextStyle(
fontSize: 32, fontSize: 32,
@ -33,3 +34,12 @@ final DARK_THEME = ThemeData.dark().copyWith(
), ),
), ),
); );
final LIGHT_THEME_CUPERTINO = CupertinoThemeData().copyWith(
textTheme: CupertinoThemeData().textTheme.copyWith(
navLargeTitleTextStyle: const TextStyle(
fontSize: 32,
fontWeight: FontWeight.w500,
),
),
);

View File

@ -1,8 +1,8 @@
import 'package:camera/camera.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:quid_faciam_hodie/constants/themes.dart'; import 'package:quid_faciam_hodie/constants/themes.dart';
import 'package:quid_faciam_hodie/screens/calendar_screen.dart'; import 'package:quid_faciam_hodie/screens/calendar_screen.dart';
@ -24,7 +24,6 @@ void main() async {
DeviceOrientation.portraitDown, DeviceOrientation.portraitDown,
]); ]);
GlobalValuesManager.setCameras(await availableCameras());
GlobalValuesManager.initializeServer(); GlobalValuesManager.initializeServer();
runApp(const MyApp()); runApp(const MyApp());
@ -46,11 +45,16 @@ class _MyAppState extends State<MyApp> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: memories, value: memories,
child: MaterialApp( child: PlatformApp(
title: 'Quid faciam hodie?', title: 'Quid faciam hodie?',
theme: LIGHT_THEME, material: (_, __) => MaterialAppData(
darkTheme: DARK_THEME, theme: LIGHT_THEME_MATERIAL,
themeMode: ThemeMode.system, darkTheme: DARK_THEME_MATERIAL,
themeMode: ThemeMode.system,
),
cupertino: (_, __) => CupertinoAppData(
theme: LIGHT_THEME_CUPERTINO,
),
localizationsDelegates: AppLocalizations.localizationsDelegates, localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,
routes: { routes: {

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:flutter_sticky_header/flutter_sticky_header.dart'; import 'package:flutter_sticky_header/flutter_sticky_header.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
@ -9,7 +10,7 @@ import 'calendar_screen/calendar_month.dart';
import 'calendar_screen/days_of_week_strip.dart'; import 'calendar_screen/days_of_week_strip.dart';
class CalendarScreen extends StatelessWidget { class CalendarScreen extends StatelessWidget {
static const ID = 'calendar'; static const ID = '/calendar';
const CalendarScreen({ const CalendarScreen({
Key? key, Key? key,
@ -18,21 +19,31 @@ class CalendarScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final memoriesManager = context.read<Memories>(); final memoriesManager = context.read<Memories>();
final theme = Theme.of(context);
final calendarManager = CalendarManager(memories: memoriesManager.memories); final calendarManager = CalendarManager(memories: memoriesManager.memories);
final monthMapping = calendarManager.getMappingForList(); final monthMapping = calendarManager.getMappingForList();
return Consumer<Memories>( return Consumer<Memories>(
builder: (context, memories, _) => Scaffold( builder: (context, memories, _) => PlatformScaffold(
appBar: isCupertino(context)
? PlatformAppBar(
title: Text('Calendar'),
)
: null,
body: Padding( body: Padding(
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE), padding: EdgeInsets.only(
top: isCupertino(context) ? HUGE_SPACE : MEDIUM_SPACE,
),
child: CustomScrollView( child: CustomScrollView(
reverse: true, reverse: true,
slivers: [ slivers: [
SliverStickyHeader( SliverStickyHeader(
header: Container( header: Container(
color: theme.canvasColor, color: platformThemeData(
context,
material: (data) => data.canvasColor,
cupertino: (data) => data.barBackgroundColor,
),
padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE), padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE),
child: const DaysOfWeekStrip(), child: const DaysOfWeekStrip(),
), ),

View File

@ -2,6 +2,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_calendar_widget/flutter_calendar_widget.dart'; import 'package:flutter_calendar_widget/flutter_calendar_widget.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/constants/values.dart'; import 'package:quid_faciam_hodie/constants/values.dart';
@ -119,8 +120,6 @@ class CalendarMonth extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
return FlutterCalendar( return FlutterCalendar(
focusedDate: firstDate, focusedDate: firstDate,
selectionMode: CalendarSelectionMode.single, selectionMode: CalendarSelectionMode.single,
@ -157,13 +156,28 @@ class CalendarMonth extends StatelessWidget {
calenderMargin: EdgeInsets.symmetric(vertical: MEDIUM_SPACE), calenderMargin: EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
), ),
textStyle: CalendarTextStyle( textStyle: CalendarTextStyle(
headerTextStyle: theme.textTheme.subtitle1!, headerTextStyle: platformThemeData(
dayOfWeekTextColor: theme.textTheme.bodyText2!.color!, context,
dayTextColor: theme.textTheme.bodyText1!.color!, material: (data) => data.textTheme.subtitle1!,
cupertino: (data) => data.textTheme.navTitleTextStyle,
),
dayTextColor: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1!.color!,
cupertino: (data) => data.textTheme.textStyle.color!,
),
// Background color // Background color
selectedDayTextColor: theme.textTheme.bodyText1!.color!, selectedDayTextColor: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1!.color!,
cupertino: (data) => data.textTheme.textStyle.color!,
),
// Foreground color // Foreground color
focusedDayTextColor: theme.dialogBackgroundColor, focusedDayTextColor: platformThemeData(
context,
material: (data) => data.dialogBackgroundColor,
cupertino: (data) => data.barBackgroundColor,
),
), ),
); );
} }

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_calendar_widget/flutter_calendar_widget.dart'; import 'package:flutter_calendar_widget/flutter_calendar_widget.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class DaysOfWeekStrip extends StatelessWidget { class DaysOfWeekStrip extends StatelessWidget {
@ -20,20 +21,23 @@ class DaysOfWeekStrip extends StatelessWidget {
TableRow( TableRow(
children: List.generate( children: List.generate(
7, 7,
(index) => Container( (index) => Align(
child: Align( child: Text(
child: Text( DateFormat.E().format(
DateFormat.E().format( DateTime(1900, 1, 1)
DateTime(1900, 1, 1) .add(
.add( Duration(days: index),
Duration(days: index), )
) .add(
.add( Duration(
Duration( days: 8 - getWeekdayNumber(DayOfWeek.mon),
days: 8 - getWeekdayNumber(DayOfWeek.mon),
),
), ),
), ),
),
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1!,
cupertino: (data) => data.textTheme.textStyle,
), ),
), ),
), ),

View File

@ -1,11 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/screens/main_screen.dart'; import 'package:quid_faciam_hodie/screens/main_screen.dart';
import 'grant_permission_screen/permissions_required_page.dart'; import 'grant_permission_screen/permissions_required_page.dart';
class GrantPermissionScreen extends StatelessWidget { class GrantPermissionScreen extends StatelessWidget {
static const ID = 'grant_permission'; static const ID = '/grant_permission';
const GrantPermissionScreen({Key? key}) : super(key: key); const GrantPermissionScreen({Key? key}) : super(key: key);
@ -13,15 +15,18 @@ class GrantPermissionScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!; final localizations = AppLocalizations.of(context)!;
return Scaffold( return PlatformScaffold(
appBar: AppBar( appBar: PlatformAppBar(
title: Text(localizations.grantPermissionScreenTitle), title: Text(localizations.grantPermissionScreenTitle),
), ),
body: Center( body: Padding(
child: PermissionsRequiredPage( padding: const EdgeInsets.all(MEDIUM_SPACE),
onPermissionsGranted: () { child: Center(
Navigator.pushReplacementNamed(context, MainScreen.ID); child: PermissionsRequiredPage(
}, onPermissionsGranted: () {
Navigator.pushReplacementNamed(context, MainScreen.ID);
},
),
), ),
), ),
); );

View File

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
class PermissionsRequiredPage extends StatefulWidget { class PermissionsRequiredPage extends StatefulWidget {
final VoidCallback onPermissionsGranted; final VoidCallback onPermissionsGranted;
@ -61,58 +63,77 @@ class _PermissionsRequiredPageState extends State<PermissionsRequiredPage> {
children: <Widget>[ children: <Widget>[
Text( Text(
localizations.permissionsRequiredPageTitle, localizations.permissionsRequiredPageTitle,
style: Theme.of(context).textTheme.headline1, style: platformThemeData(
context,
material: (data) => data.textTheme.headline1,
cupertino: (data) => data.textTheme.navLargeTitleTextStyle,
),
), ),
const SizedBox(height: MEDIUM_SPACE), const SizedBox(height: MEDIUM_SPACE),
Text(localizations.permissionsRequiredPageDescription), Text(
localizations.permissionsRequiredPageDescription,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1,
cupertino: (data) => data.textTheme.textStyle,
),
),
const SizedBox(height: LARGE_SPACE), const SizedBox(height: LARGE_SPACE),
if (hasDeniedForever) ...[ if (hasDeniedForever) ...[
Text(localizations.permissionsRequiredPagePermanentlyDenied), Text(localizations.permissionsRequiredPagePermanentlyDenied),
const SizedBox(height: LARGE_SPACE), const SizedBox(height: LARGE_SPACE),
TextButton.icon( PlatformElevatedButton(
onPressed: () => openAppSettings(), onPressed: () => openAppSettings(),
icon: const Icon(Icons.settings), child: IconButtonChild(
label: Text(localizations.permissionsRequiredPageOpenSettings), icon: Icon(context.platformIcons.settings),
label: Text(localizations.permissionsRequiredPageOpenSettings),
),
), ),
] else ...[ ] else ...[
TextButton.icon( PlatformTextButton(
onPressed: hasGrantedCameraPermission onPressed: hasGrantedCameraPermission
? null ? null
: () async { : () async {
await Permission.camera.request(); await Permission.camera.request();
await checkPermissions(); await checkPermissions();
}, },
icon: const Icon(Icons.camera_alt), child: IconButtonChild(
label: Row( icon: Icon(context.platformIcons.photoCamera),
mainAxisAlignment: MainAxisAlignment.center, label: Row(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.center,
Text( children: <Widget>[
localizations.permissionsRequiredPageGrantCameraPermission, Text(
), localizations.permissionsRequiredPageGrantCameraPermission,
if (hasGrantedCameraPermission) const Icon(Icons.check), ),
if (!hasGrantedCameraPermission) const SizedBox(), if (hasGrantedCameraPermission)
], Icon(context.platformIcons.checkMark),
if (!hasGrantedCameraPermission) const SizedBox(),
],
),
), ),
), ),
const SizedBox(height: MEDIUM_SPACE), const SizedBox(height: MEDIUM_SPACE),
TextButton.icon( PlatformTextButton(
onPressed: hasGrantedMicrophonePermission onPressed: hasGrantedMicrophonePermission
? null ? null
: () async { : () async {
await Permission.microphone.request(); await Permission.microphone.request();
await checkPermissions(); await checkPermissions();
}, },
icon: const Icon(Icons.mic), child: IconButtonChild(
label: Row( icon: Icon(context.platformIcons.mic),
mainAxisAlignment: MainAxisAlignment.center, label: Row(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.center,
Text( children: <Widget>[
localizations Text(
.permissionsRequiredPageGrantMicrophonePermission, localizations
), .permissionsRequiredPageGrantMicrophonePermission,
if (hasGrantedMicrophonePermission) const Icon(Icons.check), ),
if (!hasGrantedMicrophonePermission) const SizedBox(), if (hasGrantedMicrophonePermission)
], Icon(context.platformIcons.checkMark),
if (!hasGrantedMicrophonePermission) const SizedBox(),
],
),
), ),
), ),
], ],

View File

@ -1,16 +1,19 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/extensions/snackbar.dart'; import 'package:quid_faciam_hodie/extensions/snackbar.dart';
import 'package:quid_faciam_hodie/managers/authentication_manager.dart'; import 'package:quid_faciam_hodie/managers/authentication_manager.dart';
import 'package:quid_faciam_hodie/screens/server_loading_screen.dart'; import 'package:quid_faciam_hodie/screens/server_loading_screen.dart';
import 'package:quid_faciam_hodie/utils/loadable.dart'; import 'package:quid_faciam_hodie/utils/loadable.dart';
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:supabase_flutter/supabase_flutter.dart';
final supabase = Supabase.instance.client; final supabase = Supabase.instance.client;
class LoginScreen extends StatefulWidget { class LoginScreen extends StatefulWidget {
static const ID = 'login'; static const ID = '/login';
const LoginScreen({Key? key}) : super(key: key); const LoginScreen({Key? key}) : super(key: key);
@ -85,10 +88,9 @@ class _LoginScreenState extends AuthState<LoginScreen> with Loadable {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!; final localizations = AppLocalizations.of(context)!;
final theme = Theme.of(context);
return Scaffold( return PlatformScaffold(
appBar: AppBar( appBar: PlatformAppBar(
title: Text(localizations.loginScreenTitle), title: Text(localizations.loginScreenTitle),
), ),
body: Padding( body: Padding(
@ -99,38 +101,63 @@ class _LoginScreenState extends AuthState<LoginScreen> with Loadable {
children: <Widget>[ children: <Widget>[
Text( Text(
localizations.loginScreenTitle, localizations.loginScreenTitle,
style: theme.textTheme.headline1, style: platformThemeData(
context,
material: (data) => data.textTheme.headline1,
cupertino: (data) => data.textTheme.navLargeTitleTextStyle,
),
), ),
const SizedBox(height: LARGE_SPACE), const SizedBox(height: LARGE_SPACE),
Text(localizations.loginScreenHelpText), Text(
localizations.loginScreenHelpText,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1,
cupertino: (data) => data.textTheme.textStyle,
),
),
const SizedBox(height: MEDIUM_SPACE), const SizedBox(height: MEDIUM_SPACE),
TextField( PlatformTextField(
controller: emailController, controller: emailController,
autofocus: true, autofocus: true,
autofillHints: const [AutofillHints.email], autofillHints: const [AutofillHints.email],
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( material: (_, __) => MaterialTextFieldData(
labelText: localizations.loginScreenFormEmailLabel, decoration: InputDecoration(
prefixIcon: const Icon(Icons.email), labelText: localizations.loginScreenFormEmailLabel,
prefixIcon: Icon(context.platformIcons.mail),
),
),
cupertino: (_, __) => CupertinoTextFieldData(
placeholder: localizations.loginScreenFormEmailLabel,
prefix: Icon(context.platformIcons.mail),
), ),
), ),
const SizedBox(height: SMALL_SPACE), const SizedBox(height: SMALL_SPACE),
TextField( PlatformTextField(
obscureText: true, obscureText: true,
controller: passwordController, controller: passwordController,
decoration: InputDecoration( material: (_, __) => MaterialTextFieldData(
labelText: localizations.loginScreenFormPasswordLabel, decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock), labelText: localizations.loginScreenFormPasswordLabel,
prefixIcon: Icon(context.platformIcons.padLock),
),
),
cupertino: (_, __) => CupertinoTextFieldData(
placeholder: localizations.loginScreenFormPasswordLabel,
prefix: Icon(context.platformIcons.padLock),
), ),
onSubmitted: (value) => callWithLoading(signIn), onSubmitted: (value) => callWithLoading(signIn),
), ),
const SizedBox(height: MEDIUM_SPACE), const SizedBox(height: MEDIUM_SPACE),
ElevatedButton.icon( PlatformElevatedButton(
icon: const Icon(Icons.arrow_right),
label: Text(localizations.loginScreenFormSubmitButton),
onPressed: isLoading ? null : () => callWithLoading(signIn), onPressed: isLoading ? null : () => callWithLoading(signIn),
) child: IconButtonChild(
icon: Icon(context.platformIcons.forward),
label: Text(localizations.loginScreenFormSubmitButton),
),
),
], ],
), ),
), ),

View File

@ -5,6 +5,7 @@ import 'package:camera/camera.dart';
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart'; import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/constants/values.dart'; import 'package:quid_faciam_hodie/constants/values.dart';
import 'package:quid_faciam_hodie/extensions/snackbar.dart'; import 'package:quid_faciam_hodie/extensions/snackbar.dart';
@ -23,7 +24,7 @@ import 'main_screen/today_photo_button.dart';
import 'main_screen/uploading_photo.dart'; import 'main_screen/uploading_photo.dart';
class MainScreen extends StatefulWidget { class MainScreen extends StatefulWidget {
static const ID = 'main'; static const ID = '/main';
const MainScreen({Key? key}) : super(key: key); const MainScreen({Key? key}) : super(key: key);
@ -63,7 +64,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
void initState() { void initState() {
super.initState(); super.initState();
onNewCameraSelected(GlobalValuesManager.cameras[0]); loadCameras();
} }
@override @override
@ -77,6 +78,12 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
_updateCamera(state); _updateCamera(state);
} }
Future<void> loadCameras() async {
GlobalValuesManager.setCameras(await availableCameras());
onNewCameraSelected(GlobalValuesManager.cameras[0]);
}
void _updateCamera(final AppLifecycleState state) { void _updateCamera(final AppLifecycleState state) {
final CameraController? cameraController = controller; final CameraController? cameraController = controller;
@ -125,6 +132,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
}); });
await controller!.initialize(); await controller!.initialize();
await controller!.prepareForVideoRecording();
await determineZoomLevels(); await determineZoomLevels();
@ -165,31 +173,34 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
}); });
try { try {
context.showPendingSnackBar( if (isMaterial(context))
message: localizations.mainScreenTakePhotoActionTakingPhoto, context.showPendingSnackBar(
); message: localizations.mainScreenTakePhotoActionTakingPhoto,
);
controller!.setFlashMode(FlashMode.off);
final file = File((await controller!.takePicture()).path); final file = File((await controller!.takePicture()).path);
setState(() { setState(() {
uploadingPhotoAnimation = file.readAsBytesSync(); uploadingPhotoAnimation = file.readAsBytesSync();
}); });
context.showPendingSnackBar( if (isMaterial(context))
message: localizations.mainScreenTakePhotoActionUploadingPhoto, context.showPendingSnackBar(
); message: localizations.mainScreenTakePhotoActionUploadingPhoto,
);
try { try {
await FileManager.uploadFile(_user, file); await FileManager.uploadFile(_user, file);
} catch (error) { } catch (error) {
context.showErrorSnackBar(message: error.toString()); if (isMaterial(context))
context.showErrorSnackBar(message: error.toString());
return; return;
} }
context.showSuccessSnackBar( if (isMaterial(context))
message: localizations.mainScreenUploadSuccess, context.showSuccessSnackBar(
); message: localizations.mainScreenUploadSuccess,
);
} finally { } finally {
setState(() { setState(() {
lockCamera = false; lockCamera = false;
@ -215,28 +226,31 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
}); });
try { try {
context.showPendingSnackBar( if (isMaterial(context))
message: localizations.mainScreenTakeVideoActionSaveVideo, context.showPendingSnackBar(
); message: localizations.mainScreenTakeVideoActionSaveVideo,
);
final file = File((await controller!.stopVideoRecording()).path); final file = File((await controller!.stopVideoRecording()).path);
context.showPendingSnackBar( if (isMaterial(context))
message: localizations.mainScreenTakeVideoActionUploadingVideo, context.showPendingSnackBar(
); message: localizations.mainScreenTakeVideoActionUploadingVideo,
);
try { try {
await FileManager.uploadFile(_user, file); await FileManager.uploadFile(_user, file);
} catch (error) { } catch (error) {
if (mounted) { if (isMaterial(context)) {
context.showErrorSnackBar(message: error.toString()); context.showErrorSnackBar(message: error.toString());
} }
return; return;
} }
context.showSuccessSnackBar( if (isMaterial(context))
message: localizations.mainScreenUploadSuccess, context.showSuccessSnackBar(
); message: localizations.mainScreenUploadSuccess,
);
} finally { } finally {
setState(() { setState(() {
lockCamera = false; lockCamera = false;
@ -248,18 +262,25 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!; final localizations = AppLocalizations.of(context)!;
return Scaffold( return PlatformScaffold(
backgroundColor: Colors.black, backgroundColor: Colors.black,
bottomSheet: () { body: () {
if (isLoading) { if (isLoading) {
return Center( return Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
const CircularProgressIndicator(), PlatformCircularProgressIndicator(),
const SizedBox(height: MEDIUM_SPACE), const SizedBox(height: MEDIUM_SPACE),
Text(localizations.mainScreenLoadingCamera), Text(
localizations.mainScreenLoadingCamera,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1,
cupertino: (data) => data.textTheme.textStyle,
),
),
], ],
), ),
); );
@ -304,72 +325,83 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
), ),
), ),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
const Padding( const Padding(
padding: EdgeInsets.symmetric(vertical: MEDIUM_SPACE), padding: EdgeInsets.symmetric(
vertical: MEDIUM_SPACE,
horizontal: MEDIUM_SPACE,
),
child: SheetIndicator(), child: SheetIndicator(),
), ),
Padding( Padding(
padding: const EdgeInsets.all(LARGE_SPACE), padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
FadeAndMoveInAnimation( Expanded(
translationDuration: DEFAULT_TRANSLATION_DURATION * child: FadeAndMoveInAnimation(
SECONDARY_BUTTONS_DURATION_MULTIPLIER, translationDuration: DEFAULT_TRANSLATION_DURATION *
opacityDuration: DEFAULT_OPACITY_DURATION * SECONDARY_BUTTONS_DURATION_MULTIPLIER,
SECONDARY_BUTTONS_DURATION_MULTIPLIER, opacityDuration: DEFAULT_OPACITY_DURATION *
child: ChangeCameraButton( SECONDARY_BUTTONS_DURATION_MULTIPLIER,
disabled: lockCamera, child: ChangeCameraButton(
onChangeCamera: () { disabled: lockCamera,
final currentCameraIndex = GlobalValuesManager onChangeCamera: () {
.cameras final currentCameraIndex = GlobalValuesManager
.indexOf(controller!.description); .cameras
final availableCameras = .indexOf(controller!.description);
GlobalValuesManager.cameras.length; final availableCameras =
GlobalValuesManager.cameras.length;
onNewCameraSelected( onNewCameraSelected(
GlobalValuesManager.cameras[ GlobalValuesManager.cameras[
(currentCameraIndex + 1) % (currentCameraIndex + 1) %
availableCameras], availableCameras],
); );
}, },
),
), ),
), ),
FadeAndMoveInAnimation( Expanded(
child: RecordButton( child: FadeAndMoveInAnimation(
disabled: lockCamera, child: RecordButton(
active: isRecording, disabled: lockCamera,
onVideoBegin: () async { active: isRecording,
setState(() { onVideoBegin: () async {
isRecording = true; setState(() {
}); isRecording = true;
});
if (controller!.value.isRecordingVideo) { if (controller!.value.isRecordingVideo) {
// A recording has already started, do nothing. // A recording has already started, do nothing.
return; return;
} }
await controller!.startVideoRecording(); await controller!.startVideoRecording();
}, },
onVideoEnd: takeVideo, onVideoEnd: takeVideo,
onPhotoShot: takePhoto, onPhotoShot: takePhoto,
),
), ),
), ),
FadeAndMoveInAnimation( Expanded(
translationDuration: DEFAULT_TRANSLATION_DURATION * child: FadeAndMoveInAnimation(
SECONDARY_BUTTONS_DURATION_MULTIPLIER, translationDuration: DEFAULT_TRANSLATION_DURATION *
opacityDuration: DEFAULT_OPACITY_DURATION * SECONDARY_BUTTONS_DURATION_MULTIPLIER,
SECONDARY_BUTTONS_DURATION_MULTIPLIER, opacityDuration: DEFAULT_OPACITY_DURATION *
child: TodayPhotoButton( SECONDARY_BUTTONS_DURATION_MULTIPLIER,
onLeave: () { child: TodayPhotoButton(
controller!.setFlashMode(FlashMode.off); onLeave: () {
}, controller!.setFlashMode(FlashMode.off);
onComeBack: () { },
if (isTorchEnabled) { onComeBack: () {
controller!.setFlashMode(FlashMode.torch); if (isTorchEnabled) {
} controller!.setFlashMode(FlashMode.torch);
}, }
},
),
), ),
), ),
], ],
@ -378,69 +410,76 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
], ],
), ),
), ),
expandableContent: Padding( expandableContent: Container(
padding: const EdgeInsets.only( color: Colors.black,
left: LARGE_SPACE, child: Padding(
right: LARGE_SPACE, padding: const EdgeInsets.only(
bottom: MEDIUM_SPACE, left: LARGE_SPACE,
), right: LARGE_SPACE,
child: Row( bottom: MEDIUM_SPACE,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, ),
children: <Widget>[ child: Row(
ElevatedButton.icon( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
icon: const Icon(Icons.flashlight_on_rounded), children: <Widget>[
label: Text(AppLocalizations.of(context)! ElevatedButton.icon(
.mainScreenActionsTorchButton), icon: const Icon(Icons.flashlight_on_rounded),
style: ButtonStyle( label: Text(AppLocalizations.of(context)!
backgroundColor: MaterialStateProperty.resolveWith<Color>( .mainScreenActionsTorchButton),
(_) => isTorchEnabled ? Colors.white : Colors.black, style: ButtonStyle(
), backgroundColor:
foregroundColor: MaterialStateProperty.resolveWith<Color>( MaterialStateProperty.resolveWith<Color>(
(_) => isTorchEnabled ? Colors.black : Colors.white, (_) => isTorchEnabled ? Colors.white : Colors.black,
),
foregroundColor:
MaterialStateProperty.resolveWith<Color>(
(_) => isTorchEnabled ? Colors.black : Colors.white,
),
), ),
onPressed: () {
setState(() {
isTorchEnabled = !isTorchEnabled;
if (isTorchEnabled) {
controller!.setFlashMode(FlashMode.torch);
} else {
controller!.setFlashMode(FlashMode.off);
}
});
},
), ),
onPressed: () { ElevatedButton(
setState(() { style: ButtonStyle(
isTorchEnabled = !isTorchEnabled; backgroundColor:
MaterialStateProperty.resolveWith<Color>(
(_) => Colors.white10,
),
foregroundColor:
MaterialStateProperty.resolveWith<Color>(
(_) => Colors.white,
),
),
onPressed: zoomLevels == null
? null
: () {
final newZoomLevelIndex =
((currentZoomLevelIndex + 1) %
zoomLevels!.length);
if (isTorchEnabled) { controller!
controller!.setFlashMode(FlashMode.torch); .setZoomLevel(zoomLevels![newZoomLevelIndex]);
} else {
controller!.setFlashMode(FlashMode.off); setState(() {
} currentZoomLevelIndex = newZoomLevelIndex;
}); });
}, },
), child: zoomLevels == null
ElevatedButton( ? const Text('1x')
style: ButtonStyle( : Text(
backgroundColor: MaterialStateProperty.resolveWith<Color>( formatZoomLevel(currentZoomLevel),
(_) => Colors.white10, ),
),
foregroundColor: MaterialStateProperty.resolveWith<Color>(
(_) => Colors.white,
),
), ),
onPressed: zoomLevels == null ],
? null ),
: () {
final newZoomLevelIndex =
((currentZoomLevelIndex + 1) %
zoomLevels!.length);
controller!
.setZoomLevel(zoomLevels![newZoomLevelIndex]);
setState(() {
currentZoomLevelIndex = newZoomLevelIndex;
});
},
child: zoomLevels == null
? const Text('1x')
: Text(
formatZoomLevel(currentZoomLevel),
),
),
],
), ),
), ),
), ),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
class ChangeCameraButton extends StatelessWidget { class ChangeCameraButton extends StatelessWidget {
final VoidCallback onChangeCamera; final VoidCallback onChangeCamera;
@ -13,9 +14,7 @@ class ChangeCameraButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return GestureDetector(
enableFeedback: false,
highlightColor: Colors.transparent,
onTap: () { onTap: () {
if (disabled) { if (disabled) {
return; return;
@ -34,9 +33,9 @@ class ChangeCameraButton extends StatelessWidget {
size: 60, size: 60,
color: Colors.white.withOpacity(.2), color: Colors.white.withOpacity(.2),
), ),
const Icon( Icon(
Icons.camera_alt, context.platformIcons.switchCamera,
size: 30, size: 25,
color: Colors.white, color: Colors.white,
), ),
], ],

View File

@ -28,6 +28,17 @@ class _RecordButtonState extends State<RecordButton> {
bool animateToVideoIcon = false; bool animateToVideoIcon = false;
bool videoInAnimationActive = false; bool videoInAnimationActive = false;
void cancelAnimation() {
if (videoInAnimationActive || animateToVideoIcon) {
return;
}
setState(() {
videoInAnimationActive = false;
animateToVideoIcon = false;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
@ -57,6 +68,7 @@ class _RecordButtonState extends State<RecordButton> {
} }
setState(() { setState(() {
animateToVideoIcon = false;
videoInAnimationActive = true; videoInAnimationActive = true;
}); });
@ -96,69 +108,69 @@ class _RecordButtonState extends State<RecordButton> {
}); });
}, },
// Cancel icon animation // Cancel icon animation
onTapCancel: () { onTapCancel: cancelAnimation,
if (videoInAnimationActive || animateToVideoIcon) { onPanCancel: cancelAnimation,
return; onLongPressCancel: cancelAnimation,
}
setState(() {
videoInAnimationActive = false;
animateToVideoIcon = false;
});
},
// Cancel icon animation
onPanCancel: () {
if (videoInAnimationActive || animateToVideoIcon) {
return;
}
setState(() {
videoInAnimationActive = false;
animateToVideoIcon = false;
});
},
child: Opacity( child: Opacity(
opacity: widget.disabled ? 0.5 : 1.0, opacity: widget.disabled ? 0.5 : 1.0,
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
Icon( AnimatedContainer(
Icons.circle, duration: videoInAnimationActive ? Duration.zero : OUT_DURATION,
size: 75, width: 60,
color: Colors.white.withOpacity(.2), height: 60,
), decoration: BoxDecoration(
AnimatedScale( color: videoInAnimationActive
duration: animateToVideoIcon ? kLongPressTimeout : OUT_DURATION, ? Colors.white
curve: Curves.easeInOut, : Colors.white.withOpacity(.2),
scale: animateToVideoIcon ? (75 / 50) : 1, borderRadius: BorderRadius.circular(30),
child: const Icon(
Icons.circle,
size: 50,
color: Colors.white,
), ),
), ),
AnimatedScale( AnimatedScale(
duration: () {
if (videoInAnimationActive) {
return Duration(milliseconds: 400);
}
if (animateToVideoIcon) {
return kLongPressTimeout;
}
return OUT_DURATION;
}(),
curve: Curves.easeInOut, curve: Curves.easeInOut,
duration: animateToVideoIcon scale: () {
? const Duration(milliseconds: 180) if (videoInAnimationActive) {
: OUT_DURATION, return .6;
scale: videoInAnimationActive ? 1 : 0, }
child: const Icon(
Icons.circle, if (animateToVideoIcon) {
size: 65, return 60 / 40;
color: Colors.red, }
),
), return 1.0;
AnimatedScale( }(),
curve: animateToVideoIcon ? Curves.easeOut : Curves.linear, child: AnimatedContainer(
duration: animateToVideoIcon duration: () {
? const Duration(milliseconds: 250) if (videoInAnimationActive) {
: OUT_DURATION, return Duration(milliseconds: 400);
scale: videoInAnimationActive ? 1 : .6, }
child: const Icon(
Icons.stop, if (animateToVideoIcon) {
size: 45, return kLongPressTimeout;
color: Colors.white, }
return OUT_DURATION;
}(),
width: 40,
height: 40,
decoration: BoxDecoration(
color: videoInAnimationActive ? Colors.red : Colors.white,
borderRadius: videoInAnimationActive
? BorderRadius.circular(4)
: BorderRadius.circular(50),
),
), ),
), ),
], ],

View File

@ -70,7 +70,7 @@ class _TodayPhotoButtonState extends State<TodayPhotoButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return GestureDetector(
onTap: () async { onTap: () async {
widget.onLeave(); widget.onLeave();
@ -85,25 +85,27 @@ class _TodayPhotoButtonState extends State<TodayPhotoButton> {
widget.onComeBack(); widget.onComeBack();
}, },
child: Container( child: Align(
width: 45, child: Container(
height: 45, width: 45,
decoration: BoxDecoration( height: 45,
border: Border.all( decoration: BoxDecoration(
color: Colors.white, border: Border.all(
width: 2, color: Colors.white,
width: 2,
),
borderRadius: BorderRadius.circular(SMALL_SPACE),
color: Colors.grey,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(SMALL_SPACE),
child: (data == null || type == null)
? const SizedBox.shrink()
: RawMemoryDisplay(
data: data!,
type: type!,
),
), ),
borderRadius: BorderRadius.circular(SMALL_SPACE),
color: Colors.grey,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(SMALL_SPACE),
child: (data == null || type == null)
? const SizedBox.shrink()
: RawMemoryDisplay(
data: data!,
type: type!,
),
), ),
), ),
); );

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/managers/global_values_manager.dart'; import 'package:quid_faciam_hodie/managers/global_values_manager.dart';
@ -11,7 +12,7 @@ import 'server_loading_screen/dot_animation.dart';
import 'welcome_screen.dart'; import 'welcome_screen.dart';
class ServerLoadingScreen extends StatefulWidget { class ServerLoadingScreen extends StatefulWidget {
static const ID = 'server_loading'; static const ID = '/server_loading';
final String? nextScreen; final String? nextScreen;
@ -63,7 +64,11 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
const Icon(Icons.cloud, size: 60), const Icon(
Icons.cloud,
size: 60,
color: Colors.white,
),
const SizedBox(height: SMALL_SPACE), const SizedBox(height: SMALL_SPACE),
const DotAnimation( const DotAnimation(
initialFadeInDelay: Duration.zero, initialFadeInDelay: Duration.zero,
@ -87,9 +92,20 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
fadeOutDelay: Duration.zero, fadeOutDelay: Duration.zero,
), ),
const SizedBox(height: SMALL_SPACE), const SizedBox(height: SMALL_SPACE),
const Icon(Icons.smartphone, size: 60), const Icon(
Icons.phone_android_rounded,
size: 60,
color: Colors.white,
),
const SizedBox(height: LARGE_SPACE), const SizedBox(height: LARGE_SPACE),
Text(localizations.serverLoadingScreenDescription), Text(
localizations.serverLoadingScreenDescription,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1,
cupertino: (data) => data.textTheme.textStyle,
),
),
], ],
), ),
), ),

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:quid_faciam_hodie/extensions/date.dart'; import 'package:quid_faciam_hodie/extensions/date.dart';
import 'package:quid_faciam_hodie/models/memories.dart'; import 'package:quid_faciam_hodie/models/memories.dart';
@ -12,7 +13,7 @@ import 'timeline_screen/timeline_page.dart';
final supabase = Supabase.instance.client; final supabase = Supabase.instance.client;
class TimelineScreen extends StatefulWidget { class TimelineScreen extends StatefulWidget {
static const ID = 'timeline'; static const ID = '/timeline';
final DateTime? date; final DateTime? date;
@ -92,7 +93,12 @@ class _TimelineScreenState extends State<TimelineScreen> with Loadable {
return true; return true;
}, },
child: Scaffold( child: PlatformScaffold(
appBar: isCupertino(context)
? PlatformAppBar(
title: Text('Timeline'),
)
: null,
body: ChangeNotifierProvider.value( body: ChangeNotifierProvider.value(
value: timeline, value: timeline,
child: PageView.builder( child: PageView.builder(

View File

@ -3,6 +3,7 @@ import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/enums.dart'; import 'package:quid_faciam_hodie/enums.dart';
import 'package:quid_faciam_hodie/foreign_types/memory.dart'; import 'package:quid_faciam_hodie/foreign_types/memory.dart';
@ -81,14 +82,19 @@ class _MemoryViewState extends State<MemoryView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!; final localizations = AppLocalizations.of(context)!;
final theme = Theme.of(context);
if (status == MemoryFetchStatus.error) { if (status == MemoryFetchStatus.error) {
return Center( return Center(
child: Text( child: Text(
localizations.memoryViewDownloadFailed, localizations.memoryViewDownloadFailed,
style: theme.textTheme.bodyText2!.copyWith( style: platformThemeData(
color: Colors.white, context,
material: (data) => data.textTheme.bodyText2!.copyWith(
color: Colors.white,
),
cupertino: (data) => data.textTheme.textStyle.copyWith(
color: Colors.white,
),
), ),
), ),
); );
@ -126,15 +132,21 @@ class _MemoryViewState extends State<MemoryView> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
const CircularProgressIndicator(), PlatformCircularProgressIndicator(),
const SizedBox(height: SMALL_SPACE), const SizedBox(height: SMALL_SPACE),
() { () {
switch (status) { switch (status) {
case MemoryFetchStatus.downloading: case MemoryFetchStatus.downloading:
return Text( return Text(
localizations.memoryViewIsDownloading, localizations.memoryViewIsDownloading,
style: theme.textTheme.bodyText2!.copyWith( style: platformThemeData(
color: Colors.white, context,
material: (data) => data.textTheme.bodyText2!.copyWith(
color: Colors.white,
),
cupertino: (data) => data.textTheme.textStyle.copyWith(
color: Colors.white,
),
), ),
); );
default: default:

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
@ -18,14 +19,14 @@ class TimelineOverlay extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
final timeline = context.watch<TimelineModel>(); final timeline = context.watch<TimelineModel>();
return Stack( return Stack(
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: const EdgeInsets.only( padding: EdgeInsets.only(
top: LARGE_SPACE, // Cupertino needs more space as the top bar is shown to provide a pop button
top: isCupertino(context) ? HUGE_SPACE : LARGE_SPACE,
left: MEDIUM_SPACE, left: MEDIUM_SPACE,
right: MEDIUM_SPACE, right: MEDIUM_SPACE,
), ),
@ -36,9 +37,16 @@ class TimelineOverlay extends StatelessWidget {
child: Text( child: Text(
DateFormat.yMMMd().format(date), DateFormat.yMMMd().format(date),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline1!.copyWith( style: platformThemeData(
color: Colors.white, context,
), material: (data) => data.textTheme.headline1!.copyWith(
color: Colors.white,
),
cupertino: (data) =>
data.textTheme.navLargeTitleTextStyle.copyWith(
color: Colors.white,
),
),
), ),
), ),
), ),
@ -59,16 +67,27 @@ class TimelineOverlay extends StatelessWidget {
curve: Curves.linearToEaseOut, curve: Curves.linearToEaseOut,
child: Icon( child: Icon(
Icons.public, Icons.public,
size: theme.textTheme.titleSmall!.fontSize, size: platformThemeData(
context,
material: (data) => data.textTheme.bodyLarge!.fontSize,
cupertino: (data) => data.textTheme.textStyle.fontSize,
),
color: Colors.white, color: Colors.white,
), ),
), ),
const SizedBox(width: SMALL_SPACE), const SizedBox(width: SMALL_SPACE),
Text( Text(
'$memoryIndex/$memoriesAmount', '$memoryIndex/$memoriesAmount',
style: Theme.of(context).textTheme.titleSmall!.copyWith( style: platformThemeData(
color: Colors.white, context,
), material: (data) => data.textTheme.titleSmall!.copyWith(
color: Colors.white,
),
cupertino: (data) =>
data.textTheme.navTitleTextStyle.copyWith(
color: Colors.white,
),
),
) )
], ],
), ),

View File

@ -1,57 +1,73 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:quid_faciam_hodie/constants/spacing.dart'; import 'package:quid_faciam_hodie/constants/spacing.dart';
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
import 'package:quid_faciam_hodie/widgets/logo.dart'; import 'package:quid_faciam_hodie/widgets/logo.dart';
import 'grant_permission_screen.dart'; import 'grant_permission_screen.dart';
class WelcomeScreen extends StatelessWidget { class WelcomeScreen extends StatelessWidget {
static const ID = 'welcome'; static const ID = '/';
const WelcomeScreen({Key? key}) : super(key: key); const WelcomeScreen({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!; final localizations = AppLocalizations.of(context)!;
final theme = Theme.of(context);
return Scaffold( return PlatformScaffold(
body: Padding( body: Padding(
padding: const EdgeInsets.all(MEDIUM_SPACE), padding: const EdgeInsets.all(MEDIUM_SPACE),
child: Column( child: Center(
mainAxisAlignment: MainAxisAlignment.center, child: Column(
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
const Logo(), const Logo(),
const SizedBox(height: LARGE_SPACE), const SizedBox(height: LARGE_SPACE),
Text( Text(
localizations.appTitleQuestion, localizations.appTitleQuestion,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: theme.textTheme.headline1, style: platformThemeData(
),
const SizedBox(height: SMALL_SPACE),
Text(
localizations.welcomeScreenSubtitle,
style: theme.textTheme.bodySmall,
),
const SizedBox(height: LARGE_SPACE),
Text(
localizations.welcomeScreenDescription,
textAlign: TextAlign.center,
style: theme.textTheme.bodyText2,
),
const SizedBox(height: LARGE_SPACE),
ElevatedButton.icon(
icon: const Icon(Icons.arrow_right),
label: Text(localizations.welcomeScreenStartButtonTitle),
onPressed: () {
Navigator.pushReplacementNamed(
context, context,
GrantPermissionScreen.ID, material: (data) => data.textTheme.headline1,
); cupertino: (data) => data.textTheme.navLargeTitleTextStyle,
}, ),
), ),
], const SizedBox(height: SMALL_SPACE),
Text(
localizations.welcomeScreenSubtitle,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodySmall,
cupertino: (data) => data.textTheme.navTitleTextStyle,
),
),
const SizedBox(height: LARGE_SPACE),
Text(
localizations.welcomeScreenDescription,
textAlign: TextAlign.center,
style: platformThemeData(
context,
material: (data) => data.textTheme.bodyText1,
cupertino: (data) => data.textTheme.textStyle,
),
),
const SizedBox(height: LARGE_SPACE),
PlatformElevatedButton(
child: IconButtonChild(
icon: Icon(context.platformIcons.forward),
label: Text(localizations.welcomeScreenStartButtonTitle),
),
onPressed: () {
Navigator.pushReplacementNamed(
context,
GrantPermissionScreen.ID,
);
},
)
],
),
), ),
), ),
); );

View File

@ -0,0 +1,30 @@
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
class IconButtonChild extends StatelessWidget {
final Widget label;
final Widget icon;
const IconButtonChild({
Key? key,
required this.label,
required this.icon,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final double scale = MediaQuery.maybeOf(context)?.textScaleFactor ?? 1;
final double gap = scale <= 1 ? 8 : lerpDouble(8, 4, min(scale - 1, 1))!;
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
icon,
SizedBox(width: gap),
Flexible(child: label),
],
);
}
}

View File

@ -158,6 +158,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_platform_widgets:
dependency: "direct main"
description:
name: flutter_platform_widgets
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:

View File

@ -53,6 +53,7 @@ dependencies:
expandable_bottom_sheet: ^1.1.1+1 expandable_bottom_sheet: ^1.1.1+1
flutter_sticky_header: ^0.6.4 flutter_sticky_header: ^0.6.4
flutter_calendar_widget: ^0.0.2 flutter_calendar_widget: ^0.0.2
flutter_platform_widgets: ^2.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: