The cat said

Seeing this picture makes my neck ache… I did it this way, although it looks cool, and then you have to move your neck up and down, which is a lot harder than moving your neck left to right.

Today’s recommended reading is about Flutter desktop development. There are links to the original article and Git code below.

React Native said, “Develop in multiple applications the same way.” It’s not like you can compile the same code for ios, Android, Web, Windows, Linux… , but the code is highly reusable, so some students in the multi-terminal architecture should pay attention to unpack.

For example, your business code, apis, Entity, and function functions are often reused. But the underlying, interactive experience of each platform is personalization.

Don’t be fooled by smooth compatibility on both sides of ios and Android.

This application demonstrates examples of multi-window, modal dialog boxes, drag-and-drop, menus, toolbars, file manipulation, and system API calls. It is a good reference if you are doing research.

Old iron remember to forward, Brother Cat will present more Flutter good articles ~~~~

Ducafecat WeChat group

The original

Matejknopp.com/post/introd…

video

code

Github.com/nativeshell…

reference

  • airflow.app/
  • airflow.app/remote-app/
  • Github.com/nativeshell…
  • Github.com/nativeshell…
  • Github.com/nativeshell…

The body of the

Ever since I first saw Turbo Vision, I’ve been interested in desktop applications. Those text-mode resizable Windows in DOS seemed like magic to me. It sparked interest in user interface frameworks that are still going strong more than 20 years later.

For the past decade or so, the focus has largely shifted to the web and mobile devices, and that doesn’t make me particularly happy. So I think it’s time to crawl out of the shadows, get out of my comfort zone and try to bring some of the spotlight back to where it belongs. Get to the table! 🙂

The road to Flutter

The last desktop application I worked on was (and still is) Airflow. It’s a mix of Qt and a lot of platform-specific code. If I say so myself, I’m very happy with the end result, but the developer experience and overall productivity leave a lot to be desired.

airflow.app/

About two years ago, I needed a stream app for iOS and Android. After several prototypes, the decision was made that I went to Flutter. I do like to think I have my own UI development experience, after all, I’ve used over a dozen GUI frameworks on different platforms, so nothing can surprise me now, right? Wrong. The biggest surprise for all of them was how good it felt to work with Flutter. Never in my life, never once, has it made more sense to build a user interface.

airflow.app/remote-app/

Wouldn’t it be amazing if I could build desktop applications this way? Sure, it’s possible, but the reality was a grim mistress at a time when desktop embedding was still in its infancy. So let’s go back to Qt. But I couldn’t get the idea out of my head.

A year or two later, many things have changed. There is still a lot of work to be done, but desktop embedding has matured a lot, and Flutter on Desktop is beginning to become a viable option.

Flutter desktop embedded

Now you may be asking: Matt, isn’t Flutter already embedded in the desktop? So what’s all this for?

Yes, indeed. Creative Shell is built on them. You can think of the Flutter desktop embed as a platform view component (think GtkWidget, NSView or, dare I say it, HWND). It handles mouse and keyboard input, painting, but it does not attempt to manage Windows, or Flutter engine/isolation. Or do things like platform menus and drag and drop. To make things even more complicated, Flutter embed has a completely different API on each platform. Therefore, if you want to create an engine or register platform channel handlers for some low-level code, you need to do this separately for each platform.

nativeshell.dev/

This is where NativeShell comes in

Start where the Flutter desktop insert ends. It provides a consistent, platform-independent API for existing Flutter embedding. It manages the engine and Windows. It provides drag-and-drop support, access to platform menus, and other features that go beyond Flutter embedding. And it exposes all of this through the easy-to-use Dart API.

NativeShell was written in rust. Rust is great because it lets you write efficient low-level platform-specific code if you need to, but it also lets you use NativeShell without having to know anything about rust. Simply performing a shipment of goods is all it takes to get things going. Cargo is the Rust package manager (just like PUB is for Dart) and is responsible for downloading and building all dependencies.

start

  • Install Rust www.rust-lang.org/tools/insta…

  • Install the Flutter Flutter. Dev/docs/get – st…

  • Enable desktop support in Flutter (select one for your platform)

$ flutter config --enable-windows-desktop
$ flutter config --enable-macos-desktop
$ flutter config --enable-linux-desktop
Copy the code
  • Switch to Flutter Master
$ flutter channel master
$ flutter upgrade
Copy the code

After this, you should be ready to start:

$ git clone https://github.com/nativeshell/examples.git
$ cd examples
$ cargo run
Copy the code

NativeShell transparently integrates the Flutter building process and cargo. If the Gods of Rust and darts are smiling at you, this is what you should be seeing right now:

Platform Channels

If you need to invoke native code from the Flutter application, the two options are platform channel or FFI. Platform channels are pre-designed for general use because they are easier to use and deliver messages appropriately between platform and UI threads.

This is what happens when you register a platform channel handler with NativeShell (and the only Rust code, I promise)

fn register_example_channel(context: Rc<Context>) {
    context
        .message_manager
        .borrow_mut()
        .register_method_handler("example_channel", |call, reply, engine| {
            match call.method.as_str() {
                "echo"=> { reply.send_ok(call.args); } _ => {}}}); }Copy the code

To do this directly using existing platform embedding apis, you need to write this code individually for each platform using platform-specific apis. Then ensure that handlers are registered each time a new engine is created (they may be logged out when the engine is shut down).

With NativeShell, you only need to register the handler once, and it can be called from any engine. Messages can be transparently serialized and deserialized into the Rust structure (using the standard method of codec for Flutter) via Serde.

Github.com/nativeshell…

Window Management

Surely you want your desktop application to have multiple Windows? NativeShell has covered for you. Adjust window size to content or set minimum window size so that Flutter layout does not flow? It can do the same. It also ensures that the window is displayed only after the content is ready, eliminating the ugly flicker.

Currently, each window runs as a separate, independent form. NativeShell provides apis for creating Windows, setting and adjusting geometry, updating styles, and window titles. It also provides apis to facilitate communication between Windows.

Videos can be sized to fit the content, as well as to fit the content.

  • Many window

  • Mode dialog box

This will be a minimal demonstration of how to create and manage multiple Windows in Dart:

void main() async {
  runApp(MinimalApp());
}

class MinimalApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Widgets above WindowWidget will be same in all windows. The actual
    // window content will be determined by WindowState
    returnMaterialApp( home: WindowWidget( onCreateState: (initData) { WindowState? context; context ?? = OtherWindowState.fromInitData(initData);// possibly no init data, this is main windowcontext ?? = MainWindowState();returncontext; },),); }}class MainWindowState extends WindowState {
  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () async {
        // This will create new isolate for a window. Whatever is given to
        // Window.create will be provided by WindowWidget in new isolate
        final window = await Window.create(OtherWindowState.toInitData());
        // you can use the window object to communicate with newly created
        // window or register handlers for window events
        window.closeEvent.addListener(() {
          print('Window closed');
        });
      },
      child: Text('Open Another Window')); }}class OtherWindowState extends WindowState {
  @override
  Widget build(BuildContext context) {
    return Text('This is Another Window! ');
  }

  // This can be anything that fromInitData recognizes
  static dynamic toInitData() => {
        'class': 'OtherWindow'};static OtherWindowState? fromInitData(dynamic initData) {
    if (initData is Map && initData['class'] = ='OtherWindow') {
      return OtherWindowState();
    }
    return null; }}Copy the code

Drag & Drop

It’s hard to think of a desktop user interface framework that doesn’t support drag and drop. NativeShell supports drag-and-drop file paths, urls, custom Dart data (serialized by StandardMethodCodec), and even extension to handle custom platform-specific formats.

It should be easy to use, and I’m pleased with the results, although it does involve writing some code that looks pretty scary.

Github.com/nativeshell…

Github.com/nativeshell…

Popup Menu

It always surprises me how many frameworks and applications make this mistake. It’s only recently that Firefox has started using native pop-up menus on macOS. No matter how polished your app is, if your menu makes a mistake, you’re going to feel wrong.

Allows you to easily create and display context menus. Given the power of the menu system, this menu API seems simple. Menus are reactive. You can ask to rebuild the menu while visible and NativeShell will calculate the delta and just update the menu item that has actually changed.

  int _counter = 0;

  void _showContextMenu(TapDownDetails e) async {
    final menu = Menu(_buildContextMenu);

    // Menu can be updated while visible
    final timer = Timer.periodic(Duration(milliseconds: 500), (timer) {
      ++_counter;
      // This will call the _buildContextMenu() function, diff the old
      // and new menu items and only update those platform menu items that
      // actually changed
      menu.update();
    });

    await Window.of(context).showPopupMenu(menu, e.globalPosition);

    timer.cancel();
  }

  List<MenuItem> _buildContextMenu() => [
        MenuItem(title: 'Context menu Item', action: () {}),
        MenuItem(title: 'Menu Update Counter $_counter', action: null),
        MenuItem.separator(),
        MenuItem.children(title: 'Submenu', children: [
          MenuItem(title: 'Submenu Item 1', action: () {}),
          MenuItem(title: 'Submenu Item 2', action: () {}),
        ]),
      ];
Copy the code

MenuBar

Probably my favorite feature in Creative Shell. On macOS, it renders as an empty widget, instead placing the menu on the system menu bar (at the top of the screen). On Windows and Linux, it renders top-level menu items using the Flutter widget, and then processes the rest using the native menu. This means that the menu bar can be located anywhere in the widget hierarchy, it is not limited to the top of the window, and it does not rely on GDI or Gtk to draw ISELF.

It supports mouse tracking and keyboard navigation, just like the normal system menu bar, but without any limitations.

What’s going on now?

NativeShell is being heavily developed. Things are likely to fall apart. More documentation and examples are urgently needed. But I think the shape might work for some people.

All three supported platforms (macOS, Windows, Linux) have full equivalence.

Github.com/nativeshell…

Github.com/nativeshell…

Github.com/nativeshell…

If you make it all the way here, you can continue with Nativesshell.dev.

nativeshell.dev/

Thank you for your feedback!

Github.com/nativeshell…


The elder brother of the © cat

ducafecat.tech/

github.com/ducafecat

The issue of

Open source

GetX Quick Start

Github.com/ducafecat/g…

News client

Github.com/ducafecat/f…

Strapi manual translation

getstrapi.cn

Wechat discussion group Ducafecat

A series of collections

The translation

Ducafecat. Tech/categories /…

The open source project

Ducafecat. Tech/categories /…

Dart programming language basics

Space.bilibili.com/404904528/c…

Start Flutter with zero basics

Space.bilibili.com/404904528/c…

Flutter combat news client from scratch

Space.bilibili.com/404904528/c…

Flutter component development

Space.bilibili.com/404904528/c…

Flutter Bloc

Space.bilibili.com/404904528/c…

Flutter Getx4

Space.bilibili.com/404904528/c…

Docker Yapi

Space.bilibili.com/404904528/c…