flterm 0.0.2 copy "flterm: ^0.0.2" to clipboard
flterm: ^0.0.2 copied to clipboard

Flutter terminal widget on top of Ghostty's libghostty-vt engine.

example/lib/main.dart

import 'package:flterm/flterm.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'demo_page.dart';
import 'themes.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (kIsWeb) {
    await initializeForWeb(
      Uri.parse('assets/assets/libghostty-wasm32-freestanding.wasm'),
    );
  }
  runApp(const _App());
}

class _App extends StatefulWidget {
  const _App();

  @override
  State<_App> createState() => _AppState();
}

class _AppState extends State<_App> {
  var _themeIndex = 0;

  @override
  Widget build(BuildContext context) {
    final entry = TerminalThemes.all[_themeIndex];
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(),
      home: Scaffold(
        backgroundColor: entry.theme.background,
        body: SafeArea(child: DemoPage(theme: entry.theme)),
        floatingActionButton: Builder(
          builder: (innerContext) => FloatingActionButton(
            onPressed: () => _showThemePicker(innerContext),
            tooltip: 'Theme',
            backgroundColor: Colors.black54,
            foregroundColor: Colors.white,
            child: const Icon(Icons.palette),
          ),
        ),
      ),
    );
  }

  Future<void> _showThemePicker(BuildContext context) {
    final isLarge = MediaQuery.of(context).size.width >= 600;
    if (isLarge) {
      return showDialog<void>(
        context: context,
        builder: (dialogContext) => Dialog(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 360, maxHeight: 480),
            child: _ThemeList(
              currentIndex: _themeIndex,
              onSelect: (i) {
                setState(() => _themeIndex = i);
                Navigator.of(dialogContext).pop();
              },
            ),
          ),
        ),
      );
    }
    return showModalBottomSheet<void>(
      context: context,
      builder: (sheetContext) => SafeArea(
        child: _ThemeList(
          currentIndex: _themeIndex,
          onSelect: (i) {
            setState(() => _themeIndex = i);
            Navigator.of(sheetContext).pop();
          },
        ),
      ),
    );
  }
}

class _ThemeList extends StatelessWidget {
  final int currentIndex;
  final ValueChanged<int> onSelect;

  const _ThemeList({required this.currentIndex, required this.onSelect});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      itemCount: TerminalThemes.all.length,
      itemBuilder: (_, i) {
        final entry = TerminalThemes.all[i];
        return ListTile(
          leading: Container(
            width: 36,
            height: 36,
            decoration: BoxDecoration(
              color: entry.theme.background,
              borderRadius: BorderRadius.circular(6),
              border: Border.all(color: entry.theme.foreground),
            ),
          ),
          title: Text(entry.name),
          selected: i == currentIndex,
          onTap: () => onSelect(i),
        );
      },
    );
  }
}
0
likes
160
points
196
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter terminal widget on top of Ghostty's libghostty-vt engine.

Homepage
Repository (GitHub)
View/report issues

Topics

#terminal #terminal-emulator #ghostty #libghostty #vt100

License

MIT (license)

Dependencies

flutter, image, libghostty, meta

More

Packages that depend on flterm