mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2026-02-07 08:44:48 +01:00
Merge branch 'android_service'
This commit is contained in:
@@ -9,6 +9,7 @@ import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:server_box/app.dart';
|
||||
import 'package:server_box/core/channel/bg_run.dart';
|
||||
import 'package:server_box/core/utils/sync/icloud.dart';
|
||||
import 'package:server_box/core/utils/sync/webdav.dart';
|
||||
import 'package:server_box/data/model/app/menu/server_func.dart';
|
||||
@@ -109,6 +110,10 @@ void _doPlatformRelated() async {
|
||||
if (isAndroid) {
|
||||
// try switch to highest refresh rate
|
||||
FlutterDisplayMode.setHighRefreshRate();
|
||||
if (Stores.setting.bgRun.fetch()) {
|
||||
Loggers.app.info('Start foreground service');
|
||||
BgRunMC.startService();
|
||||
}
|
||||
}
|
||||
|
||||
final serversCount = Stores.server.box.keys.length;
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/utils/ssh_auth.dart';
|
||||
@@ -85,6 +84,7 @@ class SSHPageState extends State<SSHPage>
|
||||
_terminalController.dispose();
|
||||
_discontinuityTimer?.cancel();
|
||||
if (!Stores.setting.generalWakeLock.fetch()) WakelockPlus.disable();
|
||||
_setupDiscontinuityTimer();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -95,7 +95,7 @@ class SSHPageState extends State<SSHPage>
|
||||
2 => true,
|
||||
_ => context.isDark,
|
||||
};
|
||||
_media = MediaQuery.of(context);
|
||||
_media = context.media;
|
||||
|
||||
_terminalTheme = _isDark ? TerminalThemes.dark : TerminalThemes.light;
|
||||
_terminalTheme = _terminalTheme.copyWith(selectionCursor: UIs.primaryColor);
|
||||
@@ -415,8 +415,6 @@ class SSHPageState extends State<SSHPage>
|
||||
_listen(session.stdout);
|
||||
_listen(session.stderr);
|
||||
|
||||
_initService();
|
||||
|
||||
for (final snippet in SnippetProvider.snippets.value) {
|
||||
if (snippet.autoRunOn?.contains(widget.spi.id) == true) {
|
||||
snippet.runInTerm(_terminal, widget.spi);
|
||||
@@ -451,64 +449,43 @@ class SSHPageState extends State<SSHPage>
|
||||
.listen(_terminal.write);
|
||||
}
|
||||
|
||||
// void _setupDiscontinuityTimer() {
|
||||
// _discontinuityTimer = Timer.periodic(
|
||||
// const Duration(seconds: 5),
|
||||
// (_) async {
|
||||
// var throwTimeout = true;
|
||||
// Future.delayed(const Duration(seconds: 3), () {
|
||||
// if (throwTimeout) {
|
||||
// _catchTimeout();
|
||||
// }
|
||||
// });
|
||||
// await _client?.ping();
|
||||
// throwTimeout = false;
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
void _setupDiscontinuityTimer() {
|
||||
_discontinuityTimer = Timer.periodic(
|
||||
const Duration(seconds: 5),
|
||||
(_) async {
|
||||
var throwTimeout = true;
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
if (throwTimeout) {
|
||||
_catchTimeout();
|
||||
}
|
||||
});
|
||||
await _client?.ping();
|
||||
throwTimeout = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// void _catchTimeout() {
|
||||
// _discontinuityTimer?.cancel();
|
||||
// if (!mounted) return;
|
||||
// _writeLn('\n\nConnection lost\r\n');
|
||||
// context.showRoundDialog(
|
||||
// title: Text(l10n.attention),
|
||||
// child: Text('${l10n.disconnected}\n${l10n.goBackQ}'),
|
||||
// barrierDismiss: false,
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// if (mounted) {
|
||||
// context.pop();
|
||||
// if (widget.pop) {
|
||||
// context.pop();
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: Text(l10n.ok),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
void _catchTimeout() {
|
||||
_discontinuityTimer?.cancel();
|
||||
if (!mounted) return;
|
||||
_writeLn('\n\nConnection lost\r\n');
|
||||
context.showRoundDialog(
|
||||
title: libL10n.attention,
|
||||
child: Text('${l10n.disconnected}\n${l10n.goBackQ}'),
|
||||
barrierDismiss: false,
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
},
|
||||
).toList,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
Future<void> _initService() async {
|
||||
if (!isAndroid) return;
|
||||
|
||||
await FlutterBackgroundService().configure(
|
||||
androidConfiguration: AndroidConfiguration(
|
||||
onStart: _onStart,
|
||||
autoStart: true,
|
||||
isForegroundMode: true,
|
||||
initialNotificationTitle: 'SSH',
|
||||
initialNotificationContent: l10n.bgRun,
|
||||
),
|
||||
iosConfiguration: IosConfiguration(),
|
||||
);
|
||||
}
|
||||
|
||||
void _initStoredCfg() {
|
||||
final fontFamilly = Stores.setting.fontPath.fetch().getFileName();
|
||||
final textSize = Stores.setting.termFontSize.fetch();
|
||||
@@ -546,5 +523,3 @@ class SSHPageState extends State<SSHPage>
|
||||
if (Stores.setting.sshWakeLock.fetch()) WakelockPlus.enable();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onStart(ServiceInstance service) async {}
|
||||
|
||||
@@ -107,18 +107,18 @@ class _SSHTabPageState extends State<SSHTabPage>
|
||||
final idxs = _tabMap.keys
|
||||
.map((e) => reg.firstMatch(e))
|
||||
.map((e) => e?.group(1))
|
||||
.where((e) => e != null);
|
||||
.whereType<String>();
|
||||
if (idxs.isEmpty) {
|
||||
return _tabMap.keys.contains(spi.name) ? '${spi.name}(1)' : spi.name;
|
||||
}
|
||||
final biggest = idxs.reduce((a, b) => a!.length > b!.length ? a : b);
|
||||
final biggestInt = int.tryParse(biggest ?? '0');
|
||||
final biggest = idxs.reduce((a, b) => a.length > b.length ? a : b);
|
||||
final biggestInt = int.tryParse(biggest);
|
||||
if (biggestInt != null && biggestInt > 0) {
|
||||
return '${spi.name}(${biggestInt + 1})';
|
||||
}
|
||||
return spi.name;
|
||||
}();
|
||||
final key = GlobalKey<SSHPageState>();
|
||||
final key = Key(name);
|
||||
_tabMap[name] = (
|
||||
page: SSHPage(
|
||||
// Keep it, or the Flutter will works unexpectedly
|
||||
@@ -259,11 +259,11 @@ class _AddPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const viewPadding = 3.0;
|
||||
const viewPadding = 7.0;
|
||||
final viewWidth = context.media.size.width - 2 * viewPadding;
|
||||
|
||||
final itemCount = ServerProvider.servers.length;
|
||||
const itemPadding = 3.0;
|
||||
const itemPadding = 1.0;
|
||||
const itemWidth = 150.0;
|
||||
const itemHeight = 50.0;
|
||||
|
||||
@@ -272,62 +272,55 @@ class _AddPage extends StatelessWidget {
|
||||
max(viewWidth ~/ (visualCrossCount * itemPadding + itemWidth), 1);
|
||||
final mainCount = itemCount ~/ crossCount + 1;
|
||||
|
||||
return Center(
|
||||
key: const Key('sshTabAddServer'),
|
||||
child: ServerProvider.serverOrder.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(
|
||||
child: Text(libL10n.empty, textAlign: TextAlign.center),
|
||||
);
|
||||
}
|
||||
return ServerProvider.serverOrder.listenVal((order) {
|
||||
if (order.isEmpty) {
|
||||
return Center(
|
||||
child: Text(libL10n.empty, textAlign: TextAlign.center),
|
||||
);
|
||||
}
|
||||
|
||||
// Custom grid
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(viewPadding),
|
||||
children: List.generate(
|
||||
mainCount,
|
||||
(rowIndex) => Row(
|
||||
children: List.generate(crossCount, (columnIndex) {
|
||||
final idx = rowIndex * crossCount + columnIndex;
|
||||
final id = order.elementAtOrNull(idx);
|
||||
if (id == null) return _placeholder;
|
||||
// Custom grid
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(viewPadding),
|
||||
children: List.generate(
|
||||
mainCount,
|
||||
(rowIndex) => Row(
|
||||
children: List.generate(crossCount, (columnIndex) {
|
||||
final idx = rowIndex * crossCount + columnIndex;
|
||||
final id = order.elementAtOrNull(idx);
|
||||
final spi = ServerProvider.pick(id: id)?.value.spi;
|
||||
if (spi == null) return _placeholder;
|
||||
|
||||
final spi = ServerProvider.pick(id: order[idx])?.value.spi;
|
||||
if (spi == null) return _placeholder;
|
||||
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(itemPadding),
|
||||
child: CardX(
|
||||
child: InkWell(
|
||||
onTap: () => onTapInitCard(spi),
|
||||
child: Container(
|
||||
height: itemHeight,
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: const EdgeInsets.only(left: 17, right: 7),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
spi.name,
|
||||
style: UIs.text18,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.chevron_right)
|
||||
],
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(itemPadding),
|
||||
child: InkWell(
|
||||
onTap: () => onTapInitCard(spi),
|
||||
child: Container(
|
||||
height: itemHeight,
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: const EdgeInsets.only(left: 17, right: 7),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
spi.name,
|
||||
style: UIs.text18,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.chevron_right)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
).cardx,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user