diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 0c9e8729d..09b391392 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -4,18 +4,18 @@ on: push: branches: - main - workflow_dispatch: env: - FLUTTER_VERSION: 3.16.5 + FLUTTER_VERSION: 3.16.9 jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: subosito/flutter-action@v2 + - uses: subosito/flutter-action@v1 with: + channel: 'stable' flutter-version: ${{env.FLUTTER_VERSION}} - uses: bluefireteam/flutter-gh-pages@v7 with: diff --git a/assets/yaru_icons.otf b/assets/yaru_icons.otf index d129f6f3d..40b69a825 100644 Binary files a/assets/yaru_icons.otf and b/assets/yaru_icons.otf differ diff --git a/example/lib/example.dart b/example/lib/example.dart index 5ff512423..ced4dcde6 100644 --- a/example/lib/example.dart +++ b/example/lib/example.dart @@ -7,14 +7,22 @@ import 'package:yaru/yaru.dart'; import 'code_snippet_button.dart'; import 'example_model.dart'; import 'example_page_items.dart'; +import 'pages/icons_page/provider/icon_view_model.dart'; class Example extends StatefulWidget { // ignore: unused_element const Example({super.key}); static Widget create(BuildContext context) { - return ChangeNotifierProvider( - create: (_) => ExampleModel(getService()), + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => ExampleModel(getService()), + ), + ChangeNotifierProvider( + create: (_) => IconViewModel(), + ), + ], child: const Example(), ); } @@ -62,7 +70,7 @@ class _MasterDetailPage extends StatelessWidget { length: pageItems.length, tileBuilder: (context, index, selected, availableWidth) => YaruMasterTile( leading: pageItems[index].iconBuilder(context, selected), - title: buildTitle(context, pageItems[index]), + title: Text(pageItems[index].title), ), pageBuilder: (context, index) => YaruDetailPage( appBar: YaruWindowTitleBar( diff --git a/example/lib/example_page_items.dart b/example/lib/example_page_items.dart index 014b541f9..a9c9e0ed1 100644 --- a/example/lib/example_page_items.dart +++ b/example/lib/example_page_items.dart @@ -251,8 +251,9 @@ final examplePageItems = [ ), PageItem( title: 'YaruIcons', + titleBuilder: createIconsPageAppBar, pageBuilder: (context) { - return IconsPage.create(context: context); + return const IconsPage(); }, iconBuilder: (context, selected) => selected ? const Icon(YaruIcons.placeholder_icon_filled) diff --git a/example/lib/pages/icons_page/common/clickable_icon.dart b/example/lib/pages/icons_page/common/clickable_icon.dart index 887c2bdc5..a28c5eb8b 100644 --- a/example/lib/pages/icons_page/common/clickable_icon.dart +++ b/example/lib/pages/icons_page/common/clickable_icon.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:yaru/yaru.dart'; import '../icon_items.dart'; import 'icon_dialog.dart'; @@ -18,6 +19,7 @@ class ClickableIcon extends StatelessWidget { return AspectRatio( aspectRatio: 1, child: InkWell( + borderRadius: BorderRadius.circular(kYaruButtonRadius), onTap: () => showDialog( context: context, builder: (context) => IconDialog( diff --git a/example/lib/pages/icons_page/common/icon_dialog.dart b/example/lib/pages/icons_page/common/icon_dialog.dart index be0cef992..006a1bd0b 100644 --- a/example/lib/pages/icons_page/common/icon_dialog.dart +++ b/example/lib/pages/icons_page/common/icon_dialog.dart @@ -33,9 +33,8 @@ class IconDialog extends StatelessWidget { title: Text(beautifyIconName(iconItem.name)), ), children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, + Wrap( + crossAxisAlignment: WrapCrossAlignment.center, children: [ for (final size in _iconDialogSizes) Padding( diff --git a/example/lib/pages/icons_page/common/icon_grid.dart b/example/lib/pages/icons_page/common/icon_grid.dart index 35577757d..a1298d25a 100644 --- a/example/lib/pages/icons_page/common/icon_grid.dart +++ b/example/lib/pages/icons_page/common/icon_grid.dart @@ -20,7 +20,12 @@ class IconGrid extends StatelessWidget { gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: iconSize * 1.5, ), - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.only( + top: 10, + bottom: 20, + left: 20, + right: 20, + ), itemCount: iconItems.length, itemBuilder: (context, index) { return Tooltip( diff --git a/example/lib/pages/icons_page/common/icon_table.dart b/example/lib/pages/icons_page/common/icon_table.dart index 8ecbdade0..a64c5adc8 100644 --- a/example/lib/pages/icons_page/common/icon_table.dart +++ b/example/lib/pages/icons_page/common/icon_table.dart @@ -19,40 +19,41 @@ class IconTable extends StatelessWidget { @override Widget build(BuildContext context) { return ListView.builder( - padding: const EdgeInsets.all(16), itemCount: iconItems.length, - itemBuilder: (context, index) => Column( - children: [ - Row( - children: [ - SizedBox.square( - dimension: iconSize * 1.5, - child: ClickableIcon( - iconItem: iconItems[index], - iconSize: iconSize, + itemBuilder: (context, index) { + return Column( + children: [ + Row( + children: [ + SizedBox.square( + dimension: iconSize * 1.5, + child: ClickableIcon( + iconItem: iconItems[index], + iconSize: iconSize, + ), ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: SelectableText( - beautifyIconName(iconItems[index].name), - style: Theme.of(context).textTheme.bodySmall, + const SizedBox( + width: 16, ), - ), - Expanded( - child: IconUsage( - usage: iconItems[index].usage, - label: false, - mainAxisAlignment: MainAxisAlignment.start, + Expanded( + child: SelectableText( + beautifyIconName(iconItems[index].name), + style: Theme.of(context).textTheme.bodySmall, + ), ), - ), - ], - ), - if (index < iconItems.length - 1) const Divider(), - ], - ), + Expanded( + child: IconUsage( + usage: iconItems[index].usage, + label: false, + mainAxisAlignment: MainAxisAlignment.start, + ), + ), + ], + ), + if (index < iconItems.length - 1) const Divider(), + ], + ); + }, ); } } diff --git a/example/lib/pages/icons_page/common/icon_usage.dart b/example/lib/pages/icons_page/common/icon_usage.dart index 0e52cfe27..760afe7ca 100644 --- a/example/lib/pages/icons_page/common/icon_usage.dart +++ b/example/lib/pages/icons_page/common/icon_usage.dart @@ -30,15 +30,20 @@ class IconUsage extends StatelessWidget { width: 8, ), ], - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: Theme.of(context).highlightColor, - ), - child: SelectableText( - usage, - style: usageTextStyle, + Flexible( + child: Padding( + padding: const EdgeInsets.only(right: 20), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Theme.of(context).highlightColor, + ), + child: SelectableText( + usage, + style: usageTextStyle, + ), + ), ), ), ], diff --git a/example/lib/pages/icons_page/icon_items.dart b/example/lib/pages/icons_page/icon_items.dart index fe4757c51..fbe5543a5 100644 --- a/example/lib/pages/icons_page/icon_items.dart +++ b/example/lib/pages/icons_page/icon_items.dart @@ -18,10 +18,17 @@ final List _staticIconItems = [ IconItem( name: iconName, usage: 'YaruIcons.$iconName', - iconBuilder: (context, iconSize) => Icon( - YaruIcons.all[iconName]!, - size: iconSize, - ), + iconBuilder: (context, iconSize) { + final data = YaruIcons.all[iconName]; + + if (data == null) { + return const Placeholder(); + } + return Icon( + data, + size: iconSize, + ); + }, ), ]; diff --git a/example/lib/pages/icons_page/icons_page.dart b/example/lib/pages/icons_page/icons_page.dart index cfed0992c..a8bec3ca7 100644 --- a/example/lib/pages/icons_page/icons_page.dart +++ b/example/lib/pages/icons_page/icons_page.dart @@ -22,112 +22,105 @@ class IconsPage extends StatefulWidget { State createState() => _IconsPageState(); } -class _IconsPageState extends State { +class _IconsPageState extends State + with SingleTickerProviderStateMixin { + int index = 0; + @override Widget build(BuildContext context) { - final iconSize = context.select((m) => m.iconSize); - final isMinIconSize = - context.select((m) => m.isMinIconSize); - final isMaxIconSize = - context.select((m) => m.isMaxIconSize); - final gridView = context.select((m) => m.gridView); - final searchActive = - context.select((m) => m.searchActive); - - return Scaffold( - appBar: AppBar( - title: YaruSearchTitleField( - searchActive: searchActive, - width: 250, - title: const Text( - 'Flutter Yaru Icons Demo', - ), - onSearchActive: context.read().toggleSearch, - onClear: context.read().toggleSearch, - onChanged: context.read().onSearchChanged, - ), - actions: [ - Tooltip( - message: gridView ? 'Toggle list view' : 'Toggle grid view', - child: IconButton( - onPressed: context.read().toggleGridView, - icon: gridView - ? const Icon(YaruIcons.unordered_list) - : const Icon(YaruIcons.app_grid), + return DefaultTabController( + length: 3, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + left: kYaruPagePadding, + right: kYaruPagePadding, + top: 10, ), - ), - Tooltip( - message: 'Decrease icon size', - child: IconButton( - onPressed: isMinIconSize - ? null - : context.read().decreaseIconSize, - icon: const Icon(YaruIcons.minus), + child: SizedBox( + width: 700, + child: YaruTabBar( + onTap: (value) => setState(() => index = value), + tabs: const [ + Tab( + text: 'Static', + ), + Tab( + text: 'Animated', + ), + Tab( + text: 'Widgets', + ), + ], + ), ), ), - Text('${iconSize.truncate()}px'), - Tooltip( - message: 'Increase icon size', - child: IconButton( - onPressed: isMaxIconSize - ? null - : context.read().increaseIconSize, - icon: const Icon(YaruIcons.plus), + Expanded( + child: IconView( + iconItems: switch (index) { + 0 => IconItems.static, + 1 => IconItems.animated, + 2 => IconItems.widget, + _ => throw 'Invalid index' + }, ), ), ], ), - body: YaruNavigationPage( - length: 3, - itemBuilder: (context, index, selected) { - const style = YaruNavigationRailStyle.labelled; - - switch (index) { - case 0: - return const YaruNavigationRailItem( - icon: Icon(YaruIcons.image), - label: Text('Static icons'), - tooltip: 'Static icons', - style: style, - ); - case 1: - return const YaruNavigationRailItem( - icon: Icon(YaruIcons.video), - label: Text('Animated icons'), - tooltip: 'Animated icons', - style: style, - ); - case 2: - return const YaruNavigationRailItem( - icon: Icon(YaruIcons.rule_and_pen), - label: Text('Widget icons'), - tooltip: 'Widget icons', - style: style, - ); - default: - throw 'Invalid index'; - } - }, - pageBuilder: (context, index) { - List iconItems; + ); + } +} - switch (index) { - case 0: - iconItems = IconItems.static; - break; - case 1: - iconItems = IconItems.animated; - break; - case 2: - iconItems = IconItems.widget; - break; - default: - throw 'Invalid index'; - } +YaruWindowTitleBar createIconsPageAppBar(BuildContext context) { + final model = context.read(); + final iconSize = context.select((m) => m.iconSize); + final isMinIconSize = + context.select((m) => m.isMinIconSize); + final isMaxIconSize = + context.select((m) => m.isMaxIconSize); + final gridView = context.select((m) => m.gridView); + final searchActive = + context.select((m) => m.searchActive); - return IconView(iconItems: iconItems); - }, + return YaruWindowTitleBar( + backgroundColor: Colors.transparent, + border: BorderSide.none, + leading: YaruSearchButton( + searchActive: searchActive, + onPressed: model.toggleSearch, + ), + title: searchActive + ? YaruSearchField( + onClear: model.toggleSearch, + onChanged: model.onSearchChanged, + ) + : const Text('YaruIcons'), + actions: [ + Tooltip( + message: gridView ? 'Toggle list view' : 'Toggle grid view', + child: IconButton( + onPressed: model.toggleGridView, + icon: gridView + ? const Icon(YaruIcons.unordered_list) + : const Icon(YaruIcons.app_grid), + ), ), - ); - } + Tooltip( + message: 'Decrease icon size', + child: IconButton( + onPressed: isMinIconSize ? null : model.decreaseIconSize, + icon: const Icon(YaruIcons.minus), + ), + ), + Text('${iconSize.truncate()}px'), + Tooltip( + message: 'Increase icon size', + child: IconButton( + onPressed: isMaxIconSize ? null : model.increaseIconSize, + icon: const Icon(YaruIcons.plus), + ), + ), + ], + ); } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 4d4f07493..87e99b387 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -5,7 +5,7 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.10.0" + flutter: ">=3.16.0" dependencies: collection: ^1.17.0 @@ -31,3 +31,7 @@ flutter: assets: - assets/ + fonts: + - family: YaruIcons + fonts: + - asset: ../assets/yaru_icons.otf diff --git a/pubspec.yaml b/pubspec.yaml index eab4e6603..625c7a072 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,6 +19,8 @@ dependencies: yaru_window: ^0.2.0 dev_dependencies: + animated_vector_gen: ^0.2.1 + build_runner: ^2.4.6 flutter_lints: ^3.0.1 flutter_test: sdk: flutter @@ -30,31 +32,31 @@ dev_dependencies: flutter: fonts: - - family: Ubuntu - fonts: - - asset: assets/fonts/Ubuntu-L.ttf - weight: 300 - - asset: assets/fonts/Ubuntu-LI.ttf - weight: 300 - style: italic - - asset: assets/fonts/Ubuntu-R.ttf - weight: 400 - - asset: assets/fonts/Ubuntu-RI.ttf - weight: 400 - style: italic - - asset: assets/fonts/Ubuntu-M.ttf - weight: 500 - - asset: assets/fonts/Ubuntu-MI.ttf - weight: 500 - style: italic - - asset: assets/fonts/Ubuntu-B.ttf - weight: 700 - - asset: assets/fonts/Ubuntu-BI.ttf - weight: 700 - style: italic - - family: YaruIcons - fonts: - - asset: assets/yaru_icons.otf + - family: Ubuntu + fonts: + - asset: assets/fonts/Ubuntu-L.ttf + weight: 300 + - asset: assets/fonts/Ubuntu-LI.ttf + weight: 300 + style: italic + - asset: assets/fonts/Ubuntu-R.ttf + weight: 400 + - asset: assets/fonts/Ubuntu-RI.ttf + weight: 400 + style: italic + - asset: assets/fonts/Ubuntu-M.ttf + weight: 500 + - asset: assets/fonts/Ubuntu-MI.ttf + weight: 500 + style: italic + - asset: assets/fonts/Ubuntu-B.ttf + weight: 700 + - asset: assets/fonts/Ubuntu-BI.ttf + weight: 700 + style: italic + - family: YaruIcons + fonts: + - asset: assets/yaru_icons.otf icon_font: input_svg_dir: "assets/icons/"