mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 23:35:25 +02:00
added empty screen; improvements & bugfixes
This commit is contained in:
parent
927b15b63f
commit
e8c850f5f0
1
assets/lottie/flying-astronaut.json
Normal file
1
assets/lottie/flying-astronaut.json
Normal file
File diff suppressed because one or more lines are too long
@ -25,7 +25,7 @@ class Memory {
|
|||||||
creationDate: DateTime.parse(jsonData['created_at']),
|
creationDate: DateTime.parse(jsonData['created_at']),
|
||||||
location: jsonData['location'],
|
location: jsonData['location'],
|
||||||
isPublic: jsonData['is_public'],
|
isPublic: jsonData['is_public'],
|
||||||
userID: jsonData['user'],
|
userID: jsonData['user_id'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,5 +52,11 @@
|
|||||||
"memorySheetDownloadMemory": "In Gallerie speichern",
|
"memorySheetDownloadMemory": "In Gallerie speichern",
|
||||||
"memorySheetUpdateMemoryMakePublic": "Veröffentlichen",
|
"memorySheetUpdateMemoryMakePublic": "Veröffentlichen",
|
||||||
"memorySheetUpdateMemoryMakePrivate": "Privat machen",
|
"memorySheetUpdateMemoryMakePrivate": "Privat machen",
|
||||||
"memorySheetDeleteMemory": "Erinnerung löschen"
|
"memorySheetDeleteMemory": "Erinnerung löschen",
|
||||||
|
|
||||||
|
|
||||||
|
"emptyScreenTitle": "Houston, wir haben ein Problem",
|
||||||
|
"emptyScreenSubtitle": "Der Benutzer hat noch keine Erinnerungen erstellt!",
|
||||||
|
"emptyScreenDescription": "Um deinen Zeitstrahl sehen zu können musst du zuerst ein paar Erinnerungen erstellen! :)",
|
||||||
|
"emptyScreenCreateMemory": "Erinnerung erstellen"
|
||||||
}
|
}
|
@ -52,5 +52,11 @@
|
|||||||
"memorySheetDownloadMemory": "Download to Gallery",
|
"memorySheetDownloadMemory": "Download to Gallery",
|
||||||
"memorySheetUpdateMemoryMakePublic": "Make Public",
|
"memorySheetUpdateMemoryMakePublic": "Make Public",
|
||||||
"memorySheetUpdateMemoryMakePrivate": "Make Private",
|
"memorySheetUpdateMemoryMakePrivate": "Make Private",
|
||||||
"memorySheetDeleteMemory": "Delete Memory"
|
"memorySheetDeleteMemory": "Delete Memory",
|
||||||
|
|
||||||
|
|
||||||
|
"emptyScreenTitle": "Houston, we have a problem",
|
||||||
|
"emptyScreenSubtitle": "The user hasn't created any memories yet!",
|
||||||
|
"emptyScreenDescription": "To view your timeline you need to create some memories first! :)",
|
||||||
|
"emptyScreenCreateMemory": "Create a Memory"
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ import 'package:quid_faciam_hodie/screens/welcome_screen.dart';
|
|||||||
|
|
||||||
import 'managers/global_values_manager.dart';
|
import 'managers/global_values_manager.dart';
|
||||||
import 'models/memories.dart';
|
import 'models/memories.dart';
|
||||||
|
import 'screens/empty_screen.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -62,6 +63,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
GrantPermissionScreen.ID: (context) => const GrantPermissionScreen(),
|
GrantPermissionScreen.ID: (context) => const GrantPermissionScreen(),
|
||||||
CalendarScreen.ID: (context) => const CalendarScreen(),
|
CalendarScreen.ID: (context) => const CalendarScreen(),
|
||||||
ServerLoadingScreen.ID: (context) => const ServerLoadingScreen(),
|
ServerLoadingScreen.ID: (context) => const ServerLoadingScreen(),
|
||||||
|
EmptyScreen.ID: (context) => const EmptyScreen(),
|
||||||
},
|
},
|
||||||
initialRoute: ServerLoadingScreen.ID,
|
initialRoute: ServerLoadingScreen.ID,
|
||||||
),
|
),
|
||||||
|
@ -47,7 +47,7 @@ class FileManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final memoryResponse = await supabase.from('memories').insert({
|
final memoryResponse = await supabase.from('memories').insert({
|
||||||
'user': user.id,
|
'user_id': user.id,
|
||||||
'location': path,
|
'location': path,
|
||||||
}).execute();
|
}).execute();
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class FileManager {
|
|||||||
final response = await supabase
|
final response = await supabase
|
||||||
.from('memories')
|
.from('memories')
|
||||||
.select()
|
.select()
|
||||||
.eq('user', user.id)
|
.eq('user_id', user.id)
|
||||||
.order('created_at', ascending: false)
|
.order('created_at', ascending: false)
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.single()
|
.single()
|
||||||
|
@ -39,7 +39,6 @@ class Memories extends PropertyChangeNotifier<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void removeMemoryByID(final String id) {
|
void removeMemoryByID(final String id) {
|
||||||
print("remooooooved");
|
|
||||||
_memories.removeWhere((memory) => memory.id == id);
|
_memories.removeWhere((memory) => memory.id == id);
|
||||||
notifyListeners('memories');
|
notifyListeners('memories');
|
||||||
}
|
}
|
||||||
@ -93,8 +92,9 @@ class Memories extends PropertyChangeNotifier<String> {
|
|||||||
final memory = Memory.parse(response.newRecord!);
|
final memory = Memory.parse(response.newRecord!);
|
||||||
final id = response.oldRecord!['id'];
|
final id = response.oldRecord!['id'];
|
||||||
|
|
||||||
removeMemoryByID(id);
|
_memories.removeWhere((memory) => memory.id == id);
|
||||||
addMemory(memory);
|
memories.add(memory);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
lib/screens/empty_screen.dart
Normal file
68
lib/screens/empty_screen.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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:lottie/lottie.dart';
|
||||||
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
|
import 'package:quid_faciam_hodie/screens/main_screen.dart';
|
||||||
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
|
|
||||||
|
import '../widgets/icon_button_child.dart';
|
||||||
|
|
||||||
|
class EmptyScreen extends StatelessWidget {
|
||||||
|
static const ID = '/empty';
|
||||||
|
|
||||||
|
const EmptyScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final localizations = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
|
return PlatformScaffold(
|
||||||
|
body: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Lottie.asset('assets/lottie/flying-astronaut.json'),
|
||||||
|
const SizedBox(height: LARGE_SPACE),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
localizations.emptyScreenTitle,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: getTitleTextStyle(context),
|
||||||
|
),
|
||||||
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
|
Text(
|
||||||
|
localizations.emptyScreenSubtitle,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: getSubTitleTextStyle(context),
|
||||||
|
),
|
||||||
|
const SizedBox(height: SMALL_SPACE),
|
||||||
|
Text(
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
localizations.emptyScreenDescription,
|
||||||
|
style: getBodyTextTextStyle(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
|
PlatformElevatedButton(
|
||||||
|
child: IconButtonChild(
|
||||||
|
icon: Icon(context.platformIcons.back),
|
||||||
|
label: Text(localizations.emptyScreenCreateMemory),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pushNamedAndRemoveUntil(
|
||||||
|
context, MainScreen.ID, (_) => false);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
|||||||
import 'package:camera/camera.dart';
|
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/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:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
@ -270,233 +271,244 @@ 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 PlatformScaffold(
|
return WillPopScope(
|
||||||
backgroundColor: Colors.black,
|
onWillPop: () async {
|
||||||
body: () {
|
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
||||||
if (isLoading) {
|
SystemNavigator.pop();
|
||||||
return Center(
|
exit(0);
|
||||||
child: Column(
|
},
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: PlatformScaffold(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
backgroundColor: Colors.black,
|
||||||
children: <Widget>[
|
body: () {
|
||||||
PlatformCircularProgressIndicator(),
|
if (isLoading) {
|
||||||
const SizedBox(height: MEDIUM_SPACE),
|
return Center(
|
||||||
Text(
|
|
||||||
localizations.mainScreenLoadingCamera,
|
|
||||||
style: platformThemeData(
|
|
||||||
context,
|
|
||||||
material: (data) => data.textTheme.bodyText1,
|
|
||||||
cupertino: (data) => data.textTheme.textStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
color: Colors.black,
|
|
||||||
child: ExpandableBottomSheet(
|
|
||||||
background: SafeArea(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: AnimateInBuilder(
|
|
||||||
builder: (showPreview) => AnimatedOpacity(
|
|
||||||
opacity: showPreview ? 1.0 : 0.0,
|
|
||||||
duration: const Duration(milliseconds: 1100),
|
|
||||||
curve: Curves.easeOutQuad,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(SMALL_SPACE),
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1 / controller!.value.aspectRatio,
|
|
||||||
child: Stack(
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: <Widget>[
|
|
||||||
controller!.buildPreview(),
|
|
||||||
if (isRecording)
|
|
||||||
RecordingOverlay(controller: controller!),
|
|
||||||
if (uploadingPhotoAnimation != null)
|
|
||||||
UploadingPhoto(
|
|
||||||
data: uploadingPhotoAnimation!,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
persistentHeader: Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: Colors.black,
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(LARGE_SPACE),
|
|
||||||
topRight: Radius.circular(LARGE_SPACE),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
const Padding(
|
PlatformCircularProgressIndicator(),
|
||||||
padding: EdgeInsets.symmetric(
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
vertical: MEDIUM_SPACE,
|
Text(
|
||||||
horizontal: MEDIUM_SPACE,
|
localizations.mainScreenLoadingCamera,
|
||||||
),
|
style: platformThemeData(
|
||||||
child: SheetIndicator(),
|
context,
|
||||||
),
|
material: (data) => data.textTheme.bodyText1,
|
||||||
Padding(
|
cupertino: (data) => data.textTheme.textStyle,
|
||||||
padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: FadeAndMoveInAnimation(
|
|
||||||
translationDuration: DEFAULT_TRANSLATION_DURATION *
|
|
||||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
|
||||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
|
||||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
|
||||||
child: ChangeCameraButton(
|
|
||||||
disabled: lockCamera || isRecording,
|
|
||||||
onChangeCamera: () {
|
|
||||||
final currentCameraIndex = GlobalValuesManager
|
|
||||||
.cameras
|
|
||||||
.indexOf(controller!.description);
|
|
||||||
final availableCameras =
|
|
||||||
GlobalValuesManager.cameras.length;
|
|
||||||
|
|
||||||
onNewCameraSelected(
|
|
||||||
GlobalValuesManager.cameras[
|
|
||||||
(currentCameraIndex + 1) %
|
|
||||||
availableCameras],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
await controller!.startVideoRecording();
|
|
||||||
},
|
|
||||||
onVideoEnd: takeVideo,
|
|
||||||
onPhotoShot: takePhoto,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
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(
|
|
||||||
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) {
|
return Container(
|
||||||
controller!.setFlashMode(FlashMode.torch);
|
color: Colors.black,
|
||||||
} else {
|
child: ExpandableBottomSheet(
|
||||||
controller!.setFlashMode(FlashMode.off);
|
background: SafeArea(
|
||||||
}
|
child: Align(
|
||||||
});
|
alignment: Alignment.topCenter,
|
||||||
},
|
child: AnimateInBuilder(
|
||||||
child: IconButtonChild(
|
builder: (showPreview) => AnimatedOpacity(
|
||||||
icon: const Icon(Icons.flashlight_on_rounded),
|
opacity: showPreview ? 1.0 : 0.0,
|
||||||
label: Text(localizations.mainScreenActionsTorchButton),
|
duration: const Duration(milliseconds: 1100),
|
||||||
|
curve: Curves.easeOutQuad,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(SMALL_SPACE),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1 / controller!.value.aspectRatio,
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: <Widget>[
|
||||||
|
controller!.buildPreview(),
|
||||||
|
if (isRecording)
|
||||||
|
RecordingOverlay(controller: controller!),
|
||||||
|
if (uploadingPhotoAnimation != null)
|
||||||
|
UploadingPhoto(
|
||||||
|
data: uploadingPhotoAnimation!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
),
|
||||||
style: ButtonStyle(
|
),
|
||||||
backgroundColor:
|
),
|
||||||
MaterialStateProperty.resolveWith<Color>(
|
persistentHeader: Container(
|
||||||
(_) => Colors.white10,
|
decoration: const BoxDecoration(
|
||||||
),
|
color: Colors.black,
|
||||||
foregroundColor:
|
borderRadius: BorderRadius.only(
|
||||||
MaterialStateProperty.resolveWith<Color>(
|
topLeft: Radius.circular(LARGE_SPACE),
|
||||||
(_) => Colors.white,
|
topRight: Radius.circular(LARGE_SPACE),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: MEDIUM_SPACE,
|
||||||
|
horizontal: MEDIUM_SPACE,
|
||||||
),
|
),
|
||||||
onPressed: zoomLevels == null
|
child: SheetIndicator(),
|
||||||
? null
|
),
|
||||||
: () {
|
Padding(
|
||||||
final newZoomLevelIndex =
|
padding:
|
||||||
((currentZoomLevelIndex + 1) %
|
const EdgeInsets.symmetric(vertical: SMALL_SPACE),
|
||||||
zoomLevels!.length);
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: FadeAndMoveInAnimation(
|
||||||
|
translationDuration:
|
||||||
|
DEFAULT_TRANSLATION_DURATION *
|
||||||
|
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||||
|
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||||
|
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||||
|
child: ChangeCameraButton(
|
||||||
|
disabled: lockCamera || isRecording,
|
||||||
|
onChangeCamera: () {
|
||||||
|
final currentCameraIndex = GlobalValuesManager
|
||||||
|
.cameras
|
||||||
|
.indexOf(controller!.description);
|
||||||
|
final availableCameras =
|
||||||
|
GlobalValuesManager.cameras.length;
|
||||||
|
|
||||||
controller!
|
onNewCameraSelected(
|
||||||
.setZoomLevel(zoomLevels![newZoomLevelIndex]);
|
GlobalValuesManager.cameras[
|
||||||
|
(currentCameraIndex + 1) %
|
||||||
setState(() {
|
availableCameras],
|
||||||
currentZoomLevelIndex = newZoomLevelIndex;
|
);
|
||||||
});
|
},
|
||||||
},
|
),
|
||||||
child: zoomLevels == null
|
|
||||||
? const Text('1x')
|
|
||||||
: Text(
|
|
||||||
formatZoomLevel(currentZoomLevel),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
await controller!.startVideoRecording();
|
||||||
|
},
|
||||||
|
onVideoEnd: takeVideo,
|
||||||
|
onPhotoShot: takePhoto,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
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(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: IconButtonChild(
|
||||||
|
icon: const Icon(Icons.flashlight_on_rounded),
|
||||||
|
label:
|
||||||
|
Text(localizations.mainScreenActionsTorchButton),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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);
|
||||||
|
|
||||||
|
controller!.setZoomLevel(
|
||||||
|
zoomLevels![newZoomLevelIndex]);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
currentZoomLevelIndex = newZoomLevelIndex;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: zoomLevels == null
|
||||||
|
? const Text('1x')
|
||||||
|
: Text(
|
||||||
|
formatZoomLevel(currentZoomLevel),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}(),
|
||||||
}(),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,14 @@ class _TodayPhotoButtonState extends State<TodayPhotoButton> {
|
|||||||
|
|
||||||
final memories = context.read<Memories>();
|
final memories = context.read<Memories>();
|
||||||
|
|
||||||
|
if (memories.memories.isEmpty) {
|
||||||
|
setState(() {
|
||||||
|
data = null;
|
||||||
|
type = null;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final lastMemory = memories.memories.first;
|
final lastMemory = memories.memories.first;
|
||||||
|
|
||||||
final file = await lastMemory.downloadToFile();
|
final file = await lastMemory.downloadToFile();
|
||||||
|
@ -7,12 +7,13 @@ import 'package:quid_faciam_hodie/managers/global_values_manager.dart';
|
|||||||
import 'package:quid_faciam_hodie/models/memories.dart';
|
import 'package:quid_faciam_hodie/models/memories.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
|
import 'empty_screen.dart';
|
||||||
import 'main_screen.dart';
|
import 'main_screen.dart';
|
||||||
import 'server_loading_screen/dot_animation.dart';
|
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 = '/';
|
||||||
|
|
||||||
final String? nextScreen;
|
final String? nextScreen;
|
||||||
|
|
||||||
@ -44,12 +45,29 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
|||||||
await memories.initialize();
|
await memories.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (widget.nextScreen == null) {
|
||||||
|
Navigator.pushNamed(
|
||||||
|
context,
|
||||||
|
MainScreen.ID,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (memories.memories.isEmpty) {
|
||||||
|
Navigator.pushReplacementNamed(
|
||||||
|
context,
|
||||||
|
EmptyScreen.ID,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.pushReplacementNamed(
|
||||||
|
context,
|
||||||
|
widget.nextScreen!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushReplacementNamed(
|
||||||
context,
|
context,
|
||||||
widget.nextScreen ?? MainScreen.ID,
|
WelcomeScreen.ID,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
Navigator.pushReplacementNamed(context, WelcomeScreen.ID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import 'package:quid_faciam_hodie/utils/loadable.dart';
|
|||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
import 'calendar_screen.dart';
|
import 'calendar_screen.dart';
|
||||||
|
import 'empty_screen.dart';
|
||||||
import 'timeline_screen/timeline_page.dart';
|
import 'timeline_screen/timeline_page.dart';
|
||||||
|
|
||||||
final supabase = Supabase.instance.client;
|
final supabase = Supabase.instance.client;
|
||||||
@ -49,6 +50,18 @@ class _TimelineScreenState extends State<TimelineScreen> with Loadable {
|
|||||||
timeline.setCurrentIndex(initialIndex);
|
timeline.setCurrentIndex(initialIndex);
|
||||||
|
|
||||||
memoriesModel.addListener(() {
|
memoriesModel.addListener(() {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memoriesModel.memories.isEmpty) {
|
||||||
|
Navigator.pushReplacementNamed(
|
||||||
|
context,
|
||||||
|
EmptyScreen.ID,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
timeline.refresh(memoriesModel.memories);
|
timeline.refresh(memoriesModel.memories);
|
||||||
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
@ -8,7 +8,7 @@ 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 = '/';
|
static const ID = '/welcome';
|
||||||
|
|
||||||
const WelcomeScreen({Key? key}) : super(key: key);
|
const WelcomeScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class WelcomeScreen extends StatelessWidget {
|
|||||||
label: Text(localizations.welcomeScreenStartButtonTitle),
|
label: Text(localizations.welcomeScreenStartButtonTitle),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
GrantPermissionScreen.ID,
|
GrantPermissionScreen.ID,
|
||||||
);
|
);
|
||||||
|
@ -55,6 +55,13 @@ class _FadeAndMoveInAnimationState extends State<FadeAndMoveInAnimation>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
translationController.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
14
pubspec.lock
14
pubspec.lock
@ -1,6 +1,13 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.3.1"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -329,6 +336,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
lottie:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: lottie
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.1"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -54,6 +54,7 @@ dependencies:
|
|||||||
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
|
flutter_platform_widgets: ^2.0.0
|
||||||
|
lottie: ^1.4.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -80,6 +81,7 @@ flutter:
|
|||||||
|
|
||||||
assets:
|
assets:
|
||||||
- assets/
|
- assets/
|
||||||
|
- assets/lottie/flying-astronaut.json
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user