import 'dart:convert'; import 'dart:typed_data'; import 'package:animate_do/animate_do.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'package:vnc_viewer/flutter_rfb.dart'; import 'package:vnc_viewer/rfb/remote_frame_buffer_isolate_messages.dart'; import 'package:vnc_viewer/utils/winkey_blocker.dart'; import 'package:window_manager/window_manager.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await windowManager.ensureInitialized(); windowManager.waitUntilReadyToShow().then((_) async { // await windowManager.setSize(const Size(2560, 1440)); await windowManager.setSize(const Size(1920, 1080)); await windowManager.center(); // await windowManager.setFullScreen(true); await windowManager.setTitle('Viewer'); await windowManager.show(); }); final logger = Logger( filter: ProductionFilter(), printer: PrettyPrinter() ); runApp(MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Viewer', theme: ThemeData( // This is the theme of your application. // // TRY THIS: Try running your application with "flutter run". You'll see // the application has a purple toolbar. Then, without quitting the app, // try changing the seedColor in the colorScheme below to Colors.green // and then invoke "hot reload" (save your changes or press the "hot // reload" button in a Flutter-supported IDE, or press "r" if you used // the command line to start the app). // // Notice that the counter didn't reset back to zero; the application // state is not lost during the reload. To reset the state, use hot // restart instead. // // This works for code too, not just values: Most code changes can be // tested with just a hot reload. colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), ), home: const MyHomePage(title: 'Viewer'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); // This widget is the home page of your application. It is stateful, meaning // that it has a State object (defined below) that contains fields that affect // how it looks. // This class is the configuration for the state. It holds the values (in this // case the title) provided by the parent (in this case the App widget) and // used by the build method of the State. Fields in a Widget subclass are // always marked "final". final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { bool _connected = false; bool _fullscreen = false; TextEditingController _host = TextEditingController(text: "hmsn.ink"); TextEditingController _port = TextEditingController(text: "5910"); TextEditingController _passwd = TextEditingController(text: ""); @override Widget build(BuildContext context) { return CallbackShortcuts( bindings: { const SingleActivator(LogicalKeyboardKey.f11): () { setState(() { _fullscreen = !_fullscreen; }); windowManager.setFullScreen(_fullscreen); }, }, child: Focus( autofocus: true, child: Scaffold( body: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ ..._connected ? [ Expanded( child: Center( child: InteractiveViewer( constrained: true, maxScale: 1, minScale: 1, child: Builder( builder: (final BuildContext context) => RemoteFrameBufferWidget( hostName: _host.text, port: int.parse(_port.text), isFullscreen: _fullscreen, onError: (final Object error) { ScaffoldMessenger.of( context, ).showSnackBar( SnackBar( content: Text('Error: $error'), ), ); setState(() { _connected = false; }); }, password: _passwd.text, ), ), ), ), ), ] : [ Container( height: 400, decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/background.png'), fit: BoxFit.fill, ), ), child: Stack( children: [ Positioned( left: 30, width: 80, height: 200, child: FadeInUp( duration: Duration(seconds: 1), child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/light-1.png', ), ), ), ), ), ), Positioned( left: 140, width: 80, height: 150, child: FadeInUp( duration: Duration(milliseconds: 1200), child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/light-2.png', ), ), ), ), ), ), Positioned( right: 40, top: 40, width: 80, height: 150, child: FadeInUp( duration: Duration(milliseconds: 1300), child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/clock.png', ), ), ), ), ), ), Positioned( child: FadeInUp( duration: Duration(milliseconds: 1600), child: Container( margin: EdgeInsets.only(top: 50), child: Center( child: Text( "Vnc", style: TextStyle( color: Colors.white, fontSize: 40, fontWeight: FontWeight.bold, ), ), ), ), ), ), ], ), ), Padding( padding: EdgeInsets.only(left: 530.0, right: 530.0, top: 30.0, bottom: 30.0), child: Column( children: [ FadeInUp( duration: Duration(milliseconds: 1800), child: Container( padding: EdgeInsets.all(5), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all( color: Color.fromRGBO(143, 148, 251, 1), ), boxShadow: [ BoxShadow( color: Color.fromRGBO( 143, 148, 251, .2, ), blurRadius: 20.0, offset: Offset(0, 10), ), ], ), child: Column( children: [ Container( padding: EdgeInsets.all(8.0), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Color.fromRGBO( 143, 148, 251, 1, ), ), ), ), child: TextField( controller: _host, decoration: InputDecoration( border: InputBorder.none, hintText: "Host", hintStyle: TextStyle( color: Colors.grey[700], ), ), ), ), Container( padding: EdgeInsets.all(8.0), decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Color.fromRGBO( 143, 148, 251, 1, ), ), ), ), child: TextField( controller: _port, decoration: InputDecoration( border: InputBorder.none, hintText: "Port", hintStyle: TextStyle( color: Colors.grey[700], ), ), ), ), Container( padding: EdgeInsets.all(8.0), child: TextField( controller: _passwd, obscureText: true, decoration: InputDecoration( border: InputBorder.none, hintText: "Password", hintStyle: TextStyle( color: Colors.grey[700], ), ), ), ), ], ), ), ), SizedBox(height: 30), FadeInUp( duration: Duration(milliseconds: 1900), child: InkWell( onTap: () { setState(() { _connected = true; windowManager.setTitle("Desktop"); }); }, child: Container( height: 50, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), gradient: LinearGradient( colors: [ Color.fromRGBO(143, 148, 251, 1), Color.fromRGBO(143, 148, 251, .6), ], ), ), child: Center( child: Text( "접속", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ), ), ), ], ), ), ], ], ), ), ), ), ); } }