main.dart 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter_acrylic/flutter_acrylic.dart';
  6. import 'package:flutter_pty/flutter_pty.dart';
  7. import 'package:xterm/xterm.dart';
  8. void main() {
  9. WidgetsFlutterBinding.ensureInitialized();
  10. if (isDesktop) {
  11. setupAcrylic();
  12. }
  13. runApp(MyApp());
  14. }
  15. bool get isDesktop {
  16. if (kIsWeb) return false;
  17. return [
  18. TargetPlatform.windows,
  19. TargetPlatform.linux,
  20. TargetPlatform.macOS,
  21. ].contains(defaultTargetPlatform);
  22. }
  23. Future<void> setupAcrylic() async {
  24. await Window.initialize();
  25. await Window.makeTitlebarTransparent();
  26. await Window.setEffect(effect: WindowEffect.aero);
  27. await Window.setBlurViewState(MacOSBlurViewState.active);
  28. }
  29. class MyApp extends StatelessWidget {
  30. @override
  31. Widget build(BuildContext context) {
  32. return MaterialApp(
  33. title: 'xterm.dart demo',
  34. debugShowCheckedModeBanner: false,
  35. home: MyHomePage(),
  36. );
  37. }
  38. }
  39. class MyHomePage extends StatefulWidget {
  40. MyHomePage({Key? key}) : super(key: key);
  41. @override
  42. // ignore: library_private_types_in_public_api
  43. _MyHomePageState createState() => _MyHomePageState();
  44. }
  45. class _MyHomePageState extends State<MyHomePage> {
  46. final terminal = Terminal(
  47. maxLines: 10000,
  48. );
  49. late final Pty pty;
  50. @override
  51. void initState() {
  52. super.initState();
  53. WidgetsBinding.instance.endOfFrame.then(
  54. (_) {
  55. if (mounted) _startPty();
  56. },
  57. );
  58. }
  59. void _startPty() {
  60. pty = Pty.start(
  61. shell,
  62. columns: terminal.viewWidth,
  63. rows: terminal.viewHeight,
  64. );
  65. pty.output
  66. .cast<List<int>>()
  67. .transform(Utf8Decoder())
  68. .listen(terminal.write);
  69. pty.exitCode.then((code) {
  70. terminal.write('the process exited with exit code $code');
  71. });
  72. terminal.onOutput = (data) {
  73. pty.write(const Utf8Encoder().convert(data));
  74. };
  75. terminal.onResize = (w, h, pw, ph) {
  76. pty.resize(h, w);
  77. };
  78. }
  79. @override
  80. Widget build(BuildContext context) {
  81. return Scaffold(
  82. backgroundColor: Colors.transparent,
  83. body: SafeArea(
  84. child: TerminalView(
  85. terminal,
  86. backgroundOpacity: 0.8,
  87. ),
  88. ),
  89. );
  90. }
  91. }
  92. String get shell {
  93. if (Platform.isMacOS || Platform.isLinux) {
  94. return Platform.environment['SHELL'] ?? 'bash';
  95. }
  96. if (Platform.isWindows) {
  97. return 'cmd.exe';
  98. }
  99. return 'sh';
  100. }