Skip to content

Commit

Permalink
support remote configure scroll text in full screen (#10)
Browse files Browse the repository at this point in the history
* support remote configure scroll text in full screen

Signed-off-by: kuromesi <[email protected]>

* add config dump

Signed-off-by: kuromesi <[email protected]>

---------

Signed-off-by: kuromesi <[email protected]>
  • Loading branch information
Kuromesi authored Nov 15, 2024
1 parent fbb4c05 commit 8470326
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 96 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# landscape

Act your mobile phones as landscape.
Act your mobile phones as landscape.

## Remote Control Apis

### ScrollTextConfiguration

#### Properties

- **text** (`String`): The text content to be displayed. This is a required field.
- **direction** (`String?`): The direction in which the text should scroll. Possible values are `"ltr"`, `"rtl"`.
- **fontSize** (`double?`): The font size of the text.
- **scrollSpeed** (`double?`): The speed at which the text should scroll.
- **fontColor** (`int?`): The color of the text in ARGB format.
- **adaptiveColor** (`bool?`): Whether the text color should adapt to the display mode (dark mode or light mode), this will override the color settings.

#### Example Usage

```shell
# 192.168.1.8 is the IP address of you mobile phone
curl 192.168.1.8:8080/configure/scroll-text -X POST -H "Content-Type: application/json" -d '{"text":"Hello this is kuromesi speaking!", "fontSize":100}'
```
21 changes: 19 additions & 2 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,18 @@ class Landscape extends StatefulWidget {
_LandscapeState createState() => _LandscapeState();
}

Map<String, int> _pagesMap = {
Map<String, int> routePageMap = {
'/gif': 1,
'/scroll-text': 2,
"/remote-http": 3,
};

Map<int, String> pageRouteMap = {
1: '/gif',
2: '/scroll-text',
3: "/remote-http",
};

class _LandscapeState extends State<Landscape> {
bool _isDarkTheme = false;
bool _keepScreenOn = false;
Expand All @@ -55,12 +61,23 @@ class _LandscapeState extends State<Landscape> {
@override
void initState() {
_loadPreferences();
configDump['landscape'] = exportState;
super.initState();
}

Map<String, dynamic> exportState() {
return {
'currentPage': pageRouteMap[_pageIndex],
'keepScreenOn': _keepScreenOn,
'isDarkTheme': _isDarkTheme
};
}

@override
void dispose() {
_savePreferences();
// remove key from config dump map
configDump.remove('landscape');
_pageController.dispose();
super.dispose();
}
Expand Down Expand Up @@ -89,7 +106,7 @@ class _LandscapeState extends State<Landscape> {

void _showPage(String page) {
setState(() {
_pageIndex = _pagesMap[page] ?? 0;
_pageIndex = routePageMap[page] ?? 0;
_pageController.jumpToPage(_pageIndex);
});
}
Expand Down
184 changes: 155 additions & 29 deletions lib/pages/scroll_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,28 @@ class _ScrollTextPageState extends State<ScrollTextPage>
@override
void initState() {
super.initState();
configDump['scrollText'] = exportState;
_loadPreferences();
_addRemoteHttpListener();
}

void _addRemoteHttpListener() {
notifier!.addListener(() => mounted
? setState(() {
_text = notifier!.configuration.text;
if (notifier!.configuration.direction != null) {
_textDirection = notifier!.configuration.direction == 'rtl'
? TextDirection.rtl
: TextDirection.ltr;
}
_fontSize = notifier!.configuration.fontSize ?? _fontSize;
_scrollSpeed = notifier!.configuration.scrollSpeed ?? _scrollSpeed;
_fontColor = notifier!.configuration.fontColor == null
? _fontColor
: Color(notifier!.configuration.fontColor!);
_adaptiveColor =
notifier!.configuration.adaptiveColor ?? _adaptiveColor;
})
: null);
}

@override
void dispose() {
notifier!.removeListener(() {});
_savePreferences();
configDump.remove('scrollText');
super.dispose();
}

Map<String, dynamic> exportState() {
return {
'text': _text,
'textDirection': _textDirection.name,
'fontSize': _fontSize,
'adaptiveColor': _adaptiveColor,
'fontColor': _fontColor.toString(),
'scrollSpeed': _scrollSpeed,
};
}

Future<void> _loadPreferences() async {
_text = await _prefs.getString("scrollText") ?? defaultScrollText;
_textDirection = (await _prefs.getString("scrollTextDirection")) == 'rtl'
Expand Down Expand Up @@ -233,12 +224,151 @@ class _ScrollTextPageState extends State<ScrollTextPage>
);
}

void _playFullScreen() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RemoteScrollText(
text: _text,
scrollSpeed: _scrollSpeed,
fontColor: _fontColor,
adaptiveColor: _adaptiveColor,
fontSize: _fontSize,
textDirection: _textDirection,
)),
);
}

Widget _buttons() {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
heroTag: "scroll_play",
onPressed: () => {_playFullScreen()},
child: Icon(Icons.play_arrow),
),
SizedBox(height: 16),
FloatingActionButton(
heroTag: "scroll_settings",
onPressed: _showSettingsDialog,
child: Icon(Icons.settings),
),
],
);
}

@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: FullScreenWrapper.wrap(
Center(
body: FullScreenWrapper(
child: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextScroll(
_text,
textDirection: _textDirection,
style: TextStyle(
fontSize: _fontSize,
color: _adaptiveColor ? null : _fontColor,
),
velocity:
Velocity(pixelsPerSecond: Offset(_scrollSpeed * 100, 0)),
),
],
),
),
),
),
floatingActionButton: _buttons(),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);
}
}

class RemoteScrollText extends StatefulWidget {
const RemoteScrollText({
Key? key,
this.adaptiveColor,
this.fontColor,
this.scrollSpeed,
required this.text,
this.textDirection,
this.fontSize,
}) : super(key: key);

final String text;

final TextDirection? textDirection;
final double? fontSize;
final bool? adaptiveColor;
final Color? fontColor;
final double? scrollSpeed;

@override
_RemoteScrollTextState createState() => _RemoteScrollTextState();
}

class _RemoteScrollTextState extends State<RemoteScrollText> {
late String _text;
late TextDirection _textDirection;
late double _fontSize;
late bool _adaptiveColor;
late Color _fontColor;
late double _scrollSpeed;

@override
void initState() {
super.initState();
_text = widget.text;
_textDirection = widget.textDirection ?? TextDirection.ltr;
_fontSize = widget.fontSize ?? 24;
_scrollSpeed = widget.scrollSpeed ?? 1;
_fontColor = widget.fontColor ?? Colors.black;
_adaptiveColor = widget.adaptiveColor ?? true;
_addRemoteHttpListener();
}

void _addRemoteHttpListener() {
notifier!.addListener(() => mounted
? setState(() {
_text = notifier!.configuration.text;
if (notifier!.configuration.direction != null) {
_textDirection = notifier!.configuration.direction == 'rtl'
? TextDirection.rtl
: TextDirection.ltr;
}
_fontSize = notifier!.configuration.fontSize ?? _fontSize;
_scrollSpeed = notifier!.configuration.scrollSpeed ?? _scrollSpeed;
_fontColor = notifier!.configuration.fontColor == null
? _fontColor
: Color(notifier!.configuration.fontColor!);
_adaptiveColor =
notifier!.configuration.adaptiveColor ?? _adaptiveColor;
})
: null);
}

@override
void dispose() {
notifier!.removeListener(() {});
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GestureDetector(
onTap: () {
Navigator.pop(
context,
);
},
child: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
Expand All @@ -257,12 +387,8 @@ class _ScrollTextPageState extends State<ScrollTextPage>
),
),
),
context),
floatingActionButton: FloatingActionButton(
onPressed: _showSettingsDialog,
child: Icon(Icons.settings),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);
}
}
39 changes: 30 additions & 9 deletions lib/remote/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_router/shelf_router.dart' as shelf_router;
import 'package:landscape/constants/constants.dart';
import 'package:landscape/utils/utils.dart';

Map<String, String> headers = {'Content-type': 'application/json'};

Expand All @@ -18,10 +19,11 @@ class RemoteHttpServerPage extends StatefulWidget {
_RemoteHttpServerPageState createState() => _RemoteHttpServerPageState();
}

class _RemoteHttpServerPageState extends State<RemoteHttpServerPage> with AutomaticKeepAliveClientMixin {
class _RemoteHttpServerPageState extends State<RemoteHttpServerPage>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;

late HttpServer _server;
bool _started = false;
List<String> _logEntries = [];
Expand Down Expand Up @@ -171,10 +173,10 @@ class Service {
final router = shelf_router.Router();

router.get('/', (Request request) {
return Response.ok('Hi, this is Kuromesi speaking!');
return Response.ok('Hi, this is Kuromesi speaking!\n');
});

router.mount('/configure', Api().router.call);
router.mount('/configure', ConfigureApi().router.call);
router.mount('/', HealthCheck().router.call);

return router.call;
Expand All @@ -199,26 +201,45 @@ class HealthCheck {
}
}

class Api {
class ConfigureApi {
Future<Response> _messages(Request request) async {
return Response.ok('Apis for configuring players.');
return Response.ok('Apis for configuring players.\n');
}

Future<Response> _scrollText(Request request) async {
String body = await request.readAsString();
ScrollTextConfiguration conf =
ScrollTextConfiguration.fromJson(jsonDecode(body));
notifier!.updateConfiguration(conf);
try {
ScrollTextConfiguration conf =
ScrollTextConfiguration.fromJson(jsonDecode(body));
notifier!.updateConfiguration(conf);
} catch (e) {
return Response.badRequest(body: e.toString());
}

return Response.ok(null);
}

Future<Response> _configDump(Request request) async {
try {
Map<String, dynamic> config = Map();
for (var k in configDump.keys) {
config[k] = configDump[k]!();
}
return Response.ok(encoding: utf8, headers: headers, jsonEncode(config));
} catch (e) {
return Response.internalServerError(body: e.toString());
}
}

shelf_router.Router get router {
final router = shelf_router.Router();

router.get('/', _messages);

router.post('/scroll-text', _scrollText);

router.get('/config-dump', _configDump);

return router;
}
}
1 change: 1 addition & 0 deletions lib/utils/config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Map<String, Function> configDump = {};
3 changes: 2 additions & 1 deletion lib/utils/utils.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export 'package:landscape/utils/wrapper.dart';
export 'package:landscape/utils/upgrader.dart';
export 'package:landscape/utils/upgrader.dart';
export 'package:landscape/utils/config.dart';
Loading

0 comments on commit 8470326

Please sign in to comment.