123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- import 'package:debounce_throttle/debounce_throttle.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:flutter_hbb/common.dart';
- import 'package:flutter_hbb/consts.dart';
- import 'package:flutter_hbb/models/platform_model.dart';
- import 'package:get/get.dart';
- customImageQualityWidget(
- {required double initQuality,
- required double initFps,
- required Function(double)? setQuality,
- required Function(double)? setFps,
- required bool showFps,
- required bool showMoreQuality}) {
- if (initQuality < kMinQuality ||
- initQuality > (showMoreQuality ? kMaxMoreQuality : kMaxQuality)) {
- initQuality = kDefaultQuality;
- }
- if (initFps < kMinFps || initFps > kMaxFps) {
- initFps = kDefaultFps;
- }
- final qualityValue = initQuality.obs;
- final fpsValue = initFps.obs;
- final RxBool moreQualityChecked = RxBool(qualityValue.value > kMaxQuality);
- final debouncerQuality = Debouncer<double>(
- Duration(milliseconds: 1000),
- onChanged: setQuality,
- initialValue: qualityValue.value,
- );
- final debouncerFps = Debouncer<double>(
- Duration(milliseconds: 1000),
- onChanged: setFps,
- initialValue: fpsValue.value,
- );
- onMoreChanged(bool? value) {
- if (value == null) return;
- moreQualityChecked.value = value;
- if (!value && qualityValue.value > 100) {
- qualityValue.value = 100;
- }
- debouncerQuality.value = qualityValue.value;
- }
- return Column(
- children: [
- Obx(() => Row(
- children: [
- Expanded(
- flex: 3,
- child: Slider(
- value: qualityValue.value,
- min: kMinQuality,
- max: moreQualityChecked.value ? kMaxMoreQuality : kMaxQuality,
- divisions: moreQualityChecked.value
- ? ((kMaxMoreQuality - kMinQuality) / 10).round()
- : ((kMaxQuality - kMinQuality) / 5).round(),
- onChanged: setQuality == null
- ? null
- : (double value) async {
- qualityValue.value = value;
- debouncerQuality.value = value;
- },
- ),
- ),
- Expanded(
- flex: 1,
- child: Text(
- '${qualityValue.value.round()}%',
- style: const TextStyle(fontSize: 15),
- )),
- Expanded(
- flex: isMobile ? 2 : 1,
- child: Text(
- translate('Bitrate'),
- style: const TextStyle(fontSize: 15),
- )),
- // mobile doesn't have enough space
- if (showMoreQuality && !isMobile)
- Expanded(
- flex: 1,
- child: Row(
- children: [
- Checkbox(
- value: moreQualityChecked.value,
- onChanged: onMoreChanged,
- ),
- Expanded(
- child: Text(translate('More')),
- )
- ],
- ))
- ],
- )),
- if (showMoreQuality && isMobile)
- Obx(() => Row(
- children: [
- Expanded(
- child: Align(
- alignment: Alignment.centerRight,
- child: Checkbox(
- value: moreQualityChecked.value,
- onChanged: onMoreChanged,
- ),
- ),
- ),
- Expanded(
- child: Text(translate('More')),
- )
- ],
- )),
- if (showFps)
- Obx(() => Row(
- children: [
- Expanded(
- flex: 3,
- child: Slider(
- value: fpsValue.value,
- min: kMinFps,
- max: kMaxFps,
- divisions: ((kMaxFps - kMinFps) / 5).round(),
- onChanged: setFps == null
- ? null
- : (double value) async {
- fpsValue.value = value;
- debouncerFps.value = value;
- },
- ),
- ),
- Expanded(
- flex: 1,
- child: Text(
- '${fpsValue.value.round()}',
- style: const TextStyle(fontSize: 15),
- )),
- Expanded(
- flex: 2,
- child: Text(
- translate('FPS'),
- style: const TextStyle(fontSize: 15),
- ))
- ],
- )),
- ],
- );
- }
- customImageQualitySetting() {
- final qualityKey = 'custom_image_quality';
- final fpsKey = 'custom-fps';
- final initQuality =
- (double.tryParse(bind.mainGetUserDefaultOption(key: qualityKey)) ??
- kDefaultQuality);
- final isQuanlityFixed = isOptionFixed(qualityKey);
- final initFps =
- (double.tryParse(bind.mainGetUserDefaultOption(key: fpsKey)) ??
- kDefaultFps);
- final isFpsFixed = isOptionFixed(fpsKey);
- return customImageQualityWidget(
- initQuality: initQuality,
- initFps: initFps,
- setQuality: isQuanlityFixed
- ? null
- : (v) {
- bind.mainSetUserDefaultOption(
- key: qualityKey, value: v.toString());
- },
- setFps: isFpsFixed
- ? null
- : (v) {
- bind.mainSetUserDefaultOption(key: fpsKey, value: v.toString());
- },
- showFps: true,
- showMoreQuality: true);
- }
- List<Widget> ServerConfigImportExportWidgets(
- List<TextEditingController> controllers,
- List<RxString> errMsgs,
- ) {
- import() {
- Clipboard.getData(Clipboard.kTextPlain).then((value) {
- importConfig(controllers, errMsgs, value?.text);
- });
- }
- export() {
- final text = ServerConfig(
- idServer: controllers[0].text.trim(),
- relayServer: controllers[1].text.trim(),
- apiServer: controllers[2].text.trim(),
- key: controllers[3].text.trim())
- .encode();
- debugPrint("ServerConfig export: $text");
- Clipboard.setData(ClipboardData(text: text));
- showToast(translate('Export server configuration successfully'));
- }
- return [
- Tooltip(
- message: translate('Import server config'),
- child: IconButton(
- icon: Icon(Icons.paste, color: Colors.grey), onPressed: import),
- ),
- Tooltip(
- message: translate('Export Server Config'),
- child: IconButton(
- icon: Icon(Icons.copy, color: Colors.grey), onPressed: export))
- ];
- }
- List<(String, String)> otherDefaultSettings() {
- List<(String, String)> v = [
- ('View Mode', kOptionViewOnly),
- if ((isDesktop || isWebDesktop))
- ('show_monitors_tip', kKeyShowMonitorsToolbar),
- if ((isDesktop || isWebDesktop))
- ('Collapse toolbar', kOptionCollapseToolbar),
- ('Show remote cursor', kOptionShowRemoteCursor),
- ('Follow remote cursor', kOptionFollowRemoteCursor),
- ('Follow remote window focus', kOptionFollowRemoteWindow),
- if ((isDesktop || isWebDesktop)) ('Zoom cursor', kOptionZoomCursor),
- ('Show quality monitor', kOptionShowQualityMonitor),
- ('Mute', kOptionDisableAudio),
- if (isDesktop) ('Enable file copy and paste', kOptionEnableFileCopyPaste),
- ('Disable clipboard', kOptionDisableClipboard),
- ('Lock after session end', kOptionLockAfterSessionEnd),
- ('Privacy mode', kOptionPrivacyMode),
- if (isMobile) ('Touch mode', kOptionTouchMode),
- ('True color (4:4:4)', kOptionI444),
- ('Reverse mouse wheel', kKeyReverseMouseWheel),
- ('swap-left-right-mouse', kOptionSwapLeftRightMouse),
- if (isDesktop)
- (
- 'Show displays as individual windows',
- kKeyShowDisplaysAsIndividualWindows
- ),
- if (isDesktop)
- (
- 'Use all my displays for the remote session',
- kKeyUseAllMyDisplaysForTheRemoteSession
- )
- ];
- return v;
- }
- class TrackpadSpeedWidget extends StatefulWidget {
- final SimpleWrapper<int> value;
- // If null, no debouncer will be applied.
- final Function(int)? onDebouncer;
- TrackpadSpeedWidget({Key? key, required this.value, this.onDebouncer});
- @override
- TrackpadSpeedWidgetState createState() => TrackpadSpeedWidgetState();
- }
- class TrackpadSpeedWidgetState extends State<TrackpadSpeedWidget> {
- final TextEditingController _controller = TextEditingController();
- late final Debouncer<int> debouncerSpeed;
- set value(int v) => widget.value.value = v;
- int get value => widget.value.value;
- void updateValue(int newValue) {
- setState(() {
- value = newValue.clamp(kMinTrackpadSpeed, kMaxTrackpadSpeed);
- // Scale the trackpad speed value to a percentage for display purposes.
- _controller.text = value.toString();
- if (widget.onDebouncer != null) {
- debouncerSpeed.setValue(value);
- }
- });
- }
- @override
- void initState() {
- super.initState();
- debouncerSpeed = Debouncer<int>(
- Duration(milliseconds: 1000),
- onChanged: widget.onDebouncer,
- initialValue: widget.value.value,
- );
- }
- @override
- Widget build(BuildContext context) {
- if (_controller.text.isEmpty) {
- _controller.text = value.toString();
- }
- return Row(
- children: [
- Expanded(
- flex: 3,
- child: Slider(
- value: value.toDouble(),
- min: kMinTrackpadSpeed.toDouble(),
- max: kMaxTrackpadSpeed.toDouble(),
- divisions: ((kMaxTrackpadSpeed - kMinTrackpadSpeed) / 10).round(),
- onChanged: (double v) => updateValue(v.round()),
- ),
- ),
- Expanded(
- flex: 1,
- child: Row(
- children: [
- SizedBox(
- width: 56,
- child: TextField(
- controller: _controller,
- keyboardType: TextInputType.number,
- textAlign: TextAlign.center,
- onSubmitted: (text) {
- int? v = int.tryParse(text);
- if (v != null) {
- updateValue(v);
- }
- },
- style: const TextStyle(fontSize: 13),
- decoration: InputDecoration(
- contentPadding:
- EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
- ),
- ),
- ).marginOnly(right: 8.0),
- Text(
- '%',
- style: const TextStyle(fontSize: 15),
- )
- ],
- )),
- ],
- );
- }
- }
|