Skip to content

Commit 61d5925

Browse files
committed
Add rpc communication and screenshot support
1 parent 4c8092d commit 61d5925

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2039
-575
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Jaime Blasco
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

flutter-package/LICENSE

+21-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
TODO: Add your license here.
1+
MIT License
2+
3+
Copyright (c) 2020 Jaime Blasco
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import 'dart:async';
2+
import 'dart:convert';
3+
import 'dart:io';
4+
5+
import 'package:json_rpc_2/json_rpc_2.dart';
6+
import 'package:stream_channel/stream_channel.dart';
7+
import 'package:web_socket_channel/web_socket_channel.dart';
8+
9+
import 'preview.dart';
10+
11+
class DaemonService extends MultiplePeer {
12+
final int port;
13+
DaemonService(this.port);
14+
15+
@override
16+
registerMethods(Peer server) {
17+
server.registerMethod('preview.getPort', () {
18+
return port;
19+
});
20+
21+
server.registerMethod('preview.setActiveFile', (Parameters params) {
22+
final path = params['path'].asString;
23+
changeActiveFile(path);
24+
return true;
25+
});
26+
27+
server.registerMethod('preview.restart', (Parameters params) {
28+
_server.sendNotification('preview.restart');
29+
return true;
30+
});
31+
}
32+
}
33+
34+
class Stoutsink extends StreamSink<String> {
35+
@override
36+
void add(String event) {
37+
stdout.writeln(event);
38+
}
39+
40+
@override
41+
void addError(Object error, [StackTrace stackTrace]) {
42+
stdout.addError(error, stackTrace);
43+
}
44+
45+
@override
46+
Future addStream(Stream<String> stream) {
47+
return stdout.addStream(stream.transform(Utf8Encoder()));
48+
}
49+
50+
@override
51+
Future close() {
52+
return stdout.close();
53+
}
54+
55+
@override
56+
Future get done => stdout.close();
57+
}
58+
59+
abstract class MultiplePeer {
60+
Peer _server;
61+
Map<WebSocketChannel, Peer> sockets = {};
62+
63+
//StreamChannel<String> _socket;
64+
65+
bool isListening = false;
66+
67+
addWebSocket(WebSocketChannel webSocket) {
68+
assert(sockets[webSocket] == null);
69+
final peer = Peer(webSocket.cast<String>(), strictProtocolChecks: false);
70+
sockets[webSocket] = peer;
71+
registerMethods(peer);
72+
if (isListening) {
73+
peer.listen();
74+
}
75+
}
76+
77+
removeWebSocket(WebSocketChannel webSocket) {
78+
final peer = sockets[webSocket];
79+
peer.close();
80+
sockets[webSocket] = null;
81+
}
82+
83+
Future run() async {
84+
// assert(port != null && webSocket != null);
85+
try {
86+
/* _socket = webSocket ??
87+
WebSocketChannel.connect(Uri.parse('ws://127.0.0.1:$port/ws'))
88+
.cast<String>(); */
89+
} catch (e, s) {
90+
stderr.addError(e, s);
91+
}
92+
93+
final channel = StreamChannel<String>(
94+
stdin.transform(Utf8Decoder()).transform(LineSplitter()),
95+
Stoutsink(),
96+
);
97+
98+
_server = Peer(channel, strictProtocolChecks: false,
99+
onUnhandledError: (error, stacktrace) {
100+
stdout.write('Error $error');
101+
});
102+
103+
registerMethods(_server);
104+
}
105+
106+
Future listen() async {
107+
isListening = true;
108+
for (final socket in sockets.entries) {
109+
socket.value.listen().then(
110+
(value) {
111+
removeWebSocket(socket.key);
112+
},
113+
);
114+
}
115+
return await _server.listen();
116+
}
117+
118+
Future close() async {
119+
for (final peer in sockets.values) {
120+
await peer.close();
121+
}
122+
return _server.close();
123+
}
124+
125+
/* void registerMethod(String name, Function callback) =>
126+
_server.registerMethod(name, callback); */
127+
128+
void sendNotification(String method, [dynamic parameters]) {
129+
_server.sendNotification(method, parameters);
130+
sockets.values.forEach((e) {
131+
e.sendNotification(method, parameters);
132+
});
133+
}
134+
135+
registerMethods(Peer server);
136+
}
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'dart:io';
2+
import 'package:path/path.dart' as path;
3+
4+
final localAddress = InternetAddress('127.0.0.1');
5+
6+
class AssetServer {
7+
HttpServer _server;
8+
9+
Future<bool> runServer(int port) async {
10+
try {
11+
_server = await HttpServer.bind(localAddress, port);
12+
return true;
13+
} catch (e, s) {
14+
stderr.addError(e, s);
15+
return false;
16+
}
17+
}
18+
19+
Future<void> listen() async {
20+
await for (final request in _server) {
21+
try {
22+
if (request.uri.path.startsWith('/asset/')) {
23+
final File file =
24+
new File(request.uri.path.replaceFirst('/asset/', ''));
25+
26+
if (file.existsSync()) {
27+
final raw = await file.readAsBytes();
28+
29+
request.response.headers
30+
.set('Content-Type', 'image/${path.extension(file.path)}');
31+
request.response.headers.set('Content-Length', raw.length);
32+
request.response.add(raw);
33+
await request.response.close();
34+
} else {
35+
request.response.statusCode = HttpStatus.notFound;
36+
request.response.write('Not found');
37+
await request.response.close();
38+
}
39+
} else {
40+
request.response.statusCode = HttpStatus.notFound;
41+
request.response.write('Not found');
42+
await request.response.close();
43+
}
44+
} catch (e, s) {
45+
stderr.addError(e, s);
46+
request.response.statusCode = HttpStatus.internalServerError;
47+
request.response.write('Internal Error');
48+
await request.response.close();
49+
}
50+
}
51+
}
52+
53+
Future<void> close() async {
54+
await _server.close();
55+
}
56+
}

0 commit comments

Comments
 (0)