### Start Local Development Server Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md This command starts a local development server, typically at `localhost:4321`, allowing you to preview your site in real-time as you make changes. ```bash npm run dev ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md Run this command in the root of your project to install all the necessary Node.js dependencies defined in `package.json`. ```bash npm install ``` -------------------------------- ### Installation Bundle Configuration Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Configures the installation prefix to create a relocatable bundle in the build directory. It also ensures a clean bundle directory on each installation. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) ``` -------------------------------- ### Example Server Import JSON Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/bulk-import.md This example demonstrates the JSON format for importing multiple servers, including production and development environments. It highlights the use of tags for organization and SSH keys for authentication. ```json [ { "name": "Production", "ip": "prod.example.com", "port": 22, "user": "admin", "pubKeyId": "my-key", "tags": ["production", "web"] }, { "name": "Development", "ip": "dev.example.com", "port": 2222, "user": "dev", "pubKeyId": "dev-key", "tags": ["development"] } ] ``` -------------------------------- ### Example Custom Commands Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md Examples of common system information commands to display on the server detail page. These include memory usage, disk space, and system uptime. ```json { "Memory": "free -h", "Disk": "df -h", "Uptime": "uptime" } ``` -------------------------------- ### Installing Application and Bundle Contents Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Installs the application executable, ICU data file, Flutter library, and bundled plugin libraries into the specified bundle directories. ```cmake set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) ``` -------------------------------- ### Compile Flutter Server Box from Source Source: https://github.com/lollipopkit/flutter_server_box/wiki/Home Clone the repository and follow Flutter installation instructions. Compile for your target platform using the provided commands. ```bash git clone https://github.com/lollipopkit/flutter_server_box ``` ```bash flutter build windows ``` ```bash flutter build linux ``` ```bash flutter build macos ``` -------------------------------- ### Install Server Box with Homebrew Cask on macOS Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/installation.mdx Use this command to install Server Box on macOS using Homebrew Cask. Ensure Homebrew is installed first. ```sh brew install --cask server-box ``` -------------------------------- ### Data Flow Example Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/architecture.md Describes the typical data flow within the application, from user interaction to UI rebuild. ```text User Action → Widget → Provider → Service/Store → Model Update → UI Rebuild ``` -------------------------------- ### Install Native Assets Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Copies native assets from the build directory to the installation bundle. This ensures that any native code or resources required by the application are correctly placed. ```cmake set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Android Widget Configuration Example Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/widgets.md Configure home screen widgets in the ServerBox app by mapping a widget ID to its status URL. This example shows a widget ID of '17' linked to a server URL. ```text - Key: "17" - Value: "https://my-server.com/status" ``` -------------------------------- ### Unit Test Example Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/testing.md Example of a unit test for a data model. This test verifies the logic for calculating CPU percentage. ```dart test('should calculate CPU percentage', () { final cpu = CpuModel(usage: 75.0); expect(cpu.usagePercentage, '75%'); }); ``` -------------------------------- ### Manage ServerBox Scripts with ShellFuncManager Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Use ShellFuncManager to get script paths, build install commands, and generate script bodies for remote execution. It supports custom directories and disabling specific command types. ```dart import 'package:server_box/data/model/app/scripts/shell_func.dart'; import 'package:server_box/data/model/server/system.dart'; const serverId = 'aB3xZ9'; // --- Get the path where the script will be stored --- final scriptPath = ShellFuncManager.getScriptPath( serverId, systemType: SystemType.linux, customDir: null, // null = use default tmp/home dir ); print(scriptPath); // e.g. "/tmp/.sb_aB3xZ9/sb.sh" // --- Custom script directory (set in ServerCustom.scriptDir) --- final customPath = ShellFuncManager.getScriptPath( serverId, systemType: SystemType.linux, customDir: '/opt/serverbox', ); print(customPath); // "/opt/serverbox/sb.sh" // --- Build the install command (writes the script bytes to stdin) --- final installCmd = ShellFuncManager.getInstallShellCmd( serverId, systemType: SystemType.linux, customDir: null, ); // installCmd is used as the SSH exec entry point; script bytes are piped to stdin // --- Generate the full script body (written as stdin data) --- final script = ShellFuncManager.allScript( {'ping-check': 'ping -c1 8.8.8.8 | tail -1'}, // custom commands systemType: SystemType.linux, disabledCmdTypes: ['nvidia'], // skip nvidia-smi collection ); // --- Get the command that invokes the status function --- final statusCmd = ShellFunc.status.exec( serverId, systemType: SystemType.linux, customDir: null, ); print(statusCmd); // e.g. "sh /tmp/.sb_aB3xZ9/sb.sh -s" // --- Switch script dir from /tmp to $HOME (fallback on write failure) --- ShellFuncManager.switchScriptDir(serverId, systemType: SystemType.linux); ``` -------------------------------- ### Provider Test Example Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/testing.md Example of testing a Riverpod provider. This test checks if the `serverStatusProvider` returns the expected status model. ```dart test('serverStatusProvider returns status', () async { final container = ProviderContainer(); final status = await container.read(serverStatusProvider(testServer).future); expect(status, isA()); }); ``` -------------------------------- ### Widget Test Example Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/testing.md Example of a widget test for a UI component. This test ensures that the `ServerCard` widget correctly displays the server name. ```dart testWidgets('ServerCard displays server name', (tester) async { await tester.pumpWidget( ProviderScope( child: MaterialApp( home: ServerCard(server: testServer), ), ), ); expect(find.text('Test Server'), findsOneWidget); }); ``` -------------------------------- ### Open SFTP Page with Current Directory Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/terminal.md Get the terminal's current working directory and navigate to the SFTP page, initializing it with the retrieved path. ```dart void openSftp() async { final cwd = await terminal.getCurrentWorkingDirectory(); Navigator.push( context, SftpPage(initialPath: cwd), ); } ``` -------------------------------- ### Define a Family Provider for Server Containers Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Family Providers allow providers to accept parameters. This example fetches a list of containers for a specific server. ```dart @riverpod Future> containers(ContainersRef ref, Server server) async { final client = await ref.watch(sshClientProvider(server).future); return await client.listContainers(); } ``` -------------------------------- ### Project Initialization and Basic Settings Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Initializes the CMake project, sets the minimum version, project name, executable name, and application ID. It also opts into modern CMake behaviors and sets the installation RPATH. ```cmake cmake_minimum_required(VERSION 3.10) project(runner LANGUAGES CXX) set(BINARY_NAME "ServerBox") set(APPLICATION_ID "tech.lolli.toolbox") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") ``` -------------------------------- ### Define Store Property (Dart) Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/json-settings.md Example of how settings are defined in the Dart code, showing the structure for `settingName`, `settingKey`, and `defaultValue`. ```dart late final settingName = StoreProperty(box, 'settingKey', defaultValue); ``` -------------------------------- ### Parse CPU Metrics with Cpus and SingleCpuCore Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Parse raw /proc/stat output for Linux or BSD/macOS top output to get CPU core details. Initialize Cpus with two snapshots to calculate usage percentages and maintain a history for charting. ```dart import 'package:server_box/data/model/server/cpu.dart'; // --- Parse /proc/stat output --- const procStatRaw = ''' cpu 12345 200 5678 900000 150 0 30 0 0 0 cpu0 6000 100 2800 450000 75 0 15 0 0 0 cpu1 6345 100 2878 450000 75 0 15 0 0 0 '''; final cores = SingleCpuCore.parse(procStatRaw); // cores[0].id == "cpu" (aggregate) // cores[1].id == "cpu0" // --- Build Cpus with two successive snapshots --- // (In practice the app calls `cpus.add(newCores)` each poll cycle) final cpus = Cpus(cores, cores); // init1 == init2 → delta is 0 // After a real second snapshot is available the delta becomes meaningful: print(cpus.usedPercent()); // overall usage 0–100 print(cpus.user); // user-space % print(cpus.sys); // kernel % print(cpus.iowait); // I/O wait % print(cpus.idle); // idle % print(cpus.coresCount); // number of logical cores // The rolling FlSpot history for the chart (last 30 samples) for (final fifo in cpus.spots) { print(fifo.toList().map((s) => '(${s.x},${s.y.toStringAsFixed(1)})').join(' ')); } // --- BSD / macOS parsing --- const macosTopLine = 'CPU usage: 14.70% user, 12.76% sys, 72.52% idle'; final bsdCpus = parseBsdCpu(macosTopLine); print(bsdCpus.usedPercent()); // ≈ 27.46 const freebsdLine = 'CPU: 5.2% user, 0.0% nice, 3.1% system, 0.1% interrupt, 91.6% idle'; final fbCpus = parseBsdCpu(freebsdLine); print(fbCpus.user); // 5.2 ``` -------------------------------- ### Get Help with Astro CLI Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md Displays the help message for the Astro CLI, providing information on available commands and their usage. ```bash npm run astro -- --help ``` -------------------------------- ### Format Command Output with awk Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md Use tools like `awk` to extract specific information from command output. This example isolates the CPU load average from the `uptime` command. ```json {"CPU Load": "uptime | awk -F'load average:' '{print $2}'"} ``` -------------------------------- ### Limit Command Output with tail Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md To keep output concise and improve performance, limit the amount of data displayed. This example shows the last 20 lines of the system log. ```json {"Logs": "tail -20 /var/log/syslog"} ``` -------------------------------- ### Pipe Commands for Complex Output Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md Combine multiple shell commands using pipes to process and filter output. This example shows how to find the top 5 CPU-consuming processes. ```json {"Top Process": "ps aux | sort -rk 3 | head -5"} ``` -------------------------------- ### Run Flutter in Development Mode Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Use `flutter run` to start the application in development mode. Specify a device ID with `-d ` to target a specific device. ```bash flutter run ``` ```bash flutter run -d ``` -------------------------------- ### Define a StateProvider for ThemeMode Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Use StateProvider for simple, observable state. This example defines a ThemeNotifier to manage the application's theme mode, loading it from settings and persisting changes. ```dart @riverpod class ThemeNotifier extends _$ThemeNotifier { @override ThemeMode build() { // Load from settings return SettingStore.themeMode; } void setTheme(ThemeMode mode) { state = mode; SettingStore.themeMode = mode; // Persist } } ``` -------------------------------- ### Perform a Clean Build Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md To resolve build issues, perform a clean build by running `flutter clean`, `dart run build_runner build --delete-conflicting-outputs`, and `flutter pub get`. ```bash flutter clean dart run build_runner build --delete-conflicting-outputs flutter pub get ``` -------------------------------- ### Build Process Overview Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/architecture.md Illustrates the sequence of operations in the custom build system. ```bash make.dart (version) → fl_build (build) → Platform output ``` -------------------------------- ### Preview Production Build Locally Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md Use this command to preview the production build locally before deploying. It serves the contents of the `./dist/` directory. ```bash npm run preview ``` -------------------------------- ### Create and Manage Server Private Info (Spi) Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Demonstrates creating a minimal server entry, validating it, persisting it to local storage, and serializing/deserializing it. Also shows how to check for reconnection needs and parse alternate URLs. ```dart import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/custom.dart'; import 'package:server_box/data/model/server/wol_cfg.dart'; // --- Create a minimal server entry --- final spi = Spi( name: 'prod-web-01', ip: '203.0.113.10', port: 22, user: 'deploy', pwd: 's3cr3t', // password auth; omit when using keyId keyId: null, // or set to a PrivateKeyStore id tags: ['production', 'web'], autoConnect: true, // Jump through a bastion host jumpIds: ['bastion-server-id'], // Optional WoL to wake the machine before connecting wolCfg: WakeOnLanCfg( mac: 'AA:BB:CC:DD:EE:FF', ip: '255.255.255.255', ), // Per-server customisation custom: ServerCustom( cmds: {'disk-free': 'df -h /'}, // extra status commands shown on detail page preferTempDev: 'nvme-pci-0400', // temperature device to highlight pveAddr: 'https://pve.example.com', // optional Proxmox VE address pveIgnoreCert: true, netDev: 'eth0', // network interface for home card ), ); // --- Validate before saving (throws SpiValidationException on conflict) --- spi.validateOrThrow(); // throws if jumpId AND proxyCommand are both set // --- Persist to local storage --- spi.save(); // calls ServerStore.instance.put(spi) // --- Serialize / deserialize --- final json = spi.toJson(); final restored = Spi.fromJson(json); print(restored.oldId); // "deploy@203.0.113.10:22" print(restored.id); // stable short id, e.g. "aB3xZ9" // --- Check connection info equality (triggers reconnect logic) --- final needsReconnect = spi.shouldReconnect(restored); // false – nothing changed // --- Parse alternate URL for failover --- // alterUrl format: "user@host:port" final spiWithAlt = spi.copyWith(alterUrl: 'deploy@203.0.113.11:2222'); final (altIp, altUser, altPort) = spiWithAlt.parseAlterUrl(); // altIp = "203.0.113.11", altUser = "deploy", altPort = 2222 ``` -------------------------------- ### Build Production Site Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md Generates a production-ready build of your website in the `./dist/` directory. This is the output you would deploy to a hosting service. ```bash npm run build ``` -------------------------------- ### Install AOT Library Conditionally Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Installs the Ahead-Of-Time (AOT) compiled library only on non-Debug builds. This is typically done to optimize performance for release versions of the application. ```cmake if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### Create SFTP Client Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/sftp.md Establishes an SFTP client by first obtaining an SSH client and then opening the SFTP subsystem. ```dart Future createSftpClient(Spi spi) async { // 1. Get SSH client (reuse if available) final sshClient = await genClient(spi); // 2. Open SFTP subsystem final sftp = await sshClient.openSftp(); return sftp; } ``` -------------------------------- ### Main Entry Point Initialization Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/architecture.md Initializes the Flutter application with Riverpod's ProviderScope. ```dart void main() { runApp( ProviderScope( child: MyApp(), ), ); } ``` -------------------------------- ### Create Astro Project with Starlight Template Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md Use this command to create a new Astro project initialized with the Starlight template. This sets up the basic structure for your documentation site. ```bash npm create astro@latest -- --template starlight ``` -------------------------------- ### Initialize and Access Stores with Stores Facade Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Initialize the Stores facade once during app startup. Access individual stores like server, snippet, and settings. Use lastModTime to check the most recent write timestamp for sync decisions. ```dart import 'package:server_box/data/res/store.dart'; // --- Initialise (called once in main before runApp) --- await Stores.init(); // --- Access individual stores --- final servers = Stores.server.fetch(); // List final snippets = Stores.snippet.fetch(); // List final timeout = Stores.setting.timeout.fetch(); // int // --- Check the most recent write timestamp (for sync decisions) --- final ts = Stores.lastModTime; // milliseconds since epoch print('Last modified: ${DateTime.fromMillisecondsSinceEpoch(ts)}'); // --- Stores available --- // Stores.setting — app preferences // Stores.server — server list (Spi) // Stores.container — docker host overrides // Stores.key — SSH private keys // Stores.snippet — shell snippets // Stores.history — SFTP path history // Stores.connectionStats — connection latency records // Stores.portForward — port-forwarding rules ``` -------------------------------- ### Define an AsyncNotifierProvider for Server Status Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Use AsyncNotifierProvider for data that loads asynchronously. This example fetches and refreshes the status of a server. ```dart @riverpod class ServerStatus extends _$ServerStatus { @override Future build(Server server) async { // Initial load return await fetchStatus(server); } Future refresh() async { state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { return await fetchStatus(server); }); } } ``` -------------------------------- ### Manage Persistent Server List with ServerStore Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Shows how to add, fetch, update, and delete servers from the persistent store. Includes cache invalidation and migration of old IDs. ```dart import 'package:server_box/data/store/server.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; final store = ServerStore.instance; // --- Add a new server --- final spi = Spi(name: 'db-01', ip: '10.0.0.5', port: 22, user: 'root'); store.put(spi); // --- Fetch all servers (cached after first call) --- final List all = store.fetch(); print(all.map((s) => s.name).join(', ')); // "db-01, ..." // --- Update an entry (preserves order-related state) --- final updated = spi.copyWith(name: 'db-primary'); store.update(spi, updated); // --- Delete by id --- store.delete(spi.id); // --- Check existence --- print(store.have(spi)); // false (just deleted) // --- Invalidate cache (force reload on next fetch) --- store.invalidateCache(); // --- Migrate old "user@host:port" keys to ShortId format (called once at startup) --- store.migrateIds(); ``` -------------------------------- ### Define a Derived State Provider Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Derived state providers filter or transform data from other providers. This example returns a list of only the online servers. ```dart @riverpod List onlineServers(OnlineServersRef ref) { final all = ref.watch(serversProvider); return all.where((s) => s.isOnline).toList(); } ``` -------------------------------- ### Bulk Server Import JSON Format Source: https://github.com/lollipopkit/flutter_server_box/wiki/Home Import servers using a JSON array where each object contains server connection details. Ensure 'keyId' is the name of a private key stored within the app. ```jsonc [ { "name": "Server1", "ip": "exmaple.com", "port": 22, "user": "root", "pwd": "password", "keyId": "", "tags": ["tag1"], "alterUrl": "root@192.168.1.1", "autoConnect": false } ] ``` -------------------------------- ### Configure Flutter Library and Dependencies Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/flutter/CMakeLists.txt This section finds necessary system libraries using PkgConfig and sets up the Flutter library and its headers. It defines interface targets for linking and includes directories. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") # Published to parent scope for install step. set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS "fl_basic_message_channel.h" "fl_binary_codec.h" "fl_binary_messenger.h" "fl_dart_project.h" "fl_engine.h" "fl_json_message_codec.h" "fl_json_method_codec.h" "fl_message_codec.h" "fl_method_call.h" "fl_method_channel.h" "fl_method_codec.h" "fl_method_response.h" "fl_plugin_registrar.h" "fl_plugin_registry.h" "fl_standard_message_codec.h" "fl_standard_method_codec.h" "fl_string_codec.h" "fl_value.h" "fl_view.h" "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) add_dependencies(flutter flutter_assemble) ``` -------------------------------- ### Run Flutter App in Development Mode Source: https://github.com/lollipopkit/flutter_server_box/blob/main/CLAUDE.md Use this command to run the Flutter application during development. It starts the app with hot reload and debugging enabled. ```bash flutter run ``` -------------------------------- ### Combined URL Placeholders for Distribution and Theme Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-logo.md Combine {DIST} and {BRIGHT} placeholders to create image URLs that dynamically adapt to both the Linux distribution and the current theme. This offers the most granular control over custom server card logos. ```url https://example.com/{DIST}-{BRIGHT}.png ``` -------------------------------- ### Define a Computed State Provider Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Computed state providers derive their value from other providers. This example calculates the total number of servers based on a list of servers. ```dart @riverpod int totalServers(TotalServersRef ref) { final servers = ref.watch(serversProvider); return servers.length; } ``` -------------------------------- ### Define a Per-Server State Provider Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Each server can have its own isolated state managed by a provider. This example defines a ServerProvider to manage the state for a single server, including connection logic. ```dart @riverpod class ServerProvider extends _$ServerProvider { @override ServerState build(Server server) { return ServerState.disconnected(); } Future connect() async { state = ServerState.connecting(); try { final client = await genClient(server.spi); state = ServerState.connected(client); } catch (e) { state = ServerState.error(e.toString()); } } } ``` -------------------------------- ### Define a StreamProvider for Real-time CPU Usage Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Use StreamProvider for continuous data streams. This example monitors CPU usage and automatically disposes of the stream when no longer watched. ```dart @riverpod Stream cpuUsage(CpuUsageRef ref, Server server) { final client = ref.watch(sshClientProvider(server)); final stream = client.monitorCpu(); // Auto-dispose when not watched ref.onDispose(() { client.stopMonitoring(); }); return stream; } ``` -------------------------------- ### Run Unit Tests Source: https://github.com/lollipopkit/flutter_server_box/blob/main/CLAUDE.md Execute all unit tests defined in the project. This command is used to verify the correctness of individual components and functions. ```bash flutter test ``` -------------------------------- ### Modify State using Notifiers Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/state.md Update state by accessing the provider's notifier and calling its methods. Use `ref.read()` to get the notifier without subscribing to changes. ```dart ref.read(settingsProvider.notifier).update(newSettings); ``` -------------------------------- ### Build for Windows Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Build the project for Windows using `dart run fl_build -p windows`. This requires Windows with Visual Studio. ```bash dart run fl_build -p windows ``` -------------------------------- ### Fetch System Info with SSH Client Dependency Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Watch for an SSH client provider to become available before fetching system information. This ensures the SSH connection is established first. ```dart @riverpod Future systemInfo(SystemInfoRef ref, Server server) async { // Wait for SSH client first final client = await ref.watch(sshClientProvider(server).future); // Then fetch system info return await client.getSystemInfo(); } ``` -------------------------------- ### Astro + Starlight Project Structure Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/README.md This is the standard directory layout for an Astro project using the Starlight documentation theme. Documentation files reside in `src/content/docs/`. ```bash . ├── public/ ├── src/ │ ├── assets/ │ ├── content/ │ │ └── docs/ │ └── content.config.ts ├── astro.config.mjs ├── package.json └── tsconfig.json ``` -------------------------------- ### Build for Linux Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Build the project for Linux using `dart run fl_build -p linux`. ```bash dart run fl_build -p linux ``` -------------------------------- ### Global Server State Management with ServersNotifier Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Use ServersNotifier to manage a list of servers, their display order, and perform add/delete/update operations. It also handles starting an auto-refresh timer. ```dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:server_box/data/provider/server/all.dart'; // --- Inside a ConsumerWidget --- class ServerListPage extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(serversProvider); return Column(children: [ // Display ordered server names for (final id in state.serverOrder) Text(state.servers[id]?.name ?? id), // Available tag filters Wrap(children: state.tags.map((t) => Chip(label: Text(t))).toList()), // --- Actions via notifier --- ElevatedButton( onPressed: () { // Add server and immediately start connecting ref.read(serversProvider.notifier).addServer( Spi(name: 'new-host', ip: '192.168.1.50', port: 22, user: 'admin'), ); }, child: const Text('Add'), ), ElevatedButton( onPressed: () async { // Remove a server and clear all its stats await ref.read(serversProvider.notifier).delServer('server-id'); }, child: const Text('Delete'), ), ElevatedButton( onPressed: () { // Manual refresh all servers; pass spi: x to refresh just one ref.read(serversProvider.notifier).refresh(); }, child: const Text('Refresh All'), ), ElevatedButton( onPressed: () { // Start periodic auto-refresh (interval from SettingStore) ref.read(serversProvider.notifier).startAutoRefresh(); }, child: const Text('Start Auto Refresh'), ), ]); } } // --- Programmatic usage (outside a widget, e.g. in a service) --- Future example(WidgetRef ref) async { final notifier = ref.read(serversProvider.notifier); // Update display order (drag-and-drop result) notifier.updateServerOrder(['id-b', 'id-a', 'id-c']); // Disconnect one server without removing it notifier.closeServer(id: 'id-a'); // Disconnect all servers notifier.setDisconnected(); // Stop the periodic timer notifier.stopAutoRefresh(); print(notifier.isAutoRefreshOn); // false } ``` -------------------------------- ### System Dependencies and Application ID Definition Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Finds PkgConfig modules and checks for GTK, then defines the APPLICATION_ID preprocessor macro. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") ``` -------------------------------- ### Display Command on Server Card Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md Use the special key `server_card_top_right` to display a command's output directly on the home page server card. This is useful for quick status checks. ```json { "server_card_top_right": "your-command-here" } ``` -------------------------------- ### Manage Docker/Podman Containers with ContainerNotifier Source: https://context7.com/lollipopkit/flutter_server_box/llms.txt Integrate ContainerNotifier into a Flutter widget to display and manage Docker or Podman containers. Requires an existing SSHClient. Handles container listing, starting, stopping, restarting, and pruning. ```dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:server_box/data/provider/container.dart'; import 'package:server_box/data/model/container/type.dart'; // --- In a ConsumerWidget for a server that already has an SSHClient --- class ContainerPage extends ConsumerWidget { final SSHClient client; final String serverId; final String userName; const ContainerPage({required this.client, required this.serverId, required this.userName}); @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch( containerProvider(client, userName, serverId, context), ); if (state.isBusy) return const CircularProgressIndicator(); if (state.error != null) return Text('Error: ${state.error}'); return Column(children: [ Text('Docker ${state.version ?? "unknown"}'), // Container list for (final ps in state.items ?? []) ListTile( title: Text(ps.name ?? ps.id ?? '?'), subtitle: Text(ps.status ?? ''), trailing: Row(mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.stop), onPressed: () => ref .read(containerProvider(client, userName, serverId, context).notifier) .stop(ps.id!), ), IconButton( icon: const Icon(Icons.restart_alt), onPressed: () => ref .read(containerProvider(client, userName, serverId, context).notifier) .restart(ps.id!), ), ]), ), // Switch to Podman ElevatedButton( onPressed: () => ref .read(containerProvider(client, userName, serverId, context).notifier) .setType(ContainerType.podman), child: const Text('Use Podman'), ), // Prune stopped containers ElevatedButton( onPressed: () async { final err = await ref .read(containerProvider(client, userName, serverId, context).notifier) .pruneContainers(); if (err != null) print('Prune error: $err'); }, child: const Text('Prune Containers'), ), ]); } } ``` -------------------------------- ### Dart Class for SFTP Transfer Progress Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/sftp.md Tracks the progress of an SFTP transfer, including total and transferred bytes, start time, and calculated percentage and speed. Provides methods to format transfer speed. ```dart class TransferProgress { final SftpReq request; final int total; final int transferred; final DateTime startTime; double get percentage => (transferred / total) * 100; Duration get elapsed => DateTime.now().difference(startTime); String get speedFormatted { final bytesPerSecond = transferred / elapsed.inSeconds; return formatSpeed(bytesPerSecond); } } ``` -------------------------------- ### URL Placeholder for Linux Distribution Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-logo.md Use the {DIST} placeholder to automatically insert the detected Linux distribution into the image URL. This allows for dynamic logo selection based on the server's OS. ```url https://example.com/{DIST}.png ``` -------------------------------- ### Build for macOS Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Build the project for macOS using `dart run fl_build -p macos`. ```bash dart run fl_build -p macos ``` -------------------------------- ### Run Android Release Locally with Debug Signing Source: https://github.com/lollipopkit/flutter_server_box/blob/main/CLAUDE.md This command allows running the Android release version locally for verification purposes. It falls back to debug signing if needed. ```bash flutter run --release -PallowDebugReleaseSigning=true ``` -------------------------------- ### Build for iOS Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Build the project for iOS using `dart run fl_build -p ios`. This requires macOS with Xcode, CocoaPods, and an Apple Developer account for signing. ```bash dart run fl_build -p ios ``` -------------------------------- ### Build for Android Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Build the project for Android using `dart run fl_build -p android`. This requires the Android SDK, Java Development Kit, and a Keystore for signing. ```bash dart run fl_build -p android ``` -------------------------------- ### Configure SSH Server Alive Settings Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/troubleshooting.md Add these lines to `/etc/ssh/sshd_config` on the server to prevent frequent disconnections due to inactivity. Restart the SSH service after changes. ```bash # /etc/ssh/sshd_config ClientAliveInterval 60 ClientAliveCountMax 3 ``` -------------------------------- ### Handle StreamProvider State in UI Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Demonstrates consuming a StreamProvider to display real-time data, including loading and error states. ```dart final cpu = ref.watch(cpuUsageProvider(server)); cpu.when( data: (usage) => CpuChart(usage), loading: () => CircularProgressIndicator(), error: (error, stack) => ErrorWidget(error), ) ``` -------------------------------- ### Build for Specific Platform with fl_build Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Execute `dart run fl_build -p ` to build the project for a specified platform. Available platforms include ios, android, macos, linux, and windows. ```bash dart run fl_build -p ``` -------------------------------- ### Cross-Building System Root Configuration Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Configures the system root and find paths for cross-building based on the FLUTTER_TARGET_PLATFORM_SYSROOT variable. ```cmake if(FLUTTER_TARGET_PLATFORM_SYSROOT) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) endif() ``` -------------------------------- ### Upgrade Flutter Dependencies Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/building.md Ensure dependency compatibility by running `flutter pub upgrade`. ```bash flutter pub upgrade ``` -------------------------------- ### Layered Architecture Diagram Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/architecture.md Illustrates the layered architecture of the Server Box project, showing the Presentation, Business Logic, and Data layers and their dependencies. ```text ┌─────────────────────────────────────┐ │ Presentation Layer │ │ (lib/view/page/) │ │ - Pages, Widgets, Controllers │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Business Logic Layer │ │ (lib/data/provider/) │ │ - Riverpod Providers │ │ - State Management │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Data Layer │ │ (lib/data/model/, store/) │ │ - Models, Storage, Services │ └─────────────────────────────────────┘ ``` -------------------------------- ### Basic Custom Command Format Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-commands.md Define custom commands using a JSON object where keys are display names and values are shell commands. Ensure commands are fast and avoid modifying system state. ```json { "Display Name": "shell command" } ``` -------------------------------- ### Paginate SFTP Directory Listings Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/sftp.md Use pagination to retrieve directory listings in manageable chunks. This class defines a page size and provides a method to fetch a specific page of directory contents using SFTP offset and limit parameters. ```dart class PaginatedDirectory { static const pageSize = 100; Future> getPage(int page) async { final offset = page * pageSize; return await sftp.listDir( path, offset: offset, limit: pageSize, ); } } ``` -------------------------------- ### Custom Logo URL Format Source: https://github.com/lollipopkit/flutter_server_box/wiki/Home Use placeholders like {DIST} for distribution name and {BRIGHT} for theme brightness in your logo URL. The list of supported distributions may not be up-to-date. ```plaintext https://example.com/{DIST}.png ``` ```plaintext https://example.com/{BRIGHT}.png ``` -------------------------------- ### Handle AsyncNotifierProvider State in UI Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Shows how to consume an AsyncNotifierProvider using .when() to handle data, loading, and error states. ```dart final status = ref.watch(serverStatusProvider(server)); status.when( data: (data) => StatusWidget(data), loading: () => LoadingWidget(), error: (error, stack) => ErrorWidget(error), ) ``` -------------------------------- ### Create SSH Terminal Session Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/terminal.md Initializes an SSH client, opens a pseudo-terminal (PTY), and sets up a terminal emulator with a resize handler. Requires an Spi object for SSH connection details. ```dart Future createSession(Spi spi) async { // 1. Get SSH client final client = await genClient(spi); // 2. Create PTY final pty = await client.openPty( term: 'xterm-256color', cols: 80, rows: 24, ); // 3. Initialize terminal emulator final terminal = Terminal( backend: PtyBackend(pty), ); // 4. Setup resize handler terminal.onResize.listen((size) { pty.resize(size.cols, size.rows); }); return TerminalSession( terminal: terminal, pty: pty, client: client, ); } ``` -------------------------------- ### Watch ThemeProvider in a Widget Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/state.md Demonstrates how to watch a StateProvider within a ConsumerWidget to access and display the current theme mode. ```dart class MyWidget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themeNotifierProvider); return Text('Theme: $theme'); } } ``` -------------------------------- ### Run Specific Test File Source: https://github.com/lollipopkit/flutter_server_box/blob/main/CLAUDE.md Execute a single test file. This is useful for focusing on testing a specific feature or bug fix. ```bash flutter test test/battery_test.dart ``` -------------------------------- ### URL Placeholder for Theme Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/advanced/custom-logo.md Use the {BRIGHT} placeholder to automatically insert the current theme (light or dark) into the image URL. This enables theme-aware logo display. ```url https://example.com/{BRIGHT}.png ``` -------------------------------- ### Application Executable Definition Source: https://github.com/lollipopkit/flutter_server_box/blob/main/linux/CMakeLists.txt Defines the main application executable, listing its source files. New source files should be added here. ```cmake add_executable(${BINARY_NAME} "main.cc" "my_application.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) ``` -------------------------------- ### List Directory Contents Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/principles/sftp.md Lists directory contents and sorts them by name, size, or modification time. Optionally places directories before files. ```dart Future> listDirectory(String path) async { final sftp = await getSftpClient(spiId); // List directory final files = await sftp.listDir(path); // Sort based on settings files.sort((a, b) { switch (sortOption) { case SortOption.name: return a.name.toLowerCase().compareTo(b.name.toLowerCase()); case SortOption.size: return a.size.compareTo(b.size); case SortOption.time: return a.modified.compareTo(b.modified); } }); // Folders first if enabled if (showFoldersFirst) { final dirs = files.where((f) => f.isDirectory); final regular = files.where((f) => !f.isDirectory); return [...dirs, ...regular]; } return files; } ``` -------------------------------- ### Running Flutter Tests Source: https://github.com/lollipopkit/flutter_server_box/blob/main/docs/src/content/docs/development/testing.md Commands to execute tests in a Flutter project. Use `flutter test` to run all tests, specify a file path for individual tests, or add the `--coverage` flag to generate a coverage report. ```bash # Run all tests flutter test # Run specific test file flutter test test/battery_test.dart # Run with coverage flutter test --coverage ```