Compare commits

..

No commits in common. "f569041ab389e211a3487a12b1bc769b0bf0ebda" and "4663ff9094ceb4a7540a84d99fa72a3a6dce066e" have entirely different histories.

27 changed files with 171 additions and 216 deletions

View file

@ -40,7 +40,7 @@ template: |
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
exclude-labels: exclude-labels:
- "skip changelog" - "skip-changelog"
exclude-contributors: exclude-contributors:
- "Dr-Blank" - "Dr-Blank"
@ -55,15 +55,15 @@ autolabeler:
branch: branch:
- '/feature\/.+/' - '/feature\/.+/'
title: title:
- "/^feat(ure)?/i" - "/feat(ure)?/i"
body: body:
- "/JIRA-[0-9]{1,4}/" - "/JIRA-[0-9]{1,4}/"
- label: "chore" - label: "chore"
title: title:
- "/^chore\b/i" - "/chore/i"
- label: "ui" - label: "ui"
title: title:
- "/^ui\b/i" - "/^ui\b/i"
- label: "refactor" - label: "refactor"
title: title:
- "/^refactor/i" - "/refactor/i"

View file

@ -48,10 +48,6 @@ jobs:
# - name: Run static analysis # - name: Run static analysis
# run: flutter analyze # run: flutter analyze
- name: Check formatting
run: |
dart format -o none --set-exit-if-changed lib/
- name: Run tests - name: Run tests
run: flutter test run: flutter test

View file

@ -10,4 +10,5 @@ class HeroTagPrefixes {
static const String bookTitle = 'book_title_'; static const String bookTitle = 'book_title_';
static const String narratorName = 'narrator_name_'; static const String narratorName = 'narrator_name_';
static const String libraryItemPlayButton = 'library_item_play_button_'; static const String libraryItemPlayButton = 'library_item_play_button_';
} }

View file

@ -98,10 +98,8 @@ class MySearchBar extends HookConsumerWidget {
// opacity: 0.5 for the hint text // opacity: 0.5 for the hint text
hintStyle: WidgetStatePropertyAll( hintStyle: WidgetStatePropertyAll(
Theme.of(context).textTheme.bodyMedium!.copyWith( Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context) color:
.colorScheme Theme.of(context).colorScheme.onSurface.withOpacity(0.5),
.onSurface
.withValues(alpha: 0.5),
), ),
), ),
textInputAction: TextInputAction.search, textInputAction: TextInputAction.search,

View file

@ -199,10 +199,8 @@ class _LibraryItemProgressIndicator extends HookConsumerWidget {
'${remainingTime.smartBinaryFormat} left', '${remainingTime.smartBinaryFormat} left',
style: Theme.of(context).textTheme.bodySmall?.copyWith( style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context) color:
.colorScheme Theme.of(context).colorScheme.onSurface.withOpacity(0.75),
.onSurface
.withValues(alpha: 0.75),
), ),
), ),
], ],
@ -229,7 +227,7 @@ class _HeroSectionSubLabelWithIcon extends HookConsumerWidget {
ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage; ref.watch(appSettingsProvider).themeSettings.useMaterialThemeOnItemPage;
final color = useMaterialThemeOnItemPage final color = useMaterialThemeOnItemPage
? themeData.colorScheme.primary ? themeData.colorScheme.primary
: themeData.colorScheme.onSurface.withValues(alpha: 0.75); : themeData.colorScheme.onSurface.withOpacity(0.75);
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 8.0), padding: const EdgeInsets.only(bottom: 8.0),
child: Row( child: Row(
@ -445,7 +443,7 @@ class _BookTitle extends StatelessWidget {
? const SizedBox.shrink() ? const SizedBox.shrink()
: Text( : Text(
style: themeData.textTheme.titleSmall?.copyWith( style: themeData.textTheme.titleSmall?.copyWith(
color: themeData.colorScheme.onSurface.withValues(alpha: 0.8), color: themeData.colorScheme.onSurface.withOpacity(0.8),
), ),
itemBookMetadata?.subtitle ?? '', itemBookMetadata?.subtitle ?? '',
), ),

View file

@ -96,10 +96,7 @@ class LibraryItemMetadata extends HookConsumerWidget {
return VerticalDivider( return VerticalDivider(
indent: 6, indent: 6,
endIndent: 6, endIndent: 6,
color: Theme.of(context) color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
.colorScheme
.onSurface
.withValues(alpha: 0.6),
); );
}, },
), ),
@ -128,7 +125,7 @@ class _MetadataItem extends StatelessWidget {
children: [ children: [
Text( Text(
style: themeData.textTheme.titleMedium?.copyWith( style: themeData.textTheme.titleMedium?.copyWith(
color: themeData.colorScheme.onSurface.withValues(alpha: 0.90), color: themeData.colorScheme.onSurface.withOpacity(0.90),
), ),
value, value,
maxLines: 1, maxLines: 1,
@ -136,7 +133,7 @@ class _MetadataItem extends StatelessWidget {
), ),
Text( Text(
style: themeData.textTheme.bodySmall?.copyWith( style: themeData.textTheme.bodySmall?.copyWith(
color: themeData.colorScheme.onSurface.withValues(alpha: 0.7), color: themeData.colorScheme.onSurface.withOpacity(0.7),
), ),
title, title,
maxLines: 1, maxLines: 1,

View file

@ -13,37 +13,6 @@ class OnboardingSinglePage extends HookConsumerWidget {
super.key, super.key,
}); });
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Center(
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 600,
minWidth:
constraints.maxWidth < 600 ? constraints.maxWidth : 0,
),
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: SafeArea(child: OnboardingBody()),
),
),
),
);
},
),
);
}
}
class OnboardingBody extends HookConsumerWidget {
const OnboardingBody({
super.key,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final apiSettings = ref.watch(apiSettingsProvider); final apiSettings = ref.watch(apiSettingsProvider);
@ -70,65 +39,65 @@ class OnboardingBody extends HookConsumerWidget {
); );
} }
return Column( return Scaffold(
mainAxisAlignment: MainAxisAlignment.center, body: SingleChildScrollView(
crossAxisAlignment: CrossAxisAlignment.center, child: Column(
children: [ mainAxisAlignment: MainAxisAlignment.center,
Padding( children: [
padding: const EdgeInsets.all(8.0), Padding(
child: Text( padding: const EdgeInsets.all(8.0),
'Welcome to Vaani', child: Text(
style: Theme.of(context).textTheme.headlineSmall, 'Welcome to Vaani',
), style: Theme.of(context).textTheme.headlineSmall,
),
),
const SizedBox.square(
dimension: 16.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedSwitcher(
duration: 500.ms,
transitionBuilder: fadeSlideTransitionBuilder,
child: canUserLogin.value
? Text(
'Server connected, please login',
key: const ValueKey('connected'),
style: Theme.of(context).textTheme.bodyMedium,
)
: Text(
'Please enter the URL of your AudiobookShelf Server',
key: const ValueKey('not_connected'),
style: Theme.of(context).textTheme.bodyMedium,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AddNewServer(
controller: serverUriController,
allowEmpty: true,
onPressed: () {
canUserLogin.value = serverUriController.text.isNotEmpty;
},
),
),
AnimatedSwitcher(
duration: 500.ms,
transitionBuilder: fadeSlideTransitionBuilder,
child: canUserLogin.value
? UserLoginWidget(
server: audiobookshelfUri,
)
// ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0)
: const RedirectToABS().animate().fadeIn().slideY(
curve: Curves.easeInOut,
duration: 500.ms,
),
),
],
), ),
const SizedBox.square( ),
dimension: 16.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedSwitcher(
duration: 500.ms,
transitionBuilder: fadeSlideTransitionBuilder,
child: canUserLogin.value
? Text(
'Server connected, please login',
key: const ValueKey('connected'),
style: Theme.of(context).textTheme.bodyMedium,
)
: Text(
'Please enter the URL of your AudiobookShelf Server',
key: const ValueKey('not_connected'),
style: Theme.of(context).textTheme.bodyMedium,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AddNewServer(
controller: serverUriController,
allowEmpty: true,
onPressed: () {
canUserLogin.value = serverUriController.text.isNotEmpty;
},
),
),
const SizedBox.square(
dimension: 16.0,
),
AnimatedSwitcher(
duration: 500.ms,
transitionBuilder: fadeSlideTransitionBuilder,
child: canUserLogin.value
? UserLoginWidget(
server: audiobookshelfUri,
)
// ).animate().fade(duration: 600.ms).slideY(begin: 0.3, end: 0)
: const RedirectToABS().animate().fadeIn().slideY(
curve: Curves.easeInOut,
duration: 500.ms,
),
),
],
); );
} }
} }

View file

@ -130,11 +130,11 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
return Center( return Center(
child: InactiveFocusScopeObserver( child: InactiveFocusScopeObserver(
child: AutofillGroup( child: AutofillGroup(
child: Column( child: Padding(
children: [ padding: const EdgeInsets.all(8.0),
Padding( child: Column(
padding: const EdgeInsets.all(8.0), children: [
child: Wrap( Wrap(
// mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.center,
spacing: 10, spacing: 10,
runAlignment: WrapAlignment.center, runAlignment: WrapAlignment.center,
@ -174,10 +174,10 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
), ),
], ],
), ),
), const SizedBox.square(
Padding( dimension: 8,
padding: const EdgeInsets.all(8.0), ),
child: switch (methodChoice.value) { switch (methodChoice.value) {
AuthMethodChoice.authToken => UserLoginWithToken( AuthMethodChoice.authToken => UserLoginWithToken(
server: server, server: server,
addServer: addServer, addServer: addServer,
@ -192,8 +192,8 @@ class UserLoginMultipleAuth extends HookConsumerWidget {
openIDButtonText: openIDButtonText, openIDButtonText: openIDButtonText,
), ),
}, },
), ],
], ),
), ),
), ),
), ),

View file

@ -29,7 +29,6 @@ class UserLoginWithPassword extends HookConsumerWidget {
final usernameController = useTextEditingController(); final usernameController = useTextEditingController();
final passwordController = useTextEditingController(); final passwordController = useTextEditingController();
final isPasswordVisibleAnimationController = useAnimationController( final isPasswordVisibleAnimationController = useAnimationController(
initialValue: 1,
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
); );
@ -93,76 +92,76 @@ class UserLoginWithPassword extends HookConsumerWidget {
return Center( return Center(
child: InactiveFocusScopeObserver( child: InactiveFocusScopeObserver(
child: AutofillGroup( child: AutofillGroup(
child: Column( child: Padding(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.all(8.0),
children: [ child: Column(
TextFormField( mainAxisAlignment: MainAxisAlignment.center,
controller: usernameController, children: [
autofocus: true, TextFormField(
autofillHints: const [AutofillHints.username], controller: usernameController,
textInputAction: TextInputAction.next, autofocus: true,
decoration: InputDecoration( autofillHints: const [AutofillHints.username],
labelText: 'Username', textInputAction: TextInputAction.next,
labelStyle: TextStyle( decoration: InputDecoration(
color: Theme.of(context) labelText: 'Username',
.colorScheme labelStyle: TextStyle(
.onSurface color: Theme.of(context)
.withValues(alpha: 0.8),
),
border: const OutlineInputBorder(),
),
),
const SizedBox(height: 10),
TextFormField(
controller: passwordController,
autofillHints: const [AutofillHints.password],
textInputAction: TextInputAction.done,
obscureText: !isPasswordVisible.value,
onFieldSubmitted: (_) {
loginAndSave();
},
decoration: InputDecoration(
labelText: 'Password',
labelStyle: TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface
.withValues(alpha: 0.8),
),
border: const OutlineInputBorder(),
suffixIcon: ColorFiltered(
colorFilter: ColorFilter.mode(
Theme.of(context)
.colorScheme .colorScheme
.primary .onSurface
.withValues(alpha: 0.8), .withOpacity(0.8),
BlendMode.srcIn,
), ),
child: InkWell( border: const OutlineInputBorder(),
borderRadius: BorderRadius.circular(50), ),
onTap: () { ),
isPasswordVisible.value = !isPasswordVisible.value; const SizedBox(height: 10),
}, TextFormField(
child: Container( controller: passwordController,
margin: const EdgeInsets.only(left: 8, right: 8), autofillHints: const [AutofillHints.password],
child: Lottie.asset( textInputAction: TextInputAction.done,
'assets/animations/Animation - 1714930099660.json', obscureText: !isPasswordVisible.value,
controller: isPasswordVisibleAnimationController, onFieldSubmitted: (_) {
loginAndSave();
},
decoration: InputDecoration(
labelText: 'Password',
labelStyle: TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
),
border: const OutlineInputBorder(),
suffixIcon: ColorFiltered(
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.primary.withOpacity(0.8),
BlendMode.srcIn,
),
child: InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () {
isPasswordVisible.value = !isPasswordVisible.value;
},
child: Container(
margin: const EdgeInsets.only(left: 8, right: 8),
child: Lottie.asset(
'assets/animations/Animation - 1714930099660.json',
controller: isPasswordVisibleAnimationController,
),
), ),
), ),
), ),
), suffixIconConstraints: const BoxConstraints(
suffixIconConstraints: const BoxConstraints( maxHeight: 45,
maxHeight: 45, ),
), ),
), ),
), const SizedBox(height: 30),
const SizedBox(height: 30), ElevatedButton(
ElevatedButton( onPressed: loginAndSave,
onPressed: loginAndSave, child: const Text('Login'),
child: const Text('Login'), ),
), ],
], ),
), ),
), ),
), ),

View file

@ -84,10 +84,7 @@ class UserLoginWithToken extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'API Token', labelText: 'API Token',
labelStyle: TextStyle( labelStyle: TextStyle(
color: Theme.of(context) color: Theme.of(context).colorScheme.onSurface.withOpacity(0.8),
.colorScheme
.onSurface
.withValues(alpha: 0.8),
), ),
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
), ),

View file

@ -104,10 +104,8 @@ class PlayerWhenExpanded extends HookConsumerWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Theme.of(context) color:
.colorScheme Theme.of(context).colorScheme.primary.withOpacity(0.1),
.primary
.withValues(alpha: 0.1),
blurRadius: 32 * earlyPercentage, blurRadius: 32 * earlyPercentage,
spreadRadius: 8 * earlyPercentage, spreadRadius: 8 * earlyPercentage,
// offset: Offset(0, 16 * earlyPercentage), // offset: Offset(0, 16 * earlyPercentage),
@ -173,7 +171,7 @@ class PlayerWhenExpanded extends HookConsumerWidget {
color: Theme.of(context) color: Theme.of(context)
.colorScheme .colorScheme
.onSurface .onSurface
.withValues(alpha: 0.7), .withOpacity(0.7),
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View file

@ -93,7 +93,7 @@ class PlayerWhenMinimized extends HookConsumerWidget {
color: Theme.of(context) color: Theme.of(context)
.colorScheme .colorScheme
.onSurface .onSurface
.withValues(alpha: 0.7), .withOpacity(0.7),
), ),
), ),
], ],

View file

@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart'; import 'package:list_wheel_scroll_view_nls/list_wheel_scroll_view_nls.dart';
import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart';
import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/shared/hooks.dart';
const double itemExtent = 25; const double itemExtent = 25;

View file

@ -11,6 +11,7 @@ import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart'
import 'package:vaani/main.dart'; import 'package:vaani/main.dart';
import 'package:vaani/settings/app_settings_provider.dart'; import 'package:vaani/settings/app_settings_provider.dart';
import 'package:vaani/shared/extensions/duration_format.dart'; import 'package:vaani/shared/extensions/duration_format.dart';
import 'package:vaani/shared/hooks.dart';
class SleepTimerButton extends HookConsumerWidget { class SleepTimerButton extends HookConsumerWidget {
const SleepTimerButton({ const SleepTimerButton({

View file

@ -261,7 +261,9 @@ class ServerManagerPage extends HookConsumerWidget {
}, },
), ),
), ),
MiniPlayerBottomPadding(), MiniPlayerBottomPadding(),
], ],
), ),
), ),

View file

@ -76,7 +76,7 @@ class HomePage extends HookConsumerWidget {
child: ListView.separated( child: ListView.separated(
itemBuilder: (context, index) => shelvesToDisplay[index], itemBuilder: (context, index) => shelvesToDisplay[index],
separatorBuilder: (context, index) => Divider( separatorBuilder: (context, index) => Divider(
color: Theme.of(context).dividerColor.withValues(alpha: 0.1), color: Theme.of(context).dividerColor.withOpacity(0.1),
indent: 16, indent: 16,
endIndent: 16, endIndent: 16,
), ),

View file

@ -61,7 +61,7 @@ class LibraryPage extends HookConsumerWidget {
child: ListView.separated( child: ListView.separated(
itemBuilder: (context, index) => shelvesToDisplay[index], itemBuilder: (context, index) => shelvesToDisplay[index],
separatorBuilder: (context, index) => Divider( separatorBuilder: (context, index) => Divider(
color: Theme.of(context).dividerColor.withValues(alpha: 0.1), color: Theme.of(context).dividerColor.withOpacity(0.1),
indent: 16, indent: 16,
endIndent: 16, endIndent: 16,
), ),

View file

@ -16,4 +16,5 @@ class LibraryItemExtras with _$LibraryItemExtras {
BookMinified? book, BookMinified? book,
@Default('') String heroTagSuffix, @Default('') String heroTagSuffix,
}) = _LibraryItemExtras; }) = _LibraryItemExtras;
} }

View file

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart' show immutable; import 'package:flutter/foundation.dart' show immutable;
@immutable @immutable
class AppMetadata { class AppMetadata {
const AppMetadata._(); const AppMetadata._();

View file

@ -40,7 +40,7 @@ class NavigationWithSwitchTile extends AbstractSettingsTile {
child: Row( child: Row(
children: [ children: [
VerticalDivider( VerticalDivider(
color: Theme.of(context).dividerColor.withValues(alpha: 0.5), color: Theme.of(context).dividerColor.withOpacity(0.5),
indent: 8.0, indent: 8.0,
endIndent: 8.0, endIndent: 8.0,
), ),

View file

@ -1,3 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';

View file

@ -68,7 +68,7 @@ class AddNewServer extends HookConsumerWidget {
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Server URI', labelText: 'Server URI',
labelStyle: TextStyle( labelStyle: TextStyle(
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.8), color: Theme.of(context).colorScheme.onSurface.withOpacity(0.8),
), ),
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
prefixText: prefixText:

View file

@ -3,6 +3,7 @@ import 'package:go_router/go_router.dart';
import 'package:vaani/features/you/view/server_manager.dart'; import 'package:vaani/features/you/view/server_manager.dart';
import 'package:vaani/router/router.dart'; import 'package:vaani/router/router.dart';
class MyDrawer extends StatelessWidget { class MyDrawer extends StatelessWidget {
const MyDrawer({ const MyDrawer({
super.key, super.key,

View file

@ -39,7 +39,7 @@ class ExpandableDescription extends HookWidget {
// header with carrot icon is tapable // header with carrot icon is tapable
InkWell( InkWell(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
onTap: () { onTap: () {
isDescExpanded.value = !isDescExpanded.value; isDescExpanded.value = !isDescExpanded.value;
if (isDescExpanded.value) { if (isDescExpanded.value) {

View file

@ -255,10 +255,8 @@ class _BookOnShelfPlayButton extends HookConsumerWidget {
child: CircularProgressIndicator( child: CircularProgressIndicator(
value: userProgress.progress, value: userProgress.progress,
strokeWidth: strokeWidth, strokeWidth: strokeWidth,
backgroundColor: Theme.of(context) backgroundColor:
.colorScheme Theme.of(context).colorScheme.onPrimary.withOpacity(0.8),
.onPrimary
.withValues(alpha: 0.8),
valueColor: AlwaysStoppedAnimation<Color>( valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary, Theme.of(context).colorScheme.primary,
), ),
@ -276,10 +274,7 @@ class _BookOnShelfPlayButton extends HookConsumerWidget {
const Size(size, size), const Size(size, size),
), ),
backgroundColor: WidgetStateProperty.all( backgroundColor: WidgetStateProperty.all(
Theme.of(context) Theme.of(context).colorScheme.onPrimary.withOpacity(0.9),
.colorScheme
.onPrimary
.withValues(alpha: 0.9),
), ),
), ),
onPressed: () async { onPressed: () async {
@ -321,10 +316,9 @@ class BookCoverSkeleton extends StatelessWidget {
child: SizedBox( child: SizedBox(
width: 150, width: 150,
child: Shimmer.fromColors( child: Shimmer.fromColors(
baseColor: baseColor: Theme.of(context).colorScheme.surface.withOpacity(0.3),
Theme.of(context).colorScheme.surface.withValues(alpha: 0.3),
highlightColor: highlightColor:
Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.1), Theme.of(context).colorScheme.onSurface.withOpacity(0.1),
child: Container( child: Container(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
), ),

View file

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 0.0.17+8 version: 0.0.16+7
environment: environment:
sdk: ">=3.3.4 <4.0.0" sdk: ">=3.3.4 <4.0.0"

@ -1 +1 @@
Subproject commit 5cc545ca87c05615473ab9c363cfa29e341d1e2a Subproject commit ac8e94df7b28c4334165a11c3b445cd0cc497495