mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-19 07:35:26 +02:00
improved settings & grant permission screens for iOS
This commit is contained in:
parent
1a6174bcd4
commit
e58462c313
@ -1,7 +1,13 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- Alamofire (5.6.2)
|
||||||
- camera_avfoundation (0.0.1):
|
- camera_avfoundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_osm_plugin (0.0.1):
|
||||||
|
- Alamofire
|
||||||
|
- Flutter
|
||||||
|
- Polyline
|
||||||
|
- Tangram-es
|
||||||
- flutter_secure_storage (3.3.1):
|
- flutter_secure_storage (3.3.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- fluttertoast (0.0.2):
|
- fluttertoast (0.0.2):
|
||||||
@ -9,10 +15,14 @@ PODS:
|
|||||||
- Toast
|
- Toast
|
||||||
- gallery_saver (0.0.1):
|
- gallery_saver (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- location (0.0.1):
|
||||||
|
- Flutter
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- permission_handler_apple (9.0.4):
|
- permission_handler_apple (9.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- Polyline (5.0.2)
|
||||||
|
- Tangram-es (0.17.1)
|
||||||
- Toast (4.0.0)
|
- Toast (4.0.0)
|
||||||
- uni_links (0.0.1):
|
- uni_links (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -24,9 +34,11 @@ PODS:
|
|||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_osm_plugin (from `.symlinks/plugins/flutter_osm_plugin/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
- gallery_saver (from `.symlinks/plugins/gallery_saver/ios`)
|
- gallery_saver (from `.symlinks/plugins/gallery_saver/ios`)
|
||||||
|
- location (from `.symlinks/plugins/location/ios`)
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||||
@ -35,6 +47,9 @@ DEPENDENCIES:
|
|||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
|
- Alamofire
|
||||||
|
- Polyline
|
||||||
|
- Tangram-es
|
||||||
- Toast
|
- Toast
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
@ -42,12 +57,16 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/camera_avfoundation/ios"
|
:path: ".symlinks/plugins/camera_avfoundation/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_osm_plugin:
|
||||||
|
:path: ".symlinks/plugins/flutter_osm_plugin/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
fluttertoast:
|
fluttertoast:
|
||||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||||
gallery_saver:
|
gallery_saver:
|
||||||
:path: ".symlinks/plugins/gallery_saver/ios"
|
:path: ".symlinks/plugins/gallery_saver/ios"
|
||||||
|
location:
|
||||||
|
:path: ".symlinks/plugins/location/ios"
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
@ -60,18 +79,23 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
Alamofire: d368e1ff8a298e6dde360e35a3e68e6c610e7204
|
||||||
camera_avfoundation: 07c77549ea54ad95d8581be86617c094a46280d9
|
camera_avfoundation: 07c77549ea54ad95d8581be86617c094a46280d9
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
|
flutter_osm_plugin: f06ae1e854af57270c61ae27bdb8a386cfd4afa5
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
|
fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
|
||||||
gallery_saver: 9fc173c9f4fcc48af53b2a9ebea1b643255be542
|
gallery_saver: 9fc173c9f4fcc48af53b2a9ebea1b643255be542
|
||||||
|
location: 3a2eed4dd2fab25e7b7baf2a9efefe82b512d740
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||||
|
Polyline: fce41d72e1146c41c6d081f7656827226f643dff
|
||||||
|
Tangram-es: 628b634f7fc09d2217469b9914de00d9de49ff9d
|
||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
||||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
||||||
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
||||||
|
|
||||||
PODFILE CHECKSUM: 844e8fbcd0235060f60f771d03577fc655617b90
|
PODFILE CHECKSUM: c1e56e861085e01c426a686306e59660903e6fa6
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.11.3
|
||||||
|
@ -75,5 +75,8 @@
|
|||||||
|
|
||||||
<key>NSLocationUsageDescription</key>
|
<key>NSLocationUsageDescription</key>
|
||||||
<string>Accessing your location allows you to tag your memories</string>
|
<string>Accessing your location allows you to tag your memories</string>
|
||||||
|
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string>Accessing your location allows you to tag your memories</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -3,6 +3,7 @@ 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';
|
||||||
import 'package:quid_faciam_hodie/screens/login_screen.dart';
|
import 'package:quid_faciam_hodie/screens/login_screen.dart';
|
||||||
|
import 'package:quid_faciam_hodie/screens/server_loading_screen.dart';
|
||||||
|
|
||||||
import 'grant_permission_screen/permissions_required_page.dart';
|
import 'grant_permission_screen/permissions_required_page.dart';
|
||||||
|
|
||||||
@ -24,7 +25,14 @@ class GrantPermissionScreen extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: PermissionsRequiredPage(
|
child: PermissionsRequiredPage(
|
||||||
onPermissionsGranted: () {
|
onPermissionsGranted: () {
|
||||||
Navigator.pushReplacementNamed(context, LoginScreen.ID);
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const ServerLoadingScreen(
|
||||||
|
nextScreen: LoginScreen.ID,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -156,7 +156,7 @@ class _PermissionsRequiredPageState extends State<PermissionsRequiredPage> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
localizations
|
localizations
|
||||||
.permissionsRequiredPageGrantMicrophonePermission,
|
.permissionsRequiredPageGrantLocationPermission,
|
||||||
),
|
),
|
||||||
if (hasGrantedLocationPermission)
|
if (hasGrantedLocationPermission)
|
||||||
Icon(context.platformIcons.checkMark),
|
Icon(context.platformIcons.checkMark),
|
||||||
|
@ -219,10 +219,12 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
|||||||
|
|
||||||
LocationData? locationData;
|
LocationData? locationData;
|
||||||
|
|
||||||
if (Platform.isAndroid && (await Permission.location.isGranted)) {
|
if (await Permission.location.isGranted) {
|
||||||
locationData = await Location().getLocation();
|
locationData = await Location().getLocation();
|
||||||
|
|
||||||
await tagLocationToImage(file, locationData);
|
if (Platform.isAndroid) {
|
||||||
|
await tagLocationToImage(file, locationData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -48,7 +48,12 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
|||||||
final memories = context.read<Memories>();
|
final memories = context.read<Memories>();
|
||||||
final session = Supabase.instance.client.auth.session();
|
final session = Supabase.instance.client.auth.session();
|
||||||
|
|
||||||
if (session != null) {
|
if (session == null) {
|
||||||
|
Navigator.pushReplacementNamed(
|
||||||
|
context,
|
||||||
|
WelcomeScreen.ID,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
if (!memories.isInitialized) {
|
if (!memories.isInitialized) {
|
||||||
await memories.initialize();
|
await memories.initialize();
|
||||||
}
|
}
|
||||||
@ -58,7 +63,7 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (widget.nextScreen == null) {
|
if (widget.nextScreen == null) {
|
||||||
Navigator.pushNamed(
|
Navigator.pushReplacementNamed(
|
||||||
context,
|
context,
|
||||||
MainScreen.ID,
|
MainScreen.ID,
|
||||||
);
|
);
|
||||||
@ -75,11 +80,6 @@ class _ServerLoadingScreenState extends State<ServerLoadingScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Navigator.pushReplacementNamed(
|
|
||||||
context,
|
|
||||||
WelcomeScreen.ID,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import 'package:quid_faciam_hodie/screens/welcome_screen.dart';
|
|||||||
import 'package:quid_faciam_hodie/utils/auth_required.dart';
|
import 'package:quid_faciam_hodie/utils/auth_required.dart';
|
||||||
import 'package:quid_faciam_hodie/utils/loadable.dart';
|
import 'package:quid_faciam_hodie/utils/loadable.dart';
|
||||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
|
import 'package:quid_faciam_hodie/widgets/cupertino_dropdown.dart';
|
||||||
import 'package:settings_ui/settings_ui.dart';
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
@ -81,11 +82,49 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget getPicker() {
|
||||||
|
final settings = GlobalValuesManager.settings!;
|
||||||
|
final resolutionTextMapping = getResolutionTextMapping(context);
|
||||||
|
final items = ResolutionPreset.values
|
||||||
|
.map(
|
||||||
|
(value) => DropdownMenuItem<ResolutionPreset>(
|
||||||
|
value: value,
|
||||||
|
child: Text(resolutionTextMapping[value]!),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (isMaterial(context)) {
|
||||||
|
return DropdownButtonFormField<ResolutionPreset>(
|
||||||
|
value: settings.resolution,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.setResolution(value);
|
||||||
|
},
|
||||||
|
items: items,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return CupertinoDropdownButton<ResolutionPreset>(
|
||||||
|
itemExtent: 30,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.setResolution(value);
|
||||||
|
},
|
||||||
|
value: settings.resolution,
|
||||||
|
items: items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final settings = GlobalValuesManager.settings!;
|
|
||||||
final localizations = AppLocalizations.of(context)!;
|
final localizations = AppLocalizations.of(context)!;
|
||||||
final resolutionTextMapping = getResolutionTextMapping(context);
|
|
||||||
|
|
||||||
return PlatformScaffold(
|
return PlatformScaffold(
|
||||||
appBar: PlatformAppBar(
|
appBar: PlatformAppBar(
|
||||||
@ -163,23 +202,7 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
|||||||
localizations
|
localizations
|
||||||
.settingsScreenGeneralSectionQualityLabel,
|
.settingsScreenGeneralSectionQualityLabel,
|
||||||
),
|
),
|
||||||
title: DropdownButtonFormField<ResolutionPreset>(
|
title: getPicker(),
|
||||||
value: settings.resolution,
|
|
||||||
onChanged: (value) async {
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.setResolution(value);
|
|
||||||
},
|
|
||||||
items: ResolutionPreset.values
|
|
||||||
.map((value) =>
|
|
||||||
DropdownMenuItem<ResolutionPreset>(
|
|
||||||
value: value,
|
|
||||||
child: Text(resolutionTextMapping[value]!),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -135,114 +135,114 @@ class _MemorySheetState extends State<MemorySheet> with Loadable {
|
|||||||
background: GestureDetector(
|
background: GestureDetector(
|
||||||
onTap: () => Navigator.pop(context),
|
onTap: () => Navigator.pop(context),
|
||||||
),
|
),
|
||||||
persistentHeader: Container(
|
persistentHeader: Material(
|
||||||
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
borderRadius: const BorderRadius.only(
|
||||||
decoration: BoxDecoration(
|
topLeft: Radius.circular(LARGE_SPACE),
|
||||||
color: backgroundColor,
|
topRight: Radius.circular(LARGE_SPACE),
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(LARGE_SPACE),
|
|
||||||
topRight: Radius.circular(LARGE_SPACE),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
color: backgroundColor,
|
||||||
children: <Widget>[
|
child: Padding(
|
||||||
if (widget.memory.location != null) ...[
|
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||||
const Padding(
|
child: Column(
|
||||||
padding: EdgeInsets.all(SMALL_SPACE),
|
children: <Widget>[
|
||||||
child: SheetIndicator(),
|
if (widget.memory.location != null) ...[
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(SMALL_SPACE),
|
||||||
|
child: SheetIndicator(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
|
],
|
||||||
|
Text(
|
||||||
|
localizations.memorySheetTitle,
|
||||||
|
style: getTitleTextStyle(context),
|
||||||
),
|
),
|
||||||
const SizedBox(height: MEDIUM_SPACE),
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
],
|
ListTile(
|
||||||
Text(
|
leading: PlatformWidget(
|
||||||
localizations.memorySheetTitle,
|
cupertino: (_, __) => Icon(
|
||||||
style: getTitleTextStyle(context),
|
CupertinoIcons.down_arrow,
|
||||||
),
|
color: getBodyTextColor(context),
|
||||||
const SizedBox(height: MEDIUM_SPACE),
|
),
|
||||||
ListTile(
|
material: (_, __) => Icon(
|
||||||
leading: PlatformWidget(
|
Icons.download,
|
||||||
cupertino: (_, __) => Icon(
|
color: getBodyTextColor(context),
|
||||||
CupertinoIcons.down_arrow,
|
|
||||||
color: getBodyTextColor(context),
|
|
||||||
),
|
|
||||||
material: (_, __) => Icon(
|
|
||||||
Icons.download,
|
|
||||||
color: getBodyTextColor(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
localizations.memorySheetDownloadMemory,
|
|
||||||
style: getBodyTextTextStyle(context),
|
|
||||||
),
|
|
||||||
enabled: !getIsLoadingSpecificID('download'),
|
|
||||||
onTap: getIsLoadingSpecificID('download')
|
|
||||||
? null
|
|
||||||
: () => callWithLoading(downloadFile, 'download'),
|
|
||||||
trailing: getIsLoadingSpecificID('download')
|
|
||||||
? buildLoadingIndicator()
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(
|
|
||||||
widget.memory.isPublic
|
|
||||||
? Icons.public_off_rounded
|
|
||||||
: Icons.public,
|
|
||||||
color: getBodyTextColor(context),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
widget.memory.isPublic
|
|
||||||
? localizations.memorySheetUpdateMemoryMakePrivate
|
|
||||||
: localizations.memorySheetUpdateMemoryMakePublic,
|
|
||||||
style: getBodyTextTextStyle(context),
|
|
||||||
),
|
|
||||||
enabled: !getIsLoadingSpecificID('public'),
|
|
||||||
onTap: getIsLoadingSpecificID('public')
|
|
||||||
? null
|
|
||||||
: () => callWithLoading(changeVisibility, 'public'),
|
|
||||||
trailing: getIsLoadingSpecificID('public')
|
|
||||||
? buildLoadingIndicator()
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(
|
|
||||||
context.platformIcons.delete,
|
|
||||||
color: getBodyTextColor(context),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
localizations.memorySheetDeleteMemory,
|
|
||||||
style: getBodyTextTextStyle(context),
|
|
||||||
),
|
|
||||||
enabled: !getIsLoadingSpecificID('delete'),
|
|
||||||
onTap: getIsLoadingSpecificID('delete')
|
|
||||||
? null
|
|
||||||
: () => callWithLoading(deleteFile, 'delete'),
|
|
||||||
trailing: getIsLoadingSpecificID('delete')
|
|
||||||
? buildLoadingIndicator()
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
const SizedBox(height: MEDIUM_SPACE),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
context.platformIcons.time,
|
|
||||||
size: platformThemeData(
|
|
||||||
context,
|
|
||||||
material: (data) => data.textTheme.bodyLarge!.fontSize,
|
|
||||||
cupertino: (data) => data.textTheme.textStyle.fontSize,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: TINY_SPACE),
|
title: Text(
|
||||||
Text(
|
localizations.memorySheetDownloadMemory,
|
||||||
localizations.memorySheetCreatedAtDataKey(
|
|
||||||
DateFormat.jms().format(
|
|
||||||
widget.memory.creationDate,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
style: getBodyTextTextStyle(context),
|
style: getBodyTextTextStyle(context),
|
||||||
),
|
),
|
||||||
],
|
enabled: !getIsLoadingSpecificID('download'),
|
||||||
),
|
onTap: getIsLoadingSpecificID('download')
|
||||||
],
|
? null
|
||||||
|
: () => callWithLoading(downloadFile, 'download'),
|
||||||
|
trailing: getIsLoadingSpecificID('download')
|
||||||
|
? buildLoadingIndicator()
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
widget.memory.isPublic
|
||||||
|
? Icons.public_off_rounded
|
||||||
|
: Icons.public,
|
||||||
|
color: getBodyTextColor(context),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
widget.memory.isPublic
|
||||||
|
? localizations.memorySheetUpdateMemoryMakePrivate
|
||||||
|
: localizations.memorySheetUpdateMemoryMakePublic,
|
||||||
|
style: getBodyTextTextStyle(context),
|
||||||
|
),
|
||||||
|
enabled: !getIsLoadingSpecificID('public'),
|
||||||
|
onTap: getIsLoadingSpecificID('public')
|
||||||
|
? null
|
||||||
|
: () => callWithLoading(changeVisibility, 'public'),
|
||||||
|
trailing: getIsLoadingSpecificID('public')
|
||||||
|
? buildLoadingIndicator()
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
context.platformIcons.delete,
|
||||||
|
color: getBodyTextColor(context),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
localizations.memorySheetDeleteMemory,
|
||||||
|
style: getBodyTextTextStyle(context),
|
||||||
|
),
|
||||||
|
enabled: !getIsLoadingSpecificID('delete'),
|
||||||
|
onTap: getIsLoadingSpecificID('delete')
|
||||||
|
? null
|
||||||
|
: () => callWithLoading(deleteFile, 'delete'),
|
||||||
|
trailing: getIsLoadingSpecificID('delete')
|
||||||
|
? buildLoadingIndicator()
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
context.platformIcons.time,
|
||||||
|
size: platformThemeData(
|
||||||
|
context,
|
||||||
|
material: (data) => data.textTheme.bodyLarge!.fontSize,
|
||||||
|
cupertino: (data) => data.textTheme.textStyle.fontSize,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: TINY_SPACE),
|
||||||
|
Text(
|
||||||
|
localizations.memorySheetCreatedAtDataKey(
|
||||||
|
DateFormat.jms().format(
|
||||||
|
widget.memory.creationDate,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
style: getBodyTextTextStyle(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expandableContent: widget.memory.location == null
|
expandableContent: widget.memory.location == null
|
||||||
|
116
lib/widgets/cupertino_dropdown.dart
Normal file
116
lib/widgets/cupertino_dropdown.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Adopted from https://github.com/Enough-Software/enough_platform_widgets/blob/main/lib/src/cupertino/cupertino_dropdown_button.dart
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
|
|
||||||
|
class CupertinoDropdownButton<T> extends StatefulWidget {
|
||||||
|
final List<DropdownMenuItem<T>>? items;
|
||||||
|
final List<Widget> Function(BuildContext context)? selectedItemBuilder;
|
||||||
|
final T? value;
|
||||||
|
final void Function(T? value)? onChanged;
|
||||||
|
final double itemExtent;
|
||||||
|
final Widget? hint;
|
||||||
|
|
||||||
|
const CupertinoDropdownButton({
|
||||||
|
Key? key,
|
||||||
|
required this.items,
|
||||||
|
this.selectedItemBuilder,
|
||||||
|
this.value,
|
||||||
|
this.onChanged,
|
||||||
|
this.hint,
|
||||||
|
required this.itemExtent,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CupertinoDropdownButtonState<T> createState() =>
|
||||||
|
_CupertinoDropdownButtonState<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CupertinoDropdownButtonState<T>
|
||||||
|
extends State<CupertinoDropdownButton<T>> {
|
||||||
|
int? _selectedIndex;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final itms = widget.items;
|
||||||
|
if (itms == null || itms.isEmpty) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
final builder = widget.selectedItemBuilder;
|
||||||
|
final children = (builder != null)
|
||||||
|
? builder(context)
|
||||||
|
.map((widget) => Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||||
|
child: FittedBox(child: widget),
|
||||||
|
))
|
||||||
|
.toList()
|
||||||
|
: itms
|
||||||
|
.map((itm) => Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||||
|
child: FittedBox(child: itm.child),
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
final currentValue = widget.value;
|
||||||
|
|
||||||
|
final currentIndex =
|
||||||
|
max(itms.indexWhere((item) => item.value == currentValue), 0);
|
||||||
|
final child = currentValue == null
|
||||||
|
? widget.hint ?? const Icon(CupertinoIcons.arrow_down)
|
||||||
|
: children[currentIndex];
|
||||||
|
return CupertinoButton(
|
||||||
|
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||||
|
child: FittedBox(child: child),
|
||||||
|
onPressed: () async {
|
||||||
|
final scrollController = (currentValue == null)
|
||||||
|
? null
|
||||||
|
: FixedExtentScrollController(
|
||||||
|
initialItem: currentIndex,
|
||||||
|
);
|
||||||
|
final result = await showCupertinoModalPopup<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.7,
|
||||||
|
child: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
color: CupertinoTheme.of(context).barBackgroundColor,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
CupertinoButton(
|
||||||
|
child: const Icon(Icons.clear),
|
||||||
|
onPressed: () => Navigator.of(context).pop(false)),
|
||||||
|
CupertinoButton(
|
||||||
|
child: const Icon(CupertinoIcons.check_mark),
|
||||||
|
onPressed: () => Navigator.of(context).pop(true)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
itemExtent: widget.itemExtent,
|
||||||
|
onSelectedItemChanged: (index) =>
|
||||||
|
_selectedIndex = index,
|
||||||
|
scrollController: scrollController,
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result == true && _selectedIndex != null) {
|
||||||
|
final callback = widget.onChanged;
|
||||||
|
if (callback != null) {
|
||||||
|
callback(widget.items![_selectedIndex!].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user