Chuyển đến nội dung chính

Bài đăng

Hiển thị các bài đăng có nhãn Desktop

RustDesk: lõi Rust, vỏ Flutter

Không phải mọi vấn đề pixel là vấn đề Dart. RustDesk giữ capture/encode/networking trong Rust và dùng Flutter làm shell tương tác — dạng hybrid bạn nên hiểu trước khi rewrite module native bằng Dart thuần. Phân chia trách nhiệm Mục Nơi Capture màn, codec, relay Lõi Rust UX kết nối, settings, session UI Flutter Tích hợp OS Platform channel / FFI Học theo Vẽ biên cứng: vòng UI nóng vs vòng data nóng. Ưu tiên FFI cho throughput; channel cho event thưa. Giữ session state ngoài cây widget. Cạm bẫy Build hybrid nhân đôi ma trận CI. ABI và packaging installer desktop không đơn giản. App nặng UI có thể chỉ cần Flutter. App nặng pipeline hãy copy biên giới của RustDesk, chưa chắc đã copy Rust. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

RustDesk: Rust core, Flutter shell

Not every pixel problem is a Dart problem. RustDesk keeps capture/encode/networking in Rust and uses Flutter as the interactive shell — a hybrid you should understand before you rewrite a native module in pure Dart. Split of responsibilities Concern Home Screen capture, codecs, relay Rust core Connection UX, settings, session UI Flutter OS integration Platform channels / FFI Steal this Draw a hard boundary: hot UI loop vs hot data loop. Prefer FFI for throughput; channels for infrequent events. Keep session state outside widget trees. Pitfalls Hybrid builds double your CI matrix. ABI and packaging for desktop installers are non-trivial. If your app is UI-heavy, Flutter alone may suffice. If it is pipeline-heavy, copy RustDesk’s boundary , not necessarily Rust itself. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

desktop_multi_window: quản lý nhiều cửa sổ desktop có chủ đích

desktop_multi_window: quản lý nhiều cửa sổ desktop có chủ đích desktop_multi_window đáng chú ý vì nó giải quyết lifecycle cửa sổ, arguments, ranh giới isolate và giới hạn platform. Bài này trình bày cách đặt package vào đúng boundary của một ứng dụng Flutter production thay vì chỉ copy một snippet vào màn hình. Package này sở hữu phần nào? Giữ API của package ở một adapter hoặc feature boundary có tên rõ ràng. Đưa lifecycle, lỗi và trạng thái loading vào contract mà UI có thể kiểm thử. Chỉ expose capability cần thiết; đừng để toàn app phụ thuộc vào chi tiết triển khai. Snippet bắt đầu final window = await WindowController . create ( WindowConfiguration (arguments : jsonEncode ({ 'route' : '/settings' })), ); await window. show (); await window. setTitle ( 'Settings' ); Checklist trước khi ship Đọc README và changelog của package đúng version đang pin. Viết một test cho lifecycle, lỗi và hành vi khi app về background. Kiểm tra Android...

desktop_multi_window: isolate desktop surfaces intentionally

desktop_multi_window: isolate desktop surfaces intentionally desktop_multi_window is useful because it focuses on window lifecycle, arguments, isolate boundaries, and platform constraints. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point final window = await WindowController . create ( WindowConfiguration (arguments : jsonEncode ({ 'route' : '/settings' })), ); await window. show (); await window. setTitle ( 'Settings' ); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app bac...

Desktop multi-window: popups, dialogs, and windowHandle — hướng dẫn Flutter

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Experimental windowing APIs accelerate with Canonical as desktop steward. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Keep the primary workflow single-window until APIs graduate. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi bou...

API multi-window desktop: popup, dialog và windowHandle

App desktop cần nhiều surface: context menu, palette công cụ, inspector tách rời. API windowing experimental của Flutter — được Canonical đẩy nhanh với vai trò Strategic Steward cho Flutter Desktop — là đường đi. Đã landing từ 3.44 → 3.47 Cửa sổ tooltip và dialog trên Linux/macOS/Windows. Popup trên Linux và Windows (macOS có sớm hơn). showDialog có thể tạo cửa sổ con thật trên nền tảng hỗ trợ windowing. Cửa sổ theo nội dung và windowHandle ( HWND / NSWindow / GtkWindow ) cho tích hợp native nâng cao. Khi nào dùng Nhu cầu Hướng API Context menu / palette Popup window Tool tách rời Regular window + test multi-window Docking native windowHandle + code platform Cảnh báo trạng thái Các API này ở main-channel / experimental . Đừng ship multi-window production làm UX duy nhất khi chưa có fallback. Theo dõi example multiple_windows và file issue vào embedder. Mẹo thực tế Thiết kế feature sao cho workflow chính vẫn chạy được single-window. Multi-wind...

Desktop multi-window: popups, dialogs, and windowHandle

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Experimental windowing APIs accelerate with Canonical as desktop steward. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Keep the primary workflow single-window until APIs graduate. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh...

Desktop multi-window APIs: popups, dialogs, and windowHandle

Desktop apps need more than one surface: context menus, tool palettes, detached inspectors. Flutter’s experimental windowing APIs , accelerated by Canonical as Strategic Steward for Flutter Desktop, are how you get there. What landed through 3.44 → 3.47 Tooltip and dialog windows across Linux/macOS/Windows. Popup windows on Linux and Windows (macOS earlier). showDialog can create a real child window on platforms that support windowing. Content-sized windows and windowHandle ( HWND / NSWindow / GtkWindow ) for advanced native integration. When to use it Need API direction Context menu / palette Popup window Detached tool Regular window + multi-window tests Native docking windowHandle + platform code Status warning These APIs have been main-channel / experimental . Do not ship production multi-window as your only UX path without a fallback. Track the multiple_windows example and file issues against the embedders. Practical tip Design your feature...

Impeller on desktop: SDF text and Metal/Vulkan defaults — hướng dẫn Flutter

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc ...

Impeller on desktop: SDF text and Metal/Vulkan defaults

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an ...

Window management APIs for Flutter desktop apps — hướng dẫn Flutter

Desktop apps are multi-surface. Window APIs are catching up with Canonical. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Multi-window state, focus fixes, and native handle access. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Persist window size/position yourself — the framework will not. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có ki...

Product flavors on Windows and Linux for CI matrices — hướng dẫn Flutter

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Per-flavor assets and —flavor builds join Android/iOS on desktop. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế CI can produce side-by-side installers with different IDs and icons. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary...

Window management APIs for Flutter desktop apps

Desktop apps are multi-surface. Window APIs are catching up with Canonical. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Multi-window state, focus fixes, and native handle access. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Persist window size/position yourself — the framework will not. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use c...

Product flavors on Windows and Linux for CI matrices

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Per-flavor assets and —flavor builds join Android/iOS on desktop. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model CI can produce side-by-side installers with different IDs and icons. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or ...

Desktop multi-window: popups, dialogs, and windowHandle — hướng dẫn Flutter

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Experimental windowing APIs accelerate with Canonical as desktop steward. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Keep the primary workflow single-window until APIs graduate. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi bou...

desktop_multi_window: isolate desktop surfaces intentionally

desktop_multi_window: isolate desktop surfaces intentionally desktop_multi_window is useful because it focuses on window lifecycle, arguments, isolate boundaries, and platform constraints. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point final window = await WindowController . create ( WindowConfiguration (arguments : jsonEncode ({ 'route' : '/settings' })), ); await window. show (); await window. setTitle ( 'Settings' ); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app bac...

Impeller on desktop: SDF text and Metal/Vulkan defaults — hướng dẫn Flutter

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc ...

Flutter trên desktop: cửa sổ giờ là một phần của ứng dụng bạn

Một ứng dụng Flutter chạy được trên desktop và một ứng dụng Flutter thuộc về desktop là hai phần mềm khác nhau. Cái thứ nhất là bố cục điện thoại kéo giãn ra 1920 pixel. Cái thứ hai biết cửa sổ của mình có thể bị co lại tới mức phi lý, biết người dùng mong Cmd+W đóng một tab, biết chuột phải phải bật menu ngữ cảnh, và biết cuộn bằng trackpad không phải cùng một cử chỉ với kéo bằng ngón tay. Chẳng có gì trong số này là khó. Nó chỉ là danh sách những thứ mà di động chưa bao giờ bắt bạn nghĩ tới. Cửa sổ có vòng đời do bạn điều khiển Future < void > main () async { WidgetsFlutterBinding . ensureInitialized (); await windowManager. ensureInitialized (); const options = WindowOptions ( size : Size ( 1200 , 800 ), minimumSize : Size ( 720 , 480 ), center : true , titleBarStyle : TitleBarStyle .normal, ); await windowManager. waitUntilReadyToShow (options, () async { await windowManager. show (); await windowManager. focus ()...

Desktop multi-window: popups, dialogs, and windowHandle

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Experimental windowing APIs accelerate with Canonical as desktop steward. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Keep the primary workflow single-window until APIs graduate. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh...

Window management APIs for Flutter desktop apps — hướng dẫn Flutter

Desktop apps are multi-surface. Window APIs are catching up with Canonical. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Multi-window state, focus fixes, and native handle access. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Persist window size/position yourself — the framework will not. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có ki...