diff --git a/.metadata b/.metadata index f1f62691..30800709 100644 --- a/.metadata +++ b/.metadata @@ -4,8 +4,8 @@ # This file should be version controlled and should not be manually edited. version: - revision: "2828ddd9a707d09af00b793a42faaa0f0e2b957f" - channel: "master" + revision: "41456452f29d64e8deb623a3c927524bcf9f111b" + channel: "stable" project_type: app @@ -13,11 +13,17 @@ project_type: app migration: platforms: - platform: root - create_revision: 2828ddd9a707d09af00b793a42faaa0f0e2b957f - base_revision: 2828ddd9a707d09af00b793a42faaa0f0e2b957f - - platform: aurora - create_revision: 2828ddd9a707d09af00b793a42faaa0f0e2b957f - base_revision: 2828ddd9a707d09af00b793a42faaa0f0e2b957f + create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + - platform: linux + create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + - platform: macos + create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + - platform: windows + create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b + base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b # User provided section diff --git a/.vscode/settings.json b/.vscode/settings.json index d0a5bedc..47a449e1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,13 @@ { + "dart.lineLength": 120, + "files.insertFinalNewline": true, "java.configuration.updateBuildConfiguration": "interactive", - "cmake.configureOnOpen": false -} \ No newline at end of file + "cmake.configureOnOpen": false, + "dart.flutterSdkPath": ".fvm/flutter_sdk", + "search.exclude": { + "**/.fvm": true + }, + "files.watcherExclude": { + "**/.fvm": true + }, +} diff --git a/api/pubspec.yaml b/api/pubspec.yaml index db3c5542..f90e21d1 100644 --- a/api/pubspec.yaml +++ b/api/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: collection: ^1.16.0 - dart_frog: ^1.0.1 + dart_frog: ^1.1.0 equatable: ^2.0.5 http: ^1.1.2 intl: ^0.18.1 diff --git a/lib/common/oauth.dart b/lib/common/oauth.dart index 2b024e64..6765800d 100644 --- a/lib/common/oauth.dart +++ b/lib/common/oauth.dart @@ -1,6 +1,10 @@ +import 'dart:io'; + +import 'package:oauth2_client/interfaces.dart'; import 'package:oauth2_client/oauth2_client.dart'; import 'package:oauth2_client/oauth2_helper.dart'; import 'package:rtu_mirea_app/common/constants.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class MireaNinjaOauth2Client extends OAuth2Client { MireaNinjaOauth2Client({ @@ -14,6 +18,8 @@ class MireaNinjaOauth2Client extends OAuth2Client { ); } +final isDesktop = !(Platform.isAndroid || Platform.isIOS); + class LksOauth2 { late final OAuth2Helper oauth2Helper; late final MireaNinjaOauth2Client oauth2Client; @@ -22,17 +28,42 @@ class LksOauth2 { String? redirectUri, String? customUriScheme, }) { + if (!isDesktop) { + redirectUri = 'ninja.mirea.mireaapp://oauth2redirect'; + customUriScheme = 'ninja.mirea.mireaapp'; + } else { + redirectUri = 'http://localhost:9094/oauth2redirect'; + customUriScheme = 'http://localhost:9094/oauth2redirect'; + } oauth2Client = MireaNinjaOauth2Client( - customUriScheme: customUriScheme ?? 'ninja.mirea.mireaapp', - redirectUri: redirectUri ?? 'ninja.mirea.mireaapp://oauth2redirect', + customUriScheme: customUriScheme, + redirectUri: redirectUri, ); - oauth2Helper = OAuth2Helper( - oauth2Client, - grantType: OAuth2Helper.authorizationCode, - clientId: lkClientId, - clientSecret: lkClientSecret, - scopes: ['profile', 'livestream', 'employees', 'attendance', 'scores'], - ); + oauth2Helper = OAuth2Helper(oauth2Client, + grantType: OAuth2Helper.authorizationCode, + clientId: lkClientId, + clientSecret: lkClientSecret, + scopes: ['profile', 'livestream', 'employees', 'attendance', 'scores'], + webAuthOpts: { + 'useWebview': false, + }, + tokenStorage: isDesktop ? TokenStorage('windows', storage: _WindowsTokenStorage()) : null); + } +} + +class _WindowsTokenStorage extends BaseStorage { + _WindowsTokenStorage(); + + @override + Future read(String key) async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString(key); + } + + @override + Future write(String key, String value) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(key, value); } } diff --git a/lib/common/widget_data_init.dart b/lib/common/widget_data_init.dart deleted file mode 100644 index c3bafccb..00000000 --- a/lib/common/widget_data_init.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'dart:developer'; -import 'dart:io'; - -import 'package:home_widget/home_widget.dart'; - -/// Sets data for home widgets -class WidgetDataProvider { - static void initData() { - HomeWidget.setAppGroupId('group.mirea.ninja.mireaapp'); - _init(); - } - - /// initial settings - static _init() async { - if (!(Platform.isIOS || Platform.isAndroid)) { - return; - } - - // TODO: implement - _update(); - } - - /// Refresh widgets - static _update() { - log('widget update'); - HomeWidget.updateWidget( - name: 'HomeWidgetExampleProvider', - androidName: 'HomeWidgetProvider', - iOSName: 'HomeWidget', - ); - } -} diff --git a/lib/data/models/update_info_model/update_info_model.freezed.dart b/lib/data/models/update_info_model/update_info_model.freezed.dart index 423e3406..4cb71b8a 100644 --- a/lib/data/models/update_info_model/update_info_model.freezed.dart +++ b/lib/data/models/update_info_model/update_info_model.freezed.dart @@ -180,7 +180,7 @@ class _$UpdateInfoModelImpl implements _UpdateInfoModel { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$UpdateInfoModelImpl && diff --git a/lib/navigation/routes/routes.dart b/lib/navigation/routes/routes.dart index a1614e8f..3a4c4a82 100644 --- a/lib/navigation/routes/routes.dart +++ b/lib/navigation/routes/routes.dart @@ -230,16 +230,14 @@ GoRouter createRouter() => GoRouter( GoRoute( parentNavigatorKey: _rootNavigatorKey, path: '/image', - pageBuilder: (context, state) { - return CustomTransitionPage( - fullscreenDialog: true, - opaque: false, - transitionsBuilder: (_, __, ___, child) => child, - child: ImagesViewGallery( - imageUrls: List.from(state.extra as List), - ), - ); - }, + pageBuilder: (context, state) => CustomTransitionPage( + fullscreenDialog: true, + opaque: false, + transitionsBuilder: (_, __, ___, child) => child, + child: ImagesViewGallery( + imageUrls: List.from(state.extra as List), + ), + ), ), ], observers: [ diff --git a/lib/navigation/widgets/sidebar.dart b/lib/navigation/widgets/sidebar.dart index 154538db..2cd535a7 100644 --- a/lib/navigation/widgets/sidebar.dart +++ b/lib/navigation/widgets/sidebar.dart @@ -23,45 +23,88 @@ class Sidebar extends StatelessWidget { return Container( width: sidebarWith, color: AppTheme.colorsOf(context).background01, - child: ListView( - children: [ - ListTile( - leading: const Icon(Icons.library_books_rounded), - title: Text("Новости", style: AppTextStyle.tab), - selected: currentIndex == 0, - onTap: () => onClick(0), - selectedColor: AppTheme.colors.primary, - ), - ListTile( - leading: const Icon(Icons.calendar_today_rounded), - title: Text("Расписание", style: AppTextStyle.tab), - selected: currentIndex == 1, - onTap: () => onClick(1), - selectedColor: AppTheme.colors.primary, - ), - ListTile( - leading: const Icon(Icons.widgets_rounded), - title: Text("Сервисы", style: AppTextStyle.tab), - selected: currentIndex == 2, - onTap: () => onClick(2), - selectedColor: AppTheme.colors.primary, - ), - isDesktop - ? ListTile( - leading: const Icon(UniconsLine.info_circle), - title: Text("О приложении", style: AppTextStyle.tab), - selected: currentIndex == 3, - onTap: () => onClick(3), - selectedColor: AppTheme.colors.primary, - ) - : ListTile( - leading: const Icon(Icons.person), - title: Text("Профиль", style: AppTextStyle.tab), - selected: currentIndex == 3, - onTap: () => onClick(3), - selectedColor: AppTheme.colors.primary, + child: Padding( + padding: const EdgeInsets.all(16), + child: ListView( + children: [ + SidebarNavButton( + isSelected: currentIndex == 0, + title: "Новости", + icon: const Icon(Icons.library_books_rounded), + onClick: () => onClick(0), + ), + SidebarNavButton( + isSelected: currentIndex == 1, + title: "Расписание", + icon: const Icon(Icons.calendar_today_rounded), + onClick: () => onClick(1), + ), + SidebarNavButton( + isSelected: currentIndex == 2, + title: "Сервисы", + icon: const Icon(Icons.widgets_rounded), + onClick: () => onClick(2), + ), + SidebarNavButton( + isSelected: currentIndex == 3, + title: "Профиль", + icon: const Icon(Icons.person), + onClick: () => onClick(3), + ), + ], + ), + ), + ); + } +} + +class SidebarNavButton extends StatelessWidget { + const SidebarNavButton({ + Key? key, + required this.isSelected, + required this.title, + required this.icon, + required this.onClick, + }) : super(key: key); + + final bool isSelected; + final String title; + final Widget icon; + final VoidCallback onClick; + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(top: 8), + decoration: isSelected + ? BoxDecoration( + color: AppTheme.colorsOf(context).colorful03, + borderRadius: BorderRadius.circular(8), + ) + : null, + child: TextButton( + onPressed: onClick, + style: TextButton.styleFrom( + padding: const EdgeInsets.all(16), + foregroundColor: isSelected ? AppTheme.colorsOf(context).background01 : AppTheme.colorsOf(context).active, + ), + child: Row( + children: [ + Theme( + data: ThemeData( + iconTheme: IconThemeData( + color: AppTheme.colorsOf(context).active, ), - ], + ), + child: icon, + ), + const SizedBox(width: 16), + Text( + title, + style: AppTextStyle.buttonS.copyWith(color: AppTheme.colorsOf(context).active), + ), + ], + ), ), ); } diff --git a/lib/neon/bloc/neon_state.dart b/lib/neon/bloc/neon_state.dart index 8976ae30..21955786 100644 --- a/lib/neon/bloc/neon_state.dart +++ b/lib/neon/bloc/neon_state.dart @@ -19,8 +19,7 @@ class NeonState extends Equatable { bool? isRegisterOfferViewed, }) { return NeonState( - isRegisterOfferViewed: - isRegisterOfferViewed ?? this.isRegisterOfferViewed, + isRegisterOfferViewed: isRegisterOfferViewed ?? this.isRegisterOfferViewed, ); } } diff --git a/lib/presentation/pages/profile/profile_page.dart b/lib/presentation/pages/profile/profile_page.dart index 77c68280..7b865fb6 100644 --- a/lib/presentation/pages/profile/profile_page.dart +++ b/lib/presentation/pages/profile/profile_page.dart @@ -168,6 +168,7 @@ class _InitialProfileStatePage extends StatelessWidget { @override Widget build(BuildContext context) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(0, 24, 0, 24), diff --git a/lib/schedule/view/schedule_page.dart b/lib/schedule/view/schedule_page.dart index 0103169c..a37851c6 100644 --- a/lib/schedule/view/schedule_page.dart +++ b/lib/schedule/view/schedule_page.dart @@ -8,6 +8,7 @@ import 'package:rtu_mirea_app/presentation/widgets/bottom_modal_sheet.dart'; import 'package:rtu_mirea_app/schedule/bloc/schedule_bloc.dart'; import 'package:rtu_mirea_app/schedule/models/models.dart'; import 'package:rtu_mirea_app/stories/view/stories_view.dart'; +import 'package:table_calendar/table_calendar.dart'; import 'package:university_app_server_api/client.dart'; import '../widgets/widgets.dart'; @@ -85,133 +86,179 @@ class _SchedulePageState extends State { }); } else if (state.selectedSchedule != null) { return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (_, __) => [ - SliverAppBar( - pinned: false, - title: Text( - _getAppBarTitle, - ), - actions: [ - SizedBox( - width: 60, - height: 60, - child: IconButton( - icon: FaIcon( - FontAwesomeIcons.ellipsis, - color: AppTheme.colorsOf(context).active, - ), - onPressed: () { - BottomModalSheet.show( - context, - child: const SettingsMenu(), - title: 'Управление расписанием', - description: - 'Редактирование сохраненных расписаний и добавление новых, а также настройки отображения расписания.', - backgroundColor: AppTheme.colorsOf(context).background03, + body: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + bool isWideScreen = constraints.maxWidth > 880; + + final eventsPageView = EventsPageView( + controller: _schedulePageController, + itemBuilder: (context, index) { + final day = Calendar.firstCalendarDay.add(Duration(days: index)); + final schedules = Calendar.getSchedulePartsByDay( + schedule: state.selectedSchedule?.schedule ?? [], + day: day, + ); + + final holiday = schedules.firstWhereOrNull( + (element) => element is HolidaySchedulePart, + ); + + if (holiday != null) { + return HolidayPage(title: (holiday as HolidaySchedulePart).title); + } + + if (day.weekday == DateTime.sunday) { + return const HolidayPage(title: 'Выходной'); + } + + final lessons = schedules.whereType().toList(); + + if (state.showEmptyLessons) { + return ListView.builder( + itemCount: 6, + itemBuilder: (context, index) { + final lesson = lessons.firstWhereOrNull( + (element) => element.lessonBells.number == index + 1, ); - }, - ), - ), - ], - bottom: const PreferredSize( - preferredSize: Size.fromHeight(80), - child: StoriesView(), - ), - ), - SliverToBoxAdapter( - child: Calendar( - pageViewController: _schedulePageController, - schedule: state.selectedSchedule?.schedule ?? [], - comments: state.comments, - showCommentsIndicators: state.showCommentsIndicators, - ), - ), - ], - body: EventsPageView( - controller: _schedulePageController, - itemBuilder: (context, index) { - final day = Calendar.firstCalendarDay.add(Duration(days: index)); - final schedules = Calendar.getSchedulePartsByDay( - schedule: state.selectedSchedule?.schedule ?? [], - day: day, - ); - - final holiday = schedules.firstWhereOrNull( - (element) => element is HolidaySchedulePart, - ); - - if (holiday != null) { - return HolidayPage(title: (holiday as HolidaySchedulePart).title); - } - - if (day.weekday == DateTime.sunday) { - return const HolidayPage(title: 'Выходной'); - } - - final lessons = schedules.whereType().toList(); - - if (state.showEmptyLessons) { - return ListView.builder( - itemCount: 6, - itemBuilder: (context, index) { - final lesson = lessons.firstWhereOrNull( - (element) => element.lessonBells.number == index + 1, - ); - - if (lesson != null) { + + if (lesson != null) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: LessonCard( + lesson: lesson, + onTap: (lesson) { + context.go( + '/schedule/details', + extra: (lesson, day), + ); + }, + ), + ); + } + return Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0, ), - child: LessonCard( - lesson: lesson, - onTap: (lesson) { - context.go( - '/schedule/details', - extra: (lesson, day), - ); - }, - ), + child: EmptyLessonCard(lessonNumber: index + 1), ); - } + }, + ); + } - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: EmptyLessonCard(lessonNumber: index + 1), - ); - }, + return ListView( + children: schedules + .whereType() + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: LessonCard( + lesson: e, + onTap: (lesson) { + context.go( + '/schedule/details', + extra: (lesson, day), + ); + }, + ), + ), + ) + .toList(), ); - } + }, + ); - return ListView( - children: schedules - .whereType() - .map( - (e) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: LessonCard( - lesson: e, - onTap: (lesson) { - context.go( - '/schedule/details', - extra: (lesson, day), - ); - }, + return NestedScrollView( + headerSliverBuilder: (_, __) => [ + SliverAppBar( + pinned: false, + title: Text( + _getAppBarTitle, + ), + actions: [ + SizedBox( + width: 60, + height: 60, + child: IconButton( + icon: FaIcon( + FontAwesomeIcons.ellipsis, + color: AppTheme.colorsOf(context).active, ), + onPressed: () { + BottomModalSheet.show( + context, + child: const SettingsMenu(), + title: 'Управление расписанием', + description: + 'Редактирование сохраненных расписаний и добавление новых, а также настройки отображения расписания.', + backgroundColor: AppTheme.colorsOf(context).background03, + ); + }, ), + ), + ], + bottom: const PreferredSize( + preferredSize: Size.fromHeight(80), + child: StoriesView(), + ), + ), + if (!isWideScreen) + SliverToBoxAdapter( + child: Calendar( + pageViewController: _schedulePageController, + schedule: state.selectedSchedule?.schedule ?? [], + comments: state.comments, + showCommentsIndicators: state.showCommentsIndicators, + ), + ), + ], + body: isWideScreen + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 2, + child: eventsPageView, + ), + Flexible( + flex: 1, + child: ConstrainedBox( + constraints: const BoxConstraints( + minHeight: 100, + maxHeight: 466, + ), + child: Container( + margin: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + border: Border.all( + color: AppTheme.colorsOf(context).deactiveDarker, + ), + borderRadius: BorderRadius.circular(16.0), + ), + child: Calendar( + pageViewController: _schedulePageController, + schedule: state.selectedSchedule?.schedule ?? [], + comments: state.comments, + showCommentsIndicators: state.showCommentsIndicators, + calendarFormat: CalendarFormat.month, + canChangeFormat: false, + ), + ), + ), + ), + ], ) - .toList(), - ); - }, - ), + : eventsPageView, + ); + }, ), ); } else { diff --git a/lib/schedule/widgets/calendar.dart b/lib/schedule/widgets/calendar.dart index 1a298ce5..38322d2c 100644 --- a/lib/schedule/widgets/calendar.dart +++ b/lib/schedule/widgets/calendar.dart @@ -18,12 +18,16 @@ class Calendar extends StatefulWidget { required this.schedule, required this.comments, required this.showCommentsIndicators, + this.calendarFormat = CalendarFormat.week, + this.canChangeFormat = true, }) : super(key: key); final PageController pageViewController; final List schedule; final List comments; final bool showCommentsIndicators; + final CalendarFormat calendarFormat; + final bool canChangeFormat; static List getSchedulePartsByDay({ required List schedule, @@ -72,7 +76,7 @@ class Calendar extends StatefulWidget { } class _CalendarState extends State { - CalendarFormat _calendarFormat = CalendarFormat.week; + late CalendarFormat _calendarFormat; late DateTime _focusedDay; late DateTime _selectedDay; @@ -83,8 +87,8 @@ class _CalendarState extends State { void initState() { super.initState(); + _calendarFormat = widget.calendarFormat; _focusedDay = Calendar.getDayInAvailableRange(Calendar.getNowWithoutTime()); - _selectedPage = Calendar.getPageIndex(_focusedDay); widget.pageViewController.addListener(() { @@ -115,7 +119,6 @@ class _CalendarState extends State { Widget build(BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { - final isDesktop = constraints.maxWidth > tabletBreakpoint + 150; return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: TableCalendar( @@ -155,13 +158,13 @@ class _CalendarState extends State { ); }, ), - calendarFormat: isDesktop ? CalendarFormat.month : _calendarFormat, + calendarFormat: _calendarFormat, firstDay: Calendar.firstCalendarDay, lastDay: Calendar.lastCalendarDay, sixWeekMonthsEnforced: true, startingDayOfWeek: StartingDayOfWeek.monday, headerStyle: HeaderStyle( - formatButtonVisible: !isDesktop, + formatButtonVisible: widget.canChangeFormat, formatButtonShowsNext: false, titleTextStyle: AppTextStyle.captionL.copyWith( color: AppTheme.colorsOf(context).active, @@ -230,6 +233,9 @@ class _CalendarState extends State { } }, onFormatChanged: (format) { + if (!widget.canChangeFormat) { + return; + } if (_calendarFormat != format) { // Call `setState()` when updating calendar format setState(() { diff --git a/lib/schedule/widgets/lesson_card.dart b/lib/schedule/widgets/lesson_card.dart index 6fc2731e..31b3c9b9 100644 --- a/lib/schedule/widgets/lesson_card.dart +++ b/lib/schedule/widgets/lesson_card.dart @@ -131,6 +131,7 @@ class LessonCard extends StatelessWidget { highlightColor: Colors.transparent, ), child: InkWell( + borderRadius: BorderRadius.circular(12), onTap: () { onTap?.call(lesson); }, diff --git a/lib/services/view/services_page.dart b/lib/services/view/services_page.dart index d2464e77..3b67d289 100644 --- a/lib/services/view/services_page.dart +++ b/lib/services/view/services_page.dart @@ -76,8 +76,7 @@ class _ServicesViewState extends State { const SizedBox(height: 24), PrimaryButton( onClick: () { - launchUrlString('https://t.me/cloud_mirea_ninja_bot', - mode: LaunchMode.externalApplication); + launchUrlString('https://t.me/cloud_mirea_ninja_bot', mode: LaunchMode.externalApplication); }, text: 'Создать аккаунт', ), @@ -251,8 +250,7 @@ class _ServicesViewState extends State { ).image, ), launchMode: LaunchMode.externalApplication, - description: - 'Кафедра Инструментального и прикладного программного обеспечения', + description: 'Кафедра Инструментального и прикладного программного обеспечения', ), ], ), diff --git a/lib/stories/view/stories_page_view.dart b/lib/stories/view/stories_page_view.dart index ebb3b03e..4a1412cd 100644 --- a/lib/stories/view/stories_page_view.dart +++ b/lib/stories/view/stories_page_view.dart @@ -36,38 +36,44 @@ class _StoriesPageViewState extends State { onDismissed: () => context.pop(), isFullScreen: false, direction: DismissiblePageDismissDirection.vertical, - backgroundColor: Colors.transparent, + backgroundColor: Colors.black.withOpacity(0.8), child: Center( - child: Material( - color: Colors.transparent, - child: Hero( - tag: widget.stories[widget.storyIndex].title, - child: StoryPageView( - indicatorDuration: const Duration(seconds: 6, milliseconds: 500), - initialPage: widget.storyIndex, - itemBuilder: (context, pageIndex, storyIndex) { - if (pageIndex != _prevStoryIndex) { - _prevStoryIndex = pageIndex; - context.read().add( - TrackAnalyticsEvent( - ViewStory( - storyTitle: widget.stories[pageIndex].title, - ), - ), - ); - } - final author = widget.stories[pageIndex].author; - final page = widget.stories[pageIndex].pages[storyIndex]; - return _buildStoryPage(author, page); - }, - gestureItemBuilder: (context, pageIndex, storyIndex) { - return _buildGestureItems(pageIndex, storyIndex); - }, - pageLength: widget.stories.length, - storyLength: (int pageIndex) { - return widget.stories[pageIndex].pages.length; - }, - onPageLimitReached: () => context.pop(), + child: AspectRatio( + aspectRatio: 9 / 16, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Material( + color: Colors.transparent, + child: Hero( + tag: widget.stories[widget.storyIndex].title, + child: StoryPageView( + indicatorDuration: const Duration(seconds: 6, milliseconds: 500), + initialPage: widget.storyIndex, + itemBuilder: (context, pageIndex, storyIndex) { + if (pageIndex != _prevStoryIndex) { + _prevStoryIndex = pageIndex; + context.read().add( + TrackAnalyticsEvent( + ViewStory( + storyTitle: widget.stories[pageIndex].title, + ), + ), + ); + } + final author = widget.stories[pageIndex].author; + final page = widget.stories[pageIndex].pages[storyIndex]; + return _buildStoryPage(author, page); + }, + gestureItemBuilder: (context, pageIndex, storyIndex) { + return _buildGestureItems(pageIndex, storyIndex); + }, + pageLength: widget.stories.length, + storyLength: (int pageIndex) { + return widget.stories[pageIndex].pages.length; + }, + onPageLimitReached: () => context.pop(), + ), + ), ), ), ), diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 00000000..d3896c98 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 00000000..a7daf60c --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "rtu_mirea_mobile") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "ninja.mirea.rtu_mirea_mobile") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 00000000..d5bd0164 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index a034fb71..d676e07f 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,7 @@ #include "generated_plugin_registrant.h" +#include #include #include #include @@ -17,6 +18,9 @@ #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); + desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 89fea00a..bf28f9e8 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + desktop_webview_window dynamic_color emoji_picker_flutter file_selector_linux @@ -15,7 +16,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_zxing ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 00000000..e7c5c543 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 00000000..c5c0f561 --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "context_menus"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "context_menus"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 00000000..72271d5e --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 00000000..746adbb6 --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 00000000..c2efd0b6 --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 00000000..c2efd0b6 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 49252e26..a2de9d35 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,6 +6,7 @@ import FlutterMacOS import Foundation import connectivity_plus +import desktop_webview_window import device_info_plus import dynamic_color import emoji_picker_flutter @@ -31,6 +32,7 @@ import window_to_front func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) EmojiPickerFlutterPlugin.register(with: registry.registrar(forPlugin: "EmojiPickerFlutterPlugin")) diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 61fa4f46..e6e4180d 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,10 +1,10 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=C:\src\flutter -FLUTTER_APPLICATION_PATH=C:\Users\foran\Desktop\Sources\rtu_mirea_mobile +FLUTTER_ROOT=/mnt/c/src/flutter +FLUTTER_APPLICATION_PATH=/mnt/c/Users/foran/Desktop/Sources/rtu_mirea_mobile COCOAPODS_PARALLEL_CODE_SIGN=true FLUTTER_BUILD_DIR=build FLUTTER_BUILD_NAME=1.5.0 -FLUTTER_BUILD_NUMBER=74 +FLUTTER_BUILD_NUMBER=79 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index bed9e619..cd9ba6ba 100644 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,11 +1,11 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=C:\src\flutter" -export "FLUTTER_APPLICATION_PATH=C:\Users\foran\Desktop\Sources\rtu_mirea_mobile" +export "FLUTTER_ROOT=/mnt/c/src/flutter" +export "FLUTTER_APPLICATION_PATH=/mnt/c/Users/foran/Desktop/Sources/rtu_mirea_mobile" export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_NAME=1.5.0" -export "FLUTTER_BUILD_NUMBER=74" +export "FLUTTER_BUILD_NUMBER=79" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..f433def6 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,695 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* rtu_mirea_mobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "rtu_mirea_mobile.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* rtu_mirea_mobile.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* rtu_mirea_mobile.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ninja.mirea.rtuMireaMobile.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/rtu_mirea_mobile.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/rtu_mirea_mobile"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ninja.mirea.rtuMireaMobile.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/rtu_mirea_mobile.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/rtu_mirea_mobile"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ninja.mirea.rtuMireaMobile.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/rtu_mirea_mobile.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/rtu_mirea_mobile"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..d4e4ab6c --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 00000000..d53ef643 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a2ec33f1 --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 00000000..82b6f9d9 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 00000000..13b35eba Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 00000000..0a3f5fa4 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 00000000..bdb57226 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 00000000..f083318e Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 00000000..326c0e72 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 00000000..2f1632cf Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 00000000..80e867a4 --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 00000000..7707df83 --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = rtu_mirea_mobile + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = ninja.mirea.rtuMireaMobile + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 ninja.mirea. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 00000000..36b0fd94 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 00000000..dff4f495 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 00000000..42bcbf47 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 00000000..dddb8a30 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 00000000..4789daa6 --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 00000000..3cc05eb2 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 00000000..852fa1a4 --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..5418c9f5 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/melos.yaml b/melos.yaml index 31fb2519..13dc1621 100644 --- a/melos.yaml +++ b/melos.yaml @@ -1,5 +1,5 @@ name: neon -repository: https://github.com/nextcloud/neon +sdkPath: .fvm/flutter_sdk bootstrap: # It seems so that running "pub get" in parallel has some issues (like @@ -8,6 +8,7 @@ bootstrap: runPubGetInParallel: false packages: + - packages/* - packages/neon/packages/* - packages/neon/packages/dynamite/* - packages/neon/packages/neon/* @@ -34,5 +35,5 @@ scripts: test: > melos exec --no-flutter --concurrency=1 --fail-fast --dir-exists=test -- "dart test --concurrency=$(nproc --all) --fail-fast" && melos exec --flutter --concurrency=1 --fail-fast --dir-exists=test -- "flutter test --concurrency=$(nproc --all) --fail-fast" - generate:neon:build_runner: melos exec --scope="neon*" --file-exists="build.yaml" -- dart run build_runner build --delete-conflicting-outputs && melos run format + generate:neon:build_runner: melos exec --file-exists="build.yaml" -- dart run build_runner build --delete-conflicting-outputs && melos run format generate:neon:l10n: melos exec --flutter --dir-exists="lib/l10n" flutter gen-l10n && melos run format diff --git a/packages/analytics_repository/lib/src/analytics_repository.dart b/packages/analytics_repository/lib/src/analytics_repository.dart index 9f10a4d3..15890495 100644 --- a/packages/analytics_repository/lib/src/analytics_repository.dart +++ b/packages/analytics_repository/lib/src/analytics_repository.dart @@ -37,14 +37,14 @@ class SetUserIdFailure extends AnalyticsFailure { /// {@endtemplate} class AnalyticsRepository { /// {@macro analytics_repository} - const AnalyticsRepository(FirebaseAnalytics analytics) : _analytics = analytics; + const AnalyticsRepository({FirebaseAnalytics? analytics}) : _analytics = analytics; - final FirebaseAnalytics _analytics; + final FirebaseAnalytics? _analytics; /// Tracks the provided [AnalyticsEvent]. Future track(AnalyticsEvent event) async { try { - await _analytics.logEvent( + await _analytics?.logEvent( name: event.name, parameters: event.properties, ); @@ -58,7 +58,7 @@ class AnalyticsRepository { /// Setting a null [userId] will clear the user identifier. Future setUserId(String? userId) async { try { - await _analytics.setUserId(id: userId); + await _analytics?.setUserId(id: userId); } catch (error, stackTrace) { Error.throwWithStackTrace(SetUserIdFailure(error), stackTrace); } diff --git a/packages/neon/packages/app/linux/flutter/generated_plugins.cmake b/packages/neon/packages/app/linux/flutter/generated_plugins.cmake index 64a9330b..5679afe0 100644 --- a/packages/neon/packages/app/linux/flutter/generated_plugins.cmake +++ b/packages/neon/packages/app/linux/flutter/generated_plugins.cmake @@ -12,7 +12,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_zxing ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/packages/neon/packages/app/pubspec.lock b/packages/neon/packages/app/pubspec.lock index 12b82898..6ad7b71c 100644 --- a/packages/neon/packages/app/pubspec.lock +++ b/packages/neon/packages/app/pubspec.lock @@ -73,46 +73,6 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.0" - camera: - dependency: transitive - description: - name: camera - sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" - url: "https://pub.dev" - source: hosted - version: "0.10.5+9" - camera_android: - dependency: transitive - description: - name: camera_android - sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" - url: "https://pub.dev" - source: hosted - version: "0.10.8+16" - camera_avfoundation: - dependency: transitive - description: - name: camera_avfoundation - sha256: "6f89cacd6039d37c122c4b2365d23b2a7493395300767873b5d39359ddbc5d5f" - url: "https://pub.dev" - source: hosted - version: "0.9.13+11" - camera_platform_interface: - dependency: transitive - description: - name: camera_platform_interface - sha256: e971ebca970f7cfee396f76ef02070b5e441b4aa04942da9c108d725f57bbd32 - url: "https://pub.dev" - source: hosted - version: "2.7.2" - camera_web: - dependency: transitive - description: - name: camera_web - sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d - url: "https://pub.dev" - source: hosted - version: "0.3.2+4" characters: dependency: transitive description: @@ -440,14 +400,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_zxing: - dependency: transitive - description: - name: flutter_zxing - sha256: ed8da1a0e4650c7645e94b5ab92f855a6b628385d815641761ccbdcaee131683 - url: "https://pub.dev" - source: hosted - version: "1.5.2" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -1158,14 +1110,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" - url: "https://pub.dev" - source: hosted - version: "2.1.0" string_scanner: dependency: transitive description: diff --git a/packages/neon/packages/neon_framework/lib/src/pages/login.dart b/packages/neon/packages/neon_framework/lib/src/pages/login.dart index c60f29d1..c463bd45 100644 --- a/packages/neon/packages/neon_framework/lib/src/pages/login.dart +++ b/packages/neon/packages/neon_framework/lib/src/pages/login.dart @@ -85,19 +85,6 @@ class _LoginPageState extends State { icon: const Icon(Icons.login), label: const Text('Войти через Cloud Mirea Ninja'), ), - if (NeonPlatform.instance.canUseCamera) ...[ - const SizedBox( - height: 50, - ), - IconButton( - tooltip: NeonLocalizations.of(context).loginUsingQRcode, - icon: const Icon( - Icons.qr_code_scanner_rounded, - size: 60, - ), - onPressed: () => const LoginQRcodeRoute().go(context), - ), - ], ], ), ), diff --git a/packages/neon/packages/neon_framework/lib/src/pages/login_qr_code.dart b/packages/neon/packages/neon_framework/lib/src/pages/login_qr_code.dart deleted file mode 100644 index 5e04bd96..00000000 --- a/packages/neon/packages/neon_framework/lib/src/pages/login_qr_code.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_zxing/flutter_zxing.dart'; -import 'package:meta/meta.dart'; -import 'package:neon_framework/l10n/localizations.dart'; -import 'package:neon_framework/src/models/account.dart'; -import 'package:neon_framework/src/router.dart'; -import 'package:neon_framework/src/utils/exceptions.dart'; -import 'package:neon_framework/src/widgets/error.dart'; - -@internal -class LoginQRcodePage extends StatefulWidget { - const LoginQRcodePage({ - super.key, - }); - - @override - State createState() => _LoginQRcodePageState(); -} - -class _LoginQRcodePageState extends State { - String? _lastErrorURL; - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(), - body: SafeArea( - child: ReaderWidget( - codeFormat: Format.qrCode, - showGallery: false, - showToggleCamera: false, - showScannerOverlay: false, - tryHarder: true, - cropPercent: 0, - scanDelaySuccess: const Duration(seconds: 3), - onScan: (code) async { - String? url; - try { - url = code.text; - if (url == null) { - throw const InvalidQRcodeException(); - } - final match = LoginQRcode.tryParse(url); - if (match == null) { - throw const InvalidQRcodeException(); - } - - LoginCheckServerStatusRoute.withCredentials( - serverUrl: match.serverURL, - loginName: match.username, - password: match.password, - ).pushReplacement(context); - } catch (e, s) { - if (_lastErrorURL != url) { - debugPrint(e.toString()); - debugPrint(s.toString()); - - _lastErrorURL = url; - NeonError.showSnackbar(context, e); - } - } - }, - ), - ), - ); -} - -/// Exception which is thrown when an invalid QR code is encountered. -@immutable -class InvalidQRcodeException extends NeonException { - /// Creates a new [InvalidQRcodeException]. - const InvalidQRcodeException(); - - @override - NeonExceptionDetails get details => NeonExceptionDetails( - getText: (context) => NeonLocalizations.of(context).errorInvalidQRcode, - ); -} diff --git a/packages/neon/packages/neon_framework/lib/src/platform/platform.dart b/packages/neon/packages/neon_framework/lib/src/platform/platform.dart index 6b2eb2b2..e74fe5c0 100644 --- a/packages/neon/packages/neon_framework/lib/src/platform/platform.dart +++ b/packages/neon/packages/neon_framework/lib/src/platform/platform.dart @@ -5,6 +5,7 @@ import 'package:meta/meta.dart'; import 'package:neon_framework/src/platform/android.dart'; import 'package:neon_framework/src/platform/ios.dart'; import 'package:neon_framework/src/platform/linux.dart'; +import 'package:neon_framework/src/platform/windows.dart'; import 'package:universal_io/io.dart'; /// Implements platform specific functionality and exposes the availability of certain features. @@ -36,6 +37,8 @@ abstract interface class NeonPlatform { _platform = const LinuxNeonPlatform(); } else if (Platform.isIOS) { _platform = const IosNeonPlatform(); + } else if (Platform.isWindows) { + _platform = const WindowsNeonPlatform(); } else { throw UnimplementedError('No implementation for platform ${Platform.operatingSystem} found'); } diff --git a/packages/neon/packages/neon_framework/lib/src/platform/windows.dart b/packages/neon/packages/neon_framework/lib/src/platform/windows.dart new file mode 100644 index 00000000..4aae87fc --- /dev/null +++ b/packages/neon/packages/neon_framework/lib/src/platform/windows.dart @@ -0,0 +1,56 @@ +import 'dart:typed_data'; + +import 'package:file_picker/file_picker.dart'; +import 'package:meta/meta.dart'; +import 'package:neon_framework/src/platform/android.dart'; +import 'package:neon_framework/src/platform/platform.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:universal_io/io.dart'; + +/// Linux specific platform information. +/// +/// See: +/// * [NeonPlatform] to initialize and acquire an instance +/// * [AndroidNeonPlatform] for the Android implementation +@immutable +@internal +class WindowsNeonPlatform implements NeonPlatform { + /// Creates a new Linux Neon platform. + const WindowsNeonPlatform(); + + @override + bool get canUseWebView => false; + + @override + bool get canUseQuickActions => false; + + @override + bool get canUseWindowManager => true; + + @override + bool get canUseCamera => false; + + @override + bool get canUsePushNotifications => false; + + @override + bool get canUseSharing => false; + + @override + void init() { + sqfliteFfiInit(); + databaseFactory = databaseFactoryFfi; + } + + @override + Future saveFileWithPickDialog(String fileName, Uint8List data) async { + final result = await FilePicker.platform.saveFile( + fileName: fileName, + ); + if (result != null) { + await File(result).writeAsBytes(data); + } + + return result; + } +} diff --git a/packages/neon/packages/neon_framework/lib/src/router.dart b/packages/neon/packages/neon_framework/lib/src/router.dart index 85fae6d6..a6fe317f 100644 --- a/packages/neon/packages/neon_framework/lib/src/router.dart +++ b/packages/neon/packages/neon_framework/lib/src/router.dart @@ -16,7 +16,6 @@ import 'package:neon_framework/src/pages/login.dart'; import 'package:neon_framework/src/pages/login_check_account.dart'; import 'package:neon_framework/src/pages/login_check_server_status.dart'; import 'package:neon_framework/src/pages/login_flow.dart'; -import 'package:neon_framework/src/pages/login_qr_code.dart'; import 'package:neon_framework/src/pages/route_not_found.dart'; import 'package:neon_framework/src/pages/settings.dart'; import 'package:neon_framework/src/utils/findable.dart'; @@ -127,9 +126,6 @@ class AccountSettingsRoute extends GoRouteData { TypedGoRoute<_AddAccountFlowRoute>( path: 'flow', ), - TypedGoRoute<_AddAccountQRcodeRoute>( - path: 'qr-code', - ), TypedGoRoute<_AddAccountCheckServerStatusRoute>( path: 'check/server', ), @@ -185,9 +181,6 @@ class HomeRoute extends GoRouteData { TypedGoRoute( path: 'flow', ), - TypedGoRoute( - path: 'qr-code', - ), TypedGoRoute( path: 'check/server', ), @@ -249,32 +242,6 @@ class LoginFlowRoute extends GoRouteData { } } -/// {@template AppRoutes.LoginQRcodeRoute} -/// Route for the the [LoginQRcodePage]. -/// -/// Redirects to [_AddAccountQRcodeRoute] when at least one account is already -/// logged in. -/// {@endtemplate} -@immutable -class LoginQRcodeRoute extends GoRouteData { - /// {@macro AppRoutes.LoginQRcodeRoute} - const LoginQRcodeRoute(); - - @override - Widget build(BuildContext context, GoRouterState state) => const LoginQRcodePage(); - - @override - FutureOr redirect(BuildContext context, GoRouterState state) { - final hasAccounts = NeonProvider.of(context).hasAccounts; - - if (state.fullPath == location && hasAccounts) { - return const _AddAccountQRcodeRoute().location; - } - - return null; - } -} - /// {@template AppRoutes.LoginCheckServerStatusRoute} /// Route for the the [LoginCheckServerStatusPage]. /// @@ -417,11 +384,6 @@ class _AddAccountFlowRoute extends LoginFlowRoute { Uri get serverUrl => super.serverUrl; } -@immutable -class _AddAccountQRcodeRoute extends LoginQRcodeRoute { - const _AddAccountQRcodeRoute(); -} - @immutable class _AddAccountCheckServerStatusRoute extends LoginCheckServerStatusRoute { const _AddAccountCheckServerStatusRoute({ diff --git a/packages/neon/packages/neon_framework/lib/src/router.g.dart b/packages/neon/packages/neon_framework/lib/src/router.g.dart index e0dd47b5..4ef323ad 100644 --- a/packages/neon/packages/neon_framework/lib/src/router.g.dart +++ b/packages/neon/packages/neon_framework/lib/src/router.g.dart @@ -35,10 +35,6 @@ RouteBase get $homeRoute => GoRouteData.$route( path: 'flow', factory: $_AddAccountFlowRouteExtension._fromState, ), - GoRouteData.$route( - path: 'qr-code', - factory: $_AddAccountQRcodeRouteExtension._fromState, - ), GoRouteData.$route( path: 'check/server', factory: $_AddAccountCheckServerStatusRouteExtension._fromState, @@ -162,22 +158,6 @@ extension $_AddAccountFlowRouteExtension on _AddAccountFlowRoute { void replace(BuildContext context) => context.replace(location); } -extension $_AddAccountQRcodeRouteExtension on _AddAccountQRcodeRoute { - static _AddAccountQRcodeRoute _fromState(GoRouterState state) => const _AddAccountQRcodeRoute(); - - String get location => GoRouteData.$location( - 'neon/settings/account/add/qr-code', - ); - - void go(BuildContext context) => context.go(location); - - Future push(BuildContext context) => context.push(location); - - void pushReplacement(BuildContext context) => context.pushReplacement(location); - - void replace(BuildContext context) => context.replace(location); -} - extension $_AddAccountCheckServerStatusRouteExtension on _AddAccountCheckServerStatusRoute { static _AddAccountCheckServerStatusRoute _fromState(GoRouterState state) => _AddAccountCheckServerStatusRoute( serverUrl: Uri.parse(state.uri.queryParameters['server-url']!), @@ -264,10 +244,6 @@ RouteBase get $loginRoute => GoRouteData.$route( path: 'flow', factory: $LoginFlowRouteExtension._fromState, ), - GoRouteData.$route( - path: 'qr-code', - factory: $LoginQRcodeRouteExtension._fromState, - ), GoRouteData.$route( path: 'check/server', factory: $LoginCheckServerStatusRouteExtension._fromState, @@ -316,22 +292,6 @@ extension $LoginFlowRouteExtension on LoginFlowRoute { void replace(BuildContext context) => context.replace(location); } -extension $LoginQRcodeRouteExtension on LoginQRcodeRoute { - static LoginQRcodeRoute _fromState(GoRouterState state) => const LoginQRcodeRoute(); - - String get location => GoRouteData.$location( - 'neon-login/qr-code', - ); - - void go(BuildContext context) => context.go(location); - - Future push(BuildContext context) => context.push(location); - - void pushReplacement(BuildContext context) => context.pushReplacement(location); - - void replace(BuildContext context) => context.replace(location); -} - extension $LoginCheckServerStatusRouteExtension on LoginCheckServerStatusRoute { static LoginCheckServerStatusRoute _fromState(GoRouterState state) => LoginCheckServerStatusRoute( serverUrl: Uri.parse(state.uri.queryParameters['server-url']!), diff --git a/packages/neon/packages/neon_framework/pubspec.yaml b/packages/neon/packages/neon_framework/pubspec.yaml index 387ac465..59d19387 100644 --- a/packages/neon/packages/neon_framework/pubspec.yaml +++ b/packages/neon/packages/neon_framework/pubspec.yaml @@ -25,7 +25,6 @@ dependencies: flutter_material_design_icons: ^1.0.0 flutter_native_splash: ^2.0.0 flutter_svg: ^2.0.0 - flutter_zxing: ^1.0.0 go_router: ^13.0.0 http: ^1.0.0 image: ^4.0.0 diff --git a/pubspec.lock b/pubspec.lock index 9f9b719a..3486723c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7 + sha256: "1a52f1afae8ab7ac4741425114713bdbba802f1ce1e0648e167ffcc6e05e96cf" url: "https://pub.dev" source: hosted - version: "1.3.16" + version: "1.3.21" academic_calendar: dependency: "direct main" description: @@ -28,10 +28,10 @@ packages: dependency: "direct main" description: name: adaptive_theme - sha256: b0c4c35b22ef8226757881fe4dce38c40a06c551bca83236022ec7613e157c83 + sha256: f4ee609b464e5efc68131d9d15ba9aa1de4e3b5ede64be17781c6e19a52d637d url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "3.6.0" after_layout: dependency: "direct main" description: @@ -99,10 +99,10 @@ packages: dependency: transitive description: name: asn1lib - sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" + sha256: c9c85fedbe2188b95133cbe960e16f5f448860f7133330e272edbbca5893ddc6 url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.5.2" async: dependency: transitive description: @@ -179,10 +179,10 @@ packages: dependency: transitive description: name: build_runner_core - sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.11" + version: "7.3.0" built_collection: dependency: transitive description: @@ -231,46 +231,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.3" - camera: - dependency: transitive - description: - name: camera - sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" - url: "https://pub.dev" - source: hosted - version: "0.10.5+9" - camera_android: - dependency: transitive - description: - name: camera_android - sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" - url: "https://pub.dev" - source: hosted - version: "0.10.8+16" - camera_avfoundation: - dependency: transitive - description: - name: camera_avfoundation - sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9" - url: "https://pub.dev" - source: hosted - version: "0.9.14" - camera_platform_interface: - dependency: transitive - description: - name: camera_platform_interface - sha256: e971ebca970f7cfee396f76ef02070b5e441b4aa04942da9c108d725f57bbd32 - url: "https://pub.dev" - source: hosted - version: "2.7.2" - camera_web: - dependency: transitive - description: - name: camera_web - sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d - url: "https://pub.dev" - source: hosted - version: "0.3.2+4" carousel_slider: dependency: "direct main" description: @@ -307,10 +267,10 @@ packages: dependency: transitive description: name: chewie - sha256: "3427e469d7cc99536ac4fbaa069b3352c21760263e65ffb4f0e1c054af43a73e" + sha256: "8bc4ac4cf3f316e50a25958c0f5eb9bb12cf7e8308bb1d74a43b230da2cfc144" url: "https://pub.dev" source: hosted - version: "1.7.4" + version: "1.7.5" cli_launcher: dependency: transitive description: @@ -450,10 +410,10 @@ packages: dependency: transitive description: name: dart_frog - sha256: d4863f6e9f2c0b9d14d74b3e2793cc6ee8cd6fb40c9fadff9d9a22997e6b805a + sha256: a5da81b1ea4f3e8f03dfcd0bc9b44ba83a6576ce6dae1bb138a6a8f7b70fe727 url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" dart_style: dependency: transitive description: @@ -486,14 +446,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.3" + desktop_webview_window: + dependency: transitive + description: + name: desktop_webview_window + sha256: "57cf20d81689d5cbb1adfd0017e96b669398a669d927906073b0e42fc64111c0" + url: "https://pub.dev" + source: hosted + version: "0.2.3" device_info_plus: dependency: "direct main" description: name: device_info_plus - sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" url: "https://pub.dev" source: hosted - version: "9.1.1" + version: "9.1.2" device_info_plus_platform_interface: dependency: transitive description: @@ -648,34 +616,34 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "0240076090d77045d757aecb090616066d23b343840d4c21074094d6fe40a184" + sha256: edb9f9eaecf0e6431e5c12b7fabdb68be3e85ce51f941ccbfa6cb71327e8b535 url: "https://pub.dev" source: hosted - version: "10.8.0" + version: "10.8.5" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "6d9baa077d16b47ef5f19d982c4fc475597991aa53b0c601216faa3e1cdab45f" + sha256: de4a54353cf58412c6da6b660a0dbad8efacb33b345c0286bc3a2edb869124d8 url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.5" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "89a740249bce9d52a99db4e501be6087ca6749c73c47cff2b174802be10abd81" + sha256: "77e4c02ffd0204ccc7856221193265c807b7e056fa62855f973a7f77435b5d41" url: "https://pub.dev" source: hosted - version: "0.5.5+12" + version: "0.5.5+17" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb" + sha256: "7e049e32a9d347616edb39542cf92cd53fdb4a99fb6af0a0bff327c14cd76445" url: "https://pub.dev" source: hosted - version: "2.24.2" + version: "2.25.4" firebase_core_platform_interface: dependency: transitive description: @@ -688,34 +656,34 @@ packages: dependency: "direct main" description: name: firebase_core_web - sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + sha256: "57e61d6010e253b36d38191cefd6199d7849152cdcd234b61ca290cdb278a0ba" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.4" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + sha256: "9c97b20c012542252a8853f11334efd833ddae83551fe37d27f87d885c655038" url: "https://pub.dev" source: hosted - version: "14.7.10" + version: "14.7.15" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: "54e283a0e41d81d854636ad0dad73066adc53407a60a7c3189c9656e2f1b6107" + sha256: d464b255e922c7915dc4b0ebc305ebad4e1f130519bee3d6e568ef2ea1613a4b url: "https://pub.dev" source: hosted - version: "4.5.18" + version: "4.5.23" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + sha256: f3f71aeec719ec1fe2c99f75cd74d00d33f1c240cf1e402cc9d43883e84f935a url: "https://pub.dev" source: hosted - version: "3.5.18" + version: "3.6.4" firebase_notifications_client: dependency: "direct main" description: @@ -740,10 +708,10 @@ packages: dependency: "direct main" description: name: flutter_animate - sha256: cabe33af6201144be052352d53572a1b8a4f5782b46080be7520d95abe763715 + sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" url: "https://pub.dev" source: hosted - version: "4.4.1" + version: "4.5.0" flutter_bloc: dependency: "direct main" description: @@ -929,10 +897,10 @@ packages: dependency: transitive description: name: flutter_native_splash - sha256: "9cdb5d9665dab5d098dc50feab74301c2c228cd02ca25c9b546ab572cebcd6af" + sha256: "558f10070f03ee71f850a78f7136ab239a67636a294a44a06b6b7345178edb1e" url: "https://pub.dev" source: hosted - version: "2.3.9" + version: "2.3.10" flutter_nfc_kit: dependency: "direct main" description: @@ -997,6 +965,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + flutter_shaders: + dependency: transitive + description: + name: flutter_shaders + sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" + url: "https://pub.dev" + source: hosted + version: "0.1.2" flutter_svg: dependency: "direct main" description: @@ -1022,47 +998,39 @@ packages: dependency: transitive description: name: flutter_web_auth_2 - sha256: "0da41e631a368e02366fc1a9b79dd8da191e700a836878bc54466fff51c07df2" + sha256: "6621f6037ee4d125ebac6a37586b866f80f7930ade6b11da9e7c9f6fe5a8d45f" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "4.0.0-alpha.0" flutter_web_auth_2_platform_interface: dependency: transitive description: name: flutter_web_auth_2_platform_interface - sha256: f6fa7059ff3428c19cd756c02fef8eb0147131c7e64591f9060c90b5ab84f094 + sha256: af6d3088359ca5579163d3b626cdf762e19eaafda51ab21303063ecb59fd553f url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "4.0.0-alpha.0" flutter_web_plugins: dependency: transitive description: flutter source: sdk version: "0.0.0" - flutter_zxing: - dependency: transitive - description: - name: flutter_zxing - sha256: ed8da1a0e4650c7645e94b5ab92f855a6b628385d815641761ccbdcaee131683 - url: "https://pub.dev" - source: hosted - version: "1.5.2" font_awesome_flutter: dependency: "direct main" description: name: font_awesome_flutter - sha256: "52671aea66da73b58d42ec6d0912b727a42248dd9a7c76d6c20f275783c48c08" + sha256: "275ff26905134bcb59417cf60ad979136f1f8257f2f449914b2c3e05bbb4cd6f" url: "https://pub.dev" source: hosted - version: "10.6.0" + version: "10.7.0" freezed: dependency: "direct dev" description: name: freezed - sha256: "6c5031daae12c7072b3a87eff98983076434b4889ef2a44384d0cae3f82372ba" + sha256: "57247f692f35f068cae297549a46a9a097100685c6780fe67177503eea5ed4e5" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.7" freezed_annotation: dependency: "direct main" description: @@ -1122,10 +1090,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "3b40e751eaaa855179b416974d59d29669e750d2e50fcdb2b37f1cb0ca8c803a" + sha256: "170c46e237d6eb0e6e9f0e8b3f56101e14fb64f787016e42edd74c39cf8b176a" url: "https://pub.dev" source: hosted - version: "13.0.1" + version: "13.2.0" graphs: dependency: transitive description: @@ -1226,10 +1194,10 @@ packages: dependency: transitive description: name: image - sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" + sha256: "49a0d4b0c12402853d3f227fe7c315601b238d126aa4caa5dbb2dcf99421aa4a" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "4.1.6" image_picker: dependency: transitive description: @@ -1426,10 +1394,10 @@ packages: dependency: "direct dev" description: name: melos - sha256: ddd8e0871f02ba1eaa3fdc007e306d05801a5ef595d1637083d6654b272ade68 + sha256: "7266e9fc9fee5f4a0c075e5cec375c00736dfc944358f533b740b93b3d8d681e" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.1.0" meta: dependency: transitive description: @@ -1567,11 +1535,12 @@ packages: oauth2_client: dependency: "direct main" description: - name: oauth2_client - sha256: e23986d8976d6af361aa52689ef175113379c6e13859011e18bdf8ef9c6754e2 - url: "https://pub.dev" - source: hosted - version: "3.2.2" + path: "." + ref: HEAD + resolved-ref: "4d4d15e770f0589a8a02bfe9000c3e38dbf34d13" + url: "https://github.com/0niel/oauth2_client.git" + source: git + version: "3.2.5" octo_image: dependency: transitive description: @@ -1687,26 +1656,26 @@ packages: dependency: transitive description: name: permission_handler - sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" + sha256: "3c84d49f0a5e1915364707159ab71f11b3b8a429532176d3a6248a45718ad4f9" url: "https://pub.dev" source: hosted - version: "11.2.0" + version: "11.2.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb" + sha256: a5ebaa420cee8fd880ef10dedd42c6b3f493e7dbe27d7e0a7e1798669373082a url: "https://pub.dev" source: hosted - version: "12.0.3" + version: "12.0.4" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830 + sha256: "6ca25ee52518a8a26e80aaefe3c71caf6e2dfd809c1b20900d0882df6faed36e" url: "https://pub.dev" source: hosted - version: "9.3.0" + version: "9.3.1" permission_handler_html: dependency: transitive description: @@ -1926,10 +1895,10 @@ packages: dependency: transitive description: name: rrule - sha256: "535fec11dfe8882c89f14bb0a99ae08fb04d8cf1771db1e9ebb9869b1d414dd1" + sha256: "74a11d8b62bfe491340ccc2f0d19a0369402a92952180a090bb8ac865d024904" url: "https://pub.dev" source: hosted - version: "0.2.14" + version: "0.2.16" rtu_mirea_schedule_api_client: dependency: transitive description: @@ -1987,42 +1956,42 @@ packages: dependency: transitive description: name: sentry - sha256: "5686ed515bb620dc52b4ae99a6586fe720d443591183cf1f620ec5d1f0eec100" + sha256: a7946f4a90b0feb47214981d881b98149e05f6c576da9f2a2f33945bf561de25 url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" sentry_dio: dependency: "direct main" description: name: sentry_dio - sha256: "67604a5c6df11ea48f60868effd7448df7300ab1768a749fd494906d627daa98" + sha256: ab26691e0687b56e6a8673cf646f1aa71b3811b7bf2029ebce192310cd99ce5b url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "505dec3b6810562785d2c34ae871c73ff2cba6cf436c32c188f0464df226ba8f" + sha256: "6db7fa1b076faf2f5dd77d8cc9ef206171f32a290cc638842d78e5d62b441a27" url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" sentry_logging: dependency: "direct main" description: name: sentry_logging - sha256: "48736cef1aa0bc719c1c4dfeb9520b8f4f758b71c2020d6390fadf21a5d755cd" + sha256: "76af2965ec0a2c6876a61f5e62d20b58024875aa03aa4dde8136a89ce3c99afa" url: "https://pub.dev" source: hosted - version: "7.15.0" + version: "7.16.0" share_plus: dependency: transitive description: name: share_plus - sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd + sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900" url: "https://pub.dev" source: hosted - version: "7.2.1" + version: "7.2.2" share_plus_platform_interface: dependency: transitive description: @@ -2215,10 +2184,10 @@ packages: dependency: transitive description: name: sqflite - sha256: c2c32eb0c74021d987336522acc3b6bf0082fbd0c540c36a9cf4ddb8ba891ddc + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" sqflite_common: dependency: transitive description: @@ -2231,10 +2200,10 @@ packages: dependency: transitive description: name: sqflite_common_ffi - sha256: d0e3f0d04fdf668e57db8db1df758f56c4193cb429092c708e7bfcc6ab04b27e + sha256: "754927d82de369a6b9e760fb60640aa81da650f35ffd468d5a992814d6022908" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.2+1" sqlite3: dependency: transitive description: @@ -2438,10 +2407,10 @@ packages: dependency: transitive description: name: unifiedpush_android - sha256: "85a0d7c736dfb7845f059439fc92e994d8e9f56f6c30c13fb4e779cffa412ec9" + sha256: "610ad746294541f56d632adf9afba5d1c164c44e23ec0dd2162a41a6ff00a00e" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.3" unifiedpush_platform_interface: dependency: transitive description: @@ -2557,26 +2526,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172" + sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d" + sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad" + sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" url: "https://pub.dev" source: hosted - version: "1.1.9+2" + version: "1.1.10+1" vector_math: dependency: transitive description: @@ -2701,18 +2670,18 @@ packages: dependency: transitive description: name: webview_flutter - sha256: "71e1bfaef41016c8d5954291df5e9f8c6172f1f6ff3af01b5656456ddb11f94c" + sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932" url: "https://pub.dev" source: hosted - version: "4.4.4" + version: "4.7.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "4ea3c4e1b8ed590162b15b8a61b41b1ef3ff179a314627c16ce40c086d94b8af" + sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0" url: "https://pub.dev" source: hosted - version: "3.14.0" + version: "3.15.0" webview_flutter_platform_interface: dependency: transitive description: @@ -2725,10 +2694,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506 + sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86" url: "https://pub.dev" source: hosted - version: "3.11.0" + version: "3.12.0" win32: dependency: transitive description: @@ -2749,10 +2718,10 @@ packages: dependency: transitive description: name: window_manager - sha256: dcc865277f26a7dad263a47d0e405d77e21f12cb71f30333a52710a408690bd7 + sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494 url: "https://pub.dev" source: hosted - version: "0.3.7" + version: "0.3.8" window_to_front: dependency: transitive description: @@ -2789,10 +2758,10 @@ packages: dependency: transitive description: name: xml_annotation - sha256: cea1ff2d086c31c4ceb1773a180807d6008e3ceed2debed2f76a556857d571ee + sha256: fb421dd15816c45b7c004b38cadb1d00fcf72549899ce6ab61ed1738e1f13cb1 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 81614639..c68e4dff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ publish_to: 'none' # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.5.0+79 +version: 1.5.1+81 environment: sdk: ">=3.1.1" @@ -193,7 +193,9 @@ dependencies: firebase_analytics: ^10.8.0 firebase_messaging: ^14.6.8 - oauth2_client: ^3.2.2 + oauth2_client: + git: + url: https://github.com/0niel/oauth2_client.git # Flutter Secure Storage provides API to store data in secure storage. # See https://pub.dev/packages/flutter_secure_storage @@ -251,6 +253,7 @@ dev_dependencies: freezed: ^2.4.5 json_serializable: melos: ^4.0.0 + fvm: ^3.0.0 flutter_icons: android: false diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 00000000..60450ccd --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. 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:rtu_mirea_mobile/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 83ab2e7f..9accbaf3 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "rtu_mirea_mobile") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -87,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 363e7ba6..90b7f99a 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -23,6 +24,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + DesktopWebviewWindowPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); EmojiPickerFlutterPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 1c1db6c9..61bb7175 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus + desktop_webview_window dynamic_color emoji_picker_flutter file_selector_windows @@ -19,7 +20,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - flutter_zxing ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 70e3e78e..8a015a46 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -89,13 +89,13 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "ninja.mirea" "\0" - VALUE "FileDescription", "rtu_mirea_mobile" "\0" + VALUE "CompanyName", "Mirea Ninja" "\0" + VALUE "FileDescription", "Приложение РТУ МИРЭА" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "rtu_mirea_mobile" "\0" - VALUE "LegalCopyright", "Copyright (C) 2023 ninja.mirea. All rights reserved." "\0" - VALUE "OriginalFilename", "rtu_mirea_mobile.exe" "\0" - VALUE "ProductName", "rtu_mirea_mobile" "\0" + VALUE "InternalName", "Мой РТУ МИРЭА" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 Sergey Dmitriev. All rights reserved." "\0" + VALUE "OriginalFilename", "Мой РТУ МИРЭА.exe" "\0" + VALUE "ProductName", "Ninja Mirea Desktop" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" END END diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20ca..63aa5cfd 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ