mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 15:25:27 +02:00
made app cupertino compatible; improvements; bugfixes
This commit is contained in:
parent
cee08c080f
commit
0b0c2ce15f
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
@ -1 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
@ -13,6 +13,7 @@
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -32,9 +33,11 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
@ -42,6 +45,8 @@
|
||||
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>"; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -49,12 +54,24 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F2449A063F9DD54E63262023 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase 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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -72,6 +89,8 @@
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
928A05FA6D1D23BECAA39FAE /* Pods */,
|
||||
A5CF9B62B23D4F71C0785FAA /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@ -98,6 +117,14 @@
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A5CF9B62B23D4F71C0785FAA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D38127B4F5788EF3381B2B4C /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -105,12 +132,14 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
6BF4497D0DD8B6C4E3A61453 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
8C74D292913673DDB09B3D1F /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -183,6 +212,45 @@
|
||||
shellPath = /bin/sh;
|
||||
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 */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -272,7 +340,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -288,6 +356,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 6FJFK7645A;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -349,7 +418,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -398,7 +467,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -416,6 +485,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 6FJFK7645A;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -438,6 +508,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 6FJFK7645A;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
@ -4,4 +4,7 @@
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final LIGHT_THEME = ThemeData(
|
||||
final LIGHT_THEME_MATERIAL = ThemeData(
|
||||
textTheme: ThemeData().textTheme.copyWith(
|
||||
headline1: const TextStyle(
|
||||
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(
|
||||
headline1: const TextStyle(
|
||||
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,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.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:quid_faciam_hodie/constants/themes.dart';
|
||||
import 'package:quid_faciam_hodie/screens/calendar_screen.dart';
|
||||
@ -24,7 +24,6 @@ void main() async {
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
GlobalValuesManager.setCameras(await availableCameras());
|
||||
GlobalValuesManager.initializeServer();
|
||||
|
||||
runApp(const MyApp());
|
||||
@ -46,11 +45,16 @@ class _MyAppState extends State<MyApp> {
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider.value(
|
||||
value: memories,
|
||||
child: MaterialApp(
|
||||
child: PlatformApp(
|
||||
title: 'Quid faciam hodie?',
|
||||
theme: LIGHT_THEME,
|
||||
darkTheme: DARK_THEME,
|
||||
themeMode: ThemeMode.system,
|
||||
material: (_, __) => MaterialAppData(
|
||||
theme: LIGHT_THEME_MATERIAL,
|
||||
darkTheme: DARK_THEME_MATERIAL,
|
||||
themeMode: ThemeMode.system,
|
||||
),
|
||||
cupertino: (_, __) => CupertinoAppData(
|
||||
theme: LIGHT_THEME_CUPERTINO,
|
||||
),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
routes: {
|
||||
|
@ -1,4 +1,5 @@
|
||||
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:provider/provider.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';
|
||||
|
||||
class CalendarScreen extends StatelessWidget {
|
||||
static const ID = 'calendar';
|
||||
static const ID = '/calendar';
|
||||
|
||||
const CalendarScreen({
|
||||
Key? key,
|
||||
@ -18,21 +19,31 @@ class CalendarScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final memoriesManager = context.read<Memories>();
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final calendarManager = CalendarManager(memories: memoriesManager.memories);
|
||||
final monthMapping = calendarManager.getMappingForList();
|
||||
|
||||
return Consumer<Memories>(
|
||||
builder: (context, memories, _) => Scaffold(
|
||||
builder: (context, memories, _) => PlatformScaffold(
|
||||
appBar: isCupertino(context)
|
||||
? PlatformAppBar(
|
||||
title: Text('Calendar'),
|
||||
)
|
||||
: null,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
||||
padding: EdgeInsets.only(
|
||||
top: isCupertino(context) ? HUGE_SPACE : MEDIUM_SPACE,
|
||||
),
|
||||
child: CustomScrollView(
|
||||
reverse: true,
|
||||
slivers: [
|
||||
SliverStickyHeader(
|
||||
header: Container(
|
||||
color: theme.canvasColor,
|
||||
color: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.canvasColor,
|
||||
cupertino: (data) => data.barBackgroundColor,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE),
|
||||
child: const DaysOfWeekStrip(),
|
||||
),
|
||||
|
@ -2,6 +2,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.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:quid_faciam_hodie/constants/spacing.dart';
|
||||
import 'package:quid_faciam_hodie/constants/values.dart';
|
||||
@ -119,8 +120,6 @@ class CalendarMonth extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return FlutterCalendar(
|
||||
focusedDate: firstDate,
|
||||
selectionMode: CalendarSelectionMode.single,
|
||||
@ -157,13 +156,28 @@ class CalendarMonth extends StatelessWidget {
|
||||
calenderMargin: EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
||||
),
|
||||
textStyle: CalendarTextStyle(
|
||||
headerTextStyle: theme.textTheme.subtitle1!,
|
||||
dayOfWeekTextColor: theme.textTheme.bodyText2!.color!,
|
||||
dayTextColor: theme.textTheme.bodyText1!.color!,
|
||||
headerTextStyle: platformThemeData(
|
||||
context,
|
||||
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
|
||||
selectedDayTextColor: theme.textTheme.bodyText1!.color!,
|
||||
selectedDayTextColor: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText1!.color!,
|
||||
cupertino: (data) => data.textTheme.textStyle.color!,
|
||||
),
|
||||
// Foreground color
|
||||
focusedDayTextColor: theme.dialogBackgroundColor,
|
||||
focusedDayTextColor: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.dialogBackgroundColor,
|
||||
cupertino: (data) => data.barBackgroundColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_calendar_widget/flutter_calendar_widget.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class DaysOfWeekStrip extends StatelessWidget {
|
||||
@ -20,20 +21,23 @@ class DaysOfWeekStrip extends StatelessWidget {
|
||||
TableRow(
|
||||
children: List.generate(
|
||||
7,
|
||||
(index) => Container(
|
||||
child: Align(
|
||||
child: Text(
|
||||
DateFormat.E().format(
|
||||
DateTime(1900, 1, 1)
|
||||
.add(
|
||||
Duration(days: index),
|
||||
)
|
||||
.add(
|
||||
Duration(
|
||||
days: 8 - getWeekdayNumber(DayOfWeek.mon),
|
||||
),
|
||||
(index) => Align(
|
||||
child: Text(
|
||||
DateFormat.E().format(
|
||||
DateTime(1900, 1, 1)
|
||||
.add(
|
||||
Duration(days: index),
|
||||
)
|
||||
.add(
|
||||
Duration(
|
||||
days: 8 - getWeekdayNumber(DayOfWeek.mon),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText1!,
|
||||
cupertino: (data) => data.textTheme.textStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1,11 +1,13 @@
|
||||
import 'package:flutter/material.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 'grant_permission_screen/permissions_required_page.dart';
|
||||
|
||||
class GrantPermissionScreen extends StatelessWidget {
|
||||
static const ID = 'grant_permission';
|
||||
static const ID = '/grant_permission';
|
||||
|
||||
const GrantPermissionScreen({Key? key}) : super(key: key);
|
||||
|
||||
@ -13,15 +15,18 @@ class GrantPermissionScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
return PlatformScaffold(
|
||||
appBar: PlatformAppBar(
|
||||
title: Text(localizations.grantPermissionScreenTitle),
|
||||
),
|
||||
body: Center(
|
||||
child: PermissionsRequiredPage(
|
||||
onPermissionsGranted: () {
|
||||
Navigator.pushReplacementNamed(context, MainScreen.ID);
|
||||
},
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||
child: Center(
|
||||
child: PermissionsRequiredPage(
|
||||
onPermissionsGranted: () {
|
||||
Navigator.pushReplacementNamed(context, MainScreen.ID);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.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:quid_faciam_hodie/constants/spacing.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
|
||||
|
||||
class PermissionsRequiredPage extends StatefulWidget {
|
||||
final VoidCallback onPermissionsGranted;
|
||||
@ -61,58 +63,77 @@ class _PermissionsRequiredPageState extends State<PermissionsRequiredPage> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
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),
|
||||
Text(localizations.permissionsRequiredPageDescription),
|
||||
Text(
|
||||
localizations.permissionsRequiredPageDescription,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText1,
|
||||
cupertino: (data) => data.textTheme.textStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
if (hasDeniedForever) ...[
|
||||
Text(localizations.permissionsRequiredPagePermanentlyDenied),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
TextButton.icon(
|
||||
PlatformElevatedButton(
|
||||
onPressed: () => openAppSettings(),
|
||||
icon: const Icon(Icons.settings),
|
||||
label: Text(localizations.permissionsRequiredPageOpenSettings),
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.settings),
|
||||
label: Text(localizations.permissionsRequiredPageOpenSettings),
|
||||
),
|
||||
),
|
||||
] else ...[
|
||||
TextButton.icon(
|
||||
PlatformTextButton(
|
||||
onPressed: hasGrantedCameraPermission
|
||||
? null
|
||||
: () async {
|
||||
await Permission.camera.request();
|
||||
await checkPermissions();
|
||||
},
|
||||
icon: const Icon(Icons.camera_alt),
|
||||
label: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
localizations.permissionsRequiredPageGrantCameraPermission,
|
||||
),
|
||||
if (hasGrantedCameraPermission) const Icon(Icons.check),
|
||||
if (!hasGrantedCameraPermission) const SizedBox(),
|
||||
],
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.photoCamera),
|
||||
label: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
localizations.permissionsRequiredPageGrantCameraPermission,
|
||||
),
|
||||
if (hasGrantedCameraPermission)
|
||||
Icon(context.platformIcons.checkMark),
|
||||
if (!hasGrantedCameraPermission) const SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: MEDIUM_SPACE),
|
||||
TextButton.icon(
|
||||
PlatformTextButton(
|
||||
onPressed: hasGrantedMicrophonePermission
|
||||
? null
|
||||
: () async {
|
||||
await Permission.microphone.request();
|
||||
await checkPermissions();
|
||||
},
|
||||
icon: const Icon(Icons.mic),
|
||||
label: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
localizations
|
||||
.permissionsRequiredPageGrantMicrophonePermission,
|
||||
),
|
||||
if (hasGrantedMicrophonePermission) const Icon(Icons.check),
|
||||
if (!hasGrantedMicrophonePermission) const SizedBox(),
|
||||
],
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.mic),
|
||||
label: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
localizations
|
||||
.permissionsRequiredPageGrantMicrophonePermission,
|
||||
),
|
||||
if (hasGrantedMicrophonePermission)
|
||||
Icon(context.platformIcons.checkMark),
|
||||
if (!hasGrantedMicrophonePermission) const SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -1,16 +1,19 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.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/extensions/snackbar.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/utils/loadable.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
final supabase = Supabase.instance.client;
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
static const ID = 'login';
|
||||
static const ID = '/login';
|
||||
|
||||
const LoginScreen({Key? key}) : super(key: key);
|
||||
|
||||
@ -85,10 +88,9 @@ class _LoginScreenState extends AuthState<LoginScreen> with Loadable {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
return PlatformScaffold(
|
||||
appBar: PlatformAppBar(
|
||||
title: Text(localizations.loginScreenTitle),
|
||||
),
|
||||
body: Padding(
|
||||
@ -99,38 +101,63 @@ class _LoginScreenState extends AuthState<LoginScreen> with Loadable {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
localizations.loginScreenTitle,
|
||||
style: theme.textTheme.headline1,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.headline1,
|
||||
cupertino: (data) => data.textTheme.navLargeTitleTextStyle,
|
||||
),
|
||||
),
|
||||
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),
|
||||
TextField(
|
||||
PlatformTextField(
|
||||
controller: emailController,
|
||||
autofocus: true,
|
||||
autofillHints: const [AutofillHints.email],
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
textInputAction: TextInputAction.next,
|
||||
decoration: InputDecoration(
|
||||
labelText: localizations.loginScreenFormEmailLabel,
|
||||
prefixIcon: const Icon(Icons.email),
|
||||
material: (_, __) => MaterialTextFieldData(
|
||||
decoration: InputDecoration(
|
||||
labelText: localizations.loginScreenFormEmailLabel,
|
||||
prefixIcon: Icon(context.platformIcons.mail),
|
||||
),
|
||||
),
|
||||
cupertino: (_, __) => CupertinoTextFieldData(
|
||||
placeholder: localizations.loginScreenFormEmailLabel,
|
||||
prefix: Icon(context.platformIcons.mail),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: SMALL_SPACE),
|
||||
TextField(
|
||||
PlatformTextField(
|
||||
obscureText: true,
|
||||
controller: passwordController,
|
||||
decoration: InputDecoration(
|
||||
labelText: localizations.loginScreenFormPasswordLabel,
|
||||
prefixIcon: const Icon(Icons.lock),
|
||||
material: (_, __) => MaterialTextFieldData(
|
||||
decoration: InputDecoration(
|
||||
labelText: localizations.loginScreenFormPasswordLabel,
|
||||
prefixIcon: Icon(context.platformIcons.padLock),
|
||||
),
|
||||
),
|
||||
cupertino: (_, __) => CupertinoTextFieldData(
|
||||
placeholder: localizations.loginScreenFormPasswordLabel,
|
||||
prefix: Icon(context.platformIcons.padLock),
|
||||
),
|
||||
onSubmitted: (value) => callWithLoading(signIn),
|
||||
),
|
||||
const SizedBox(height: MEDIUM_SPACE),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.arrow_right),
|
||||
label: Text(localizations.loginScreenFormSubmitButton),
|
||||
PlatformElevatedButton(
|
||||
onPressed: isLoading ? null : () => callWithLoading(signIn),
|
||||
)
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.forward),
|
||||
label: Text(localizations.loginScreenFormSubmitButton),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -5,6 +5,7 @@ import 'package:camera/camera.dart';
|
||||
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
|
||||
import 'package:flutter/material.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/values.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';
|
||||
|
||||
class MainScreen extends StatefulWidget {
|
||||
static const ID = 'main';
|
||||
static const ID = '/main';
|
||||
|
||||
const MainScreen({Key? key}) : super(key: key);
|
||||
|
||||
@ -63,7 +64,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
onNewCameraSelected(GlobalValuesManager.cameras[0]);
|
||||
loadCameras();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -77,6 +78,12 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
_updateCamera(state);
|
||||
}
|
||||
|
||||
Future<void> loadCameras() async {
|
||||
GlobalValuesManager.setCameras(await availableCameras());
|
||||
|
||||
onNewCameraSelected(GlobalValuesManager.cameras[0]);
|
||||
}
|
||||
|
||||
void _updateCamera(final AppLifecycleState state) {
|
||||
final CameraController? cameraController = controller;
|
||||
|
||||
@ -125,6 +132,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
});
|
||||
|
||||
await controller!.initialize();
|
||||
await controller!.prepareForVideoRecording();
|
||||
|
||||
await determineZoomLevels();
|
||||
|
||||
@ -165,31 +173,34 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
});
|
||||
|
||||
try {
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakePhotoActionTakingPhoto,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakePhotoActionTakingPhoto,
|
||||
);
|
||||
|
||||
controller!.setFlashMode(FlashMode.off);
|
||||
final file = File((await controller!.takePicture()).path);
|
||||
|
||||
setState(() {
|
||||
uploadingPhotoAnimation = file.readAsBytesSync();
|
||||
});
|
||||
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakePhotoActionUploadingPhoto,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakePhotoActionUploadingPhoto,
|
||||
);
|
||||
|
||||
try {
|
||||
await FileManager.uploadFile(_user, file);
|
||||
} catch (error) {
|
||||
context.showErrorSnackBar(message: error.toString());
|
||||
if (isMaterial(context))
|
||||
context.showErrorSnackBar(message: error.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
context.showSuccessSnackBar(
|
||||
message: localizations.mainScreenUploadSuccess,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showSuccessSnackBar(
|
||||
message: localizations.mainScreenUploadSuccess,
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
lockCamera = false;
|
||||
@ -215,28 +226,31 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
});
|
||||
|
||||
try {
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakeVideoActionSaveVideo,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakeVideoActionSaveVideo,
|
||||
);
|
||||
|
||||
final file = File((await controller!.stopVideoRecording()).path);
|
||||
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakeVideoActionUploadingVideo,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showPendingSnackBar(
|
||||
message: localizations.mainScreenTakeVideoActionUploadingVideo,
|
||||
);
|
||||
|
||||
try {
|
||||
await FileManager.uploadFile(_user, file);
|
||||
} catch (error) {
|
||||
if (mounted) {
|
||||
if (isMaterial(context)) {
|
||||
context.showErrorSnackBar(message: error.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
context.showSuccessSnackBar(
|
||||
message: localizations.mainScreenUploadSuccess,
|
||||
);
|
||||
if (isMaterial(context))
|
||||
context.showSuccessSnackBar(
|
||||
message: localizations.mainScreenUploadSuccess,
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
lockCamera = false;
|
||||
@ -248,18 +262,25 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return Scaffold(
|
||||
return PlatformScaffold(
|
||||
backgroundColor: Colors.black,
|
||||
bottomSheet: () {
|
||||
body: () {
|
||||
if (isLoading) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const CircularProgressIndicator(),
|
||||
PlatformCircularProgressIndicator(),
|
||||
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(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: MEDIUM_SPACE,
|
||||
horizontal: MEDIUM_SPACE,
|
||||
),
|
||||
child: SheetIndicator(),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(LARGE_SPACE),
|
||||
padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
FadeAndMoveInAnimation(
|
||||
translationDuration: DEFAULT_TRANSLATION_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
child: ChangeCameraButton(
|
||||
disabled: lockCamera,
|
||||
onChangeCamera: () {
|
||||
final currentCameraIndex = GlobalValuesManager
|
||||
.cameras
|
||||
.indexOf(controller!.description);
|
||||
final availableCameras =
|
||||
GlobalValuesManager.cameras.length;
|
||||
Expanded(
|
||||
child: FadeAndMoveInAnimation(
|
||||
translationDuration: DEFAULT_TRANSLATION_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
child: ChangeCameraButton(
|
||||
disabled: lockCamera,
|
||||
onChangeCamera: () {
|
||||
final currentCameraIndex = GlobalValuesManager
|
||||
.cameras
|
||||
.indexOf(controller!.description);
|
||||
final availableCameras =
|
||||
GlobalValuesManager.cameras.length;
|
||||
|
||||
onNewCameraSelected(
|
||||
GlobalValuesManager.cameras[
|
||||
(currentCameraIndex + 1) %
|
||||
availableCameras],
|
||||
);
|
||||
},
|
||||
onNewCameraSelected(
|
||||
GlobalValuesManager.cameras[
|
||||
(currentCameraIndex + 1) %
|
||||
availableCameras],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
FadeAndMoveInAnimation(
|
||||
child: RecordButton(
|
||||
disabled: lockCamera,
|
||||
active: isRecording,
|
||||
onVideoBegin: () async {
|
||||
setState(() {
|
||||
isRecording = true;
|
||||
});
|
||||
Expanded(
|
||||
child: FadeAndMoveInAnimation(
|
||||
child: RecordButton(
|
||||
disabled: lockCamera,
|
||||
active: isRecording,
|
||||
onVideoBegin: () async {
|
||||
setState(() {
|
||||
isRecording = true;
|
||||
});
|
||||
|
||||
if (controller!.value.isRecordingVideo) {
|
||||
// A recording has already started, do nothing.
|
||||
return;
|
||||
}
|
||||
if (controller!.value.isRecordingVideo) {
|
||||
// A recording has already started, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
await controller!.startVideoRecording();
|
||||
},
|
||||
onVideoEnd: takeVideo,
|
||||
onPhotoShot: takePhoto,
|
||||
await controller!.startVideoRecording();
|
||||
},
|
||||
onVideoEnd: takeVideo,
|
||||
onPhotoShot: takePhoto,
|
||||
),
|
||||
),
|
||||
),
|
||||
FadeAndMoveInAnimation(
|
||||
translationDuration: DEFAULT_TRANSLATION_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
child: TodayPhotoButton(
|
||||
onLeave: () {
|
||||
controller!.setFlashMode(FlashMode.off);
|
||||
},
|
||||
onComeBack: () {
|
||||
if (isTorchEnabled) {
|
||||
controller!.setFlashMode(FlashMode.torch);
|
||||
}
|
||||
},
|
||||
Expanded(
|
||||
child: FadeAndMoveInAnimation(
|
||||
translationDuration: DEFAULT_TRANSLATION_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
child: TodayPhotoButton(
|
||||
onLeave: () {
|
||||
controller!.setFlashMode(FlashMode.off);
|
||||
},
|
||||
onComeBack: () {
|
||||
if (isTorchEnabled) {
|
||||
controller!.setFlashMode(FlashMode.torch);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -378,69 +410,76 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
],
|
||||
),
|
||||
),
|
||||
expandableContent: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: LARGE_SPACE,
|
||||
right: LARGE_SPACE,
|
||||
bottom: MEDIUM_SPACE,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.flashlight_on_rounded),
|
||||
label: Text(AppLocalizations.of(context)!
|
||||
.mainScreenActionsTorchButton),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(_) => isTorchEnabled ? Colors.white : Colors.black,
|
||||
),
|
||||
foregroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(_) => isTorchEnabled ? Colors.black : Colors.white,
|
||||
expandableContent: Container(
|
||||
color: Colors.black,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: LARGE_SPACE,
|
||||
right: LARGE_SPACE,
|
||||
bottom: MEDIUM_SPACE,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.flashlight_on_rounded),
|
||||
label: Text(AppLocalizations.of(context)!
|
||||
.mainScreenActionsTorchButton),
|
||||
style: ButtonStyle(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.resolveWith<Color>(
|
||||
(_) => 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: () {
|
||||
setState(() {
|
||||
isTorchEnabled = !isTorchEnabled;
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
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!.setFlashMode(FlashMode.torch);
|
||||
} else {
|
||||
controller!.setFlashMode(FlashMode.off);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(_) => Colors.white10,
|
||||
),
|
||||
foregroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||
(_) => Colors.white,
|
||||
),
|
||||
controller!
|
||||
.setZoomLevel(zoomLevels![newZoomLevelIndex]);
|
||||
|
||||
setState(() {
|
||||
currentZoomLevelIndex = newZoomLevelIndex;
|
||||
});
|
||||
},
|
||||
child: zoomLevels == null
|
||||
? const Text('1x')
|
||||
: Text(
|
||||
formatZoomLevel(currentZoomLevel),
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
|
||||
class ChangeCameraButton extends StatelessWidget {
|
||||
final VoidCallback onChangeCamera;
|
||||
@ -13,9 +14,7 @@ class ChangeCameraButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
enableFeedback: false,
|
||||
highlightColor: Colors.transparent,
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (disabled) {
|
||||
return;
|
||||
@ -34,9 +33,9 @@ class ChangeCameraButton extends StatelessWidget {
|
||||
size: 60,
|
||||
color: Colors.white.withOpacity(.2),
|
||||
),
|
||||
const Icon(
|
||||
Icons.camera_alt,
|
||||
size: 30,
|
||||
Icon(
|
||||
context.platformIcons.switchCamera,
|
||||
size: 25,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
|
@ -28,6 +28,17 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
bool animateToVideoIcon = false;
|
||||
bool videoInAnimationActive = false;
|
||||
|
||||
void cancelAnimation() {
|
||||
if (videoInAnimationActive || animateToVideoIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
@ -57,6 +68,7 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
animateToVideoIcon = false;
|
||||
videoInAnimationActive = true;
|
||||
});
|
||||
|
||||
@ -96,69 +108,69 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
});
|
||||
},
|
||||
// Cancel icon animation
|
||||
onTapCancel: () {
|
||||
if (videoInAnimationActive || animateToVideoIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
},
|
||||
// Cancel icon animation
|
||||
onPanCancel: () {
|
||||
if (videoInAnimationActive || animateToVideoIcon) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
},
|
||||
onTapCancel: cancelAnimation,
|
||||
onPanCancel: cancelAnimation,
|
||||
onLongPressCancel: cancelAnimation,
|
||||
child: Opacity(
|
||||
opacity: widget.disabled ? 0.5 : 1.0,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.circle,
|
||||
size: 75,
|
||||
color: Colors.white.withOpacity(.2),
|
||||
),
|
||||
AnimatedScale(
|
||||
duration: animateToVideoIcon ? kLongPressTimeout : OUT_DURATION,
|
||||
curve: Curves.easeInOut,
|
||||
scale: animateToVideoIcon ? (75 / 50) : 1,
|
||||
child: const Icon(
|
||||
Icons.circle,
|
||||
size: 50,
|
||||
color: Colors.white,
|
||||
AnimatedContainer(
|
||||
duration: videoInAnimationActive ? Duration.zero : OUT_DURATION,
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: videoInAnimationActive
|
||||
? Colors.white
|
||||
: Colors.white.withOpacity(.2),
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
),
|
||||
AnimatedScale(
|
||||
duration: () {
|
||||
if (videoInAnimationActive) {
|
||||
return Duration(milliseconds: 400);
|
||||
}
|
||||
|
||||
if (animateToVideoIcon) {
|
||||
return kLongPressTimeout;
|
||||
}
|
||||
|
||||
return OUT_DURATION;
|
||||
}(),
|
||||
curve: Curves.easeInOut,
|
||||
duration: animateToVideoIcon
|
||||
? const Duration(milliseconds: 180)
|
||||
: OUT_DURATION,
|
||||
scale: videoInAnimationActive ? 1 : 0,
|
||||
child: const Icon(
|
||||
Icons.circle,
|
||||
size: 65,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
AnimatedScale(
|
||||
curve: animateToVideoIcon ? Curves.easeOut : Curves.linear,
|
||||
duration: animateToVideoIcon
|
||||
? const Duration(milliseconds: 250)
|
||||
: OUT_DURATION,
|
||||
scale: videoInAnimationActive ? 1 : .6,
|
||||
child: const Icon(
|
||||
Icons.stop,
|
||||
size: 45,
|
||||
color: Colors.white,
|
||||
scale: () {
|
||||
if (videoInAnimationActive) {
|
||||
return .6;
|
||||
}
|
||||
|
||||
if (animateToVideoIcon) {
|
||||
return 60 / 40;
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}(),
|
||||
child: AnimatedContainer(
|
||||
duration: () {
|
||||
if (videoInAnimationActive) {
|
||||
return Duration(milliseconds: 400);
|
||||
}
|
||||
|
||||
if (animateToVideoIcon) {
|
||||
return kLongPressTimeout;
|
||||
}
|
||||
|
||||
return OUT_DURATION;
|
||||
}(),
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: videoInAnimationActive ? Colors.red : Colors.white,
|
||||
borderRadius: videoInAnimationActive
|
||||
? BorderRadius.circular(4)
|
||||
: BorderRadius.circular(50),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -70,7 +70,7 @@ class _TodayPhotoButtonState extends State<TodayPhotoButton> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
widget.onLeave();
|
||||
|
||||
@ -85,25 +85,27 @@ class _TodayPhotoButtonState extends State<TodayPhotoButton> {
|
||||
|
||||
widget.onComeBack();
|
||||
},
|
||||
child: Container(
|
||||
width: 45,
|
||||
height: 45,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.white,
|
||||
width: 2,
|
||||
child: Align(
|
||||
child: Container(
|
||||
width: 45,
|
||||
height: 45,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
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!,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.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:quid_faciam_hodie/constants/spacing.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';
|
||||
|
||||
class ServerLoadingScreen extends StatefulWidget {
|
||||
static const ID = 'server_loading';
|
||||
static const ID = '/server_loading';
|
||||
|
||||
final String? nextScreen;
|
||||
|
||||
@ -63,7 +64,11 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Icon(Icons.cloud, size: 60),
|
||||
const Icon(
|
||||
Icons.cloud,
|
||||
size: 60,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(height: SMALL_SPACE),
|
||||
const DotAnimation(
|
||||
initialFadeInDelay: Duration.zero,
|
||||
@ -87,9 +92,20 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
||||
fadeOutDelay: Duration.zero,
|
||||
),
|
||||
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),
|
||||
Text(localizations.serverLoadingScreenDescription),
|
||||
Text(
|
||||
localizations.serverLoadingScreenDescription,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText1,
|
||||
cupertino: (data) => data.textTheme.textStyle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:quid_faciam_hodie/extensions/date.dart';
|
||||
import 'package:quid_faciam_hodie/models/memories.dart';
|
||||
@ -12,7 +13,7 @@ import 'timeline_screen/timeline_page.dart';
|
||||
final supabase = Supabase.instance.client;
|
||||
|
||||
class TimelineScreen extends StatefulWidget {
|
||||
static const ID = 'timeline';
|
||||
static const ID = '/timeline';
|
||||
|
||||
final DateTime? date;
|
||||
|
||||
@ -92,7 +93,12 @@ class _TimelineScreenState extends State<TimelineScreen> with Loadable {
|
||||
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
child: PlatformScaffold(
|
||||
appBar: isCupertino(context)
|
||||
? PlatformAppBar(
|
||||
title: Text('Timeline'),
|
||||
)
|
||||
: null,
|
||||
body: ChangeNotifierProvider.value(
|
||||
value: timeline,
|
||||
child: PageView.builder(
|
||||
|
@ -3,6 +3,7 @@ import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.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/enums.dart';
|
||||
import 'package:quid_faciam_hodie/foreign_types/memory.dart';
|
||||
@ -81,14 +82,19 @@ class _MemoryViewState extends State<MemoryView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
if (status == MemoryFetchStatus.error) {
|
||||
return Center(
|
||||
child: Text(
|
||||
localizations.memoryViewDownloadFailed,
|
||||
style: theme.textTheme.bodyText2!.copyWith(
|
||||
color: Colors.white,
|
||||
style: platformThemeData(
|
||||
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,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const CircularProgressIndicator(),
|
||||
PlatformCircularProgressIndicator(),
|
||||
const SizedBox(height: SMALL_SPACE),
|
||||
() {
|
||||
switch (status) {
|
||||
case MemoryFetchStatus.downloading:
|
||||
return Text(
|
||||
localizations.memoryViewIsDownloading,
|
||||
style: theme.textTheme.bodyText2!.copyWith(
|
||||
color: Colors.white,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText2!.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
cupertino: (data) => data.textTheme.textStyle.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
);
|
||||
default:
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||
@ -18,14 +19,14 @@ class TimelineOverlay extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final timeline = context.watch<TimelineModel>();
|
||||
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: LARGE_SPACE,
|
||||
padding: EdgeInsets.only(
|
||||
// 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,
|
||||
right: MEDIUM_SPACE,
|
||||
),
|
||||
@ -36,9 +37,16 @@ class TimelineOverlay extends StatelessWidget {
|
||||
child: Text(
|
||||
DateFormat.yMMMd().format(date),
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.headline1!.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
style: platformThemeData(
|
||||
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,
|
||||
child: Icon(
|
||||
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,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: SMALL_SPACE),
|
||||
Text(
|
||||
'$memoryIndex/$memoriesAmount',
|
||||
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.titleSmall!.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
cupertino: (data) =>
|
||||
data.textTheme.navTitleTextStyle.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -1,57 +1,73 @@
|
||||
import 'package:flutter/material.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/widgets/icon_button_child.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/logo.dart';
|
||||
|
||||
import 'grant_permission_screen.dart';
|
||||
|
||||
class WelcomeScreen extends StatelessWidget {
|
||||
static const ID = 'welcome';
|
||||
static const ID = '/';
|
||||
|
||||
const WelcomeScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
return PlatformScaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Logo(),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
localizations.appTitleQuestion,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headline1,
|
||||
),
|
||||
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(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Logo(),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
localizations.appTitleQuestion,
|
||||
textAlign: TextAlign.center,
|
||||
style: platformThemeData(
|
||||
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,
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
30
lib/widgets/icon_button_child.dart
Normal file
30
lib/widgets/icon_button_child.dart
Normal 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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -158,6 +158,13 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -53,6 +53,7 @@ dependencies:
|
||||
expandable_bottom_sheet: ^1.1.1+1
|
||||
flutter_sticky_header: ^0.6.4
|
||||
flutter_calendar_widget: ^0.0.2
|
||||
flutter_platform_widgets: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user