diff options
68 files changed, 3396 insertions, 271 deletions
@@ -42,3 +42,5 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +.desktop-homescreen diff --git a/lib/data/data_providers/app_config_provider.dart b/lib/data/data_providers/app_config_provider.dart index 7ec8d8a..6a4ea02 100644 --- a/lib/data/data_providers/app_config_provider.dart +++ b/lib/data/data_providers/app_config_provider.dart @@ -8,9 +8,9 @@ class KuksaConfig { final String hostname; final int port; final String authorization; - final bool use_tls; - final List<int> ca_certificate; - final String tls_server_name; + final bool useTls; + final List<int> caCertificate; + final String tlsServerName; static String defaultHostname = 'localhost'; static int defaultPort = 55555; @@ -20,18 +20,18 @@ class KuksaConfig { {required this.hostname, required this.port, required this.authorization, - required this.use_tls, - required this.ca_certificate, - required this.tls_server_name}); + required this.useTls, + required this.caCertificate, + required this.tlsServerName}); static KuksaConfig defaultConfig() { return KuksaConfig( hostname: KuksaConfig.defaultHostname, port: KuksaConfig.defaultPort, authorization: "", - use_tls: false, - ca_certificate: [], - tls_server_name: ""); + useTls: false, + caCertificate: [], + tlsServerName: ""); } } @@ -120,38 +120,38 @@ class AppConfig { } //debugPrint("authorization = $token"); - bool use_tls = false; + bool useTls = false; if (kuksaMap.containsKey('use-tls')) { var value = kuksaMap['use-tls']; - if (value is bool) use_tls = value; + if (value is bool) useTls = value; } //debugPrint("Use TLS = $use_tls"); - List<int> ca_cert = []; - String ca_path = KuksaConfig.defaultCaCertPath; + List<int> caCert = []; + String caPath = KuksaConfig.defaultCaCertPath; if (kuksaMap.containsKey('ca-certificate')) { - ca_path = kuksaMap['ca-certificate']; + caPath = kuksaMap['ca-certificate']; } try { - ca_cert = File(ca_path).readAsBytesSync(); + caCert = File(caPath).readAsBytesSync(); } catch (_) { - print("ERROR: Could not read CA certificate file $ca_path"); - ca_cert = []; + print("ERROR: Could not read CA certificate file $caPath"); + caCert = []; } //debugPrint("CA cert = $ca_cert"); - String tls_server_name = ""; + String tlsServerName = ""; if (kuksaMap.containsKey('tls-server-name')) { - tls_server_name = kuksaMap['tls-server-name']; + tlsServerName = kuksaMap['tls-server-name']; } return KuksaConfig( hostname: hostname, port: port, authorization: token, - use_tls: use_tls, - ca_certificate: ca_cert, - tls_server_name: tls_server_name); + useTls: useTls, + caCertificate: caCert, + tlsServerName: tlsServerName); } catch (_) { debugPrint("Invalid KUKSA.val configuration, using defaults"); return KuksaConfig.defaultConfig(); @@ -217,9 +217,9 @@ final appConfigProvider = Provider((ref) { hostname: KuksaConfig.defaultHostname, port: KuksaConfig.defaultPort, authorization: "", - use_tls: false, - ca_certificate: [], - tls_server_name: ""); + useTls: false, + caCertificate: [], + tlsServerName: ""); } RadioConfig radioConfig; diff --git a/lib/data/data_providers/app_launcher.dart b/lib/data/data_providers/app_launcher.dart index 8762643..917dd21 100644 --- a/lib/data/data_providers/app_launcher.dart +++ b/lib/data/data_providers/app_launcher.dart @@ -1,6 +1,6 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/applauncher-api.dart'; -import 'package:protos/agl-shell-api.dart'; +import 'package:protos/applauncher_api.dart'; +import 'package:protos/agl_shell_api.dart'; class AppLauncher { final Ref ref; @@ -15,13 +15,13 @@ class AppLauncher { AppLauncher({required this.ref}) { aglShellChannel = ClientChannel('localhost', port: 14005, - options: ChannelOptions(credentials: ChannelCredentials.insecure())); + options: const ChannelOptions(credentials: ChannelCredentials.insecure())); aglShell = AglShellManagerServiceClient(aglShellChannel); appLauncherChannel = ClientChannel('localhost', port: 50052, - options: ChannelOptions(credentials: ChannelCredentials.insecure())); + options: const ChannelOptions(credentials: ChannelCredentials.insecure())); appLauncher = AppLauncherClient(appLauncherChannel); } @@ -32,14 +32,14 @@ class AppLauncher { var response = appLauncher.getStatusEvents(StatusRequest()); await for (var event in response) { if (event.hasApp()) { - AppStatus app_status = event.app; + AppStatus appStatus = event.app; debugPrint("Got app status:"); - debugPrint("$app_status"); - if (app_status.hasId() && app_status.hasStatus()) { - if (app_status.status == "started") { - activateApp(app_status.id); - } else if (app_status.status == "terminated") { - deactivateApp(app_status.id); + debugPrint("$appStatus"); + if (appStatus.hasId() && appStatus.hasStatus()) { + if (appStatus.status == "started") { + activateApp(appStatus.id); + } else if (appStatus.status == "terminated") { + deactivateApp(appStatus.id); } } } @@ -100,7 +100,7 @@ class AppLauncher { activateApp(String id) async { if (appStack.last != id) { var req = ActivateRequest(appId: id); - var response = aglShell.activateApp(req); + aglShell.activateApp(req); addAppToStack(id); } } diff --git a/lib/data/data_providers/app_provider.dart b/lib/data/data_providers/app_provider.dart index a74c0fd..ca2c3d4 100644 --- a/lib/data/data_providers/app_provider.dart +++ b/lib/data/data_providers/app_provider.dart @@ -18,7 +18,6 @@ import 'package:flutter_ics_homescreen/data/data_providers/play_controller.dart' import 'package:flutter_ics_homescreen/export.dart'; import 'package:flutter_ics_homescreen/data/models/users.dart'; -import 'package:flutter_ics_homescreen/data/models/mediaplayer_state.dart'; enum AppState { home, diff --git a/lib/data/data_providers/audio_notifier.dart b/lib/data/data_providers/audio_notifier.dart index 76b34a7..4933932 100644 --- a/lib/data/data_providers/audio_notifier.dart +++ b/lib/data/data_providers/audio_notifier.dart @@ -1,10 +1,10 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/val-api.dart'; +import 'package:protos/val_api.dart'; class AudioStateNotifier extends Notifier<AudioState> { @override AudioState build() { - return AudioState.initial(); + return const AudioState.initial(); } void resetToDefaults() { diff --git a/lib/data/data_providers/mediaplayer_notifier.dart b/lib/data/data_providers/mediaplayer_notifier.dart index 2d02e75..bb121c0 100644 --- a/lib/data/data_providers/mediaplayer_notifier.dart +++ b/lib/data/data_providers/mediaplayer_notifier.dart @@ -4,7 +4,7 @@ import 'playlist_notifier.dart'; class MediaPlayerStateNotifier extends Notifier<MediaPlayerState> { @override MediaPlayerState build() { - return MediaPlayerState.initial(); + return const MediaPlayerState.initial(); } void updatePlayState(PlayState newState) { @@ -20,6 +20,6 @@ class MediaPlayerStateNotifier extends Notifier<MediaPlayerState> { } void reset() { - state = MediaPlayerState.initial(); + state = const MediaPlayerState.initial(); } } diff --git a/lib/data/data_providers/radio_client.dart b/lib/data/data_providers/radio_client.dart index 2cde65e..3ee041a 100644 --- a/lib/data/data_providers/radio_client.dart +++ b/lib/data/data_providers/radio_client.dart @@ -1,5 +1,5 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/radio-api.dart' as api; +import 'package:protos/radio_api.dart' as api; class RadioClient { final RadioConfig config; @@ -71,7 +71,7 @@ class RadioClient { void start() async { try { - var response = await stub.start(api.StartRequest()); + await stub.start(api.StartRequest()); } catch (e) { print(e); } @@ -79,7 +79,7 @@ class RadioClient { void stop() async { try { - var response = await stub.stop(api.StopRequest()); + await stub.stop(api.StopRequest()); } catch (e) { print(e); } @@ -94,7 +94,7 @@ class RadioClient { return; } try { - var response = await stub + await stub .setFrequency(api.SetFrequencyRequest(frequency: frequency)); } catch (e) { print(e); @@ -109,7 +109,7 @@ class RadioClient { frequency = radioState.freqMax; } try { - var response = await stub + await stub .setFrequency(api.SetFrequencyRequest(frequency: frequency)); } catch (e) { print(e); @@ -125,7 +125,7 @@ class RadioClient { frequency = radioState.freqMin; } try { - var response = await stub + await stub .setFrequency(api.SetFrequencyRequest(frequency: frequency)); } catch (e) { print(e); @@ -135,7 +135,7 @@ class RadioClient { void scanForward() async { try { - var response = await stub.scanStart(api.ScanStartRequest( + await stub.scanStart(api.ScanStartRequest( direction: api.ScanDirection.SCAN_DIRECTION_FORWARD)); } catch (e) { print(e); @@ -144,7 +144,7 @@ class RadioClient { void scanBackward() async { try { - var response = await stub.scanStart(api.ScanStartRequest( + await stub.scanStart(api.ScanStartRequest( direction: api.ScanDirection.SCAN_DIRECTION_BACKWARD)); } catch (e) { print(e); @@ -153,7 +153,7 @@ class RadioClient { void scanStop() async { try { - var response = await stub.scanStop(api.ScanStopRequest()); + await stub.scanStop(api.ScanStopRequest()); } catch (e) { print(e); } diff --git a/lib/data/data_providers/radio_notifier.dart b/lib/data/data_providers/radio_notifier.dart index 90e0df5..3ef4da4 100644 --- a/lib/data/data_providers/radio_notifier.dart +++ b/lib/data/data_providers/radio_notifier.dart @@ -3,7 +3,7 @@ import 'package:flutter_ics_homescreen/export.dart'; class RadioStateNotifier extends Notifier<RadioState> { @override RadioState build() { - return RadioState.initial(); + return const RadioState.initial(); } void updateBandParameters( diff --git a/lib/data/data_providers/units_notifier.dart b/lib/data/data_providers/units_notifier.dart index 26b79da..68c9e65 100644 --- a/lib/data/data_providers/units_notifier.dart +++ b/lib/data/data_providers/units_notifier.dart @@ -1,5 +1,5 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/val-api.dart'; +import 'package:protos/val_api.dart'; class UnitsNotifier extends Notifier<Units> { @override diff --git a/lib/data/data_providers/val_client.dart b/lib/data/data_providers/val_client.dart index 5e7339c..173dbfb 100644 --- a/lib/data/data_providers/val_client.dart +++ b/lib/data/data_providers/val_client.dart @@ -1,5 +1,5 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/val-api.dart'; +import 'package:protos/val_api.dart'; class ValClient { final KuksaConfig config; @@ -11,14 +11,14 @@ class ValClient { ValClient({required this.config, required this.ref}) { debugPrint("Connecting to KUKSA.val at ${config.hostname}:${config.port}"); ChannelCredentials creds; - if (config.use_tls && config.ca_certificate.isNotEmpty) { + if (config.useTls && config.caCertificate.isNotEmpty) { print("Using TLS"); - if (config.tls_server_name.isNotEmpty) { + if (config.tlsServerName.isNotEmpty) { creds = ChannelCredentials.secure( - certificates: config.ca_certificate, - authority: config.tls_server_name); + certificates: config.caCertificate, + authority: config.tlsServerName); } else { - creds = ChannelCredentials.secure(certificates: config.ca_certificate); + creds = ChannelCredentials.secure(certificates: config.caCertificate); } } else { creds = const ChannelCredentials.insecure(); @@ -133,7 +133,7 @@ class ValClient { if (config.authorization.isNotEmpty) { metadata = {'authorization': "Bearer ${config.authorization}"}; } - debugPrint("Getting {path} value"); + debugPrint("Getting $path value"); var response = await stub.get(request, options: CallOptions(metadata: metadata)); if (response.hasError()) { diff --git a/lib/data/data_providers/vehicle_notifier.dart b/lib/data/data_providers/vehicle_notifier.dart index 6583f9a..1dc4627 100644 --- a/lib/data/data_providers/vehicle_notifier.dart +++ b/lib/data/data_providers/vehicle_notifier.dart @@ -3,12 +3,12 @@ import 'dart:async'; import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/val-api.dart'; +import 'package:protos/val_api.dart'; class VehicleNotifier extends Notifier<Vehicle> { @override Vehicle build() { - return Vehicle.initial(); + return const Vehicle.initial(); } void updateSpeed(double newValue) { @@ -103,11 +103,13 @@ class VehicleNotifier extends Notifier<Vehicle> { // Convert 0-100 to local 0-3 setting var value = entry.value.uint32; var fanSpeed = 0; - if (value > 66) + if (value > 66) { fanSpeed = 3; - else if (value > 33) + } + else if (value > 33) { fanSpeed = 2; - else if (value > 0) fanSpeed = 1; + } + else if (value > 0) { fanSpeed = 1; } state = state.copyWith(fanSpeed: fanSpeed); } break; diff --git a/lib/data/models/audio_state.dart b/lib/data/models/audio_state.dart index 60720a8..3ad4f63 100644 --- a/lib/data/models/audio_state.dart +++ b/lib/data/models/audio_state.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter_ics_homescreen/export.dart'; @immutable diff --git a/lib/data/models/radio_state.dart b/lib/data/models/radio_state.dart index da972fd..9eaeddb 100644 --- a/lib/data/models/radio_state.dart +++ b/lib/data/models/radio_state.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter_ics_homescreen/export.dart'; @immutable diff --git a/lib/presentation/common_widget/volume_and_fan_control.dart b/lib/presentation/common_widget/volume_and_fan_control.dart index 765193b..8c78b4f 100644 --- a/lib/presentation/common_widget/volume_and_fan_control.dart +++ b/lib/presentation/common_widget/volume_and_fan_control.dart @@ -19,7 +19,7 @@ class VolumeFanControl extends ConsumerWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - VolumeBar(), + const VolumeBar(), SizedBox( height: gapSize, ), diff --git a/lib/presentation/custom_icons/custom_icons.dart b/lib/presentation/custom_icons/custom_icons.dart index 2a42c95..5ca4d9b 100644 --- a/lib/presentation/custom_icons/custom_icons.dart +++ b/lib/presentation/custom_icons/custom_icons.dart @@ -18,6 +18,7 @@ /// Homepage: http://fortawesome.github.com/Font-Awesome/ /// // ignore_for_file: constant_identifier_names +library; import 'package:flutter/widgets.dart'; diff --git a/lib/presentation/screens/dashboard/widgets/car_status.dart b/lib/presentation/screens/dashboard/widgets/car_status.dart index 604d404..174905d 100644 --- a/lib/presentation/screens/dashboard/widgets/car_status.dart +++ b/lib/presentation/screens/dashboard/widgets/car_status.dart @@ -8,7 +8,7 @@ class CarStatus extends ConsumerWidget { const CarStatus({super.key}); @override - Widget build(BuildContext context, WidgetRef Ref) { + Widget build(BuildContext context, WidgetRef ref) { return Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 84), child: SizedBox( @@ -194,9 +194,9 @@ class RightCarStatus extends ConsumerWidget { class TirePressureProgressIndicator extends StatelessWidget { final double value; const TirePressureProgressIndicator({ - Key? key, + super.key, required this.value, // Require the value to be passed - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/presentation/screens/dashboard/widgets/dashboard_content.dart b/lib/presentation/screens/dashboard/widgets/dashboard_content.dart index 1d25fdf..c4239ae 100644 --- a/lib/presentation/screens/dashboard/widgets/dashboard_content.dart +++ b/lib/presentation/screens/dashboard/widgets/dashboard_content.dart @@ -15,7 +15,7 @@ class DashBoardState extends ConsumerState<DashBoard> late AnimationController _animationController; late Animation<double> _animation; static bool _isAnimationPlayed = false; - Timer? timer = null; + Timer? timer; @override void initState() { @@ -53,8 +53,9 @@ class DashBoardState extends ConsumerState<DashBoard> @override void dispose() { _animationController.dispose(); - if (timer != null) + if (timer != null) { timer?.cancel(); + } super.dispose(); } diff --git a/lib/presentation/screens/home/home_ci.dart b/lib/presentation/screens/home/home_ci.dart index 8584420..0bc6c91 100644 --- a/lib/presentation/screens/home/home_ci.dart +++ b/lib/presentation/screens/home/home_ci.dart @@ -11,9 +11,9 @@ class HomeScreenCI extends StatelessWidget { children: [ // Note that the colors are specified with hex in order to match // Qt's red/blue/green constants, which are different than Flutter's. - Container(width: 1080, height: 216, color: Color(0xFF0000FF)), - Container(width: 1080, height: 1488, color: Color(0xFFFF0000)), - Container(width: 1080, height: 216, color: Color(0xFF008000)) + Container(width: 1080, height: 216, color: const Color(0xFF0000FF)), + Container(width: 1080, height: 1488, color: const Color(0xFFFF0000)), + Container(width: 1080, height: 216, color: const Color(0xFF008000)) ], ); } diff --git a/lib/presentation/screens/home/widgets/custom_tile.dart b/lib/presentation/screens/home/widgets/custom_tile.dart index 389a75d..d167719 100644 --- a/lib/presentation/screens/home/widgets/custom_tile.dart +++ b/lib/presentation/screens/home/widgets/custom_tile.dart @@ -5,11 +5,11 @@ class CustomTile extends StatelessWidget { final Color color; final VoidCallback callback; const CustomTile({ - Key? key, + super.key, required this.name, required this.color, required this.callback, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/presentation/screens/hvac/hvac_content.dart b/lib/presentation/screens/hvac/hvac_content.dart index e541efd..a796e12 100644 --- a/lib/presentation/screens/hvac/hvac_content.dart +++ b/lib/presentation/screens/hvac/hvac_content.dart @@ -143,7 +143,7 @@ class HVACState extends ConsumerState<HVAC> { const SizedBox( height: 80, ), - Row( + const Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TemperatureControl(side: Side.left), diff --git a/lib/presentation/screens/media/media_player.dart b/lib/presentation/screens/media/media_player.dart index 0dab346..ff7ba70 100644 --- a/lib/presentation/screens/media/media_player.dart +++ b/lib/presentation/screens/media/media_player.dart @@ -57,7 +57,7 @@ class _MediaPlayerState extends ConsumerState<MediaPlayer> { const SizedBox( height: 40, ), - Column( + const Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ MediaPlayerControls(), diff --git a/lib/presentation/screens/media/media_player_controls.dart b/lib/presentation/screens/media/media_player_controls.dart index f23bcc9..478c23a 100644 --- a/lib/presentation/screens/media/media_player_controls.dart +++ b/lib/presentation/screens/media/media_player_controls.dart @@ -184,7 +184,7 @@ class MediaPlayerControlsSliderState songLength = currentSong.duration; } - return Container( + return SizedBox( height: 80, child: SliderTheme( data: SliderThemeData( diff --git a/lib/presentation/screens/media/play_list_table.dart b/lib/presentation/screens/media/play_list_table.dart index 28cb970..1159f68 100644 --- a/lib/presentation/screens/media/play_list_table.dart +++ b/lib/presentation/screens/media/play_list_table.dart @@ -3,7 +3,7 @@ import 'package:flutter_ics_homescreen/core/utils/helpers.dart'; import 'package:flutter_ics_homescreen/export.dart'; class PlayListTable extends ConsumerStatefulWidget { - PlayListTable({super.key}); + const PlayListTable({super.key}); @override ConsumerState<PlayListTable> createState() => _PlayListTableState(); @@ -182,7 +182,7 @@ class _PlayListTableState extends ConsumerState<PlayListTable> { ); }, separatorBuilder: (_, __) { - return SizedBox(height: 8); + return const SizedBox(height: 8); }, ), ]))))), diff --git a/lib/presentation/screens/media/radio_player_controls.dart b/lib/presentation/screens/media/radio_player_controls.dart index acc8291..d20724e 100644 --- a/lib/presentation/screens/media/radio_player_controls.dart +++ b/lib/presentation/screens/media/radio_player_controls.dart @@ -204,7 +204,7 @@ class RadioPlayerControlsSliderState ref.watch(radioStateProvider.select((radio) => radio.freqCurrent)) / 1000000.0; - return Container( + return SizedBox( height: 80, child: SliderTheme( data: SliderThemeData( diff --git a/lib/presentation/screens/media/radio_preset_table.dart b/lib/presentation/screens/media/radio_preset_table.dart index fcf8e2b..21f9f4a 100644 --- a/lib/presentation/screens/media/radio_preset_table.dart +++ b/lib/presentation/screens/media/radio_preset_table.dart @@ -177,7 +177,7 @@ class _RadioPresetTableState extends ConsumerState<RadioPresetTable> { ); }, separatorBuilder: (_, __) { - return SizedBox(height: 8); + return const SizedBox(height: 8); }, ), ])), diff --git a/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart b/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart index 24aa244..ec09ba2 100644 --- a/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart +++ b/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart @@ -13,10 +13,9 @@ class GradientProgressIndicator extends StatelessWidget { {required this.percent, required this.gradient, required this.backgroundColor, - Key? key, + super.key, this.height = 16, - required this.type}) - : super(key: key); + required this.type}); @override Widget build(BuildContext context) { diff --git a/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart b/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart index 6988caa..c7db820 100644 --- a/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart +++ b/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart @@ -1,5 +1,4 @@ import 'package:flutter_ics_homescreen/export.dart'; -import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart'; class CustomBalanceSlider extends ConsumerStatefulWidget { const CustomBalanceSlider({ diff --git a/lib/presentation/screens/settings/settings_screens/units/units_screen.dart b/lib/presentation/screens/settings/settings_screens/units/units_screen.dart index fde7505..a49546f 100644 --- a/lib/presentation/screens/settings/settings_screens/units/units_screen.dart +++ b/lib/presentation/screens/settings/settings_screens/units/units_screen.dart @@ -80,14 +80,14 @@ class UnitsTile extends ConsumerStatefulWidget { final VoidCallback voidCallback; final String? image; const UnitsTile({ - Key? key, + super.key, this.icon, required this.title, required this.unitName, required this.hasSwich, required this.voidCallback, this.image, - }) : super(key: key); + }); @override UnitsTileState createState() => UnitsTileState(); diff --git a/lib/presentation/screens/settings/widgets/settings_list_tile.dart b/lib/presentation/screens/settings/widgets/settings_list_tile.dart index 4720001..02aa5f9 100644 --- a/lib/presentation/screens/settings/widgets/settings_list_tile.dart +++ b/lib/presentation/screens/settings/widgets/settings_list_tile.dart @@ -6,12 +6,12 @@ class SettingsTile extends ConsumerStatefulWidget { final bool hasSwich; final VoidCallback voidCallback; const SettingsTile({ - Key? key, + super.key, required this.icon, required this.title, required this.hasSwich, required this.voidCallback, - }) : super(key: key); + }); @override SettingsTileState createState() => SettingsTileState(); @@ -110,7 +110,7 @@ class SettingsTileState extends ConsumerState<SettingsTile> { inactiveTrackColor: Colors.transparent, activeTrackColor: Colors.transparent, thumbColor: - MaterialStateProperty.all<Color>( + WidgetStateProperty.all<Color>( AGLDemoColors.periwinkleColor)), ), ) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..4ec6322 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include <rive_common/rive_plugin.h> void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) rive_common_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "RivePlugin"); + rive_plugin_register_with_registrar(rive_common_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..5c12227 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + rive_common ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/packages/flutter_calendar_carousel/.coveralls.yml b/packages/flutter_calendar_carousel/.coveralls.yml new file mode 100644 index 0000000..121a96a --- /dev/null +++ b/packages/flutter_calendar_carousel/.coveralls.yml @@ -0,0 +1 @@ +repo_token: ZZjgwJha5lf2FFsNyvzmbNsswFz2fZuKR diff --git a/packages/flutter_calendar_carousel/.github/workflows/ci.yml b/packages/flutter_calendar_carousel/.github/workflows/ci.yml new file mode 100644 index 0000000..bc4461d --- /dev/null +++ b/packages/flutter_calendar_carousel/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: Flutter CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + - uses: actions/setup-java@v4 + with: + java-version: "14.x" + + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + flutter-version: "3.x" + + - run: flutter pub get + + - run: flutter format --set-exit-if-changed . + + # - run: flutter analyze . + + - run: flutter test --coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: coverage/lcov.info + + # - run: flutter build apk + + # Upload generated apk to the artifacts. + # - uses: actions/upload-artifact@v1 + # with: + # name: release-apk + # path: build/app/outputs/apk/release/app-release.apk diff --git a/packages/flutter_calendar_carousel/.github/workflows/stale.yml b/packages/flutter_calendar_carousel/.github/workflows/stale.yml new file mode 100644 index 0000000..f2b97a0 --- /dev/null +++ b/packages/flutter_calendar_carousel/.github/workflows/stale.yml @@ -0,0 +1,21 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + + runs-on: ubuntu-latest + + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 90 + days-before-close: 7 + stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Leave a comment or this will be closed in 7 days.' + stale-pr-message: 'This PR is stale because it has been open 90 days with no activity. Leave a comment or this will be closed in 7 days' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' diff --git a/packages/flutter_calendar_carousel/.gitignore b/packages/flutter_calendar_carousel/.gitignore new file mode 100644 index 0000000..f7ea22e --- /dev/null +++ b/packages/flutter_calendar_carousel/.gitignore @@ -0,0 +1,16 @@ +.DS_Store +.dart_tool/ +.vscode/ + +.packages +.pub/ +coverage + +build/ +ios/.generated/ +ios/Flutter/Generated.xcconfig +ios/Runner/GeneratedPluginRegistrant.* + +.idea/ +flutter_calendar_carousel.iml +flutter_export_environment.sh diff --git a/packages/flutter_calendar_carousel/.travis.yml b/packages/flutter_calendar_carousel/.travis.yml new file mode 100644 index 0000000..4a8e0f5 --- /dev/null +++ b/packages/flutter_calendar_carousel/.travis.yml @@ -0,0 +1,90 @@ +matrix: + # This causes the build to complete immediately upon first failure or once + # required jobs are green. + fast_finish: true + + # Building APK/IPA takes a long time; do not wait for them to finish. + # allow_failures: + # - env: JOB=APK + # - env: JOB=IPA + + include: + # Runs unit tests without emulator. + - env: JOB=PR + os: linux + language: dart + sudo: false + addons: + apt: + # Flutter depends on /usr/lib/x86_64-linux-gnu/libstdc++.so.6 version GLIBCXX_3.4.18 + sources: + - ubuntu-toolchain-r-test # if we don't specify this, the libstdc++6 we get is the wrong version + packages: + - libstdc++6 + install: + - echo 'Avoid default Travis CI install step' + before_script: + - git clone https://github.com/flutter/flutter.git -b stable + - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH + - flutter doctor + - gem install coveralls-lcov + script: + - ./flutter/bin/flutter test --coverage + after_success: + - coveralls-lcov coverage/lcov.info + +# # Builds an APK. +# - env: JOB=APK +# os: linux +# language: android +# licenses: +# - 'android-sdk-preview-license-.+' +# - 'android-sdk-license-.+' +# - 'google-gdk-license-.+' +# android: +# components: +# - tools +# - platform-tools +# - build-tools-25.0.3 +# - android-25 +# - sys-img-armeabi-v7a-google_apis-25 +# - extra-android-m2repository +# - extra-google-m2repository +# - extra-google-android-support +# jdk: oraclejdk8 +# sudo: false +# addons: +# apt: +# # Flutter depends on /usr/lib/x86_64-linux-gnu/libstdc++.so.6 version GLIBCXX_3.4.18 +# sources: +# - ubuntu-toolchain-r-test # if we don't specify this, the libstdc++6 we get is the wrong version +# packages: +# - libstdc++6 +# - fonts-droid +# before_script: +# - wget http://services.gradle.org/distributions/gradle-3.5-bin.zip +# - unzip -qq gradle-3.5-bin.zip +# - export GRADLE_HOME=$PWD/gradle-3.5 +# - export PATH=$GRADLE_HOME/bin:$PATH +# - git clone https://github.com/flutter/flutter.git -b beta +# script: +# - ./flutter/bin/flutter -v build apk +# +# # Builds an IPA. +# - env: JOB=IPA +# os: osx +# language: generic +# osx_image: xcode8.3 +# before_script: +# - pip install six +# - brew update +# - brew install --HEAD libimobiledevice +# - brew install ideviceinstaller +# - brew install ios-deploy +# - git clone https://github.com/flutter/flutter.git -b beta +# script: +# - ./flutter/bin/flutter -v build ios --no-codesign + +cache: + directories: + - $HOME/.pub-cache diff --git a/packages/flutter_calendar_carousel/CHANGELOG.md b/packages/flutter_calendar_carousel/CHANGELOG.md new file mode 100644 index 0000000..aa8ec71 --- /dev/null +++ b/packages/flutter_calendar_carousel/CHANGELOG.md @@ -0,0 +1,306 @@ +## [2.4.3] + +Upgrade intl to `^0.18.1` + +## [2.4.2] + +Support Flutter version 3+ + +## [2.4.1] + +Update iOS podspec and `info.plist` + +## [2.1.0] + +Update build config on flutter V2 embedding (#293) + +## [2.0.3] + +Multiple days selection using `addRange` method [#285](https://github.com/dooboolab/flutter_calendar_carousel/pull/285) + +## [2.0.2] + +Multiple days selection [#282](https://github.com/dooboolab/flutter_calendar_carousel/pull/284) + +## [2.0.1] + +Null safety improvements [#272](https://github.com/dooboolab/flutter_calendar_carousel/pull/272) + +## [2.0.1] + +Added disableDayPressed option [#267](https://github.com/dooboolab/flutter_calendar_carousel/pull/267) + +## [2.0.0] + +Support null-safety [#260](https://github.com/dooboolab/flutter_calendar_carousel/pull/260) + +## [1.5.3] + +- Add `id` to event model [#257](https://github.com/dooboolab/flutter_calendar_carousel/pull/257) + +## [1.5.2] + +- Bump up `intl` dependency [#254](https://github.com/dooboolab/flutter_calendar_carousel/pull/254) + +## [1.5.1] + +- Bugfix when switching month - "The method 'call' was called on null." [#243](https://github.com/dooboolab/flutter_calendar_carousel/pull/243) + +## [1.5.0] + +- Add key to widget constructor [#234](https://github.com/dooboolab/flutter_calendar_carousel/pull/234/files) +- Enhance initilizing page numbers [#231](https://github.com/dooboolab/flutter_calendar_carousel/pull/231) + +## [1.4.12] + +- Handle issue [#207](https://github.com/dooboolab/flutter_calendar_carousel/issues/207), [#209](https://github.com/dooboolab/flutter_calendar_carousel/issues/209) + +## [1.4.11] + +- Add first day of week offset to week builder [#204](https://github.com/dooboolab/flutter_calendar_carousel/pull/204) + +## [1.4.10] + +- Fix Calendar displays incorrectly when scrolling horizontally [#193](https://github.com/dooboolab/flutter_calendar_carousel/pull/193) + +## [1.4.9] + +- Target date for custom header + +## [1.4.8] + +- Add ability to set `targetDate` on header [#183](https://github.com/dooboolab/flutter_calendar_carousel/pull/183). + +## [1.4.7] + +- Fix current day showing incorrectly when using `showOnlyCurrentMonthDate` [#181](https://github.com/dooboolab/flutter_calendar_carousel/pull/182). + +## [1.4.6] + +- Set default `minSelectedDate` and `maxSelectedDate` [#179](https://github.com/dooboolab/flutter_calendar_carousel/pull/179). + +## [1.4.4] + +- Expose `pageScrollPhysics` for pageView. + +## [1.4.2] + +- Add option for setting scrollDirection [#166](https://github.com/dooboolab/flutter_calendar_carousel/pull/166) +- Resolve [#123](https://github.com/dooboolab/flutter_calendar_carousel/issues/123) in [#165](https://github.com/dooboolab/flutter_calendar_carousel/pull/165). + +## [1.4.1] + +- Resolve [#164](https://github.com/dooboolab/flutter_calendar_carousel/issues/164). + +## [1.4.0] + +- Resolve [#154](https://github.com/dooboolab/flutter_calendar_carousel/issues/154). + +## [1.3.29] + +- Resolve [#157](https://github.com/dooboolab/flutter_calendar_carousel/issues/157). + +## [1.3.28] + +- Allow the use of generic type with Interface [#149](https://github.com/dooboolab/flutter_calendar_carousel/pull/149) +- Added doc to custom weekday builder. Weekday number is now supplied to the builder [#150](https://github.com/dooboolab/flutter_calendar_carousel/pull/150) + +## [1.3.27] + +- customDayBuilder fix. +- Remove date_utils dep. + +## [1.3.26] + +- Support custom day container feature [#145](https://github.com/dooboolab/flutter_calendar_carousel/pull/145). + +## [1.3.23] + +- Support intl >= 0.15.7 < 0.17.0 to inclease `pub` health +- Removed deprecated methods ~~`markedDates`~~, ~~`markedDateColor`~~ +- Fixes [#101](https://github.com/dooboolab/flutter_calendar_carousel/issues/101) +- Fixes [#104](https://github.com/dooboolab/flutter_calendar_carousel/issues/104) +- Fixes [#112](https://github.com/dooboolab/flutter_calendar_carousel/issues/112) +- Fixes [#119](https://github.com/dooboolab/flutter_calendar_carousel/issues/119) +- Support long pressed as a feature request[#103](https://github.com/dooboolab/flutter_calendar_carousel/issues/103) +- Support semantic label as a feature request [#139](https://github.com/dooboolab/flutter_calendar_carousel/issues/139) +- Expose `dayCrossAxisAlignment` and `dayMainAxisAlignment` to resolve [#122](https://github.com/dooboolab/flutter_calendar_carousel/issues/122) +- Expose `showIconBehindDayText` to resolve [#131](https://github.com/dooboolab/flutter_calendar_carousel/issues/131) +- Fixes [#94](https://github.com/dooboolab/flutter_calendar_carousel/issues/94) + +## [1.3.20] + +- Support intl >= 0.15.7 + +## [1.3.19] + +- Improved customizability for weekday containers [#141](https://github.com/dooboolab/flutter_calendar_carousel/pull/141) + +## [1.3.18] + +- Fix vertical scroll behavior for weekFormat calendar view. +- Reformat code with dartfmt + +## [1.3.17] + +- Added feature to only show dates from today adding `showOnlyCurrentMonthDate` parameter. + +## [1.3.16] + +- Added feature for change first day of the week. + +## [1.3.15+] + +- Ability to disable horizontal scroll to change month with `isScrollable` param. + - Resolve [#74](https://github.com/dooboolab/flutter_calendar_carousel/issues/74) +- Show events in `week` calendar. + - Resolve [#66](https://github.com/dooboolab/flutter_calendar_carousel/issues/66) +- Update breaking docs in pub. +- Expose event list to user. +- Remove print. +- Pass first date of week to onCalendarChanged in week view [#88](https://github.com/dooboolab/flutter_calendar_carousel/pull/88) +- Support for passing in custom widgets for next and previous month arrow icons [#95](https://github.com/dooboolab/flutter_calendar_carousel/pull/95) + +## [1.3.14] + +- Code refactoring [#77](https://github.com/dooboolab/flutter_calendar_carousel/pull/77) + - Seperate weekday widget + +## [1.3.13] + +- Code refactoring [#73](https://github.com/dooboolab/flutter_calendar_carousel/pull/73) + - Seperate header. + - Add first basic test code. + - Add composable header widget + +## [1.3.12] + +- Setting dot icon per event [#71](https://github.com/dooboolab/flutter_calendar_carousel/pull/71) + +## [1.3.11] + +- Fixed `selectledDayTextStyle` property not being respected [#65](https://github.com/dooboolab/flutter_calendar_carousel/pull/65). + +## [1.3.10] + +- Add property for static six week format to keep calendar height consistent between months [#62](https://github.com/dooboolab/flutter_calendar_carousel/pull/62). + +## [1.3.9] + +- Changed priority for `today` higher than `prevMonth` and `nextMonth` and `thisMonth`. + +## [1.3.7] + +- Ability to choose the weekday format on the constructor [#47](https://github.com/dooboolab/flutter_calendar_carousel/pull/47). + +## [1.3.6] + +- custom event type added [#49](https://github.com/dooboolab/flutter_calendar_carousel/pull/49). + +## [1.3.5] + +- headerTitleTouchable and onHeaderTitlePressed props added [#44](https://github.com/dooboolab/flutter_calendar_carousel/pull/44). + +## [1.3.4] + +- Bug fix. PrevDaysTextStyle and PrevDaysTextStyle overwrite weekendTextStyle [#41](https://github.com/dooboolab/flutter_calendar_carousel/issues/41). + +## [1.3.3] + +- Fixed FlatButton fill and border color. [#37](https://github.com/dooboolab/flutter_calendar_carousel/pull/37) +- EventList bug fixing. [#37](https://github.com/dooboolab/flutter_calendar_carousel/pull/36) + +## [1.3.2] + +- Mapping events for better performance. [#34](https://github.com/dooboolab/flutter_calendar_carousel/pull/34). + +## [1.3.1] + +- weekdays bug fix. + +## [1.3.0] + +- Better localization support for `weekDays`. Setting manually weekdays isn't required now. Related [#23](https://github.com/dooboolab/flutter_calendar_carousel/pull/23). +- Add custom icons in event [#28](https://github.com/dooboolab/flutter_calendar_carousel/pull/28). + +## [1.2.3] + +- Add custom physics parameter. Feature in [#21](https://github.com/dooboolab/flutter_calendar_carousel/pull/21). + +## [1.2.2] + +- headerTextStyle fix[#17](https://github.com/dooboolab/flutter_calendar_carousel/issues/17). +- Can show or hide header button with `showHeaderButton` attribute. + +## [1.2.1] + +- Week-format shows current week [#15](https://github.com/dooboolab/flutter_calendar_carousel/issues/15). + +## [1.2.0] + +- Support carousel week calendar. + +## [1.1.11] + +- Ability to customize weekend days [#13](https://github.com/dooboolab/flutter_calendar_carousel/issues/13). + +## [1.1.10] + +- Support weekFormat but without carousel. + +## [1.1.9] + +- Updated readme. + +## [1.1.8] + +- Render multiple marked dates. +- `markedDates` is deprecated. Use `markedDatesMap` instead. + +## [1.1.3] + +- Mark dates with non-zero times. + +## [1.1.2] + +- Implemented a way to change the header text style. + +## [1.1.1] + +- Expose new variables. + - headerMargin, childAspectRatio, weekDayMargin + +## [1.1.0] + +- Give proper text color in weekend when it is today. +- Compare month and year for marking today's date. Resolve #3. + +## [1.0.3] + +- Fixed pub broken image. + +## [1.0.2] + +- Use `Position` widget to mark the dates. + +## [1.0.1] + +- Show markedDates. + +## [0.2.0] + +- Customizable headerWidget. +- Setting weekdays visibility +- Customizable weekend color. + +## [0.1.3] + +- Rename the top-level "docs" directory to "doc". + +## [0.1.1] + +- Added readme. + +## [0.1.0] + +- First release diff --git a/packages/flutter_calendar_carousel/LICENSE b/packages/flutter_calendar_carousel/LICENSE new file mode 100644 index 0000000..74022ad --- /dev/null +++ b/packages/flutter_calendar_carousel/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 dooboolab + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/flutter_calendar_carousel/README.md b/packages/flutter_calendar_carousel/README.md new file mode 100644 index 0000000..daff642 --- /dev/null +++ b/packages/flutter_calendar_carousel/README.md @@ -0,0 +1,188 @@ +# flutter_calendar_carousel + +[![Pub Version](https://img.shields.io/pub/v/flutter_calendar_carousel.svg?style=flat-square)](https://pub.dartlang.org/packages/flutter_calendar_carousel) +[![Flutter CI](https://github.com/dooboolab/flutter_calendar_carousel/actions/workflows/ci.yml/badge.svg)](https://github.com/dooboolab/flutter_calendar_carousel/actions/workflows/ci.yml) +[![Coverage Status](https://codecov.io/gh/dooboolab/flutter_calendar_carousel/branch/master/graph/badge.svg?token=KTrSs3fGsS)](https://codecov.io/gh/dooboolab/flutter_calendar_carousel) +![License](https://img.shields.io/badge/license-MIT-blue.svg) + +Calendar widget for flutter that is swipeable horizontally. This widget can help you build your own calendar widget highly customizable. Now you can even add your icon for each event. + +## Notice +This widget is compatible with flutter V3 from version `2.4.+`. + +## New Feature + +[2.0.3] + +- Multiple days selection using `addRange` method [#285](https://github.com/dooboolab/flutter_calendar_carousel/pull/285) + +- Check out great feature `customDayBuilder` work done by [maxgmer](https://github.com/maxgmer) :tada:. + +#### Rectangular style + +![image](https://raw.githubusercontent.com/dooboolab/flutter_calendar_carousel/master/doc/calendar1.gif) + +#### Circular style + +![image](https://raw.githubusercontent.com/dooboolab/flutter_calendar_carousel/master/doc/calendar2.gif) + +#### No border + +![image](https://raw.githubusercontent.com/dooboolab/flutter_calendar_carousel/master/doc/calendar3.gif) + +#### Marked Dates + +![image](https://raw.githubusercontent.com/dooboolab/flutter_calendar_carousel/master/doc/calendar4.gif) + +#### Custom Icon Events + +![image](https://raw.githubusercontent.com/icemanbsi/flutter_calendar_carousel/master/doc/calendar5.gif) + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](https://flutter.io/). + +## Props + +| props | types | defaultValues | +| :----------------------------- | :------------------------: | :---------------------------------------------------------------------------------------------------------: | +| viewPortFraction | `double` | 1.0 | +| prevDaysTextStyle | `TextStyle` | | +| daysTextStyle | `TextStyle` | | +| nextDaysTextStyle | `TextStyle` | | +| prevMonthDayBorderColor | `Color` | Colors.transparent | +| thisMonthDayBorderColor | `Color` | Colors.transparent | +| nextMonthDayBorderColor | `Color` | Colors.transparent | +| dayPadding | `double` | 2.0 | +| height | `double` | double.infinity | +| width | `double` | double.infinity | +| todayTextStyle | `TextStyle` | `fontSize: 14.0, color: Colors.white` | +| dayButtonColor | `Color` | Colors.red | +| todayBorderColor | `Color` | Colors.red | +| todayButtonColor | `Colors` | Colors.red | +| selectedDateTime | `DateTime` | | +| selectedDayTextStyle | `TextStyle` | `fontSize: 14.0, color: Colors.white` | +| selectedDayBorderColor | `Color` | Colors.green | +| selectedDayButtonColor | `Color` | Colors.green | +| daysHaveCircularBorder | `bool` | | +| onDayPressed | `Func` | | +| weekdayTextStyle | `TextStyle` | `fontSize: 14.0, color: Colors.deepOrange` | +| iconColor | `Color` | Colors.blueAccent | +| headerTextStyle | `TextStyle` | `fontSize: 20.0, color: Colors.blue` | +| headerText | `Text` | `Text('${DateFormat.yMMM().format(this._dates[1])}'`) | +| weekendTextStyle | `TextStyle` | `fontSize: 14.0, color: Colors.pinkAccent` | +| markedDatesMap | `Events` | `null` | +| markedDateWidget | `Widget` | `Positioned(child: Container(color: Colors.blueAccent, height: 4.0, width: 4.0), bottom: 4.0, left: 18.0);` | +| markedDateShowIcon | `bool` | false | +| markedDateIconBorderColor | `Color` | | +| markedDateIconMaxShown | `int` | 2 | +| markedDateIconMargin | `double` | 5.0 | +| markedDateIconBuilder | `MarkedDateIconBuilder<T>` | | +| markedDateIconOffset | `double` | 5.0 | +| markedDateCustomShapeBorder | `ShapeBorder` | null | +| markedDateCustomTextStyle | `TextStyle` | null | +| markedDateMoreCustomDecoration | `Decoration` | | +| markedDateMoreCustomTextStyle | `TextStyle` | | +| headerMargin | `EdgetInsets` | `const EdgeInsets.symmetric(vertical: 16.0)` | +| headerTitleTouchable | `bool` | `false` | +| onHeaderTitlePressed | `Function` | `() => _selectDateFromPicker()` | +| showHeader | `bool` | | +| showHeaderButton | `bool` | | +| childAspectRatio | `double` | `1.0` | +| weekDayMargin | `EdgeInsets` | `const EdgeInsets.only(bottom: 4.0)` | +| weekFormat | `bool` | `false` | +| locale | `String` | `en` | +| firstDayOfWeek | `int` | `null` | +| onCalendarChanged | `Function(DateTime)` | | +| minSelectedDate | `DateTime` | | +| maxSelectedDate | `DateTime` | | +| inactiveDaysTextStyle | `TextStyle` | | +| inactiveWeekendTextStyle | `TextStyle` | | +| weekDayFormat | `WeekdayFormat` | `short` | +| staticSixWeekFormat | `bool` | `false` | +| showOnlyCurrentMonthDate | `bool` | `false` | +| dayCrossAxisAlignment | `CrossAxisAlignment` | `CrossAxisAlignment.center` | +| dayMainAxisAlignment | `MainAxisAlignment` | `CrossAlignment.center` | +| showIconBehindDayText | `bool` | `false` | +| pageScrollPhysics | `ScrollPhysics` | `ScrollPhysics` | + +With `CalendarCarousel<YourEventClass>` and `EventList<YourEventClass>` you can specifiy a custom Event class. + +## Install + +Add `flutter_calendar_carousel` as a dependency in pubspec.yaml +For help on adding as a dependency, view the [documentation](https://flutter.io/using-packages/). + +## Usage + +```dart +import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart' show CalendarCarousel; +Widget widget() { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16.0), + child: CalendarCarousel<Event>( + onDayPressed: (DateTime date, List<Event> events) { + this.setState(() => _currentDate = date); + }, + weekendTextStyle: TextStyle( + color: Colors.red, + ), + thisMonthDayBorderColor: Colors.grey, +// weekDays: null, /// for pass null when you do not want to render weekDays +// headerText: Container( /// Example for rendering custom header +// child: Text('Custom Header'), +// ), + customDayBuilder: ( /// you can provide your own build function to make custom day containers + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle textStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime day, + ) { + /// If you return null, [CalendarCarousel] will build container for current [day] with default function. + /// This way you can build custom containers for specific days only, leaving rest as default. + + // Example: every 15th of month, we have a flight, we can place an icon in the container like that: + if (day.day == 15) { + return Center( + child: Icon(Icons.local_airport), + ); + } else { + return null; + } + }, + weekFormat: false, + markedDatesMap: _markedDateMap, + height: 420.0, + selectedDateTime: _currentDate, + daysHaveCircularBorder: false, /// null for not rendering any border, true for circular border, false for rectangular border + ), + ); +} +``` + +### TODO + +- [x] Render weekdays. +- [x] Customizable headerWidget. +- [x] Set weekdays visibility. +- [x] Customizable textStyles for days in weekend. +- [x] Marked Dates. +- [x] Multiple Marked Dates. +- [x] Customizable weekend days. +- [x] Week Calendar. +- [x] Carousel Week Calendar. +- [ ] Multiple days selections. +- [x] Widget test. + +## Help Maintenance + +I've been maintaining quite many repos these days and burning out slowly. If you could help me cheer up, buying me a cup of coffee will make my life really happy and get much energy out of it. +<br/> +<a href="https://www.buymeacoffee.com/dooboolab" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/purple_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a> +[![Paypal](https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-100px.png)](https://paypal.me/dooboolab) diff --git a/packages/flutter_calendar_carousel/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/packages/flutter_calendar_carousel/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java new file mode 100644 index 0000000..d007606 --- /dev/null +++ b/packages/flutter_calendar_carousel/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -0,0 +1,23 @@ +package io.flutter.plugins; + +import io.flutter.plugin.common.PluginRegistry; + +/** + * Generated file. Do not edit. + */ +public final class GeneratedPluginRegistrant { + public static void registerWith(PluginRegistry registry) { + if (alreadyRegisteredWith(registry)) { + return; + } + } + + private static boolean alreadyRegisteredWith(PluginRegistry registry) { + final String key = GeneratedPluginRegistrant.class.getCanonicalName(); + if (registry.hasPlugin(key)) { + return true; + } + registry.registrarFor(key); + return false; + } +} diff --git a/packages/flutter_calendar_carousel/android/local.properties b/packages/flutter_calendar_carousel/android/local.properties new file mode 100644 index 0000000..81dcc8b --- /dev/null +++ b/packages/flutter_calendar_carousel/android/local.properties @@ -0,0 +1,3 @@ +sdk.dir=/Users/hyo/Library/Android/sdk +flutter.sdk=/Users/hyo/Github/others/flutter +flutter.versionName=0.0.1
\ No newline at end of file diff --git a/packages/flutter_calendar_carousel/doc/calendar1.gif b/packages/flutter_calendar_carousel/doc/calendar1.gif Binary files differnew file mode 100644 index 0000000..3974a5f --- /dev/null +++ b/packages/flutter_calendar_carousel/doc/calendar1.gif diff --git a/packages/flutter_calendar_carousel/doc/calendar2.gif b/packages/flutter_calendar_carousel/doc/calendar2.gif Binary files differnew file mode 100644 index 0000000..258c372 --- /dev/null +++ b/packages/flutter_calendar_carousel/doc/calendar2.gif diff --git a/packages/flutter_calendar_carousel/doc/calendar3.gif b/packages/flutter_calendar_carousel/doc/calendar3.gif Binary files differnew file mode 100644 index 0000000..d5bda07 --- /dev/null +++ b/packages/flutter_calendar_carousel/doc/calendar3.gif diff --git a/packages/flutter_calendar_carousel/doc/calendar4.gif b/packages/flutter_calendar_carousel/doc/calendar4.gif Binary files differnew file mode 100644 index 0000000..5006372 --- /dev/null +++ b/packages/flutter_calendar_carousel/doc/calendar4.gif diff --git a/packages/flutter_calendar_carousel/doc/calendar5.gif b/packages/flutter_calendar_carousel/doc/calendar5.gif Binary files differnew file mode 100644 index 0000000..bd4cdb1 --- /dev/null +++ b/packages/flutter_calendar_carousel/doc/calendar5.gif diff --git a/packages/flutter_calendar_carousel/issue_template.md b/packages/flutter_calendar_carousel/issue_template.md new file mode 100644 index 0000000..751e4f3 --- /dev/null +++ b/packages/flutter_calendar_carousel/issue_template.md @@ -0,0 +1,9 @@ +### Version of flutter_calendar_carousel + +### Expected behavior + +### Actual behavior + +### flutter doctor result (run flutter doctor in terminal) + +### Steps to reproduce the behavior diff --git a/packages/flutter_calendar_carousel/lib/classes/event.dart b/packages/flutter_calendar_carousel/lib/classes/event.dart new file mode 100644 index 0000000..c852a94 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/classes/event.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; + +class Event implements EventInterface { + final DateTime date; + final String? title; + final String? description; + final String? location; + final Widget? icon; + final Widget? dot; + final int? id; + Event({ + this.id, + required this.date, + this.title, + this.description, + this.location, + this.icon, + this.dot, + }); + + @override + bool operator ==(dynamic other) { + return date == other.date && + title == other.title && + description == other.description && + location == other.location && + icon == other.icon && + dot == other.dot && + id == other.id; + } + + @override + int get hashCode => Object.hash(date, description, location, title, icon, id); + + @override + DateTime getDate() { + return date; + } + + @override + int? getId() { + return id; + } + + @override + Widget? getDot() { + return dot; + } + + @override + Widget? getIcon() { + return icon; + } + + @override + String? getTitle() { + return title; + } + + @override + String? getDescription() { + return description; + } + + @override + String? getLocation() { + return location; + } +} + +abstract class EventInterface { + DateTime getDate(); + String? getTitle(); + String? getDescription(); + String? getLocation(); + Widget? getIcon(); + Widget? getDot(); + int? getId(); +} diff --git a/packages/flutter_calendar_carousel/lib/classes/event_list.dart b/packages/flutter_calendar_carousel/lib/classes/event_list.dart new file mode 100644 index 0000000..a8c9252 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/classes/event_list.dart @@ -0,0 +1,40 @@ +class EventList<T> { + Map<DateTime, List<T>> events; + + EventList({ + required this.events, + }); + + void add(DateTime date, T event) { + final eventsOfDate = events[date]; + if (eventsOfDate == null) + events[date] = [event]; + else + eventsOfDate.add(event); + } + + void addAll(DateTime date, List<T> events) { + final eventsOfDate = this.events[date]; + if (eventsOfDate == null) + this.events[date] = events; + else + eventsOfDate.addAll(events); + } + + bool remove(DateTime date, T event) { + final eventsOfDate = events[date]; + return eventsOfDate != null ? eventsOfDate.remove(event) : false; + } + + List<T> removeAll(DateTime date) { + return events.remove(date) ?? []; + } + + void clear() { + events.clear(); + } + + List<T> getEvents(DateTime date) { + return events[date] ?? []; + } +} diff --git a/packages/flutter_calendar_carousel/lib/classes/marked_date.dart b/packages/flutter_calendar_carousel/lib/classes/marked_date.dart new file mode 100644 index 0000000..a3db2d5 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/classes/marked_date.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; + +class MarkedDate implements MarkedDateInterface { + final Color color; + final int? id; + final TextStyle? textStyle; + final DateTime date; + + MarkedDate({ + required this.color, + this.id, + this.textStyle, + required this.date, + }); + + @override + bool operator ==(dynamic other) { + return date == other.date && + color == other.color && + textStyle == other.textStyle && + id == other.id; + } + + @override + DateTime getDate() => this.date; + + @override + int? getId() => this.id; + + @override + Color getColor() => this.color; + + @override + TextStyle? getTextStyle() => this.textStyle; + + @override + // TODO: implement hashCode + int get hashCode => super.hashCode; +} + +abstract class MarkedDateInterface { + DateTime getDate(); + Color getColor(); + int? getId(); + TextStyle? getTextStyle(); +} diff --git a/packages/flutter_calendar_carousel/lib/classes/multiple_marked_dates.dart b/packages/flutter_calendar_carousel/lib/classes/multiple_marked_dates.dart new file mode 100644 index 0000000..3934549 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/classes/multiple_marked_dates.dart @@ -0,0 +1,86 @@ +import 'marked_date.dart'; +import 'package:flutter/material.dart'; + +class MultipleMarkedDates { + List<MarkedDate> markedDates; + + MultipleMarkedDates({required this.markedDates}); + + void add(MarkedDate markedDate) { + markedDates.add(markedDate); + } + + void addRange(MarkedDate markedDate, {int plus = 0, int minus = 0}) { + this.add(markedDate); + + if (plus > 0) { + int start = 1; + MarkedDate newAddMarkedDate; + + while (start <= plus) { + newAddMarkedDate = new MarkedDate( + color: markedDate.color, + date: markedDate.date.add(Duration(days: start)), + textStyle: markedDate.textStyle, + ); + + this.add(newAddMarkedDate); + + start += 1; + } + } + + if (minus > 0) { + int start = 1; + MarkedDate newSubMarkedDate; + + while (start <= minus) { + newSubMarkedDate = new MarkedDate( + color: markedDate.color, + date: markedDate.date.subtract(Duration(days: start)), + textStyle: markedDate.textStyle, + ); + + this.add(newSubMarkedDate); + + start += 1; + } + } + } + + void addAll(List<MarkedDate> markedDates) { + this.markedDates.addAll(markedDates); + } + + bool remove(MarkedDate markedDate) { + return markedDates.remove(markedDate); + } + + void clear() { + markedDates.clear(); + } + + bool isMarked(DateTime date) { + final results = markedDates.firstWhere((element) => element.date == date, + orElse: () => MarkedDate(color: Colors.black, date: DateTime(0))); + return results.date.year == date.year; + } + + Color getColor(DateTime date) { + final results = markedDates.firstWhere((element) => element.date == date, + orElse: () => MarkedDate(color: Colors.black, date: DateTime(0))); + return results.color; + } + + DateTime getDate(DateTime date) { + final results = markedDates.firstWhere((element) => element.date == date, + orElse: () => MarkedDate(color: Colors.black, date: DateTime(0))); + return results.date; + } + + TextStyle? getTextStyle(DateTime date) { + final results = markedDates.firstWhere((element) => element.date == date, + orElse: () => MarkedDate(color: Colors.black, date: DateTime(0))); + return results.textStyle; + } +} diff --git a/packages/flutter_calendar_carousel/lib/flutter_calendar_carousel.dart b/packages/flutter_calendar_carousel/lib/flutter_calendar_carousel.dart new file mode 100644 index 0000000..14e6cd8 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/flutter_calendar_carousel.dart @@ -0,0 +1,1214 @@ +library flutter_calendar_dooboo; + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_calendar_carousel/classes/event.dart'; +import 'package:flutter_calendar_carousel/classes/event_list.dart'; +import 'package:flutter_calendar_carousel/src/calendar_header.dart'; +import 'package:flutter_calendar_carousel/src/default_styles.dart'; +import 'package:flutter_calendar_carousel/src/weekday_row.dart'; +import 'package:intl/date_symbol_data_local.dart'; +import 'package:intl/intl.dart' show DateFormat; + +import 'classes/multiple_marked_dates.dart'; + +export 'package:flutter_calendar_carousel/classes/event_list.dart'; + +typedef MarkedDateIconBuilder<T> = Widget? Function(T event); +typedef void OnDayLongPressed(DateTime day); + +/// This builder is called for every day in the calendar. +/// If you want to build only few custom day containers, return null for the days you want to leave with default looks +/// All characteristics like circle border are also applied to the custom day container [DayBuilder] provides. +/// (if supplied function returns null, Calendar's function will be called for [day]). +/// [isSelectable] - is between [CalendarCarousel.minSelectedDate] and [CalendarCarousel.maxSelectedDate] +/// [index] - DOES NOT equal day number! Index of the day built in current visible field +/// [isSelectedDay] - if the day is selected +/// [isToday] - if the day is similar to [DateTime.now()] +/// [isPrevMonthDay] - if the day is from previous month +/// [textStyle] - text style that would have been applied by the calendar if it was to build the day. +/// Example: if the user provided [CalendarCarousel.todayTextStyle] and [isToday] is true, +/// [CalendarCarousel.todayTextStyle] would be sent into [DayBuilder]'s [textStyle]. If user didn't +/// provide it, default [CalendarCarousel]'s textStyle would be sent. Same applies to all text styles like +/// [CalendarCarousel.prevDaysTextStyle], [CalendarCarousel.daysTextStyle] etc. +/// [isNextMonthDay] - if the day is from next month +/// [isThisMonthDay] - if the day is from next month +/// [day] - day being built. +typedef Widget? DayBuilder( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle textStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime day); + +/// This builder is called for every weekday container (7 times, from Mon to Sun). +/// [weekday] - weekday built, from 0 to 6. +/// [weekdayName] - string representation of the weekday (Mon, Tue, Wed, etc). +typedef Widget WeekdayBuilder(int weekday, String weekdayName); + +class CalendarCarousel<T extends EventInterface> extends StatefulWidget { + final double viewportFraction; + final TextStyle? prevDaysTextStyle; + final TextStyle? daysTextStyle; + final TextStyle? nextDaysTextStyle; + final Color prevMonthDayBorderColor; + final Color thisMonthDayBorderColor; + final Color nextMonthDayBorderColor; + final double dayPadding; + final double height; + final double width; + final TextStyle? todayTextStyle; + final Color dayButtonColor; + final Color todayBorderColor; + final Color todayButtonColor; + final DateTime? selectedDateTime; + final DateTime? targetDateTime; + final TextStyle? selectedDayTextStyle; + final Color selectedDayButtonColor; + final Color selectedDayBorderColor; + final bool? daysHaveCircularBorder; + final bool disableDayPressed; + final Function(DateTime, List<T>)? onDayPressed; + final TextStyle? weekdayTextStyle; + final Color iconColor; + final TextStyle? headerTextStyle; + final String? headerText; + final TextStyle? weekendTextStyle; + final EventList<T>? markedDatesMap; + + /// Change `makredDateWidget` when `markedDateShowIcon` is set to false. + final Widget? markedDateWidget; + + /// Change `OutlinedBorder` when `markedDateShowIcon` is set to false. + final OutlinedBorder? markedDateCustomShapeBorder; + + /// Change `TextStyle` when `markedDateShowIcon` is set to false. + final TextStyle? markedDateCustomTextStyle; + + /// Icon will overlap the [Day] widget when `markedDateShowIcon` is set to true. + /// This will also make below parameters work. + final bool markedDateShowIcon; + final Color? markedDateIconBorderColor; + final int markedDateIconMaxShown; + final double markedDateIconMargin; + final double markedDateIconOffset; + final MarkedDateIconBuilder<T>? markedDateIconBuilder; + + /// null - no indicator, true - show the total events, false - show the total of hidden events + final bool? markedDateMoreShowTotal; + final Decoration? markedDateMoreCustomDecoration; + final TextStyle? markedDateMoreCustomTextStyle; + final EdgeInsets headerMargin; + final double childAspectRatio; + final EdgeInsets weekDayMargin; + final EdgeInsets weekDayPadding; + final WeekdayBuilder? customWeekDayBuilder; + final DayBuilder? customDayBuilder; + final Color weekDayBackgroundColor; + final bool weekFormat; + final bool showWeekDays; + final bool showHeader; + final bool showHeaderButton; + final MultipleMarkedDates? multipleMarkedDates; + final Widget? leftButtonIcon; + final Widget? rightButtonIcon; + final ScrollPhysics? customGridViewPhysics; + final Function(DateTime)? onCalendarChanged; + final String locale; + final int? firstDayOfWeek; + final DateTime? minSelectedDate; + final DateTime? maxSelectedDate; + final TextStyle? inactiveDaysTextStyle; + final TextStyle? inactiveWeekendTextStyle; + final bool headerTitleTouchable; + final Function? onHeaderTitlePressed; + final Function? onLeftArrowPressed; + final Function? onRightArrowPressed; + final WeekdayFormat weekDayFormat; + final bool staticSixWeekFormat; + final bool isScrollable; + final Axis scrollDirection; + final bool showOnlyCurrentMonthDate; + final bool pageSnapping; + final OnDayLongPressed? onDayLongPressed; + final CrossAxisAlignment dayCrossAxisAlignment; + final MainAxisAlignment dayMainAxisAlignment; + final bool showIconBehindDayText; + final ScrollPhysics pageScrollPhysics; + final bool shouldShowTransform; + + CalendarCarousel({ + Key? key, + this.viewportFraction = 1.0, + this.prevDaysTextStyle, + this.daysTextStyle, + this.nextDaysTextStyle, + this.prevMonthDayBorderColor = Colors.transparent, + this.thisMonthDayBorderColor = Colors.transparent, + this.nextMonthDayBorderColor = Colors.transparent, + this.dayPadding = 2.0, + this.height = double.infinity, + this.width = double.infinity, + this.todayTextStyle, + this.dayButtonColor = Colors.transparent, + this.todayBorderColor = Colors.red, + this.todayButtonColor = Colors.red, + this.selectedDateTime, + this.targetDateTime, + this.selectedDayTextStyle, + this.selectedDayBorderColor = Colors.green, + this.selectedDayButtonColor = Colors.green, + this.daysHaveCircularBorder, + this.disableDayPressed = false, + this.onDayPressed, + this.weekdayTextStyle = const TextStyle(), + this.iconColor = Colors.blueAccent, + this.headerTextStyle, + this.headerText, + this.weekendTextStyle, + this.markedDatesMap, + this.markedDateShowIcon = false, + this.markedDateIconBorderColor, + this.markedDateIconMaxShown = 2, + this.markedDateIconMargin = 5.0, + this.markedDateIconOffset = 5.0, + this.markedDateIconBuilder, + this.markedDateMoreShowTotal, + this.markedDateMoreCustomDecoration, + this.markedDateCustomShapeBorder, + this.markedDateCustomTextStyle, + this.markedDateMoreCustomTextStyle, + this.markedDateWidget, + this.multipleMarkedDates, + this.headerMargin = const EdgeInsets.symmetric(vertical: 16.0), + this.childAspectRatio = 1.0, + this.weekDayMargin = const EdgeInsets.only(bottom: 4.0), + this.weekDayPadding = const EdgeInsets.all(0.0), + this.weekDayBackgroundColor = Colors.transparent, + this.customWeekDayBuilder, + this.customDayBuilder, + this.showWeekDays = true, + this.weekFormat = false, + this.showHeader = true, + this.showHeaderButton = true, + this.leftButtonIcon, + this.rightButtonIcon, + this.customGridViewPhysics, + this.onCalendarChanged, + this.locale = "en", + this.firstDayOfWeek, + this.minSelectedDate, + this.maxSelectedDate, + this.inactiveDaysTextStyle, + this.inactiveWeekendTextStyle, + this.headerTitleTouchable = false, + this.onHeaderTitlePressed, + this.onLeftArrowPressed, + this.onRightArrowPressed, + this.weekDayFormat = WeekdayFormat.short, + this.staticSixWeekFormat = false, + this.isScrollable = true, + this.scrollDirection = Axis.horizontal, + this.showOnlyCurrentMonthDate = false, + this.pageSnapping = false, + this.onDayLongPressed, + this.dayCrossAxisAlignment = CrossAxisAlignment.center, + this.dayMainAxisAlignment = MainAxisAlignment.center, + this.showIconBehindDayText = false, + this.pageScrollPhysics = const ScrollPhysics(), + this.shouldShowTransform = true, + }) : super(key: key); + + @override + _CalendarState<T> createState() => _CalendarState<T>(); +} + +enum WeekdayFormat { + weekdays, + standalone, + short, + standaloneShort, + narrow, + standaloneNarrow, +} + +class _CalendarState<T extends EventInterface> + extends State<CalendarCarousel<T>> { + late PageController _controller; + late List<DateTime> _dates; + late List<List<DateTime>> _weeks; + DateTime _selectedDate = DateTime.now(); + late DateTime _targetDate; + int _startWeekday = 0; + int _endWeekday = 0; + late DateFormat _localeDate; + int _pageNum = 0; + late DateTime minDate; + late DateTime maxDate; + + /// When FIRSTDAYOFWEEK is 0 in dart-intl, it represents Monday. However it is the second day in the arrays of Weekdays. + /// Therefore we need to add 1 modulo 7 to pick the right weekday from intl. (cf. [GlobalMaterialLocalizations]) + late int firstDayOfWeek; + + /// If the setState called from this class, don't reload the selectedDate, but it should reload selected date if called from external class + + @override + initState() { + super.initState(); + initializeDateFormatting(); + + minDate = widget.minSelectedDate ?? DateTime(2018); + maxDate = widget.maxSelectedDate ?? + DateTime( + DateTime.now().year + 1, DateTime.now().month, DateTime.now().day); + + final selectedDateTime = widget.selectedDateTime; + if (selectedDateTime != null) _selectedDate = selectedDateTime; + + _init(); + + /// setup pageController + _controller = PageController( + initialPage: this._pageNum, + keepPage: true, + viewportFraction: widget.viewportFraction, + + /// width percentage + ); + + _localeDate = DateFormat.yMMM(widget.locale); + firstDayOfWeek = widget.firstDayOfWeek ?? + (_localeDate.dateSymbols.FIRSTDAYOFWEEK + 1) % 7; + + _setDate(); + } + + @override + void didUpdateWidget(CalendarCarousel<T> oldWidget) { + if (widget.targetDateTime != null && widget.targetDateTime != _targetDate) { + _init(); + _setDate(_pageNum); + } + + super.didUpdateWidget(oldWidget); + } + + @override + dispose() { + _controller.dispose(); + super.dispose(); + } + + _init() { + final targetDateTime = widget.targetDateTime; + if (targetDateTime != null) { + if (targetDateTime.difference(minDate).inDays < 0) { + _targetDate = minDate; + } else if (targetDateTime.difference(maxDate).inDays > 0) { + _targetDate = maxDate; + } else { + _targetDate = targetDateTime; + } + } else { + _targetDate = _selectedDate; + } + if (widget.weekFormat) { + _pageNum = _targetDate.difference(_firstDayOfWeek(minDate)).inDays ~/ 7; + } else { + _pageNum = (_targetDate.year - minDate.year) * 12 + + _targetDate.month - + minDate.month; + } + } + + @override + Widget build(BuildContext context) { + final headerText = widget.headerText; + return Container( + width: widget.width, + height: widget.height, + child: Column( + children: <Widget>[ + CalendarHeader( + showHeader: widget.showHeader, + headerMargin: widget.headerMargin, + headerTitle: headerText != null + ? headerText + : widget.weekFormat + ? '${_localeDate.format(this._weeks[this._pageNum].first)}' + : '${_localeDate.format(this._dates[this._pageNum])}', + headerTextStyle: widget.headerTextStyle, + showHeaderButtons: widget.showHeaderButton, + headerIconColor: widget.iconColor, + leftButtonIcon: widget.leftButtonIcon, + rightButtonIcon: widget.rightButtonIcon, + onLeftButtonPressed: () { + widget.onLeftArrowPressed?.call(); + + if (this._pageNum > 0) _setDate(this._pageNum - 1); + }, + onRightButtonPressed: () { + widget.onRightArrowPressed?.call(); + + if (widget.weekFormat) { + if (this._weeks.length - 1 > this._pageNum) + _setDate(this._pageNum + 1); + } else { + if (this._dates.length - 1 > this._pageNum) + _setDate(this._pageNum + 1); + } + }, + onHeaderTitlePressed: widget.headerTitleTouchable + ? () { + final onHeaderTitlePressed = widget.onHeaderTitlePressed; + if (onHeaderTitlePressed != null) { + onHeaderTitlePressed(); + } else { + _selectDateFromPicker(); + } + } + : null, + ), + WeekdayRow( + firstDayOfWeek, + widget.customWeekDayBuilder, + showWeekdays: widget.showWeekDays, + weekdayFormat: widget.weekDayFormat, + weekdayMargin: widget.weekDayMargin, + weekdayPadding: widget.weekDayPadding, + weekdayBackgroundColor: widget.weekDayBackgroundColor, + weekdayTextStyle: widget.weekdayTextStyle, + localeDate: _localeDate, + ), + Expanded( + child: PageView.builder( + itemCount: + widget.weekFormat ? this._weeks.length : this._dates.length, + physics: widget.isScrollable + ? widget.pageScrollPhysics + : NeverScrollableScrollPhysics(), + scrollDirection: widget.scrollDirection, + onPageChanged: (index) { + this._setDate(index); + }, + controller: _controller, + itemBuilder: (context, index) { + return widget.weekFormat ? weekBuilder(index) : builder(index); + }, + pageSnapping: widget.pageSnapping, + )), + ], + ), + ); + } + + Widget getDefaultDayContainer( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle? textStyle, + TextStyle defaultTextStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime now, + ) { + return Container( + width: double.infinity, + height: double.infinity, + child: Row( + crossAxisAlignment: widget.dayCrossAxisAlignment, + mainAxisAlignment: widget.dayMainAxisAlignment, + children: <Widget>[ + DefaultTextStyle( + style: getDefaultDayStyle( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay), + child: Text( + '${now.day}', + semanticsLabel: now.day.toString(), + style: getDayStyle( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now), + maxLines: 1, + ), + ), + ], + ), + ); + } + + Widget renderDay( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle? textStyle, + TextStyle defaultTextStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime now, + ) { + // If day is in Multiple selection mode, get its color + bool isMultipleMarked = widget.multipleMarkedDates?.isMarked(now) ?? false; + Color? multipleMarkedColor = widget.multipleMarkedDates?.getColor(now); + + final markedDatesMap = widget.markedDatesMap; + return Container( + margin: EdgeInsets.all(widget.dayPadding), + child: GestureDetector( + onLongPress: () => _onDayLongPressed(now), + child: TextButton( + style: TextButton.styleFrom( + shape: widget.markedDateCustomShapeBorder != null && + markedDatesMap != null && + markedDatesMap.getEvents(now).length > 0 + ? widget.markedDateCustomShapeBorder + : widget.daysHaveCircularBorder == null + ? CircleBorder() + : widget.daysHaveCircularBorder ?? false + ? CircleBorder( + side: BorderSide( + color: isSelectedDay + ? widget.selectedDayBorderColor + : isToday + ? widget.todayBorderColor + : isPrevMonthDay + ? widget.prevMonthDayBorderColor + : isNextMonthDay + ? widget.nextMonthDayBorderColor + : widget.thisMonthDayBorderColor, + ), + ) + : RoundedRectangleBorder( + side: BorderSide( + color: isSelectedDay + ? widget.selectedDayBorderColor + : isToday + ? widget.todayBorderColor + : isPrevMonthDay + ? widget.prevMonthDayBorderColor + : isNextMonthDay + ? widget.nextMonthDayBorderColor + : widget.thisMonthDayBorderColor, + ), + ), + backgroundColor: isSelectedDay + ? widget.selectedDayButtonColor + : isToday + ? widget.todayButtonColor + + // If day is in Multiple selection mode, apply a different color + : isMultipleMarked + ? multipleMarkedColor + : widget.dayButtonColor, + padding: EdgeInsets.all(widget.dayPadding), + ), + onPressed: widget.disableDayPressed ? null : () => _onDayPressed(now), + child: Stack( + children: widget.showIconBehindDayText + ? <Widget>[ + widget.markedDatesMap != null + ? _renderMarkedMapContainer(now) + : Container(), + getDayContainer( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now), + ] + : <Widget>[ + getDayContainer( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now), + widget.markedDatesMap != null + ? _renderMarkedMapContainer(now) + : Container(), + ], + ), + ), + ), + ); + } + + AnimatedBuilder builder(int slideIndex) { + _startWeekday = _dates[slideIndex].weekday - firstDayOfWeek; + if (_startWeekday == 7) { + _startWeekday = 0; + } + _endWeekday = + DateTime(_dates[slideIndex].year, _dates[slideIndex].month + 1, 1) + .weekday - + firstDayOfWeek; + double screenWidth = MediaQuery.of(context).size.width; + int totalItemCount = widget.staticSixWeekFormat + ? 42 + : DateTime( + _dates[slideIndex].year, + _dates[slideIndex].month + 1, + 0, + ).day + + _startWeekday + + (7 - _endWeekday); + int year = _dates[slideIndex].year; + int month = _dates[slideIndex].month; + + return AnimatedBuilder( + animation: _controller, + builder: (context, child) { + if (!widget.shouldShowTransform) { + return child!; + } + double value = 1.0; + if (_controller.position.haveDimensions) { + value = _controller.page! - slideIndex; + value = (1 - (value.abs() * .5)).clamp(0.0, 1.0); + } + + return Center( + child: SizedBox( + height: Curves.easeOut.transform(value) * widget.height, + width: Curves.easeOut.transform(value) * screenWidth, + child: child, + ), + ); + }, + child: Stack( + children: <Widget>[ + Positioned( + child: Container( + width: double.infinity, + height: double.infinity, + child: GridView.count( + physics: widget.customGridViewPhysics, + crossAxisCount: 7, + childAspectRatio: widget.childAspectRatio, + padding: EdgeInsets.zero, + children: List.generate(totalItemCount, + + /// last day of month + weekday + (index) { + final selectedDateTime = widget.selectedDateTime; + bool isToday = + DateTime.now().day == index + 1 - _startWeekday && + DateTime.now().month == month && + DateTime.now().year == year; + bool isSelectedDay = selectedDateTime != null && + selectedDateTime.year == year && + selectedDateTime.month == month && + selectedDateTime.day == index + 1 - _startWeekday; + bool isPrevMonthDay = index < _startWeekday; + bool isNextMonthDay = index >= + (DateTime(year, month + 1, 0).day) + _startWeekday; + bool isThisMonthDay = !isPrevMonthDay && !isNextMonthDay; + + DateTime now = DateTime(year, month, 1); + TextStyle? textStyle; + TextStyle defaultTextStyle; + if (isPrevMonthDay && !widget.showOnlyCurrentMonthDate) { + now = now.subtract(Duration(days: _startWeekday - index)); + textStyle = widget.prevDaysTextStyle; + defaultTextStyle = defaultPrevDaysTextStyle; + } else if (isThisMonthDay) { + now = DateTime(year, month, index + 1 - _startWeekday); + textStyle = isSelectedDay + ? widget.selectedDayTextStyle + : isToday + ? widget.todayTextStyle + : widget.daysTextStyle; + defaultTextStyle = isSelectedDay + ? defaultSelectedDayTextStyle + : isToday + ? defaultTodayTextStyle + : defaultDaysTextStyle; + } else if (!widget.showOnlyCurrentMonthDate) { + now = DateTime(year, month, index + 1 - _startWeekday); + textStyle = widget.nextDaysTextStyle; + defaultTextStyle = defaultNextDaysTextStyle; + } else { + return Container(); + } + final markedDatesMap = widget.markedDatesMap; + if (widget.markedDateCustomTextStyle != null && + markedDatesMap != null && + markedDatesMap.getEvents(now).length > 0) { + textStyle = widget.markedDateCustomTextStyle; + } + bool isSelectable = true; + if (now.millisecondsSinceEpoch < + minDate.millisecondsSinceEpoch) + isSelectable = false; + else if (now.millisecondsSinceEpoch > + maxDate.millisecondsSinceEpoch) isSelectable = false; + return renderDay( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now); + }), + ), + ), + ), + ], + ), + ); + } + + AnimatedBuilder weekBuilder(int slideIndex) { + double screenWidth = MediaQuery.of(context).size.width; + List<DateTime> weekDays = _weeks[slideIndex]; + + weekDays = weekDays + .map((weekDay) => weekDay.add(Duration(days: firstDayOfWeek))) + .toList(); + + return AnimatedBuilder( + animation: _controller, + builder: (context, child) { + double value = 1.0; + if (_controller.position.haveDimensions) { + value = _controller.page! - slideIndex; + value = (1 - (value.abs() * .5)).clamp(0.0, 1.0); + } + + return Center( + child: SizedBox( + height: Curves.easeOut.transform(value) * widget.height, + width: Curves.easeOut.transform(value) * screenWidth, + child: child, + ), + ); + }, + child: Stack( + children: <Widget>[ + Positioned( + child: Container( + width: double.infinity, + height: double.infinity, + child: GridView.count( + physics: widget.customGridViewPhysics, + crossAxisCount: 7, + childAspectRatio: widget.childAspectRatio, + padding: EdgeInsets.zero, + children: List.generate(weekDays.length, (index) { + /// last day of month + weekday + bool isToday = weekDays[index].day == DateTime.now().day && + weekDays[index].month == DateTime.now().month && + weekDays[index].year == DateTime.now().year; + bool isSelectedDay = + this._selectedDate.year == weekDays[index].year && + this._selectedDate.month == weekDays[index].month && + this._selectedDate.day == weekDays[index].day; + bool isPrevMonthDay = + weekDays[index].month < this._targetDate.month; + bool isNextMonthDay = + weekDays[index].month > this._targetDate.month; + bool isThisMonthDay = !isPrevMonthDay && !isNextMonthDay; + + DateTime now = DateTime(weekDays[index].year, + weekDays[index].month, weekDays[index].day); + TextStyle? textStyle; + TextStyle defaultTextStyle; + if (isPrevMonthDay && !widget.showOnlyCurrentMonthDate) { + textStyle = widget.prevDaysTextStyle; + defaultTextStyle = defaultPrevDaysTextStyle; + } else if (isThisMonthDay) { + textStyle = isSelectedDay + ? widget.selectedDayTextStyle + : isToday + ? widget.todayTextStyle + : widget.daysTextStyle; + defaultTextStyle = isSelectedDay + ? defaultSelectedDayTextStyle + : isToday + ? defaultTodayTextStyle + : defaultDaysTextStyle; + } else if (!widget.showOnlyCurrentMonthDate) { + textStyle = widget.nextDaysTextStyle; + defaultTextStyle = defaultNextDaysTextStyle; + } else { + return Container(); + } + bool isSelectable = true; + if (now.millisecondsSinceEpoch < + minDate.millisecondsSinceEpoch) + isSelectable = false; + else if (now.millisecondsSinceEpoch > + maxDate.millisecondsSinceEpoch) isSelectable = false; + return renderDay( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now); + }), + ), + ), + ), + ], + )); + } + + List<DateTime> _getDaysInWeek([DateTime? selectedDate]) { + if (selectedDate == null) selectedDate = new DateTime.now(); + + var firstDayOfCurrentWeek = _firstDayOfWeek(selectedDate); + var lastDayOfCurrentWeek = _lastDayOfWeek(selectedDate); + + return _daysInRange(firstDayOfCurrentWeek, lastDayOfCurrentWeek).toList(); + } + + DateTime _firstDayOfWeek(DateTime date) { + var day = _createUTCMiddayDateTime(date); + return day.subtract(new Duration(days: date.weekday % 7)); + } + + DateTime _lastDayOfWeek(DateTime date) { + var day = _createUTCMiddayDateTime(date); + return day.add(new Duration(days: 7 - day.weekday % 7)); + } + + DateTime _createUTCMiddayDateTime(DateTime date) { + // Magic const: 12 is to maintain compatibility with date_utils + return new DateTime.utc(date.year, date.month, date.day, 12, 0, 0); + } + + Iterable<DateTime> _daysInRange(DateTime start, DateTime end) { + var offset = start.timeZoneOffset; + + return List<int>.generate(end.difference(start).inDays, (i) => i + 1) + .map((int i) { + var d = start.add(Duration(days: i - 1)); + + var timeZoneDiff = d.timeZoneOffset - offset; + if (timeZoneDiff.inSeconds != 0) { + offset = d.timeZoneOffset; + d = d.subtract(new Duration(seconds: timeZoneDiff.inSeconds)); + } + return d; + }); + } + + void _onDayLongPressed(DateTime picked) { + widget.onDayLongPressed?.call(picked); + } + + void _onDayPressed(DateTime picked) { + if (picked.millisecondsSinceEpoch < minDate.millisecondsSinceEpoch) return; + if (picked.millisecondsSinceEpoch > maxDate.millisecondsSinceEpoch) return; + + setState(() { + _selectedDate = picked; + }); + widget.onDayPressed + ?.call(picked, widget.markedDatesMap?.getEvents(picked) ?? const []); + } + + Future<Null> _selectDateFromPicker() async { + DateTime? selected = await showDatePicker( + context: context, + initialDate: _selectedDate, + firstDate: minDate, + lastDate: maxDate, + ); + + if (selected != null) { + // updating selected date range based on selected week + setState(() { + _selectedDate = selected; + }); + widget.onDayPressed?.call( + selected, widget.markedDatesMap?.getEvents(selected) ?? const []); + } + } + + void _setDatesAndWeeks() { + /// Setup default calendar format + List<DateTime> date = []; + int currentDateIndex = 0; + for (int _cnt = 0; + 0 >= + DateTime(minDate.year, minDate.month + _cnt) + .difference(DateTime(maxDate.year, maxDate.month)) + .inDays; + _cnt++) { + date.add(DateTime(minDate.year, minDate.month + _cnt, 1)); + if (0 == + date.last + .difference( + DateTime(this._targetDate.year, this._targetDate.month)) + .inDays) { + currentDateIndex = _cnt; + } + } + + /// Setup week-only format + List<List<DateTime>> week = []; + for (int _cnt = 0; + 0 >= + minDate + .add(Duration(days: 7 * _cnt)) + .difference(maxDate.add(Duration(days: 7))) + .inDays; + _cnt++) { + week.add(_getDaysInWeek(minDate.add(new Duration(days: 7 * _cnt)))); + } + + _startWeekday = date[currentDateIndex].weekday - firstDayOfWeek; + /*if (widget.showOnlyCurrentMonthDate) { + _startWeekday--; + }*/ + if (/*widget.showOnlyCurrentMonthDate && */ _startWeekday == 7) { + _startWeekday = 0; + } + _endWeekday = DateTime(date[currentDateIndex].year, + date[currentDateIndex].month + 1, 1) + .weekday - + firstDayOfWeek; + this._dates = date; + this._weeks = week; +// this._selectedDate = widget.selectedDateTime != null +// ? widget.selectedDateTime +// : DateTime.now(); + } + + void _setDate([int page = -1]) { + if (page == -1) { + setState(() { + _setDatesAndWeeks(); + }); + } else { + if (widget.weekFormat) { + setState(() { + this._pageNum = page; + this._targetDate = this._weeks[page].first; + }); + + _controller.animateToPage(page, + duration: Duration(milliseconds: 1), curve: Threshold(0.0)); + } else { + setState(() { + this._pageNum = page; + this._targetDate = this._dates[page]; + _startWeekday = _dates[page].weekday - firstDayOfWeek; + _endWeekday = _lastDayOfWeek(_dates[page]).weekday - firstDayOfWeek; + }); + _controller.animateToPage(page, + duration: Duration(milliseconds: 1), curve: Threshold(0.0)); + } + + //call callback + final onCalendarChanged = widget.onCalendarChanged; + if (onCalendarChanged != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + onCalendarChanged(!widget.weekFormat + ? this._dates[page] + : this._weeks[page][firstDayOfWeek]); + }); + } + } + } + + Widget _renderMarkedMapContainer(DateTime now) { + if (widget.markedDateShowIcon) { + return Stack( + children: _renderMarkedMap(now), + ); + } else { + return Container( + height: double.infinity, + padding: EdgeInsets.only(bottom: 4.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: _renderMarkedMap(now), + ), + ); + } + } + + List<Widget> _renderMarkedMap(DateTime now) { + final markedEvents = widget.markedDatesMap?.getEvents(now) ?? []; + final markedDateIconBuilder = widget.markedDateIconBuilder; + final markedDateWidget = widget.markedDateWidget; + final markedDateMoreShowTotal = widget.markedDateMoreShowTotal; + final markedDateMoreCustomTextStyle = widget.markedDateMoreCustomTextStyle; + final markedDateIconMargin = widget.markedDateIconMargin; + final markedDateShowIcon = widget.markedDateShowIcon; + final markedDateIconMaxShown = widget.markedDateIconMaxShown; + final markedDateIconOffset = widget.markedDateIconOffset; + final markedDateMoreCustomDecoration = + widget.markedDateMoreCustomDecoration; + + if (markedEvents.length > 0) { + List<Widget> tmp = []; + int count = 0; + int eventIndex = 0; + double offset = 0.0; + double padding = markedDateIconMargin; + markedEvents.forEach((T event) { + if (markedDateShowIcon) { + if (tmp.length > 0 && tmp.length < markedDateIconMaxShown) { + offset += markedDateIconOffset; + } + if (tmp.length < markedDateIconMaxShown && + markedDateIconBuilder != null) { + tmp.add(Center( + child: new Container( + padding: EdgeInsets.only( + top: padding + offset, + left: padding + offset, + right: padding - offset, + bottom: padding - offset, + ), + width: double.infinity, + height: double.infinity, + child: markedDateIconBuilder(event), + ))); + } else { + count++; + } + if (count > 0 && markedDateMoreShowTotal != null) { + tmp.add( + Positioned( + bottom: 0.0, + right: 0.0, + child: Container( + padding: EdgeInsets.all(4.0), + width: markedDateMoreShowTotal ? 18 : null, + height: markedDateMoreShowTotal ? 18 : null, + decoration: markedDateMoreCustomDecoration == null + ? new BoxDecoration( + color: Colors.red, + borderRadius: + BorderRadius.all(Radius.circular(1000.0)), + ) + : markedDateMoreCustomDecoration, + child: Center( + child: Text( + markedDateMoreShowTotal + ? (count + markedDateIconMaxShown).toString() + : (count.toString() + '+'), + semanticsLabel: markedDateMoreShowTotal + ? (count + markedDateIconMaxShown).toString() + : (count.toString() + '+'), + style: markedDateMoreCustomTextStyle == null + ? TextStyle( + fontSize: 9.0, + color: Colors.white, + fontWeight: FontWeight.normal) + : markedDateMoreCustomTextStyle, + ), + ), + ), + ), + ); + } + } else { + //max 5 dots + if (eventIndex < 5) { + Widget? widget; + + if (markedDateIconBuilder != null) { + widget = markedDateIconBuilder(event); + } + + if (widget != null) { + tmp.add(widget); + } else { + final dot = event.getDot(); + if (dot != null) { + tmp.add(dot); + } else if (markedDateWidget != null) { + tmp.add(markedDateWidget); + } else { + tmp.add(defaultMarkedDateWidget); + } + } + } + } + + eventIndex++; + }); + return tmp; + } + return []; + } + + TextStyle getDefaultDayStyle( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle? textStyle, + TextStyle defaultTextStyle, + bool isNextMonthDay, + bool isThisMonthDay, + ) { + return !isSelectable + ? defaultInactiveDaysTextStyle + : (_localeDate.dateSymbols.WEEKENDRANGE + .contains((index - 1 + firstDayOfWeek) % 7)) && + !isSelectedDay && + !isToday + ? (isPrevMonthDay + ? defaultPrevDaysTextStyle + : isNextMonthDay + ? defaultNextDaysTextStyle + : isSelectable + ? defaultWeekendTextStyle + : defaultInactiveWeekendTextStyle) + : isToday + ? defaultTodayTextStyle + : isSelectable && textStyle != null + ? textStyle + : defaultTextStyle; + } + + TextStyle? getDayStyle( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle? textStyle, + TextStyle defaultTextStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime now) { + // If day is in multiple selection get its style(if available) + bool isMultipleMarked = widget.multipleMarkedDates?.isMarked(now) ?? false; + TextStyle? mutipleMarkedTextStyle = + widget.multipleMarkedDates?.getTextStyle(now); + + return isSelectedDay && widget.selectedDayTextStyle != null + ? widget.selectedDayTextStyle + : isMultipleMarked + ? mutipleMarkedTextStyle + : (_localeDate.dateSymbols.WEEKENDRANGE + .contains((index - 1 + firstDayOfWeek) % 7)) && + !isSelectedDay && + isThisMonthDay && + !isToday + ? (isSelectable + ? widget.weekendTextStyle + : widget.inactiveWeekendTextStyle) + : !isSelectable + ? widget.inactiveDaysTextStyle + : isPrevMonthDay + ? widget.prevDaysTextStyle + : isNextMonthDay + ? widget.nextDaysTextStyle + : isToday + ? widget.todayTextStyle + : widget.daysTextStyle; + } + + Widget getDayContainer( + bool isSelectable, + int index, + bool isSelectedDay, + bool isToday, + bool isPrevMonthDay, + TextStyle? textStyle, + TextStyle defaultTextStyle, + bool isNextMonthDay, + bool isThisMonthDay, + DateTime now) { + final customDayBuilder = widget.customDayBuilder; + + Widget? dayContainer; + if (customDayBuilder != null) { + final appTextStyle = DefaultTextStyle.of(context).style; + + final dayStyle = getDayStyle( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now, + ); + + final styleForBuilder = appTextStyle.merge(dayStyle); + + dayContainer = customDayBuilder( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + styleForBuilder, + isNextMonthDay, + isThisMonthDay, + now); + } + + return dayContainer ?? + getDefaultDayContainer( + isSelectable, + index, + isSelectedDay, + isToday, + isPrevMonthDay, + textStyle, + defaultTextStyle, + isNextMonthDay, + isThisMonthDay, + now, + ); + } +} diff --git a/packages/flutter_calendar_carousel/lib/src/calendar_header.dart b/packages/flutter_calendar_carousel/lib/src/calendar_header.dart new file mode 100644 index 0000000..7fcfd81 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/src/calendar_header.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'default_styles.dart' show defaultHeaderTextStyle; + +class CalendarHeader extends StatelessWidget { + /// Passing in values for [leftButtonIcon] or [rightButtonIcon] will override [headerIconColor] + CalendarHeader( + {required this.headerTitle, + this.headerMargin, + required this.showHeader, + this.headerTextStyle, + this.showHeaderButtons = true, + this.headerIconColor, + this.leftButtonIcon, + this.rightButtonIcon, + required this.onLeftButtonPressed, + required this.onRightButtonPressed, + this.onHeaderTitlePressed}) + : isTitleTouchable = onHeaderTitlePressed != null; + + final String headerTitle; + final EdgeInsetsGeometry? headerMargin; + final bool showHeader; + final TextStyle? headerTextStyle; + final bool showHeaderButtons; + final Color? headerIconColor; + final Widget? leftButtonIcon; + final Widget? rightButtonIcon; + final VoidCallback onLeftButtonPressed; + final VoidCallback onRightButtonPressed; + final bool isTitleTouchable; + final VoidCallback? onHeaderTitlePressed; + + TextStyle get getTextStyle => headerTextStyle ?? defaultHeaderTextStyle; + + Widget _leftButton() => IconButton( + onPressed: onLeftButtonPressed, + icon: + leftButtonIcon ?? Icon(Icons.chevron_left, color: headerIconColor), + ); + + Widget _rightButton() => IconButton( + onPressed: onRightButtonPressed, + icon: rightButtonIcon ?? + Icon(Icons.chevron_right, color: headerIconColor), + ); + + Widget _headerTouchable() => TextButton( + onPressed: onHeaderTitlePressed, + child: Text( + headerTitle, + semanticsLabel: headerTitle, + style: getTextStyle, + ), + ); + + @override + Widget build(BuildContext context) => showHeader + ? Container( + margin: headerMargin, + child: DefaultTextStyle( + style: getTextStyle, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + showHeaderButtons ? _leftButton() : Container(), + isTitleTouchable + ? _headerTouchable() + : Text(headerTitle, style: getTextStyle), + showHeaderButtons ? _rightButton() : Container(), + ])), + ) + : Container(); +} diff --git a/packages/flutter_calendar_carousel/lib/src/default_styles.dart b/packages/flutter_calendar_carousel/lib/src/default_styles.dart new file mode 100644 index 0000000..cfeddc9 --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/src/default_styles.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +const TextStyle defaultHeaderTextStyle = const TextStyle( + fontSize: 20.0, + color: Colors.blue, +); +const TextStyle defaultPrevDaysTextStyle = const TextStyle( + color: Colors.grey, + fontSize: 14.0, +); +const TextStyle defaultNextDaysTextStyle = const TextStyle( + color: Colors.grey, + fontSize: 14.0, +); +const TextStyle defaultDaysTextStyle = const TextStyle( + color: Colors.black, + fontSize: 14.0, +); +const TextStyle defaultTodayTextStyle = const TextStyle( + color: Colors.white, + fontSize: 14.0, +); +const TextStyle defaultSelectedDayTextStyle = const TextStyle( + color: Colors.white, + fontSize: 14.0, +); +const TextStyle defaultWeekdayTextStyle = const TextStyle( + color: Colors.deepOrange, + fontSize: 14.0, +); +const TextStyle defaultWeekendTextStyle = const TextStyle( + color: Colors.pinkAccent, + fontSize: 14.0, +); +const TextStyle defaultInactiveDaysTextStyle = const TextStyle( + color: Colors.black38, + fontSize: 14.0, +); +final TextStyle defaultInactiveWeekendTextStyle = TextStyle( + color: Colors.pinkAccent.withOpacity(0.6), + fontSize: 14.0, +); +final Widget defaultMarkedDateWidget = Container( + margin: EdgeInsets.symmetric(horizontal: 1.0), + color: Colors.blueAccent, + height: 4.0, + width: 4.0, +); diff --git a/packages/flutter_calendar_carousel/lib/src/weekday_row.dart b/packages/flutter_calendar_carousel/lib/src/weekday_row.dart new file mode 100644 index 0000000..48f5b3a --- /dev/null +++ b/packages/flutter_calendar_carousel/lib/src/weekday_row.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'; +import 'package:flutter_calendar_carousel/src/default_styles.dart' + show defaultWeekdayTextStyle; +import 'package:intl/intl.dart'; + +class WeekdayRow extends StatelessWidget { + WeekdayRow(this.firstDayOfWeek, this.customWeekdayBuilder, + {required this.showWeekdays, + required this.weekdayFormat, + required this.weekdayMargin, + required this.weekdayPadding, + required this.weekdayBackgroundColor, + required this.weekdayTextStyle, + required this.localeDate}); + + final WeekdayBuilder? customWeekdayBuilder; + final bool showWeekdays; + final WeekdayFormat weekdayFormat; + final EdgeInsets weekdayMargin; + final EdgeInsets weekdayPadding; + final Color weekdayBackgroundColor; + final TextStyle? weekdayTextStyle; + final DateFormat localeDate; + final int firstDayOfWeek; + + Widget _weekdayContainer(int weekday, String weekDayName) { + final customWeekdayBuilder = this.customWeekdayBuilder; + return customWeekdayBuilder != null + ? customWeekdayBuilder(weekday, weekDayName) + : Expanded( + child: Container( + decoration: BoxDecoration( + border: Border.all(color: weekdayBackgroundColor), + color: weekdayBackgroundColor, + ), + margin: weekdayMargin, + padding: weekdayPadding, + child: Center( + child: DefaultTextStyle( + style: defaultWeekdayTextStyle, + child: Text( + weekDayName, + semanticsLabel: weekDayName, + style: weekdayTextStyle, + ), + ), + ), + )); + } + +// List<Widget> _generateWeekdays() { +// switch (weekdayFormat) { +// case WeekdayFormat.weekdays: +// return localeDate.dateSymbols.WEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// case WeekdayFormat.standalone: +// return localeDate.dateSymbols.STANDALONEWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// case WeekdayFormat.short: +// return localeDate.dateSymbols.SHORTWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// case WeekdayFormat.standaloneShort: +// return localeDate.dateSymbols.STANDALONESHORTWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// case WeekdayFormat.narrow: +// return localeDate.dateSymbols.NARROWWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// case WeekdayFormat.standaloneNarrow: +// return localeDate.dateSymbols.STANDALONENARROWWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// default: +// return localeDate.dateSymbols.STANDALONEWEEKDAYS +// .map<Widget>(_weekdayContainer) +// .toList(); +// } +// } + + // TODO - locale issues + List<Widget> _renderWeekDays() { + List<Widget> list = []; + + /// because of number of days in a week is 7, so it would be easier to count it til 7. + for (var i = firstDayOfWeek, count = 0; + count < 7; + i = (i + 1) % 7, count++) { + String weekDay; + + switch (weekdayFormat) { + case WeekdayFormat.weekdays: + weekDay = localeDate.dateSymbols.WEEKDAYS[i]; + break; + case WeekdayFormat.standalone: + weekDay = localeDate.dateSymbols.STANDALONEWEEKDAYS[i]; + break; + case WeekdayFormat.short: + weekDay = localeDate.dateSymbols.SHORTWEEKDAYS[i]; + break; + case WeekdayFormat.standaloneShort: + weekDay = localeDate.dateSymbols.STANDALONESHORTWEEKDAYS[i]; + break; + case WeekdayFormat.narrow: + weekDay = localeDate.dateSymbols.NARROWWEEKDAYS[i]; + break; + case WeekdayFormat.standaloneNarrow: + weekDay = localeDate.dateSymbols.STANDALONENARROWWEEKDAYS[i]; + break; + default: + weekDay = localeDate.dateSymbols.STANDALONEWEEKDAYS[i]; + break; + } + list.add(_weekdayContainer(count, weekDay)); + } + + return list; + } + + @override + Widget build(BuildContext context) => showWeekdays + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _renderWeekDays(), + ) + : Container(); +} diff --git a/packages/flutter_calendar_carousel/pubspec.lock b/packages/flutter_calendar_carousel/pubspec.lock new file mode 100644 index 0000000..b1a64dc --- /dev/null +++ b/packages/flutter_calendar_carousel/pubspec.lock @@ -0,0 +1,220 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7e108028e3d258667d079986da8c0bc32da4cb57431c2af03b1dc1038621a9dc" + url: "https://pub.dev" + source: hosted + version: "9.0.13" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: b06739349ec2477e943055aea30172c5c7000225f79dad4702e2ec0eda79a6ff + url: "https://pub.dev" + source: hosted + version: "1.0.5" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.dev" + source: hosted + version: "0.3.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" +sdks: + dart: ">=3.2.0-194.0.dev <4.0.0" diff --git a/packages/flutter_calendar_carousel/pubspec.yaml b/packages/flutter_calendar_carousel/pubspec.yaml new file mode 100644 index 0000000..9258aa7 --- /dev/null +++ b/packages/flutter_calendar_carousel/pubspec.yaml @@ -0,0 +1,53 @@ +name: flutter_calendar_carousel +description: Calendar widget for flutter that is swipeable. This widget can help you build customizable calendar with scrollable actions. +version: 2.4.3 +homepage: https://github.com/dooboolab/flutter_calendar_carousel + +environment: + sdk: ">=2.14.0 < 4.0.0" + +dependencies: + intl: ^0.19.0 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.io/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.io/custom-fonts/#from-packages diff --git a/packages/flutter_calendar_carousel/renovate.json b/packages/flutter_calendar_carousel/renovate.json new file mode 100644 index 0000000..39a2b6e --- /dev/null +++ b/packages/flutter_calendar_carousel/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} diff --git a/packages/flutter_calendar_carousel/test/flutter_calendar_carousel_test.dart b/packages/flutter_calendar_carousel/test/flutter_calendar_carousel_test.dart new file mode 100644 index 0000000..1a17149 --- /dev/null +++ b/packages/flutter_calendar_carousel/test/flutter_calendar_carousel_test.dart @@ -0,0 +1,180 @@ +// This is a basic Flutter widget test. +// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter +// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to +// find child widgets in the widget tree, read text, and verify that the values of widget properties +// are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'; + +import '../lib/classes/event.dart'; + +Type typeOf<T>() => T; + +void main() { + testWidgets('Default test for Calendar Carousel', + (WidgetTester tester) async { + DateTime? pressedDay; + // Build our app and trigger a frame. + final carousel = CalendarCarousel( + daysHaveCircularBorder: null, + weekendTextStyle: TextStyle( + color: Colors.red, + ), + thisMonthDayBorderColor: Colors.grey, + headerText: 'Custom Header', + weekFormat: true, + height: 200.0, + showIconBehindDayText: true, + customGridViewPhysics: NeverScrollableScrollPhysics(), + markedDateShowIcon: true, + markedDateIconMaxShown: 2, + selectedDayTextStyle: TextStyle( + color: Colors.yellow, + ), + todayTextStyle: TextStyle( + color: Colors.blue, + ), + markedDateIconBuilder: (Event event) { + return event.icon ?? Icon(Icons.help_outline); + }, + todayButtonColor: Colors.transparent, + todayBorderColor: Colors.green, + markedDateMoreShowTotal: true, + // null for not showing hidden events indicator + onDayPressed: (date, event) { + pressedDay = date; + }, + ); + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: Container( + child: carousel, + ), + ), + )); + + expect(find.byWidget(carousel), findsOneWidget); + expect(pressedDay, isNull); + }); + + testWidgets( + 'make sure onDayPressed is called when the user tap', + (WidgetTester tester) async { + DateTime? pressedDay; + + final carousel = CalendarCarousel( + weekFormat: true, + height: 200.0, + onDayPressed: (date, event) { + pressedDay = date; + }, + ); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Container( + child: carousel, + ), + ), + ), + ); + + expect(find.byWidget(carousel), findsOneWidget); + + expect(pressedDay, isNull); + + await tester.tap( + find.text(DateTime.now().subtract(Duration(days: 1)).day.toString())); + + await tester.pump(); + + expect(pressedDay, isNotNull); + }, + ); + + testWidgets( + 'should do nothing when the user tap and onDayPressed is not provided', + (WidgetTester tester) async { + final carousel = CalendarCarousel( + weekFormat: true, + height: 200.0, + ); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Container( + child: carousel, + ), + ), + ), + ); + + expect(find.byWidget(carousel), findsOneWidget); + + await tester.tap( + find.text(DateTime.now().subtract(Duration(days: 1)).day.toString())); + await tester.pump(); + }, + ); + + testWidgets( + 'make sure onDayLongPressed is called when the user press and hold', + (WidgetTester tester) async { + DateTime? longPressedDay; + + final carousel = CalendarCarousel( + weekFormat: true, + height: 200.0, + onDayLongPressed: (date) { + longPressedDay = date; + }, + ); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Container( + child: carousel, + ), + ), + ), + ); + + expect(find.byWidget(carousel), findsOneWidget); + + expect(longPressedDay, isNull); + + await tester.longPress( + find.text(DateTime.now().subtract(Duration(days: 1)).day.toString())); + await tester.pump(); + + expect(longPressedDay, isNotNull); + }, + ); + + testWidgets( + 'should do nothing when the user press and hold and onDayLongPressed is not provided', + (WidgetTester tester) async { + final carousel = CalendarCarousel( + weekFormat: true, + height: 200.0, + ); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Container( + child: carousel, + ), + ), + ), + ); + + expect(find.byWidget(carousel), findsOneWidget); + + await tester.longPress( + find.text(DateTime.now().subtract(Duration(days: 1)).day.toString())); + await tester.pump(); + }, + ); +} diff --git a/packages/flutter_calendar_carousel/test/src/header_test.dart b/packages/flutter_calendar_carousel/test/src/header_test.dart new file mode 100644 index 0000000..2f9b603 --- /dev/null +++ b/packages/flutter_calendar_carousel/test/src/header_test.dart @@ -0,0 +1,104 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_calendar_carousel/src/calendar_header.dart'; + +import 'package:flutter/material.dart'; + +void main() { + final title = "Test title"; + final margin = const EdgeInsets.symmetric(vertical: 16.0); + final iconColor = Colors.blueAccent; + + testWidgets('Verify Header Defaults', (WidgetTester tester) async { + var headerTapped = false; + var leftPressed = false; + var rightPressed = false; + + await tester.pumpWidget(wrapped(CalendarHeader( + headerTitle: title, + headerMargin: margin, + showHeader: true, + showHeaderButtons: true, + headerIconColor: iconColor, + onHeaderTitlePressed: () => headerTapped = true, + onRightButtonPressed: () => rightPressed = true, + onLeftButtonPressed: () => leftPressed = true, + ))); + + expect(find.text(title), findsOneWidget); + + await tester.tap(find.byType(TextButton)); + + await tester.pump(); + + expect(headerTapped, equals(true)); + + await tester.tap(find.widgetWithIcon(IconButton, Icons.chevron_right)); + + await tester.pump(); + + expect(rightPressed, equals(true)); + + await tester.tap(find.widgetWithIcon(IconButton, Icons.chevron_left)); + + await tester.pump(); + + expect(leftPressed, equals(true)); + }); + + testWidgets('Verify No header Renders', (WidgetTester tester) async { + final noHeaderEmpty = CalendarHeader( + showHeader: false, + headerTitle: '', + onLeftButtonPressed: () {}, + onHeaderTitlePressed: () {}, + onRightButtonPressed: () {}, + ); + + await tester.pumpWidget(Container(child: noHeaderEmpty)); + + expect(find.byWidget(noHeaderEmpty), findsOneWidget); + }); + + testWidgets('Verify Header Is Not Touchable', (WidgetTester tester) async { + await tester.pumpWidget(wrapped(CalendarHeader( + headerTitle: title, + headerMargin: margin, + showHeader: true, + showHeaderButtons: true, + headerIconColor: iconColor, + onHeaderTitlePressed: null, + onRightButtonPressed: () {}, + onLeftButtonPressed: () {}, + ))); + + // the header TextButton Should not render + final touchableHeader = find.byType(TextButton); + + expect(touchableHeader, findsNothing); + }); + + testWidgets('Verify No Header Buttons', (WidgetTester tester) async { + await tester.pumpWidget(wrapped(CalendarHeader( + headerTitle: title, + headerMargin: margin, + showHeader: true, + showHeaderButtons: false, + headerIconColor: iconColor, + onHeaderTitlePressed: () {}, + onRightButtonPressed: () {}, + onLeftButtonPressed: () {}, + ))); + + // the header IconButtons Should not render + final headerButton = find.byType(IconButton); + + expect(headerButton, findsNothing); + }); +} + +// header uses Row which requires MaterialApp as an ancestor +Widget wrapped(Widget widget) => MaterialApp( + home: Container( + child: Material(child: widget), + ), + ); diff --git a/packages/flutter_calendar_carousel/test/src/weekday_row_test.dart b/packages/flutter_calendar_carousel/test/src/weekday_row_test.dart new file mode 100644 index 0000000..95090e4 --- /dev/null +++ b/packages/flutter_calendar_carousel/test/src/weekday_row_test.dart @@ -0,0 +1,128 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart' + show WeekdayFormat; +import 'package:intl/intl.dart' show DateFormat; + +import 'package:flutter_calendar_carousel/src/weekday_row.dart'; +import 'package:flutter/material.dart'; + +void main() { + final locale = DateFormat.yMMM("en_US"); + final margin = const EdgeInsets.only(bottom: 4.0); + + testWidgets('test short weekday row', (WidgetTester tester) async { + await tester.pumpWidget(wrapped( + WeekdayRow( + 0, + null, + weekdayPadding: EdgeInsets.all(0), + weekdayBackgroundColor: Colors.transparent, + showWeekdays: true, + weekdayFormat: WeekdayFormat.short, + weekdayMargin: margin, + weekdayTextStyle: null, + localeDate: locale, + ), + )); + + expect(find.text('Sun'), findsOneWidget); + expect(find.text('Mon'), findsOneWidget); + expect(find.text('Tue'), findsOneWidget); + expect(find.text('Wed'), findsOneWidget); + expect(find.text('Thu'), findsOneWidget); + expect(find.text('Fri'), findsOneWidget); + expect(find.text('Sat'), findsOneWidget); + }); + + testWidgets('test narrow weekday row', (WidgetTester tester) async { + await tester.pumpWidget(wrapped(WeekdayRow( + 0, + null, + weekdayPadding: EdgeInsets.all(0), + weekdayBackgroundColor: Colors.transparent, + showWeekdays: true, + weekdayFormat: WeekdayFormat.standaloneNarrow, + weekdayMargin: margin, + weekdayTextStyle: null, + localeDate: locale, + ))); + + // sat and sun + expect(find.text('S'), findsNWidgets(2)); + // thurs and tues + expect(find.text('T'), findsNWidgets(2)); + + expect(find.text('M'), findsOneWidget); + expect(find.text('W'), findsOneWidget); + expect(find.text('F'), findsOneWidget); + }); + + testWidgets('test standalone weekday row', (WidgetTester tester) async { + await tester.pumpWidget(wrapped(WeekdayRow( + 0, + null, + weekdayPadding: EdgeInsets.all(0), + weekdayBackgroundColor: Colors.transparent, + showWeekdays: true, + weekdayFormat: WeekdayFormat.standalone, + weekdayMargin: margin, + weekdayTextStyle: null, + localeDate: locale, + ))); + + expect(find.text('Sunday'), findsOneWidget); + expect(find.text('Monday'), findsOneWidget); + expect(find.text('Tuesday'), findsOneWidget); + expect(find.text('Wednesday'), findsOneWidget); + expect(find.text('Thursday'), findsOneWidget); + expect(find.text('Friday'), findsOneWidget); + expect(find.text('Saturday'), findsOneWidget); + }); + + testWidgets('test standalone short weekday row', (WidgetTester tester) async { + await tester.pumpWidget(wrapped(WeekdayRow( + 0, + null, + weekdayPadding: EdgeInsets.all(0), + weekdayBackgroundColor: Colors.transparent, + showWeekdays: true, + weekdayFormat: WeekdayFormat.standaloneShort, + weekdayMargin: margin, + weekdayTextStyle: null, + localeDate: locale, + ))); + + expect(find.text('Sun'), findsOneWidget); + expect(find.text('Mon'), findsOneWidget); + expect(find.text('Tue'), findsOneWidget); + expect(find.text('Wed'), findsOneWidget); + expect(find.text('Thu'), findsOneWidget); + expect(find.text('Fri'), findsOneWidget); + expect(find.text('Sat'), findsOneWidget); + }); + + testWidgets('test row does not render', (WidgetTester tester) async { + final emptyContainer = WeekdayRow( + 0, + null, + weekdayPadding: EdgeInsets.all(0), + weekdayBackgroundColor: Colors.transparent, + showWeekdays: false, + weekdayFormat: WeekdayFormat.standaloneNarrow, + weekdayMargin: margin, + weekdayTextStyle: null, + localeDate: locale, + ); + + await tester.pumpWidget(emptyContainer); + + expect(find.byType(Container), findsOneWidget); + + expect(find.byType(Row), findsNothing); + }); +} + +Widget wrapped(Widget widget) => Directionality( + textDirection: TextDirection.ltr, + child: widget, + ); diff --git a/protos/lib/agl-shell-api.dart b/protos/lib/agl_shell_api.dart index af19dc6..af19dc6 100644 --- a/protos/lib/agl-shell-api.dart +++ b/protos/lib/agl_shell_api.dart diff --git a/protos/lib/applauncher-api.dart b/protos/lib/applauncher_api.dart index fdb181e..fdb181e 100644 --- a/protos/lib/applauncher-api.dart +++ b/protos/lib/applauncher_api.dart diff --git a/protos/lib/radio-api.dart b/protos/lib/radio_api.dart index 1b12e91..1b12e91 100644 --- a/protos/lib/radio-api.dart +++ b/protos/lib/radio_api.dart diff --git a/protos/lib/val-api.dart b/protos/lib/val_api.dart index de6dfac..de6dfac 100644 --- a/protos/lib/val-api.dart +++ b/protos/lib/val_api.dart diff --git a/protos/pubspec.yaml b/protos/pubspec.yaml index fcccfe9..3e701ca 100644 --- a/protos/pubspec.yaml +++ b/protos/pubspec.yaml @@ -4,14 +4,14 @@ version: 1.0.0 # repository: https://github.com/my_org/my_repo environment: - sdk: ^3.1.0 + sdk: ">=3.5.0 <4.0.0" # Add regular dependencies here. dependencies: - grpc: ^3.2.4 + grpc: ^4.0.1 protobuf: ^3.1.0 # path: ^1.8.0 dev_dependencies: - lints: ^2.0.0 - test: ^1.21.0 + lints: ^4.0.0 + test: ^1.25.8 diff --git a/pubspec.lock b/pubspec.lock index f790a83..d82dd3f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: archive - sha256: ca12e6c9ac022f33fd89128e7007fb5e97ab6e814d4fa05dd8d4f2db1e3c69cb + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.4.5" + version: "3.6.1" args: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" async: dependency: transitive description: @@ -65,62 +65,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" crypto: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "1.0.8" dart_mpd: dependency: "direct main" description: name: dart_mpd - sha256: dbdaef05e7cb1881911bf3a92563586e1661ce74c3c9e570645fdd75a1b8c2bc + sha256: "6322bc6b5b9d99e88e7e7b66717e00aa728534492c41143702fc6fc64cac38a8" url: "https://pub.dev" source: hosted - version: "0.3.2" + version: "0.4.1" dbus: dependency: transitive description: name: dbus - sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.10" device_frame: dependency: transitive description: name: device_frame - sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d + sha256: d031a06f5d6f4750009672db98a5aa1536aa4a231713852469ce394779a23d75 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" device_preview: dependency: "direct main" description: name: device_preview - sha256: "2f097bf31b929e15e6756dbe0ec1bcb63952ab9ed51c25dc5a2c722d2b21fdaf" + sha256: a694acdd3894b4c7d600f4ee413afc4ff917f76026b97ab06575fe886429ef19 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" fake_async: dependency: transitive description: @@ -133,10 +125,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.3" file: dependency: transitive description: @@ -157,10 +149,10 @@ packages: dependency: "direct main" description: name: flow_builder - sha256: "212a5c6575e87bec2003fa3f31dd7d80f0d89f6152db54f43fb0b6f45943e955" + sha256: "9e66aa7209e9a31c347bb316abf191d2300db41cd6b7254f89abd4e76d9b3f8d" url: "https://pub.dev" source: hosted - version: "0.0.9" + version: "0.1.0" flutter: dependency: "direct main" description: flutter @@ -177,19 +169,18 @@ packages: flutter_calendar_carousel: dependency: "direct main" description: - name: flutter_calendar_carousel - sha256: "8666447f3404d2db45a2523095cab053d4d15c4fd5438d4a893d96ea5637a3aa" - url: "https://pub.dev" - source: hosted - version: "2.4.2" + path: "packages/flutter_calendar_carousel" + relative: true + source: path + version: "2.4.3" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "4.0.0" flutter_localizations: dependency: transitive description: flutter @@ -199,18 +190,18 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: e667e406a74d67715f1fa0bd941d9ded49aff72f3a9f4440a36aece4e8d457a7 + sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.5.1" flutter_svg: dependency: "direct main" description: name: flutter_svg - sha256: "8c5d68a82add3ca76d792f058b186a0599414f279f00ece4830b9b231b570338" + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -225,74 +216,82 @@ packages: dependency: transitive description: name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" get_ip_address: dependency: "direct main" description: name: get_ip_address - sha256: "0e973f1ad61bc4b0b1d99abc2c023d91d1ddb09709f5546f6972ace067c8576d" + sha256: ad7b1ca2b6f03a247a59bc7dd7e170e495b703b01185dfbb24ae89111531d514 url: "https://pub.dev" source: hosted - version: "0.0.6" + version: "0.0.7" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 + sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + url: "https://pub.dev" + source: hosted + version: "6.2.1" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5be191523702ba8d7a01ca97c17fca096822ccf246b0a9f11923a6ded06199b6" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "0.3.1+4" googleapis_auth: dependency: transitive description: name: googleapis_auth - sha256: af7c3a3edf9d0de2e1e0a77e994fae0a581c525fa7012af4fa0d4a52ed9484da + sha256: befd71383a955535060acde8792e7efc11d2fccd03dd1d3ec434e85b68775938 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.6.0" gradient_borders: dependency: "direct main" description: name: gradient_borders - sha256: "69eeaff519d145a4c6c213ada1abae386bcc8981a4970d923e478ce7ba19e309" + sha256: b1cd969552c83f458ff755aa68e13a0327d09f06c3f42f471b423b01427f21f8 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" graphs: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" grpc: dependency: transitive description: name: grpc - sha256: e93ee3bce45c134bf44e9728119102358c7cd69de7832d9a874e2e74eb8cab40 + sha256: "5b99b7a420937d4361ece68b798c9af8e04b5bc128a7859f2a4be87427694813" url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "4.0.1" http: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.2" http2: dependency: transitive description: name: http2 - sha256: "38db0c4aa9f1cd238a5d2e86aa0cc7cc91c77e0c6c94ba64bbe85e4ff732a952" + sha256: "9ced024a160b77aba8fb8674e38f70875e321d319e6f303ec18e87bd5a4b0c1d" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" http_parser: dependency: transitive description: @@ -305,66 +304,58 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" + version: "0.19.0" json_annotation: dependency: transitive description: name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted - version: "4.8.1" + version: "4.9.0" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "4.0.0" lottie: dependency: "direct main" description: name: lottie - sha256: a93542cc2d60a7057255405f62252533f8e8956e7e06754955669fd32fb4b216 + sha256: "6a24ade5d3d918c306bb1c21a6b9a04aab0489d51a2582522eea820b4093b62b" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "3.1.2" matcher: dependency: transitive description: @@ -377,18 +368,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" nested: dependency: transitive description: @@ -401,18 +392,18 @@ packages: dependency: "direct main" description: name: network_info_plus - sha256: "2d9e88b9a459e5d4e224f828d26cc38ea140511e89b943116939994324be5c96" + sha256: "6a31fa47c1f6e240f1b60de0a57d65a092ac1af7515247660f03643576984eb8" url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "6.0.1" network_info_plus_platform_interface: dependency: transitive description: name: network_info_plus_platform_interface - sha256: "881f5029c5edaf19c616c201d3d8b366c5b1384afd5c1da5a49e4345de82fb8b" + sha256: b7f35f4a7baef511159e524499f3c15464a49faa5ec10e92ee0bce265e664906 url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "2.0.1" new_virtual_keyboard: dependency: "direct main" description: @@ -449,26 +440,26 @@ packages: dependency: transitive description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.10" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.0" path_provider_linux: dependency: transitive description: @@ -481,50 +472,42 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" petitparser: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" platform: dependency: transitive description: name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.6" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" - url: "https://pub.dev" - source: hosted - version: "3.7.3" + version: "2.1.8" protobuf: dependency: transitive description: @@ -544,90 +527,90 @@ packages: dependency: transitive description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.2" rive: dependency: "direct main" description: name: rive - sha256: fd15b219f5cc110285ebf52093b0b0f4038c3ca750f2fc5fc44d9c80a56c44f3 + sha256: daa5394a7d064b4997b39e9afa02f6882c479c38b19fa0dd60f052b99c105400 url: "https://pub.dev" source: hosted - version: "0.12.3" + version: "0.13.13" rive_common: dependency: transitive description: name: rive_common - sha256: f4e20d0a99c5040c85624a3eb2b0b6b19e614d93a693c3bb25cf6e7bb2d3d6d3 + sha256: c7bf0781b1621629361579c300ac2f8aa1a238227a242202a596e82becc244d7 url: "https://pub.dev" source: hosted - version: "0.2.8" + version: "0.4.11" riverpod: dependency: "direct main" description: name: riverpod - sha256: "494bf2cfb4df30000273d3052bdb1cc1de738574c6b678f0beb146ea56f5e208" + sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.5.1" shared_preferences: dependency: transitive description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.2" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.5.2" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -693,10 +676,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" typed_data: dependency: transitive description: @@ -709,34 +692,34 @@ packages: dependency: "direct main" description: name: uuid - sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 + sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.5.0" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: b16dadf7eb610e20da044c141b4a0199a5e8082ca21daba68322756f953ce714 + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "1.1.9" + version: "1.1.11+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: a4b01403d5c613db115e30e71eca33f7e9e09f2d3c52c3fb84e16333ecddc539 + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "1.1.9" + version: "1.1.11+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: d26c0e2f237476426523eb25512e4c09fa27c6d33ed659a0e69d79e20b5dc47f + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" url: "https://pub.dev" source: hosted - version: "1.1.9" + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -749,34 +732,42 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.5" + web: + dependency: transitive + description: + name: web + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + url: "https://pub.dev" + source: hosted + version: "1.0.0" win32: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.5.4" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" xml: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" yaml: dependency: "direct main" description: @@ -786,5 +777,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-0 <3.13.2" - flutter: ">=3.13.0" + dart: ">=3.5.0 <3.13.2" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 411e082..1304544 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=3.1.0 <3.13.2' + sdk: ">=3.5.0 <4.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -34,28 +34,29 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.8 protos: path: ./protos - flow_builder: ^0.0.9 - riverpod: ^2.4.3 - flutter_riverpod: ^2.4.3 - intl: ^0.18.1 - flutter_svg: ^2.0.7 - google_fonts: ^6.1.0 + flow_builder: ^0.1.0 + riverpod: ^2.5.1 + flutter_riverpod: ^2.5.1 + flutter_svg: ^2.0.10+1 + google_fonts: ^6.2.1 flutter_analog_clock: ^1.0.3 - uuid: ^4.1.0 - network_info_plus: ^4.1.0 + uuid: ^4.5.0 + intl: ^0.19.0 + network_info_plus: ^6.0.1 yaml: ^3.1.2 - gradient_borders: ^1.0.0 - lottie: ^2.7.0 - device_preview: ^1.1.0 - rive: ^0.12.3 + gradient_borders: ^1.0.1 + lottie: ^3.1.2 + device_preview: ^1.2.0 + rive: ^0.13.13 new_virtual_keyboard: ^0.1.4 auto_size_text: ^3.0.0 - get_ip_address: ^0.0.6 - flutter_calendar_carousel: ^2.4.2 - dart_mpd: ^0.3.2 + get_ip_address: ^0.0.7 + flutter_calendar_carousel: + path: ./packages/flutter_calendar_carousel + dart_mpd: ^0.4.1 dev_dependencies: flutter_test: @@ -66,7 +67,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec |