├── README.md ├── images ├── addasync.png ├── adding.png ├── almostdone.png ├── better.png ├── builder.png ├── command_palette.png ├── cursor.png ├── dart_add_dep.png ├── delete.png ├── donenoicons.png ├── ensureinit.png ├── example.png ├── extract_scaffold.png ├── first_locations.png ├── first_run.png ├── flutter_ext.png ├── flutter_new.png ├── gtkwindow.png ├── home.png ├── hundred.png ├── import_main_my_app.png ├── look_up.png ├── m2.png ├── mark_placeholder.png ├── materialapp.png ├── md.png ├── md3.png ├── md4.png ├── morepara.png ├── multi_cursor.png ├── my_app.png ├── new_terminal.png ├── no_my_app.png ├── noroundyaru.png ├── not_pretty.png ├── quick.png ├── restart.png ├── scaffold.png ├── settings_app.png ├── stfl.png ├── stle.png ├── wizard.png ├── yaru.png ├── yaruimport.png ├── yaruthemeimport.png └── yaruwindowtitlebar.png └── my_yaru_app ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── lib └── main.dart ├── linux ├── .gitignore ├── CMakeLists.txt ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake ├── main.cc ├── my_application.cc └── my_application.h ├── pubspec.lock └── pubspec.yaml /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Template Projects 3 | 4 | > [!TIP] 5 | > Already an experienced programmer but new to ubuntu yaru flutter apps? 6 | > Skip the tutorials and clone one of our template repositories, created with best practices, client side decorations, rounded bottom corners and CI in place, and take them as a starting point: 7 | 8 | 9 | | Calculator | Licenses | Numbers | 10 | | - | - | - | 11 | |![](https://raw.githubusercontent.com/ubuntu-flutter-community/calculator/main/screenshot.png)|![](https://raw.githubusercontent.com/ubuntu-flutter-community/licenses/main/screenshots/linux.png) |![](https://raw.githubusercontent.com/ubuntu-flutter-community/numbers/main/screenshots/linux.png) | 12 | 13 | # TL;DR Yaru.dart crash course 14 | 15 | > [!TIP] 16 | > TL;DR. Version without Explanation 17 | 18 | 1. `flutter pub add yaru` 19 | 2. `flutter pub add handy_window` 20 | 3. Modify `linux/my_application.cc` to register plugins before showing the Flutter 21 | window and view: 22 | 23 | ```diff 24 | diff --git a/linux/my_application.cc b/linux/my_application.cc 25 | index fa74baa..3133755 100644 26 | --- a/linux/my_application.cc 27 | +++ b/linux/my_application.cc 28 | @@ -48,17 +48,17 @@ static void my_application_activate(GApplication* application) { 29 | } 30 | 31 | gtk_window_set_default_size(window, 1280, 720); 32 | - gtk_widget_show(GTK_WIDGET(window)); 33 | 34 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 35 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 36 | 37 | FlView* view = fl_view_new(project); 38 | - gtk_widget_show(GTK_WIDGET(view)); 39 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 40 | 41 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 42 | 43 | + gtk_widget_show(GTK_WIDGET(window)); 44 | + gtk_widget_show(GTK_WIDGET(view)); 45 | gtk_widget_grab_focus(GTK_WIDGET(view)); 46 | } 47 | ``` 48 | 49 | 3. add 50 | ```dart 51 | await YaruWindowTitleBar.ensureInitialized(); 52 | ``` 53 | before `runApp` 54 | 4. Wrap your MaterialApp with YaruTheme and use the `yaru.theme` and `yaru.darkTheme` like so: 55 | ```dart 56 | import 'package:flutter/material.dart'; 57 | import 'package:yaru/yaru.dart'; 58 | 59 | Future main() async { 60 | await YaruWindowTitleBar.ensureInitialized(); 61 | runApp(const MyApp()); 62 | } 63 | 64 | class MyApp extends StatelessWidget { 65 | const MyApp({super.key}); 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return YaruTheme(builder: (context, yaru, child) { 70 | return MaterialApp( 71 | debugShowCheckedModeBanner: false, // <------------- 72 | theme: yaru.theme, // <----------- 73 | darkTheme: yaru.darkTheme, // <------------- 74 | home: Scaffold( 75 | appBar: const YaruWindowTitleBar(), // <------------- 76 | ), 77 | ); 78 | }); 79 | } 80 | } 81 | ``` 82 | 5. Check out our Widgets in our [Web-App](https://ubuntu.github.io/yaru.dart/) 83 | 84 | 85 | 86 | # How to create an Ubuntu Desktop Yaru application with Flutter 87 | 88 | This is a **beginner** tutorial for those new to the Dart programming language, new to programming languages in general and new to the Yaru design. 89 | 90 | ## Intro 91 | 92 | The preinstalled applications on Ubuntu are quite diverse in their programming language and tooling origins. Some examples are the Firefox internet browser and the Thunderbird e-mail client both being C++ and JavaScript applications, the Libre-Office suite being written in C++, XML, and Java and gnome-files (A.K.A. nautilus) which is written in C with gtk. 93 | 94 | Another toolkit is [Flutter](https://flutter.dev/). Flutter is a multi platform toolkit written in C++ and dart. 95 | The GUI of the new Ubuntu Desktop installer is made Flutter as well as the next iteration of Ubuntu Software plus there are hundreds of iOS, Android, Windows, Web and MacOS applications created with Flutter. 96 | 97 | Over the past years the [ubuntu-flutter-community](https://github.com/ubuntu-flutter-community) and [canonical](https://github.com/orgs/canonical/repositories?q=&type=all&language=dart&sort=) designed and developed several dart libraries which make it easy to create Ubuntu Desktop applications with Flutter. This tutorial will make all of this less mystical for people not familiar with neither Flutter nor our dart libraries. 98 | 99 | ### What you will learn 100 | 101 | - How to setup your Flutter development environment on Ubuntu 102 | - Learn VsCode basics 103 | - Get to know dart libraries to create an aesthetic and visually consistent desktop application 104 | - Create a starting point for either a multi-page, single-page or wizard-like desktop applications on Ubuntu 105 | 106 | ### Skill requirements 107 | 108 | It should be an advantage if you have created an application before, preferable with [an object oriented language](https://en.wikipedia.org/wiki/Object-oriented_programming) and if you are not scared to copy and paste commands into your terminal. But since this is a step-by-step, hands-on tutorial everyone with a bit of technical interest should do fine. 109 | 110 | ## Setup 111 | 112 | ### Install Flutter 113 | 114 | If you want to create Android or Web applications with Flutter from your Ubuntu machine, all you need should be the flutter snap (`snap install flutter --classic`). However, this tutorial is about creating apps for the Ubuntu *Desktop*. Some of our dart libraries make use of native libraries which may not behave perfectly with the way the flutter snap interacts with your system. 115 | 116 | The following lines will install the dependencies for Flutter Linux apps, create a directory in your home dir, clone the flutter git repository and export the `flutter` and `dart` commands to your path so you can run it from any user shell. 117 | 118 | - So please open up your terminal on Ubuntu by either pressing the key-combination CTRL + ALT + T or by searching for "Terminal" in your Ubuntu search. And... 119 | 120 | **...either** copy & paste the following lines successively into your terminal and press enter after: 121 | 122 | ```bash 123 | sudo apt install git curl cmake meson make clang libgtk-3-dev pkg-config 124 | mkdir -p ~/development 125 | cd ~/development 126 | git clone https://github.com/flutter/flutter.git -b stable 127 | echo 'export PATH="$PATH:$HOME/development/flutter/bin"' >> ~/.bashrc 128 | source ~/.bashrc 129 | ``` 130 | 131 | **OR** use this one-liner to copy and paste everything into your terminal, :warning: this does not stop until it is done: 132 | 133 | ```bash 134 | sudo apt -y install git curl cmake meson make clang libgtk-3-dev pkg-config && mkdir -p ~/development && cd ~/development && git clone https://github.com/flutter/flutter.git -b stable && echo 'export PATH="$PATH:$HOME/development/flutter/bin"' >> ~/.bashrc && source ~/.bashrc 135 | ``` 136 | 137 | ### Install VsCode 138 | 139 | - Run the following command to install VsCode on your Ubuntu machine (or install it from Ubuntu Software): 140 | 141 | ```bash 142 | sudo snap install code --classic 143 | ``` 144 | 145 | ### Setup VsCode 146 | 147 | - Open VsCode, click on the extension icon in the left sidebar (1), type "Flutter" and click "Install" on the first entry (3), this should be the Flutter extension by Dart Code. 148 | 149 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/flutter_ext.png) 150 | 151 | ## Let's get started: flutter create 152 | 153 | VsCode offers a command palette which you can open with either CTRL+SHIFT+P or by clicking on the :gear: icon 154 | 155 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/command_palette.png) 156 | 157 | We ***could*** now type "Flutter new project", but we don't! 158 | 159 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/flutter_new.png) 160 | 161 | However, since we want to make amount of auto created files as small as possible to make the management as easy as possible, we want to specify the platforms for our new project. 162 | 163 | - Open the integrated terminal in vscode if it is not already opened 164 | 165 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/new_terminal.png) 166 | 167 | - And run the following command to create a new Flutter project for Linux only (you can add more platforms at any point if you want) and specify the name of your organization/company and your appname: 168 | 169 | ```bash 170 | flutter create --platforms=linux --org com.test my_yaru_app 171 | ``` 172 | - Flutter created a small template app for us. Let's take a look at the three locations we need to visit first: 173 | 174 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/first_locations.png) 175 | 176 | (1) Is the `lib` directory where all of our dart code lives. For now a single `main.dart` file should be enough. All platforms our app wants to be available for gets its own directory. In our case only the `Linux` directory (2). We will come this back later. To define metadata of our app and the dependencies we want to use we need the `pubspec.yaml` file (3). 177 | 178 | ### First run 179 | 180 | - Now click on `main.dart` (1) to open the file in your editor and click on the small `Run` label above the `void main()` declaration (2) to run the app for the first time 181 | 182 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/first_run.png) 183 | 184 | | ![space-1.jpg](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/not_pretty.png) | 185 | |:--:| 186 | | *(Caution, it is not pretty yet)* | 187 | 188 | 189 | ### Clean up 190 | 191 | The Flutter template app is quite verbose explaining what it contains but we don't need most of the things in here for now. 192 | 193 | - Delete everything in your main.dart file below line 5 194 | 195 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/delete.png) 196 | 197 | Dart will now complain that the class `MyApp` does not exist any longer. Because we've just deleted it on purpose. 198 | 199 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/no_my_app.png) 200 | 201 | ### First snipped: stle 202 | 203 | The Flutter VsCode extensions is extremely helpful for almost any task and saves us a lot of lines to write. There are quick commands, snippets, auto-complete and auto fix features available which we will use in this tutorial. 204 | The first help we will use is the snippet `stle` which is short for `StatelessWidget`. 205 | 206 | - Move below line 5 and write 207 | 208 | `stle` 209 | 210 | Now a popup should ... pop-up. (if not press CTRL+ENTER, if this does not help either, there is something wrong with your setup of vscode, flutter and the Flutter VsCode extension). 211 | 212 | - (1) is your text and the cursor 213 | - (2) is the detected snippet `Flutter Stateless Widget` 214 | - (3) is a little explanation what will happen if you press ENTER now, which you please do now: 215 | 216 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/stle.png) 217 | 218 | Something happened! Now please stay calm, take your fingers off the keyboard for a moment and look at what you got. 219 | 220 | - The created snippet left a "multi-cursor" in the places which change if you change the name of your `StatelessWidget`. 221 | 222 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/multi_cursor.png) 223 | 224 | - Just start writing `MyApp` now and the text will be written into both places at once. When you are done press the ESC key on your keyboard to stop the multi-cursor. Pressing CTRL+S will save your code and the changes will be hot-reloaded immediately into your app: 225 | 226 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/my_app.png) 227 | 228 | Every time you save your code by either pressing CTRL+S or by the menu entry File->Save, Flutter will [Hot-Reload your changes right into your dart process](https://docs.flutter.dev/development/tools/hot-reload). This means that you do not need to re-run your app every time you change something in your code. However if you exchange bigger parts you might need to click on Restart (1) 229 | 230 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/restart.png) 231 | 232 | ### First recap 233 | 234 | - (1) Imports the package `material.dart` 235 | - (2) Is the main application with the `runApp` [function call](https://dart.dev/language/functions). 236 | - (3) Is your [class](https://dart.dev/language/classes) `MyApp` which [extends](https://dart.dev/language/extend) the class [`StatelessWidget`](https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html). 237 | Extending this class forces your app to implement the [`Widget build(BuildContext context)`](https://api.flutter.dev/flutter/widgets/StatelessWidget/build.html) method, which you do by returning the Widget `PlaceHolder`. 238 | 239 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/import_main_my_app.png) 240 | 241 | ### dart keywords used 242 | 243 | - [import](https://dart.dev/language/libraries#using-libraries) 244 | - [void](https://dart.dev/language/built-in-types) 245 | - [const](https://dart.dev/language/variables#final-and-const) 246 | - [class](https://dart.dev/language/classes) 247 | - [extends](https://dart.dev/language/extend) 248 | - [super](https://dart.dev/language/extend) 249 | - [return](https://dart.dev/language/functions#return-values) 250 | 251 | 252 | ## Creating the app skeleton 253 | 254 | ### MaterialApp 255 | 256 | Mark `const Placeholder` 257 | 258 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/mark_placeholder.png) 259 | 260 | and write `MaterialApp` which opens a popup with a suggested class, press ENTER to replace `PlaceHolder` with `MaterialApp()` 261 | 262 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/materialapp.png) 263 | 264 | ### Quick look into named parameters in dart 265 | 266 | Don't code now, just read. 267 | 268 | Functions in dart, as in any other modern programming language, can either have no or any kind and amount of [parameters](https://dart.dev/language/functions#parameters) (also called arguments or input variables). [*(In mathematics this is different. All functions must have at least one argument and a return value.)*](https://en.wikipedia.org/wiki/Function_(mathematics)) 269 | 270 | To make reading function calls easier dart has the optional feature of named [parameters](https://dart.dev/language/functions#parameters). Where a function, if defined with (a) named parameter(s), must be called by naming the parameter, followed by a `:` and the value that should be set. 271 | 272 | Example definition without a named parameter: 273 | ```dart 274 | int incrementByOne(int myParameter) { 275 | return myParameter + 1; 276 | } 277 | ``` 278 | 279 | Calling the function: 280 | ```dart 281 | incrementByOne(3); 282 | ``` 283 | 284 | Example definition with a named parameter: 285 | ```dart 286 | int incrementByOne({required int myParameter}) { 287 | return myParameter + 1; 288 | } 289 | ``` 290 | 291 | Calling the function: 292 | ```dart 293 | incrementByOne(myParameter: 3); 294 | ``` 295 | 296 | To create an instance of a class one needs to call the [constructor](https://dart.dev/language/constructors) "function" (to be concrete "method" because this function is defined inside class). 297 | 298 | Flutter widget classes almost always use named parameters, which is increasingly useful the more parameters a Widget has when you call its constructor method. 299 | 300 | Example Widget definition: 301 | 302 | ```dart 303 | class _MyNumberWidget extends StatelessWidget { 304 | // This is the constructor definition 305 | const _MyNumberWidget({required this.number}); 306 | // This is your parameter of the type integer. 307 | final int number; 308 | 309 | @override 310 | Widget build(BuildContext context) { 311 | // using the parameter to be shown inside the UI 312 | return Text(number.toString()); 313 | } 314 | } 315 | ``` 316 | 317 | Somewhere else (where calling functions is allowed): 318 | ```dart 319 | final Widget myNumberWidget = MyNumberWidget(number: 3) 320 | ``` 321 | 322 | #### New keywords learned 323 | 324 | - [final](https://dart.dev/language/variables#final-and-const) 325 | - [required](https://dart.dev/language/functions#named-parameters) 326 | 327 | ### Back to coding: Scaffold 328 | 329 | - Move your cursor inside the brackets of the `MaterialApp()` constructor call and insert 330 | 331 | ```home:``` 332 | 333 | - VsCode then suggests: 334 | 335 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/home.png) 336 | 337 | - Press enter, and write `Scaffold()` 338 | 339 | - VsCode then suggests: 340 | 341 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/scaffold.png) 342 | 343 | - Move the selection to `Scaffold()` by pressing your arrow-down key on your keyboard. Press enter when `Scaffold()` is selected. 344 | 345 | - Your code should now look like this: 346 | 347 | ```dart 348 | import 'package:flutter/material.dart'; 349 | 350 | void main() { 351 | runApp(const MyApp()); 352 | } 353 | 354 | class MyApp extends StatelessWidget { 355 | const MyApp({super.key}); 356 | 357 | @override 358 | Widget build(BuildContext context) { 359 | return MaterialApp(home: Scaffold()); 360 | } 361 | } 362 | ``` 363 | 364 | *Note: it is always better to let VsCode do the work by only typing until the code-completion (they call it "intellisense") popup shows up with suggestions. Pressing enter while one of the suggestions is selected is always safer because you will avoid typing errors and because VsCode will often also make the necessary import for you, too. However to not make this tutorial unnecessarily long, we won't go through this in every step.* 365 | 366 | 367 | ## Using the Yaru library 368 | ### pub.dev 369 | 370 | Pub.dev is the server infrastructure by google to host dart and flutter packages and you can use inside your flutter or dart applications by adding them as dependencies to your pubspec.yaml file. 371 | 372 | Not all packages on pub.dev are made for Linux but many. You can filter them with the platform=Linux filter. Recommended is also to check the dart3 compatible checkbox to get up to date packages. 373 | 374 | https://pub.dev/packages?q=platform%3Alinux+is%3Adart3-compatible 375 | 376 | ### Dart: add dependencies 377 | 378 | From your development environment, in case of this tutorial VsCode, you can add, update and remove dependencies with the [`dart pub`](https://dart.dev/tools/pub/cmd) and `flutter pub` commands from the terminal. 379 | In VsCode you can also use the command palette that you can open with CTRL+SHIFT+P. 380 | 381 | - Open the command palette and type `Dart: Add Dependency` 382 | 383 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/dart_add_dep.png) 384 | 385 | ### Yaru.dart 386 | 387 | - Type `yaru` and select the `yaru` package by pressing enter. The package will now be added to your `pubspec.yaml` file. 388 | 389 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/yaru.png) 390 | 391 | - Notice that two tasks are now run by VsCode. ***Wait*** until they are done 392 | 393 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/adding.png) 394 | 395 | ### YaruTheme 396 | 397 | - Move your cursor into `MaterialApp` 398 | 399 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/cursor.png) 400 | 401 | - Press the new key-combination CTRL+., which will open up a new context menu "Quick fix" and move your selection to "Wrap with Builder" 402 | 403 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/builder.png) 404 | 405 | - Press Enter, and immediately press CTRL+S after, to safe your changes. 406 | 407 | *Note: Saving your file also let's the VsCode flutter extension magically format your code in the background 408 | with the [`dart format`](https://dart.dev/tools/dart-format) command.* 409 | 410 | - Your resulting main.dart should now look like this: 411 | 412 | ```dart 413 | import 'package:flutter/material.dart'; 414 | 415 | void main() { 416 | runApp(const MyApp()); 417 | } 418 | 419 | class MyApp extends StatelessWidget { 420 | const MyApp({super.key}); 421 | 422 | @override 423 | Widget build(BuildContext context) { 424 | return Builder(builder: (context) { 425 | return MaterialApp(home: Scaffold()); 426 | }); 427 | } 428 | } 429 | ``` 430 | 431 | - Replace `Builder` with `YaruTheme`. A auto-complete context menu will pop up. 432 | 433 | - (1) Is what you write: `YaruTheme` 434 | - (2) Is your selection after pressing enter 435 | - (3) Is what will happen after you've pressed enter 436 | 437 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/yaruthemeimport.png) 438 | 439 | - The `yaru.dart` package is now useable from within your `main.dart` file because the `import 'package:yaru/yaru.dart';` has been added (1) at the top of your file 440 | 441 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/yaruimport.png) 442 | 443 | - The builder callback from `YaruTheme` needs two more parameters: an parameter of the type `YaruThemeData` and of the type `Widget?`. 444 | 445 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/morepara.png) 446 | 447 | - Add them separated by `,`behind the `context` parameter of the `builder` callback of `YaruTheme` by writing `yaru, child`. 448 | 449 | Your code should now look like this: 450 | 451 | 452 | ```dart 453 | import 'package:flutter/material.dart'; 454 | import 'package:yaru/yaru.dart'; 455 | 456 | void main() { 457 | runApp(const MyApp()); 458 | } 459 | 460 | class MyApp extends StatelessWidget { 461 | const MyApp({super.key}); 462 | 463 | @override 464 | Widget build(BuildContext context) { 465 | return YaruTheme(builder: (context, yaru, child) { 466 | return MaterialApp(home: Scaffold()); 467 | }); 468 | } 469 | } 470 | ``` 471 | 472 | `yaru` can now be used as a parameter of `MaterialApp`, and the flutter app will switch it's accent colors according to what accent color is selected in your Ubuntu settings app. 473 | 474 | - Set the theme property of Material app to `yaru.theme` and the dark theme property to `yaru.darkTheme`: 475 | 476 | ```dart 477 | import 'package:flutter/material.dart'; 478 | import 'package:yaru/yaru.dart'; 479 | 480 | void main() { 481 | runApp(const MyApp()); 482 | } 483 | 484 | class MyApp extends StatelessWidget { 485 | const MyApp({super.key}); 486 | 487 | @override 488 | Widget build(BuildContext context) { 489 | return YaruTheme(builder: (context, yaru, child) { 490 | return MaterialApp( 491 | theme: yaru.theme, // <----------- 492 | darkTheme: yaru.darkTheme, // <------------- 493 | home: Scaffold(), 494 | ); 495 | }); 496 | } 497 | } 498 | ``` 499 | 500 | - As an evidence that your app's accent color and brightness now follow your system let's add a primary color text in the middle of your `Scaffold`. 501 | 502 | - Set the `body` property of `Scaffold` to `Center()` 503 | - Set the child property of `Center` to `Text('Hello Ubuntu')` 504 | - Set the `style` property of the `Text` to `TextStyle(color: Theme.of(context).primaryColor)` 505 | 506 | Your code should now look like this (but we ain't done yet): 507 | 508 | ```dart 509 | import 'package:flutter/material.dart'; 510 | import 'package:yaru/yaru.dart'; 511 | 512 | void main() { 513 | runApp(const MyApp()); 514 | } 515 | 516 | class MyApp extends StatelessWidget { 517 | const MyApp({super.key}); 518 | 519 | @override 520 | Widget build(BuildContext context) { 521 | return YaruTheme(builder: (context, yaru, child) { 522 | return MaterialApp( 523 | theme: yaru.theme, 524 | darkTheme: yaru.darkTheme, 525 | home: Scaffold( 526 | body: Center( 527 | child: Text( 528 | 'Hello Ubuntu', 529 | style: TextStyle( 530 | color: Theme.of(context).primaryColor, 531 | ), 532 | ), 533 | ), 534 | ), 535 | ); 536 | }); 537 | } 538 | } 539 | ``` 540 | 541 | - Move your cursor onto `Scaffold` and re-open the quick-fix context menu as before with CTRL+. 542 | This time, select `Extract Widget` 543 | 544 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/extract_scaffold.png) 545 | 546 | - and press enter. 547 | 548 | - Look to the top, a little dialog appeared and asks you how the extracted Widget should be named. 549 | 550 | - Call it `_Home` (with a leading underscore): 551 | 552 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/look_up.png) 553 | 554 | - Press enter. 555 | 556 | Your code should now look like this: 557 | 558 | ```dart 559 | import 'package:flutter/material.dart'; 560 | import 'package:yaru/yaru.dart'; 561 | 562 | void main() { 563 | runApp(const MyApp()); 564 | } 565 | 566 | class MyApp extends StatelessWidget { 567 | const MyApp({super.key}); 568 | 569 | @override 570 | Widget build(BuildContext context) { 571 | return YaruTheme(builder: (context, yaru, child) { 572 | return MaterialApp( 573 | theme: yaru.theme, 574 | darkTheme: yaru.darkTheme, 575 | home: _Home(), 576 | ); 577 | }); 578 | } 579 | } 580 | 581 | class _Home extends StatelessWidget { 582 | const _Home({ 583 | super.key, 584 | }); 585 | 586 | @override 587 | Widget build(BuildContext context) { 588 | return Scaffold( 589 | body: Center( 590 | child: Text( 591 | 'Hello Ubuntu', 592 | style: TextStyle( 593 | color: Theme.of(context).primaryColor, 594 | ), 595 | ), 596 | ), 597 | ); 598 | } 599 | } 600 | ``` 601 | 602 | - Save your file and notice how the text is now colored in your system's primary accent color, while the window follows your system dark/light theme preference: 603 | 604 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/settings_app.png) 605 | 606 | 607 | ### Recap 608 | 609 | Alright, take a deep breath! 610 | 611 | The basic yaru theme and colors are in but we got more things to do: 612 | 613 | 1) **Make the window consist of 100% flutter widgets with client side window decorations** <-- next 614 | 2) Make the window have 4 founded corners 615 | 3) Create a master detail app 616 | 4) use yaru_icons 617 | 618 | ### Client side decorations with yaru.dart 619 | 620 | As you may have observed the app is living inside a GTK window. 621 | 622 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/gtkwindow.png) 623 | 624 | This is totally fine as it is because it works. However we aim to have the best look as possible, so we will need to use another YaruWindowTitleBar. 625 | 626 | 627 | - In your main.dart file write `YaruWindowTitleBar` before you call `runApp`. 628 | - (1) write `YaruWindowTitleBar` 629 | - (2) Notice the auto complete context menu 630 | - (3) Notice the nice explanation about what will be imported (eventually even read it) 631 | 632 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/yaruwindowtitlebar.png) 633 | - and press enter 634 | 635 | 636 | - Complete the line by using the `await` keyword, and calling `YaruWindowTitleBar.ensureInitialized()` 637 | 638 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/ensureinit.png) 639 | 640 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/quick.png) 641 | 642 | - Use the recommended quick fix by pressing enter when "Add 'async' modifier" is selected 643 | 644 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/addasync.png) 645 | 646 | Your `main` function should now look like this: 647 | 648 | ```dart 649 | Future main() async { 650 | await YaruWindowTitleBar.ensureInitialized(); 651 | runApp(const MyApp()); 652 | } 653 | ``` 654 | 655 | - Inside your `_Home` change the `appBar` property of `Scaffold` to `YaruWindowTitleBar()` 656 | - Inside your `MyApp` change the `debugShowCheckedModeBanner` property to have the value `false` to remove the red debug banner in the window corner 657 | 658 | Your code should now look like this: 659 | 660 | ```dart 661 | import 'package:flutter/material.dart'; 662 | import 'package:yaru/yaru.dart'; 663 | 664 | Future main() async { 665 | await YaruWindowTitleBar.ensureInitialized(); 666 | runApp(const MyApp()); 667 | } 668 | 669 | class MyApp extends StatelessWidget { 670 | const MyApp({super.key}); 671 | 672 | @override 673 | Widget build(BuildContext context) { 674 | return YaruTheme(builder: (context, yaru, child) { 675 | return MaterialApp( 676 | debugShowCheckedModeBanner: false, 677 | theme: yaru.theme, 678 | darkTheme: yaru.darkTheme, 679 | home: _Home(), 680 | ); 681 | }); 682 | } 683 | } 684 | 685 | class _Home extends StatelessWidget { 686 | const _Home({ 687 | super.key, 688 | }); 689 | 690 | @override 691 | Widget build(BuildContext context) { 692 | return Scaffold( 693 | appBar: YaruWindowTitleBar(), 694 | body: Center( 695 | child: Text( 696 | 'Hello Ubuntu', 697 | style: TextStyle( 698 | color: Theme.of(context).primaryColor, 699 | ), 700 | ), 701 | ), 702 | ); 703 | } 704 | } 705 | ``` 706 | 707 | Since yaru also modified the Linux specific files we did not look into (yet) you need to restart the app this time completely. 708 | 709 | - Stop it, and start it again. 710 | 711 | Your app should now look like this (yes no round corners yet!): 712 | 713 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/noroundyaru.png) 714 | 715 | #### New things learned 716 | 717 | - [`async` and `await` keywords](https://dart.dev/codelabs/async-await) 718 | - [`Future`](https://api.dart.dev/stable/2.19.5/dart-async/Future-class.html) 719 | 720 | ### handy_window.dart 721 | 722 | It's getting the first time a little bit complicated. Please do not panic. Everything is described step by step! 723 | 724 | Now we will need to modify two files inside the Linux directory to get the full `Yaru` look. 725 | 726 | - add `handy_window` like you've added the other dependencies before 727 | - Modify `linux/my_application.cc` to register plugins before showing the Flutter 728 | window and view: 729 | 730 | ```diff 731 | diff --git a/linux/my_application.cc b/linux/my_application.cc 732 | index fa74baa..3133755 100644 733 | --- a/linux/my_application.cc 734 | +++ b/linux/my_application.cc 735 | @@ -48,17 +48,17 @@ static void my_application_activate(GApplication* application) { 736 | } 737 | 738 | gtk_window_set_default_size(window, 1280, 720); 739 | - gtk_widget_show(GTK_WIDGET(window)); 740 | 741 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 742 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 743 | 744 | FlView* view = fl_view_new(project); 745 | - gtk_widget_show(GTK_WIDGET(view)); 746 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 747 | 748 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 749 | 750 | + gtk_widget_show(GTK_WIDGET(window)); 751 | + gtk_widget_show(GTK_WIDGET(view)); 752 | gtk_widget_grab_focus(GTK_WIDGET(view)); 753 | } 754 | ``` 755 | 756 | - Stop it, and start it again. 757 | 758 | ### Success! 759 | 760 | Tadah!!! Your app should now look like this: 761 | 762 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/almostdone.png) 763 | 764 | ## Types of apps + your ideas 765 | 766 | Most of the desktop apps we've encountered could be classified into one of the following "concepts": 767 | 768 | - Master/detail apps 769 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/md.png) 770 | 771 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/md2.png) 772 | 773 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/md3.png) 774 | 775 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/md4.png) 776 | 777 | - single page / wizard apps 778 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/wizard.png) 779 | 780 | That does not mean there aren't more types of apps and most importantly this should not limit your ideas and creativity in any way. 781 | 782 | ## Your master detail app 783 | 784 | ### YaruMasterDetailPage 785 | 786 | In this tutorial we create a master/details-app, because this type of app is pretty common in desktop environments. 787 | 788 | - replace the value of the `body` property of you `_Home` with `YaruMasterDetailPage()` 789 | - set the `length` property an integer value that matches the amount o pages you plan to add 790 | - write `tileBuilder` beneath the `length` property and wait for the auto complete context menu 791 | - press enter after you selected `(context, index, selected) {}` with pressing the arrow-down key 792 | - write `pageBuilder` beneath the `tileBuilder` property 793 | - press enter after you selected `(context, index) {}` with pressing the arrow-down key 794 | 795 | Your `_Home` code should now look like this (not done yet): 796 | 797 | ```dart 798 | class _Home extends StatelessWidget { 799 | const _Home({ 800 | super.key, 801 | }); 802 | 803 | @override 804 | Widget build(BuildContext context) { 805 | return Scaffold( 806 | appBar: YaruWindowTitleBar(), 807 | body: YaruMasterDetailPage( 808 | length: 2, 809 | tileBuilder: (context, index, selected, availableWidth) {}, 810 | pageBuilder: (context, index) {}, 811 | ), 812 | ); 813 | } 814 | } 815 | ``` 816 | 817 | - inside the `tileBuilder` callback return a different `YaruMasterTile()` depending if the value of `index` is `0` or not 818 | - inside the `pageBuilder` callback return a different `Widget` depending if the value of `index` is `0` or not 819 | 820 | Your `_Home` could now look like this, as a starting point: 821 | 822 | ```dart 823 | class _Home extends StatelessWidget { 824 | const _Home({super.key}); 825 | 826 | @override 827 | Widget build(BuildContext context) { 828 | return Scaffold( 829 | appBar: YaruWindowTitleBar(), 830 | body: YaruMasterDetailPage( 831 | length: 2, 832 | tileBuilder: (context, index, selected, availableWidth) { 833 | if (index == 0) { 834 | return YaruMasterTile(title: Text('Page 1')); 835 | } else { 836 | return YaruMasterTile(title: Text('Page 2')); 837 | } 838 | }, 839 | pageBuilder: (context, index) { 840 | if (index == 0) { 841 | return Center( 842 | child: Text('Hello Ubuntu'), 843 | ); 844 | } else { 845 | return Center( 846 | child: Text('Hello Yaru'), 847 | ); 848 | } 849 | }, 850 | ), 851 | ); 852 | } 853 | } 854 | ``` 855 | 856 | With this code, your app would look like this: 857 | 858 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/donenoicons.png) 859 | 860 | ### Yaru Icons 861 | 862 | The thin stroked, sleek [Yaru Icons](https://github.com/ubuntu/yaru.dart) are elemental for the full Yaru look and fit perfectly to the [Ubuntu font](https://design.ubuntu.com/font). 863 | Icons can be used anywhere in a Flutter app, since they are Widgets. In our example we chose them to use as a leading widget in your master view. 864 | 865 | - change the `leading` property of your `YaruMasterTile`s to have the value `Icon(YaruIcons.XXXX)` where `XXXX` is any icon you want to have 866 | - There is a nice overview of currently available icons on this website (also made with flutter): https://ubuntu.github.io/yaru.dart/ 867 | - to finally get rid of all blue underlines (warnings) run the command `dart fix --apply` 868 | 869 | The current version of your `main.dart` code for this tutorial could be the following, depending on what pages and tiles you've chosen to show: 870 | 871 | ```dart 872 | import 'package:flutter/material.dart'; 873 | import 'package:yaru/yaru.dart'; 874 | 875 | Future main() async { 876 | await YaruWindowTitleBar.ensureInitialized(); 877 | runApp(const MyApp()); 878 | } 879 | 880 | class MyApp extends StatelessWidget { 881 | const MyApp({super.key}); 882 | 883 | @override 884 | Widget build(BuildContext context) { 885 | return YaruTheme(builder: (context, yaru, child) { 886 | return MaterialApp( 887 | debugShowCheckedModeBanner: false, 888 | theme: yaru.theme, 889 | darkTheme: yaru.darkTheme, 890 | home: const _Home(), 891 | ); 892 | }); 893 | } 894 | } 895 | 896 | class _Home extends StatelessWidget { 897 | const _Home(); 898 | 899 | @override 900 | Widget build(BuildContext context) { 901 | return Scaffold( 902 | appBar: const YaruWindowTitleBar(), 903 | body: YaruMasterDetailPage( 904 | length: 2, 905 | tileBuilder: (context, index, selected, availableWidth) { 906 | if (index == 0) { 907 | return const YaruMasterTile( 908 | leading: Icon(YaruIcons.ubuntu_logo), 909 | title: Text('Page 1'), 910 | ); 911 | } else { 912 | return const YaruMasterTile( 913 | leading: Icon(YaruIcons.colors), 914 | title: Text('Page 2'), 915 | ); 916 | } 917 | }, 918 | pageBuilder: (context, index) { 919 | if (index == 0) { 920 | return const Center( 921 | child: Text('Hello Ubuntu'), 922 | ); 923 | } else { 924 | return const Center( 925 | child: Text('Hello Yaru'), 926 | ); 927 | } 928 | }, 929 | ), 930 | ); 931 | } 932 | } 933 | ``` 934 | 935 | ### Recap and design ideas 936 | 937 | - notice the four rounded window corners 938 | - notice the elegant window border and shadows 939 | - the whole window is now 100% flutter and you could add any Flutter Widget you like 940 | 941 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/hundred.png) 942 | 943 | - Idea: add a split YaruWindowTitleBar 944 | - Idea: Wrap the pages in `YaruDetailPage` and let them have their own `YaruWindowTitleBar()` 945 | - Possible `_Home` code 946 | 947 | ```dart 948 | class _Home extends StatelessWidget { 949 | const _Home(); 950 | 951 | @override 952 | Widget build(BuildContext context) { 953 | return Scaffold( 954 | body: YaruMasterDetailPage( 955 | length: 2, 956 | appBar: const YaruWindowTitleBar(), 957 | tileBuilder: (context, index, selected, availableWidth) { 958 | if (index == 0) { 959 | return const YaruMasterTile( 960 | leading: Icon(YaruIcons.ubuntu_logo), 961 | title: Text('Page 1'), 962 | ); 963 | } else { 964 | return const YaruMasterTile( 965 | leading: Icon(YaruIcons.colors), 966 | title: Text('Page 2'), 967 | ); 968 | } 969 | }, 970 | pageBuilder: (context, index) { 971 | if (index == 0) { 972 | return const YaruDetailPage( 973 | appBar: YaruWindowTitleBar( 974 | title: Text('Page 1'), 975 | ), 976 | body: Center( 977 | child: Text('Hello Ubuntu'), 978 | ), 979 | ); 980 | } else { 981 | return const YaruDetailPage( 982 | appBar: YaruWindowTitleBar( 983 | title: Text('Page 2'), 984 | ), 985 | body: Center( 986 | child: Text('Hello Yaru'), 987 | ), 988 | ); 989 | } 990 | }, 991 | ), 992 | ); 993 | } 994 | } 995 | ``` 996 | - Resulting UI (However those are just ideas which should not limit your ideas in any way!) 997 | 998 | ![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/better.png) 999 | 1000 | ### Organize your code! 1001 | 1002 | VsCode quick commands make it really easy to wrap, extract and move Widgets, wrap parts inside control blocks or quick fix. Use this power to extract and split your code into multiple files and Widgets. 1003 | 1004 | ### Explore yaru.dart 1005 | 1006 | In addition to `material.dart`, `yaru.dart` offers a ton of good looking widgets to chose from, which fit perfectly into the Ubuntu desktop. 1007 | 1008 | Check them out by either browsing https://ubuntu.github.io/yaru.dart/#/ or by installing `sudo snap install yaru-widgets-example` 1009 | 1010 | || 1011 | |-| 1012 | |![](https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/master/images/example.png)| 1013 | |*All widgets have a short example page with the source code how to use them.*| 1014 | 1015 | ## Thanks for reading 1016 | 1017 | Hopefully this tutorial was helpful, thanks for reading! 1018 | 1019 | ----------------- 1020 | ## Knowledge links and recommended dart libraries 1021 | 1022 | ### Essential Flutter knowledge 1023 | 1024 | - [The Official Flutter Website Tutorials](https://docs.flutter.dev/get-started/learn-flutter) 1025 | - [The State class](https://www.youtube.com/watch?v=FP737UMx7ss) 1026 | - [BuildContext](https://www.youtube.com/watch?v=rIaaH87z1-g) 1027 | - [Isolates/Event loops](https://www.youtube.com/watch?v=vl_AaCgudcY) 1028 | - [Future](https://www.youtube.com/watch?v=OTS-ap9_aXc) 1029 | - [Streams](https://www.youtube.com/watch?v=nQBpOIHE4eE) 1030 | - [Async/Await](https://www.youtube.com/watch?v=SmTCmDMi4BY) 1031 | 1032 | ### State managment and app architecture 1033 | 1034 | - [State Management](https://docs.flutter.dev/data-and-backend/state-mgmt/intro) 1035 | - [MVVM](https://docs.flutter.dev/app-architecture/guide) 1036 | 1037 | ### Freedesktop and other Linux specific API implementations in dart 1038 | 1039 | - [dbus.dart](https://pub.dev/packages/dbus) 1040 | - [bluez.dart](https://pub.dev/packages/bluez) 1041 | - [nm.dart](https://pub.dev/packages/nm) 1042 | - [snapd.dart](https://pub.dev/packages/snapd) 1043 | - [xdg_desktop_portal](https://pub.dev/packages/xdg_desktop_portal) 1044 | - [desktop_notifications](https://pub.dev/packages/desktop_notifications) 1045 | 1046 | ### Advanced Flutter knowledge 1047 | 1048 | - [Lifecycle of a widget](https://www.youtube.com/watch?v=_gIbneld-bw) 1049 | 1050 | ### Service Locator / Dependency Injection 1051 | 1052 | - [get_it (service/reference locator)](https://pub.dev/packages/get_it) 1053 | - [injectable (dependency injection, includes and is based on get_it)](https://pub.dev/packages/injectable) 1054 | 1055 | ### State management packages 1056 | 1057 | - [watch_it (includes get_it)](https://pub.dev/packages/watch_it) 1058 | - [provider](https://pub.dev/packages/provider) 1059 | - [riverpod (includes depedency injection)](https://pub.dev/packages/riverpod) 1060 | 1061 | ### Database access and REST services packages 1062 | 1063 | - [postgrest](https://pub.dev/packages/postgrest) 1064 | - [mysql client](https://pub.dev/packages/mysql_client) 1065 | - [isar](https://pub.dev/packages/isar) 1066 | - [conduit](https://pub.dev/packages/conduit) 1067 | 1068 | ### Creating server applications with Dart packages 1069 | 1070 | - [serverpod](https://pub.dev/packages/serverpod) 1071 | - [dart frog](https://pub.dev/packages/dart_frog) 1072 | 1073 | ### Cloud API access and BaaS clients packages 1074 | 1075 | - [supabase (open source firebase alternative)](https://pub.dev/packages/supabase) 1076 | - [appwrite (open source firebase alternative)](https://pub.dev/packages/appwrite) 1077 | - [amazon amplify](https://pub.dev/packages/amplify_flutter) (<--- Linux support in dev branch) 1078 | - [firebase](https://github.com/invertase/flutterfire_desktop) 1079 | -------------------------------------------------------------------------------- /images/addasync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/addasync.png -------------------------------------------------------------------------------- /images/adding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/adding.png -------------------------------------------------------------------------------- /images/almostdone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/almostdone.png -------------------------------------------------------------------------------- /images/better.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/better.png -------------------------------------------------------------------------------- /images/builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/builder.png -------------------------------------------------------------------------------- /images/command_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/command_palette.png -------------------------------------------------------------------------------- /images/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/cursor.png -------------------------------------------------------------------------------- /images/dart_add_dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/dart_add_dep.png -------------------------------------------------------------------------------- /images/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/delete.png -------------------------------------------------------------------------------- /images/donenoicons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/donenoicons.png -------------------------------------------------------------------------------- /images/ensureinit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/ensureinit.png -------------------------------------------------------------------------------- /images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/example.png -------------------------------------------------------------------------------- /images/extract_scaffold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/extract_scaffold.png -------------------------------------------------------------------------------- /images/first_locations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/first_locations.png -------------------------------------------------------------------------------- /images/first_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/first_run.png -------------------------------------------------------------------------------- /images/flutter_ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/flutter_ext.png -------------------------------------------------------------------------------- /images/flutter_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/flutter_new.png -------------------------------------------------------------------------------- /images/gtkwindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/gtkwindow.png -------------------------------------------------------------------------------- /images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/home.png -------------------------------------------------------------------------------- /images/hundred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/hundred.png -------------------------------------------------------------------------------- /images/import_main_my_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/import_main_my_app.png -------------------------------------------------------------------------------- /images/look_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/look_up.png -------------------------------------------------------------------------------- /images/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/m2.png -------------------------------------------------------------------------------- /images/mark_placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/mark_placeholder.png -------------------------------------------------------------------------------- /images/materialapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/materialapp.png -------------------------------------------------------------------------------- /images/md.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/md.png -------------------------------------------------------------------------------- /images/md3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/md3.png -------------------------------------------------------------------------------- /images/md4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/md4.png -------------------------------------------------------------------------------- /images/morepara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/morepara.png -------------------------------------------------------------------------------- /images/multi_cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/multi_cursor.png -------------------------------------------------------------------------------- /images/my_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/my_app.png -------------------------------------------------------------------------------- /images/new_terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/new_terminal.png -------------------------------------------------------------------------------- /images/no_my_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/no_my_app.png -------------------------------------------------------------------------------- /images/noroundyaru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/noroundyaru.png -------------------------------------------------------------------------------- /images/not_pretty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/not_pretty.png -------------------------------------------------------------------------------- /images/quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/quick.png -------------------------------------------------------------------------------- /images/restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/restart.png -------------------------------------------------------------------------------- /images/scaffold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/scaffold.png -------------------------------------------------------------------------------- /images/settings_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/settings_app.png -------------------------------------------------------------------------------- /images/stfl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/stfl.png -------------------------------------------------------------------------------- /images/stle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/stle.png -------------------------------------------------------------------------------- /images/wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/wizard.png -------------------------------------------------------------------------------- /images/yaru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/yaru.png -------------------------------------------------------------------------------- /images/yaruimport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/yaruimport.png -------------------------------------------------------------------------------- /images/yaruthemeimport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/yaruthemeimport.png -------------------------------------------------------------------------------- /images/yaruwindowtitlebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubuntu-flutter-community/yaru_tutorial/dd2375f6d30c9d9cfc878b221ea8b9001cab5610/images/yaruwindowtitlebar.png -------------------------------------------------------------------------------- /my_yaru_app/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /my_yaru_app/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "2663184aa79047d0a33a14a3b607954f8fdd8730" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 17 | base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 18 | - platform: linux 19 | create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 20 | base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /my_yaru_app/README.md: -------------------------------------------------------------------------------- 1 | # my_yaru_app 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /my_yaru_app/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | -------------------------------------------------------------------------------- /my_yaru_app/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:yaru/yaru.dart'; 3 | 4 | Future main() async { 5 | await YaruWindowTitleBar.ensureInitialized(); 6 | runApp(const MyApp()); 7 | } 8 | 9 | class MyApp extends StatelessWidget { 10 | const MyApp({super.key}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return YaruTheme(builder: (context, yaru, child) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | theme: yaru.theme, 18 | darkTheme: yaru.darkTheme, 19 | home: const _Home(), 20 | ); 21 | }); 22 | } 23 | } 24 | 25 | class _Home extends StatelessWidget { 26 | const _Home(); 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | body: YaruMasterDetailPage( 32 | length: 2, 33 | appBar: const YaruWindowTitleBar(), 34 | tileBuilder: (context, index, selected, availableWidth) { 35 | if (index == 0) { 36 | return const YaruMasterTile( 37 | leading: Icon(YaruIcons.ubuntu_logo), 38 | title: Text('Page 1'), 39 | ); 40 | } else { 41 | return const YaruMasterTile( 42 | leading: Icon(YaruIcons.colors), 43 | title: Text('Page 2'), 44 | ); 45 | } 46 | }, 47 | pageBuilder: (context, index) { 48 | if (index == 0) { 49 | return const YaruDetailPage( 50 | appBar: YaruWindowTitleBar( 51 | title: Text('Page 1'), 52 | ), 53 | body: Center( 54 | child: Text('Hello Ubuntu'), 55 | ), 56 | ); 57 | } else { 58 | return const YaruDetailPage( 59 | appBar: YaruWindowTitleBar( 60 | title: Text('Page 2'), 61 | ), 62 | body: Center( 63 | child: Text('Hello Yaru'), 64 | ), 65 | ); 66 | } 67 | }, 68 | ), 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /my_yaru_app/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /my_yaru_app/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.10) 3 | project(runner LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "my_yaru_app") 8 | # The unique GTK application identifier for this application. See: 9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID 10 | set(APPLICATION_ID "com.test.my_yaru_app") 11 | 12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 13 | # versions of CMake. 14 | cmake_policy(SET CMP0063 NEW) 15 | 16 | # Load bundled libraries from the lib/ directory relative to the binary. 17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 18 | 19 | # Root filesystem for cross-building. 20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 27 | endif() 28 | 29 | # Define build configuration options. 30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 31 | set(CMAKE_BUILD_TYPE "Debug" CACHE 32 | STRING "Flutter build mode" FORCE) 33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 34 | "Debug" "Profile" "Release") 35 | endif() 36 | 37 | # Compilation settings that should be applied to most targets. 38 | # 39 | # Be cautious about adding new options here, as plugins use this function by 40 | # default. In most cases, you should add new options to specific targets instead 41 | # of modifying this function. 42 | function(APPLY_STANDARD_SETTINGS TARGET) 43 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 47 | endfunction() 48 | 49 | # Flutter library and tool build rules. 50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 51 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 52 | 53 | # System-level dependencies. 54 | find_package(PkgConfig REQUIRED) 55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 56 | 57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 58 | 59 | # Define the application target. To change its name, change BINARY_NAME above, 60 | # not the value here, or `flutter run` will no longer work. 61 | # 62 | # Any new source files that you add to the application should be added here. 63 | add_executable(${BINARY_NAME} 64 | "main.cc" 65 | "my_application.cc" 66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 67 | ) 68 | 69 | # Apply the standard set of build settings. This can be removed for applications 70 | # that need different build settings. 71 | apply_standard_settings(${BINARY_NAME}) 72 | 73 | # Add dependency libraries. Add any application-specific dependencies here. 74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 76 | 77 | # Run the Flutter tool portions of the build. This must not be removed. 78 | add_dependencies(${BINARY_NAME} flutter_assemble) 79 | 80 | # Only the install-generated bundle's copy of the executable will launch 81 | # correctly, since the resources must in the right relative locations. To avoid 82 | # people trying to run the unbundled copy, put it in a subdirectory instead of 83 | # the default top-level location. 84 | set_target_properties(${BINARY_NAME} 85 | PROPERTIES 86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 87 | ) 88 | 89 | 90 | # Generated plugin build rules, which manage building the plugins and adding 91 | # them to the application. 92 | include(flutter/generated_plugins.cmake) 93 | 94 | 95 | # === Installation === 96 | # By default, "installing" just makes a relocatable bundle in the build 97 | # directory. 98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 99 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 101 | endif() 102 | 103 | # Start with a clean build bundle directory every time. 104 | install(CODE " 105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 106 | " COMPONENT Runtime) 107 | 108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 110 | 111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 112 | COMPONENT Runtime) 113 | 114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 115 | COMPONENT Runtime) 116 | 117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 118 | COMPONENT Runtime) 119 | 120 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) 121 | install(FILES "${bundled_library}" 122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 123 | COMPONENT Runtime) 124 | endforeach(bundled_library) 125 | 126 | # Copy the native assets provided by the build.dart from all packages. 127 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") 128 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 129 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 130 | COMPONENT Runtime) 131 | 132 | # Fully re-copy the assets directory on each build to avoid having stale files 133 | # from a previous install. 134 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 135 | install(CODE " 136 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 137 | " COMPONENT Runtime) 138 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 139 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 140 | 141 | # Install the AOT library on non-Debug builds only. 142 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 143 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 144 | COMPONENT Runtime) 145 | endif() 146 | -------------------------------------------------------------------------------- /my_yaru_app/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /my_yaru_app/linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | void fl_register_plugins(FlPluginRegistry* registry) { 16 | g_autoptr(FlPluginRegistrar) gtk_registrar = 17 | fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin"); 18 | gtk_plugin_register_with_registrar(gtk_registrar); 19 | g_autoptr(FlPluginRegistrar) handy_window_registrar = 20 | fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin"); 21 | handy_window_plugin_register_with_registrar(handy_window_registrar); 22 | g_autoptr(FlPluginRegistrar) screen_retriever_registrar = 23 | fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); 24 | screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); 25 | g_autoptr(FlPluginRegistrar) window_manager_registrar = 26 | fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); 27 | window_manager_plugin_register_with_registrar(window_manager_registrar); 28 | g_autoptr(FlPluginRegistrar) yaru_window_linux_registrar = 29 | fl_plugin_registry_get_registrar_for_plugin(registry, "YaruWindowLinuxPlugin"); 30 | yaru_window_linux_plugin_register_with_registrar(yaru_window_linux_registrar); 31 | } 32 | -------------------------------------------------------------------------------- /my_yaru_app/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /my_yaru_app/linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | gtk 7 | handy_window 8 | screen_retriever 9 | window_manager 10 | yaru_window_linux 11 | ) 12 | 13 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 14 | ) 15 | 16 | set(PLUGIN_BUNDLED_LIBRARIES) 17 | 18 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 19 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 20 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 21 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 23 | endforeach(plugin) 24 | 25 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 26 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 27 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 28 | endforeach(ffi_plugin) 29 | -------------------------------------------------------------------------------- /my_yaru_app/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /my_yaru_app/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen* screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "my_yaru_app"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "my_yaru_app"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_show(GTK_WIDGET(window)); 63 | gtk_widget_show(GTK_WIDGET(view)); 64 | 65 | gtk_widget_grab_focus(GTK_WIDGET(view)); 66 | } 67 | 68 | // Implements GApplication::local_command_line. 69 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 70 | MyApplication* self = MY_APPLICATION(application); 71 | // Strip out the first argument as it is the binary name. 72 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 73 | 74 | g_autoptr(GError) error = nullptr; 75 | if (!g_application_register(application, nullptr, &error)) { 76 | g_warning("Failed to register: %s", error->message); 77 | *exit_status = 1; 78 | return TRUE; 79 | } 80 | 81 | g_application_activate(application); 82 | *exit_status = 0; 83 | 84 | return TRUE; 85 | } 86 | 87 | // Implements GApplication::startup. 88 | static void my_application_startup(GApplication* application) { 89 | //MyApplication* self = MY_APPLICATION(object); 90 | 91 | // Perform any actions required at application startup. 92 | 93 | G_APPLICATION_CLASS(my_application_parent_class)->startup(application); 94 | } 95 | 96 | // Implements GApplication::shutdown. 97 | static void my_application_shutdown(GApplication* application) { 98 | //MyApplication* self = MY_APPLICATION(object); 99 | 100 | // Perform any actions required at application shutdown. 101 | 102 | G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); 103 | } 104 | 105 | // Implements GObject::dispose. 106 | static void my_application_dispose(GObject* object) { 107 | MyApplication* self = MY_APPLICATION(object); 108 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 109 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 110 | } 111 | 112 | static void my_application_class_init(MyApplicationClass* klass) { 113 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 114 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 115 | G_APPLICATION_CLASS(klass)->startup = my_application_startup; 116 | G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; 117 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 118 | } 119 | 120 | static void my_application_init(MyApplication* self) {} 121 | 122 | MyApplication* my_application_new() { 123 | return MY_APPLICATION(g_object_new(my_application_get_type(), 124 | "application-id", APPLICATION_ID, 125 | "flags", G_APPLICATION_NON_UNIQUE, 126 | nullptr)); 127 | } 128 | -------------------------------------------------------------------------------- /my_yaru_app/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /my_yaru_app/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | animated_vector: 5 | dependency: transitive 6 | description: 7 | name: animated_vector 8 | sha256: e15c6596549ca6e2e7491c11fbe168a1dead87475a828a4bc81cf104feca0432 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "0.2.0" 12 | animated_vector_annotations: 13 | dependency: transitive 14 | description: 15 | name: animated_vector_annotations 16 | sha256: baa6b4ed98407220f2c9634f7da3cfa5eedb46798e090466f441e666e2f7c8c0 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "0.2.0" 20 | archive: 21 | dependency: transitive 22 | description: 23 | name: archive 24 | sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "3.6.1" 28 | async: 29 | dependency: transitive 30 | description: 31 | name: async 32 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.11.0" 36 | boolean_selector: 37 | dependency: transitive 38 | description: 39 | name: boolean_selector 40 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "2.1.1" 44 | characters: 45 | dependency: transitive 46 | description: 47 | name: characters 48 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.0" 52 | clock: 53 | dependency: transitive 54 | description: 55 | name: clock 56 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.1.1" 60 | collection: 61 | dependency: transitive 62 | description: 63 | name: collection 64 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.18.0" 68 | crypto: 69 | dependency: transitive 70 | description: 71 | name: crypto 72 | sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "3.0.5" 76 | fake_async: 77 | dependency: transitive 78 | description: 79 | name: fake_async 80 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.3.1" 84 | ffi: 85 | dependency: transitive 86 | description: 87 | name: ffi 88 | sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "2.1.3" 92 | flutter: 93 | dependency: "direct main" 94 | description: flutter 95 | source: sdk 96 | version: "0.0.0" 97 | flutter_lints: 98 | dependency: "direct dev" 99 | description: 100 | name: flutter_lints 101 | sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" 102 | url: "https://pub.dev" 103 | source: hosted 104 | version: "3.0.2" 105 | flutter_test: 106 | dependency: "direct dev" 107 | description: flutter 108 | source: sdk 109 | version: "0.0.0" 110 | flutter_web_plugins: 111 | dependency: transitive 112 | description: flutter 113 | source: sdk 114 | version: "0.0.0" 115 | gtk: 116 | dependency: transitive 117 | description: 118 | name: gtk 119 | sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "2.1.0" 123 | handy_window: 124 | dependency: "direct main" 125 | description: 126 | name: handy_window 127 | sha256: "56b813e58a68b0ee2ab22051400b8b1f1b5cfe88b8cd32288623defb3926245a" 128 | url: "https://pub.dev" 129 | source: hosted 130 | version: "0.4.0" 131 | image: 132 | dependency: transitive 133 | description: 134 | name: image 135 | sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "4.2.0" 139 | leak_tracker: 140 | dependency: transitive 141 | description: 142 | name: leak_tracker 143 | sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "10.0.5" 147 | leak_tracker_flutter_testing: 148 | dependency: transitive 149 | description: 150 | name: leak_tracker_flutter_testing 151 | sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "3.0.5" 155 | leak_tracker_testing: 156 | dependency: transitive 157 | description: 158 | name: leak_tracker_testing 159 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "3.0.1" 163 | lints: 164 | dependency: transitive 165 | description: 166 | name: lints 167 | sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "3.0.0" 171 | matcher: 172 | dependency: transitive 173 | description: 174 | name: matcher 175 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "0.12.16+1" 179 | material_color_utilities: 180 | dependency: transitive 181 | description: 182 | name: material_color_utilities 183 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "0.11.1" 187 | meta: 188 | dependency: transitive 189 | description: 190 | name: meta 191 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "1.15.0" 195 | path: 196 | dependency: transitive 197 | description: 198 | name: path 199 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "1.9.0" 203 | path_parsing: 204 | dependency: transitive 205 | description: 206 | name: path_parsing 207 | sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "1.0.1" 211 | petitparser: 212 | dependency: transitive 213 | description: 214 | name: petitparser 215 | sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "6.0.2" 219 | platform: 220 | dependency: transitive 221 | description: 222 | name: platform 223 | sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "3.1.5" 227 | platform_linux: 228 | dependency: transitive 229 | description: 230 | name: platform_linux 231 | sha256: "856cfc9871e3ff3df6926991729d24bba9b70d0229ae377fa08b562344baaaa8" 232 | url: "https://pub.dev" 233 | source: hosted 234 | version: "0.1.2" 235 | plugin_platform_interface: 236 | dependency: transitive 237 | description: 238 | name: plugin_platform_interface 239 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "2.1.8" 243 | screen_retriever: 244 | dependency: transitive 245 | description: 246 | name: screen_retriever 247 | sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "0.1.9" 251 | sky_engine: 252 | dependency: transitive 253 | description: flutter 254 | source: sdk 255 | version: "0.0.99" 256 | source_span: 257 | dependency: transitive 258 | description: 259 | name: source_span 260 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 261 | url: "https://pub.dev" 262 | source: hosted 263 | version: "1.10.0" 264 | stack_trace: 265 | dependency: transitive 266 | description: 267 | name: stack_trace 268 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 269 | url: "https://pub.dev" 270 | source: hosted 271 | version: "1.11.1" 272 | stream_channel: 273 | dependency: transitive 274 | description: 275 | name: stream_channel 276 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 277 | url: "https://pub.dev" 278 | source: hosted 279 | version: "2.1.2" 280 | string_scanner: 281 | dependency: transitive 282 | description: 283 | name: string_scanner 284 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 285 | url: "https://pub.dev" 286 | source: hosted 287 | version: "1.2.0" 288 | term_glyph: 289 | dependency: transitive 290 | description: 291 | name: term_glyph 292 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 293 | url: "https://pub.dev" 294 | source: hosted 295 | version: "1.2.1" 296 | test_api: 297 | dependency: transitive 298 | description: 299 | name: test_api 300 | sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" 301 | url: "https://pub.dev" 302 | source: hosted 303 | version: "0.7.2" 304 | typed_data: 305 | dependency: transitive 306 | description: 307 | name: typed_data 308 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 309 | url: "https://pub.dev" 310 | source: hosted 311 | version: "1.3.2" 312 | vector_math: 313 | dependency: transitive 314 | description: 315 | name: vector_math 316 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 317 | url: "https://pub.dev" 318 | source: hosted 319 | version: "2.1.4" 320 | vm_service: 321 | dependency: transitive 322 | description: 323 | name: vm_service 324 | sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" 325 | url: "https://pub.dev" 326 | source: hosted 327 | version: "14.2.5" 328 | window_manager: 329 | dependency: transitive 330 | description: 331 | name: window_manager 332 | sha256: "8699323b30da4cdbe2aa2e7c9de567a6abd8a97d9a5c850a3c86dcd0b34bbfbf" 333 | url: "https://pub.dev" 334 | source: hosted 335 | version: "0.3.9" 336 | xml: 337 | dependency: transitive 338 | description: 339 | name: xml 340 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 341 | url: "https://pub.dev" 342 | source: hosted 343 | version: "6.5.0" 344 | yaru: 345 | dependency: "direct main" 346 | description: 347 | path: "." 348 | ref: "48d0c6790da12a53c3f151936fe5e1573f7ea389" 349 | resolved-ref: "48d0c6790da12a53c3f151936fe5e1573f7ea389" 350 | url: "https://github.com/ubuntu/yaru.dart" 351 | source: git 352 | version: "5.1.0" 353 | yaru_window: 354 | dependency: transitive 355 | description: 356 | name: yaru_window 357 | sha256: c9d16f78962652ad71aa160ab0a1e2e5924359439303394f980fd00eefc905eb 358 | url: "https://pub.dev" 359 | source: hosted 360 | version: "0.2.1" 361 | yaru_window_linux: 362 | dependency: transitive 363 | description: 364 | name: yaru_window_linux 365 | sha256: "3676355492eba0461f03acf1b7420f7885982d1bffe113fccdca9415fbe39f5d" 366 | url: "https://pub.dev" 367 | source: hosted 368 | version: "0.2.0" 369 | yaru_window_manager: 370 | dependency: transitive 371 | description: 372 | name: yaru_window_manager 373 | sha256: "2d358263d19ae6598df21d6d8c0d25e75c79a82f459b63b0013a13e395c48b23" 374 | url: "https://pub.dev" 375 | source: hosted 376 | version: "0.1.2" 377 | yaru_window_platform_interface: 378 | dependency: transitive 379 | description: 380 | name: yaru_window_platform_interface 381 | sha256: e9f8cd34e207d7f7b771ae70dee347ed974cee06b981819c4181b3e474e52254 382 | url: "https://pub.dev" 383 | source: hosted 384 | version: "0.1.2" 385 | yaru_window_web: 386 | dependency: transitive 387 | description: 388 | name: yaru_window_web 389 | sha256: "3ff30758a330d7626d54643df0cca6c179782f401aba7752da9cc0d60c9a6f74" 390 | url: "https://pub.dev" 391 | source: hosted 392 | version: "0.0.3" 393 | sdks: 394 | dart: ">=3.4.0 <4.0.0" 395 | flutter: ">=3.24.3" 396 | -------------------------------------------------------------------------------- /my_yaru_app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: my_yaru_app 2 | description: A new Flutter project. 3 | 4 | publish_to: "none" 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=3.0.0 <4.0.0" 10 | flutter: ">=3.24.3" 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | handy_window: ^0.4.0 16 | yaru: 17 | git: 18 | url: https://github.com/ubuntu/yaru.dart 19 | ref: 48d0c6790da12a53c3f151936fe5e1573f7ea389 20 | 21 | 22 | dev_dependencies: 23 | flutter_test: 24 | sdk: flutter 25 | 26 | flutter_lints: ^3.0.1 27 | 28 | flutter: 29 | uses-material-design: true 30 | --------------------------------------------------------------------------------