diff --git a/flutter/assets/arrow.svg b/flutter/assets/arrow.svg
new file mode 100644
index 000000000..d0f032bc2
--- /dev/null
+++ b/flutter/assets/arrow.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/dots.svg b/flutter/assets/dots.svg
new file mode 100644
index 000000000..19563b849
--- /dev/null
+++ b/flutter/assets/dots.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/file.svg b/flutter/assets/file.svg
new file mode 100644
index 000000000..21c7fb9de
--- /dev/null
+++ b/flutter/assets/file.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/folder.svg b/flutter/assets/folder.svg
new file mode 100644
index 000000000..3959f7874
--- /dev/null
+++ b/flutter/assets/folder.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/folder_new.svg b/flutter/assets/folder_new.svg
new file mode 100644
index 000000000..22b729204
--- /dev/null
+++ b/flutter/assets/folder_new.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/home.svg b/flutter/assets/home.svg
new file mode 100644
index 000000000..45a018f5d
--- /dev/null
+++ b/flutter/assets/home.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/refresh.svg b/flutter/assets/refresh.svg
new file mode 100644
index 000000000..f77fcfd4c
--- /dev/null
+++ b/flutter/assets/refresh.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/search.svg b/flutter/assets/search.svg
new file mode 100644
index 000000000..295136d7e
--- /dev/null
+++ b/flutter/assets/search.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/assets/trash.svg b/flutter/assets/trash.svg
new file mode 100644
index 000000000..f9037e0e1
--- /dev/null
+++ b/flutter/assets/trash.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart
index e1dd1a1f8..ff8dfbb09 100644
--- a/flutter/lib/common.dart
+++ b/flutter/lib/common.dart
@@ -152,7 +152,7 @@ class MyTheme {
static const Color canvasColor = Color(0xFF212121);
static const Color border = Color(0xFFCCCCCC);
static const Color idColor = Color(0xFF00B6F0);
- static const Color darkGray = Color(0xFFB9BABC);
+ static const Color darkGray = Color.fromARGB(255, 148, 148, 148);
static const Color cmIdColor = Color(0xFF21790B);
static const Color dark = Colors.black87;
static const Color button = Color(0xFF2C8CFF);
@@ -160,8 +160,9 @@ class MyTheme {
static ThemeData lightTheme = ThemeData(
brightness: Brightness.light,
- backgroundColor: Color(0xFFFFFFFF),
- scaffoldBackgroundColor: Color(0xFFEEEEEE),
+ backgroundColor: Color(0xFFEEEEEE),
+ hoverColor: Color.fromARGB(255, 224, 224, 224),
+ scaffoldBackgroundColor: Color(0xFFFFFFFF),
textTheme: const TextTheme(
titleLarge: TextStyle(fontSize: 19, color: Colors.black87),
titleSmall: TextStyle(fontSize: 14, color: Colors.black87),
@@ -169,6 +170,7 @@ class MyTheme {
bodyMedium:
TextStyle(fontSize: 14, color: Colors.black87, height: 1.25),
labelLarge: TextStyle(fontSize: 16.0, color: MyTheme.accent80)),
+ cardColor: Color(0xFFEEEEEE),
hintColor: Color(0xFFAAAAAA),
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
@@ -191,8 +193,9 @@ class MyTheme {
);
static ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
- backgroundColor: Color(0xFF252525),
- scaffoldBackgroundColor: Color(0xFF141414),
+ backgroundColor: Color(0xFF24252B),
+ hoverColor: Color.fromARGB(255, 45, 46, 53),
+ scaffoldBackgroundColor: Color(0xFF18191E),
textTheme: const TextTheme(
titleLarge: TextStyle(fontSize: 19),
titleSmall: TextStyle(fontSize: 14),
@@ -200,7 +203,7 @@ class MyTheme {
bodyMedium: TextStyle(fontSize: 14, height: 1.25),
labelLarge: TextStyle(
fontSize: 16.0, fontWeight: FontWeight.bold, color: accent80)),
- cardColor: Color(0xFF252525),
+ cardColor: Color(0xFF24252B),
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
tabBarTheme: const TabBarTheme(
@@ -217,9 +220,8 @@ class MyTheme {
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
)
: null,
- checkboxTheme: const CheckboxThemeData(
- checkColor: MaterialStatePropertyAll(dark)
- ),
+ checkboxTheme:
+ const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)),
).copyWith(
extensions: >[
ColorThemeExtension.dark,
diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart
index a4cb50025..2b73182fd 100644
--- a/flutter/lib/consts.dart
+++ b/flutter/lib/consts.dart
@@ -53,7 +53,7 @@ const int kDesktopMaxDisplayHeight = 1080;
const double kDesktopFileTransferNameColWidth = 200;
const double kDesktopFileTransferModifiedColWidth = 120;
-const double kDesktopFileTransferRowHeight = 25.0;
+const double kDesktopFileTransferRowHeight = 30.0;
const double kDesktopFileTransferHeaderHeight = 25.0;
// https://en.wikipedia.org/wiki/Non-breaking_space
diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart
index 4edffb3b6..0d55552af 100644
--- a/flutter/lib/desktop/pages/file_manager_page.dart
+++ b/flutter/lib/desktop/pages/file_manager_page.dart
@@ -2,20 +2,23 @@ import 'dart:async';
import 'dart:io';
import 'dart:math';
+import 'package:percent_indicator/percent_indicator.dart';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_breadcrumb/flutter_breadcrumb.dart';
import 'package:flutter_hbb/desktop/widgets/list_search_action_listener.dart';
+import 'package:flutter_hbb/desktop/widgets/menu_button.dart';
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
import 'package:flutter_hbb/models/file_model.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:wakelock/wakelock.dart';
+
import '../../consts.dart';
import '../../desktop/widgets/material_mod_popup_menu.dart' as mod_menu;
-
import '../../common.dart';
import '../../models/model.dart';
import '../../models/platform_model.dart';
@@ -147,7 +150,7 @@ class _FileManagerPageState extends State
value: _ffi.fileModel,
child: Consumer(builder: (context, model, child) {
return Scaffold(
- backgroundColor: Theme.of(context).backgroundColor,
+ backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: Row(
children: [
Flexible(flex: 3, child: body(isLocal: true)),
@@ -192,35 +195,42 @@ class _FileManagerPageState extends State
];
return Listener(
- onPointerDown: (e) {
- final x = e.position.dx;
- final y = e.position.dy;
- menuPos = RelativeRect.fromLTRB(x, y, x, y);
- },
- child: IconButton(
- icon: const Icon(Icons.more_vert),
- splashRadius: kDesktopIconButtonSplashRadius,
- onPressed: () => mod_menu.showMenu(
- context: context,
- position: menuPos,
- items: items
- .map((e) => e.build(
- context,
- MenuConfig(
- commonColor: CustomPopupMenuTheme.commonColor,
- height: CustomPopupMenuTheme.height,
- dividerHeight: CustomPopupMenuTheme.dividerHeight)))
- .expand((i) => i)
- .toList(),
- elevation: 8,
- ),
- ));
+ onPointerDown: (e) {
+ final x = e.position.dx;
+ final y = e.position.dy;
+ menuPos = RelativeRect.fromLTRB(x, y, x, y);
+ },
+ child: MenuButton(
+ onPressed: () => mod_menu.showMenu(
+ context: context,
+ position: menuPos,
+ items: items
+ .map(
+ (e) => e.build(
+ context,
+ MenuConfig(
+ commonColor: CustomPopupMenuTheme.commonColor,
+ height: CustomPopupMenuTheme.height,
+ dividerHeight: CustomPopupMenuTheme.dividerHeight),
+ ),
+ )
+ .expand((i) => i)
+ .toList(),
+ elevation: 8,
+ ),
+ child: SvgPicture.asset(
+ "assets/dots.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ ),
+ );
}
Widget body({bool isLocal = false}) {
final scrollController = ScrollController();
return Container(
- decoration: BoxDecoration(border: Border.all(color: Colors.black26)),
margin: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(8.0),
child: DropTarget(
@@ -231,18 +241,22 @@ class _FileManagerPageState extends State
onDragExited: (exit) {
_dropMaskVisible.value = false;
},
- child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
- headTools(isLocal),
- Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ headTools(isLocal),
+ Expanded(
child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- child: _buildFileList(context, isLocal, scrollController),
- )
- ],
- )),
- ]),
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: _buildFileList(context, isLocal, scrollController),
+ )
+ ],
+ ),
+ ),
+ ],
+ ),
),
);
}
@@ -295,8 +309,7 @@ class _FileManagerPageState extends State
});
return;
}
- _jumpToEntry(
- isLocal, searchResult.first, scrollController,
+ _jumpToEntry(isLocal, searchResult.first, scrollController,
kDesktopFileTransferRowHeight, buffer);
},
onSearch: (buffer) {
@@ -311,8 +324,7 @@ class _FileManagerPageState extends State
});
return;
}
- _jumpToEntry(
- isLocal, searchResult.first, scrollController,
+ _jumpToEntry(isLocal, searchResult.first, scrollController,
kDesktopFileTransferRowHeight, buffer);
},
child: ObxValue(
@@ -323,100 +335,115 @@ class _FileManagerPageState extends State
}).toList(growable: false)
: entries;
final rows = filteredEntries.map((entry) {
- final sizeStr =
- entry.isFile ? readableFileSize(entry.size.toDouble()) : "";
- final lastModifiedStr = entry.isDrive
- ? " "
- : "${entry.lastModified().toString().replaceAll(".000", "")} ";
+ final sizeStr =
+ entry.isFile ? readableFileSize(entry.size.toDouble()) : "";
+ final lastModifiedStr = entry.isDrive
+ ? " "
+ : "${entry.lastModified().toString().replaceAll(".000", "")} ";
final isSelected = selectedEntries.contains(entry);
- return SizedBox(
- key: ValueKey(entry.name),
- height: kDesktopFileTransferRowHeight,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- const Divider(
- height: 1,
- ),
- Expanded(
- child: Ink(
- decoration: isSelected
- ? BoxDecoration(color: Theme.of(context).hoverColor)
- : null,
- child: InkWell(
- child: Row(children: [
- GestureDetector(
- child: Container(
- width: kDesktopFileTransferNameColWidth,
- child: Tooltip(
- waitDuration: Duration(milliseconds: 500),
- message: entry.name,
- child: Row(children: [
- entry.isDrive
- ? Image(
- image: iconHardDrive,
- fit: BoxFit.scaleDown,
- color: Theme.of(context)
- .iconTheme
- .color
- ?.withOpacity(0.7))
- .paddingAll(4)
- : Icon(
- entry.isFile
- ? Icons.feed_outlined
- : Icons.folder,
- size: 20,
- color: Theme.of(context)
- .iconTheme
- .color
- ?.withOpacity(0.7),
- ).marginSymmetric(horizontal: 2),
- Expanded(
- child: Text(entry.name.nonBreaking,
- overflow: TextOverflow.ellipsis))
- ]),
- )),
- onTap: () {
- final items = getSelectedItems(isLocal);
- // handle double click
- if (_checkDoubleClick(entry)) {
- openDirectory(entry.path, isLocal: isLocal);
- items.clear();
- return;
- }
- _onSelectedChanged(
- items, filteredEntries, entry, isLocal);
- },
- ),
- GestureDetector(
- child: SizedBox(
- width: kDesktopFileTransferModifiedColWidth,
- child: Tooltip(
- waitDuration: Duration(milliseconds: 500),
- message: lastModifiedStr,
- child: Text(
- lastModifiedStr,
- style: TextStyle(
- fontSize: 12, color: MyTheme.darkGray),
- )),
- )),
- GestureDetector(
- child: Tooltip(
- waitDuration: Duration(milliseconds: 500),
- message: sizeStr,
- child: Text(
- sizeStr,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- fontSize: 10,
- color: MyTheme.darkGray),
- ))),
- ]),
- ),
+ return Padding(
+ padding: EdgeInsets.symmetric(vertical: 1),
+ child: Container(
+ decoration: BoxDecoration(
+ color: isSelected
+ ? Theme.of(context).hoverColor
+ : Theme.of(context).cardColor,
+ borderRadius: BorderRadius.all(
+ Radius.circular(5.0),
),
),
- ],
- ),
+ key: ValueKey(entry.name),
+ height: kDesktopFileTransferRowHeight,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ Expanded(
+ child: InkWell(
+ child: Row(
+ children: [
+ GestureDetector(
+ child: Container(
+ width: kDesktopFileTransferNameColWidth,
+ child: Tooltip(
+ waitDuration:
+ Duration(milliseconds: 500),
+ message: entry.name,
+ child: Row(children: [
+ entry.isDrive
+ ? Image(
+ image: iconHardDrive,
+ fit: BoxFit.scaleDown,
+ color: Theme.of(context)
+ .iconTheme
+ .color
+ ?.withOpacity(0.7))
+ .paddingAll(4)
+ : SvgPicture.asset(
+ entry.isFile
+ ? "assets/file.svg"
+ : "assets/folder.svg",
+ color: Theme.of(context)
+ .tabBarTheme
+ .labelColor,
+ ),
+ Expanded(
+ child: Text(
+ entry.name.nonBreaking,
+ overflow:
+ TextOverflow.ellipsis))
+ ]),
+ )),
+ onTap: () {
+ final items = getSelectedItems(isLocal);
+ // handle double click
+ if (_checkDoubleClick(entry)) {
+ openDirectory(entry.path,
+ isLocal: isLocal);
+ items.clear();
+ return;
+ }
+ _onSelectedChanged(
+ items, filteredEntries, entry, isLocal);
+ },
+ ),
+ GestureDetector(
+ child: SizedBox(
+ width: kDesktopFileTransferModifiedColWidth,
+ child: Tooltip(
+ waitDuration:
+ Duration(milliseconds: 500),
+ message: lastModifiedStr,
+ child: Text(
+ lastModifiedStr,
+ style: TextStyle(
+ fontSize: 12,
+ color: MyTheme.darkGray,
+ ),
+ )),
+ ),
+ ),
+ SizedBox(
+ width: 100,
+ child: GestureDetector(
+ child: Tooltip(
+ waitDuration: Duration(milliseconds: 500),
+ message: sizeStr,
+ child: Text(
+ sizeStr,
+ overflow: TextOverflow.ellipsis,
+ style: TextStyle(
+ fontSize: 10,
+ color: MyTheme.darkGray),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ )),
);
}).toList(growable: false);
@@ -520,98 +547,156 @@ class _FileManagerPageState extends State
Widget statusList() {
return PreferredSize(
preferredSize: const Size(200, double.infinity),
- child: Container(
- margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
- padding: const EdgeInsets.all(8.0),
- decoration: BoxDecoration(border: Border.all(color: Colors.grey)),
- child: Obx(
- () => ListView.builder(
- controller: ScrollController(),
- itemBuilder: (BuildContext context, int index) {
- final item = model.jobTable[index];
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Transform.rotate(
- angle: item.isRemote ? pi : 0,
- child: const Icon(Icons.send)),
- const SizedBox(
- width: 16.0,
- ),
- Expanded(
+ child: model.jobTable.isEmpty
+ ? Center(child: Text(translate("Empty")))
+ : Container(
+ margin:
+ const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
+ padding: const EdgeInsets.all(8.0),
+ child: Obx(
+ () => ListView.builder(
+ controller: ScrollController(),
+ itemBuilder: (BuildContext context, int index) {
+ final item = model.jobTable[index];
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 5),
+ child: Container(
+ decoration: BoxDecoration(
+ color: Theme.of(context).cardColor,
+ borderRadius: BorderRadius.all(
+ Radius.circular(15.0),
+ ),
+ ),
child: Column(
mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Tooltip(
- waitDuration: Duration(milliseconds: 500),
- message: item.jobName,
- child: Text(
- item.jobName,
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- )),
- Wrap(
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Text(
- '${item.display()} ${max(0, item.fileNum)}/${item.fileCount} '),
- Text(
- '${translate("files")} ${readableFileSize(item.totalSize.toDouble())} '),
- Offstage(
- offstage:
- item.state != JobState.inProgress,
- child: Text(
- '${"${readableFileSize(item.speed)}/s"} ')),
- Offstage(
- offstage: item.totalSize <= 0,
- child: Text(
- '${(item.finishedSize.toDouble() * 100 / item.totalSize.toDouble()).toStringAsFixed(2)}%'),
+ Transform.rotate(
+ angle: item.isRemote ? pi : 0,
+ child: SvgPicture.asset(
+ "assets/arrow.svg",
+ color: Theme.of(context)
+ .tabBarTheme
+ .labelColor,
+ ),
+ ).paddingOnly(left: 15),
+ const SizedBox(
+ width: 16.0,
+ ),
+ Expanded(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Tooltip(
+ waitDuration:
+ Duration(milliseconds: 500),
+ message: item.jobName,
+ child: Text(
+ item.jobName,
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ).paddingSymmetric(vertical: 10),
+ ),
+ Text(
+ '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}',
+ style: TextStyle(
+ fontSize: 12,
+ color: MyTheme.darkGray,
+ ),
+ ),
+ Offstage(
+ offstage:
+ item.state != JobState.inProgress,
+ child: Text(
+ '${translate("Speed")} ${readableFileSize(item.speed)}/s',
+ style: TextStyle(
+ fontSize: 12,
+ color: MyTheme.darkGray,
+ ),
+ ),
+ ),
+ Offstage(
+ offstage:
+ item.state == JobState.inProgress,
+ child: Text(
+ translate(
+ item.display(),
+ ),
+ style: TextStyle(
+ fontSize: 12,
+ color: MyTheme.darkGray,
+ ),
+ ),
+ ),
+ Offstage(
+ offstage:
+ item.state != JobState.inProgress,
+ child: LinearPercentIndicator(
+ padding: EdgeInsets.only(right: 15),
+ animateFromLastPercent: true,
+ center: Text(
+ '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%',
+ ),
+ barRadius: Radius.circular(15),
+ percent: item.finishedSize /
+ item.totalSize,
+ progressColor: MyTheme.accent,
+ backgroundColor:
+ Theme.of(context).hoverColor,
+ lineHeight:
+ kDesktopFileTransferRowHeight,
+ ).paddingSymmetric(vertical: 15),
+ ),
+ ],
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Offstage(
+ offstage: item.state != JobState.paused,
+ child: MenuButton(
+ onPressed: () {
+ model.resumeJob(item.id);
+ },
+ child: SvgPicture.asset(
+ "assets/refresh.svg",
+ color: Colors.white,
+ ),
+ color: MyTheme.accent,
+ hoverColor: MyTheme.accent80,
+ ),
+ ),
+ MenuButton(
+ padding: EdgeInsets.only(right: 15),
+ child: SvgPicture.asset(
+ "assets/close.svg",
+ color: Colors.white,
+ ),
+ onPressed: () {
+ model.jobTable.removeAt(index);
+ model.cancelJob(item.id);
+ },
+ color: MyTheme.accent,
+ hoverColor: MyTheme.accent80,
+ ),
+ ],
),
],
),
],
- ),
+ ).paddingSymmetric(vertical: 10),
),
- Row(
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- Offstage(
- offstage: item.state != JobState.paused,
- child: IconButton(
- onPressed: () {
- model.resumeJob(item.id);
- },
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: const Icon(Icons.restart_alt_rounded)),
- ),
- IconButton(
- icon: const Icon(Icons.close),
- splashRadius: 1,
- onPressed: () {
- model.jobTable.removeAt(index);
- model.cancelJob(item.id);
- },
- ),
- ],
- )
- ],
- ),
- SizedBox(
- height: 8.0,
- ),
- Divider(
- height: 2.0,
- )
- ],
- );
- },
- itemCount: model.jobTable.length,
- ),
- ),
- ));
+ );
+ },
+ itemCount: model.jobTable.length,
+ ),
+ ),
+ ));
}
Widget headTools(bool isLocal) {
@@ -620,95 +705,128 @@ class _FileManagerPageState extends State
final locationFocus = isLocal ? _locationNodeLocal : _locationNodeRemote;
final selectedItems = getSelectedItems(isLocal);
return Container(
- child: Column(
- children: [
- // symbols
- PreferredSize(
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Container(
- width: 50,
- height: 50,
- decoration: BoxDecoration(color: Colors.blue),
- padding: EdgeInsets.all(8.0),
- child: FutureBuilder(
- future: bind.sessionGetPlatform(
- id: _ffi.id, isRemote: !isLocal),
- builder: (context, snapshot) {
- if (snapshot.hasData && snapshot.data!.isNotEmpty) {
- return getPlatformImage('${snapshot.data}');
- } else {
- return CircularProgressIndicator(
- color: Colors.white,
- );
- }
- })),
- Text(isLocal
- ? translate("Local Computer")
- : translate("Remote Computer"))
- .marginOnly(left: 8.0)
- ],
- ),
- preferredSize: Size(double.infinity, 70)),
- // buttons
- Row(
- children: [
- Row(
- children: [
- IconButton(
- icon: const Icon(Icons.arrow_back),
- splashRadius: kDesktopIconButtonSplashRadius,
- onPressed: () {
- selectedItems.clear();
- model.goBack(isLocal: isLocal);
- },
- ),
- IconButton(
- icon: const Icon(Icons.arrow_upward),
- splashRadius: kDesktopIconButtonSplashRadius,
- onPressed: () {
- selectedItems.clear();
- model.goToParentDirectory(isLocal: isLocal);
- },
- ),
- ],
- ),
- Expanded(
- child: GestureDetector(
- onTap: () {
- locationStatus.value =
- locationStatus.value == LocationStatus.bread
- ? LocationStatus.pathLocation
- : LocationStatus.bread;
- Future.delayed(Duration.zero, () {
- if (locationStatus.value == LocationStatus.pathLocation) {
- locationFocus.requestFocus();
- }
- });
- },
- child: Obx(() => Container(
- decoration: BoxDecoration(
- border: Border.all(
- color: locationStatus.value == LocationStatus.bread
- ? Colors.black12
- : Theme.of(context)
- .colorScheme
- .primary
- .withOpacity(0.5))),
+ child: Column(
+ children: [
+ // symbols
+ PreferredSize(
child: Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Expanded(
- child: locationStatus.value == LocationStatus.bread
- ? buildBread(isLocal)
- : buildPathLocation(isLocal)),
+ Container(
+ width: 50,
+ height: 50,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(8)),
+ color: MyTheme.accent,
+ ),
+ padding: EdgeInsets.all(8.0),
+ child: FutureBuilder(
+ future: bind.sessionGetPlatform(
+ id: _ffi.id, isRemote: !isLocal),
+ builder: (context, snapshot) {
+ if (snapshot.hasData &&
+ snapshot.data!.isNotEmpty) {
+ return getPlatformImage('${snapshot.data}');
+ } else {
+ return CircularProgressIndicator(
+ color: Theme.of(context)
+ .tabBarTheme
+ .labelColor,
+ );
+ }
+ })),
+ Text(isLocal
+ ? translate("Local Computer")
+ : translate("Remote Computer"))
+ .marginOnly(left: 8.0)
],
- ))),
- )),
- Obx(() {
- switch (locationStatus.value) {
- case LocationStatus.bread:
- return IconButton(
+ ),
+ preferredSize: Size(double.infinity, 70))
+ .paddingOnly(bottom: 15),
+ // buttons
+ Row(
+ children: [
+ Row(
+ children: [
+ MenuButton(
+ padding: EdgeInsets.only(
+ right: 3,
+ ),
+ child: SvgPicture.asset(
+ "assets/arrow.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ onPressed: () {
+ selectedItems.clear();
+ model.goBack(isLocal: isLocal);
+ },
+ ),
+ MenuButton(
+ child: RotatedBox(
+ quarterTurns: 3,
+ child: SvgPicture.asset(
+ "assets/arrow.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ onPressed: () {
+ selectedItems.clear();
+ model.goToParentDirectory(isLocal: isLocal);
+ },
+ ),
+ ],
+ ),
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 3.0),
+ child: Container(
+ decoration: BoxDecoration(
+ color: Theme.of(context).cardColor,
+ borderRadius: BorderRadius.all(
+ Radius.circular(8.0),
+ ),
+ ),
+ child: Padding(
+ padding: EdgeInsets.symmetric(vertical: 2.5),
+ child: GestureDetector(
+ onTap: () {
+ locationStatus.value =
+ locationStatus.value == LocationStatus.bread
+ ? LocationStatus.pathLocation
+ : LocationStatus.bread;
+ Future.delayed(Duration.zero, () {
+ if (locationStatus.value ==
+ LocationStatus.pathLocation) {
+ locationFocus.requestFocus();
+ }
+ });
+ },
+ child: Obx(
+ () => Container(
+ child: Row(
+ children: [
+ Expanded(
+ child: locationStatus.value ==
+ LocationStatus.bread
+ ? buildBread(isLocal)
+ : buildPathLocation(isLocal)),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Obx(() {
+ switch (locationStatus.value) {
+ case LocationStatus.bread:
+ return MenuButton(
onPressed: () {
locationStatus.value = LocationStatus.fileSearchBar;
final focusNode =
@@ -716,49 +834,77 @@ class _FileManagerPageState extends State
Future.delayed(
Duration.zero, () => focusNode.requestFocus());
},
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: Icon(Icons.search));
- case LocationStatus.pathLocation:
- return IconButton(
- color: Theme.of(context).disabledColor,
+ child: SvgPicture.asset(
+ "assets/search.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ );
+ case LocationStatus.pathLocation:
+ return MenuButton(
onPressed: null,
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: Icon(Icons.close));
- case LocationStatus.fileSearchBar:
- return IconButton(
+ child: SvgPicture.asset(
+ "assets/close.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
color: Theme.of(context).disabledColor,
+ hoverColor: Theme.of(context).hoverColor,
+ );
+ case LocationStatus.fileSearchBar:
+ return MenuButton(
onPressed: () {
onSearchText("", isLocal);
locationStatus.value = LocationStatus.bread;
},
- splashRadius: 1,
- icon: Icon(Icons.close));
- }
- }),
- IconButton(
+ child: SvgPicture.asset(
+ "assets/close.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ );
+ }
+ }),
+ MenuButton(
+ padding: EdgeInsets.only(
+ left: 3,
+ ),
onPressed: () {
model.refresh(isLocal: isLocal);
},
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: const Icon(Icons.refresh)),
- ],
- ),
- Row(
- textDirection: isLocal ? TextDirection.ltr : TextDirection.rtl,
- children: [
- Expanded(
- child: Row(
- mainAxisAlignment:
- isLocal ? MainAxisAlignment.start : MainAxisAlignment.end,
- children: [
- IconButton(
- onPressed: () {
- model.goHome(isLocal: isLocal);
- },
- icon: const Icon(Icons.home_outlined),
- splashRadius: kDesktopIconButtonSplashRadius,
- ),
- IconButton(
+ child: SvgPicture.asset(
+ "assets/refresh.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ ),
+ ],
+ ),
+ Row(
+ textDirection: isLocal ? TextDirection.ltr : TextDirection.rtl,
+ children: [
+ Expanded(
+ child: Row(
+ mainAxisAlignment:
+ isLocal ? MainAxisAlignment.start : MainAxisAlignment.end,
+ children: [
+ MenuButton(
+ padding: EdgeInsets.only(
+ right: 3,
+ ),
+ onPressed: () {
+ model.goHome(isLocal: isLocal);
+ },
+ child: SvgPicture.asset(
+ "assets/home.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ ),
+ MenuButton(
onPressed: () {
final name = TextEditingController();
_ffi.dialogManager.show((setState, close) {
@@ -800,9 +946,14 @@ class _FileManagerPageState extends State
);
});
},
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: const Icon(Icons.create_new_folder_outlined)),
- IconButton(
+ child: SvgPicture.asset(
+ "assets/folder_new.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ ),
+ MenuButton(
onPressed: validItems(selectedItems)
? () async {
await (model.removeAction(selectedItems,
@@ -810,32 +961,80 @@ class _FileManagerPageState extends State
selectedItems.clear();
}
: null,
- splashRadius: kDesktopIconButtonSplashRadius,
- icon: const Icon(Icons.delete_forever_outlined)),
- menu(isLocal: isLocal),
- ],
+ child: SvgPicture.asset(
+ "assets/trash.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ color: Theme.of(context).cardColor,
+ hoverColor: Theme.of(context).hoverColor,
+ ),
+ menu(isLocal: isLocal),
+ ],
+ ),
),
- ),
- TextButton.icon(
+ ElevatedButton.icon(
+ style: ButtonStyle(
+ padding: MaterialStateProperty.all(isLocal
+ ? EdgeInsets.only(left: 10)
+ : EdgeInsets.only(right: 10)),
+ backgroundColor: MaterialStateProperty.all(
+ selectedItems.length == 0
+ ? MyTheme.accent80
+ : MyTheme.accent,
+ ),
+ shape: MaterialStateProperty.all(
+ RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(18.0),
+ ),
+ ),
+ ),
onPressed: validItems(selectedItems)
? () {
model.sendFiles(selectedItems, isRemote: !isLocal);
selectedItems.clear();
}
: null,
- icon: Transform.rotate(
- angle: isLocal ? 0 : pi,
- child: const Icon(
- Icons.send,
- ),
- ),
- label: Text(
- isLocal ? translate('Send') : translate('Receive'),
- )),
- ],
- ).marginOnly(top: 8.0)
- ],
- ));
+ icon: isLocal
+ ? Text(
+ translate('Send'),
+ textAlign: TextAlign.right,
+ style: TextStyle(
+ color: selectedItems.length == 0
+ ? MyTheme.darkGray
+ : Colors.white,
+ ),
+ )
+ : RotatedBox(
+ quarterTurns: 2,
+ child: SvgPicture.asset(
+ "assets/arrow.svg",
+ color: selectedItems.length == 0
+ ? MyTheme.darkGray
+ : Colors.white,
+ alignment: Alignment.bottomRight,
+ ),
+ ),
+ label: isLocal
+ ? SvgPicture.asset(
+ "assets/arrow.svg",
+ color: selectedItems.length == 0
+ ? MyTheme.darkGray
+ : Colors.white,
+ )
+ : Text(
+ translate('Receive'),
+ style: TextStyle(
+ color: selectedItems.length == 0
+ ? MyTheme.darkGray
+ : Colors.white,
+ ),
+ ),
+ ),
+ ],
+ ).marginOnly(top: 8.0)
+ ],
+ ),
+ );
}
bool validItems(SelectedItems items) {
@@ -890,25 +1089,27 @@ class _FileManagerPageState extends State
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
- child: Listener(
- // handle mouse wheel
- onPointerSignal: (e) {
- if (e is PointerScrollEvent) {
- final sc = getBreadCrumbScrollController(isLocal);
- final scale = Platform.isWindows ? 2 : 4;
- sc.jumpTo(sc.offset + e.scrollDelta.dy / scale);
- }
- },
- child: BreadCrumb(
- items: items,
- divider: Icon(Icons.chevron_right),
- overflow: ScrollableOverflow(
- controller:
- getBreadCrumbScrollController(isLocal)),
- ))),
+ child: Listener(
+ // handle mouse wheel
+ onPointerSignal: (e) {
+ if (e is PointerScrollEvent) {
+ final sc = getBreadCrumbScrollController(isLocal);
+ final scale = Platform.isWindows ? 2 : 4;
+ sc.jumpTo(sc.offset + e.scrollDelta.dy / scale);
+ }
+ },
+ child: BreadCrumb(
+ items: items,
+ divider: const Icon(Icons.keyboard_arrow_right_rounded),
+ overflow: ScrollableOverflow(
+ controller: getBreadCrumbScrollController(isLocal),
+ ),
+ ),
+ ),
+ ),
ActionIcon(
message: "",
- icon: Icons.arrow_drop_down,
+ icon: Icons.keyboard_arrow_down_rounded,
onTap: () async {
final renderBox = locationBarKey.currentContext
?.findRenderObject() as RenderBox;
@@ -1021,13 +1222,23 @@ class _FileManagerPageState extends State
.marginSymmetric(horizontal: 4)));
} else {
final list = PathUtil.split(path, isWindows);
- breadCrumbList.addAll(list.asMap().entries.map((e) => BreadCrumbItem(
- content: TextButton(
+ breadCrumbList.addAll(
+ list.asMap().entries.map(
+ (e) => BreadCrumbItem(
+ content: TextButton(
child: Text(e.value),
style: ButtonStyle(
- minimumSize: MaterialStateProperty.all(Size(0, 0))),
- onPressed: () => onPressed(list.sublist(0, e.key + 1)))
- .marginSymmetric(horizontal: 4))));
+ minimumSize: MaterialStateProperty.all(
+ Size(0, 0),
+ ),
+ ),
+ onPressed: () => onPressed(
+ list.sublist(0, e.key + 1),
+ ),
+ ).marginSymmetric(horizontal: 4),
+ ),
+ ),
+ );
}
return breadCrumbList;
}
@@ -1054,29 +1265,35 @@ class _FileManagerPageState extends State
: searchTextObs.value;
final textController = TextEditingController(text: text)
..selection = TextSelection.collapsed(offset: text.length);
- return Row(children: [
- Icon(
- locationStatus.value == LocationStatus.pathLocation
- ? Icons.folder
- : Icons.search,
- color: Theme.of(context).hintColor,
- ).paddingSymmetric(horizontal: 2),
- Expanded(
+ return Row(
+ children: [
+ SvgPicture.asset(
+ locationStatus.value == LocationStatus.pathLocation
+ ? "assets/folder.svg"
+ : "assets/search.svg",
+ color: Theme.of(context).tabBarTheme.labelColor,
+ ),
+ Expanded(
child: TextField(
- focusNode: focusNode,
- decoration: InputDecoration(
- border: InputBorder.none,
- isDense: true,
- prefix: Padding(padding: EdgeInsets.only(left: 4.0))),
- controller: textController,
- onSubmitted: (path) {
- openDirectory(path, isLocal: isLocal);
- },
- onChanged: locationStatus.value == LocationStatus.fileSearchBar
- ? (searchText) => onSearchText(searchText, isLocal)
- : null,
- ))
- ]);
+ focusNode: focusNode,
+ decoration: InputDecoration(
+ border: InputBorder.none,
+ isDense: true,
+ prefix: Padding(
+ padding: EdgeInsets.only(left: 4.0),
+ ),
+ ),
+ controller: textController,
+ onSubmitted: (path) {
+ openDirectory(path, isLocal: isLocal);
+ },
+ onChanged: locationStatus.value == LocationStatus.fileSearchBar
+ ? (searchText) => onSearchText(searchText, isLocal)
+ : null,
+ ),
+ )
+ ],
+ );
}
onSearchText(String searchText, bool isLocal) {
@@ -1145,12 +1362,13 @@ class _FileManagerPageState extends State
Text(
name,
style: headerTextStyle,
- ).marginSymmetric(
- horizontal: sortBy == SortBy.name ? 4 : 0.0),
+ ).marginSymmetric(horizontal: 4),
ascending.value != null
- ? Icon(ascending.value!
- ? Icons.arrow_upward
- : Icons.arrow_downward)
+ ? Icon(
+ ascending.value!
+ ? Icons.keyboard_arrow_up_rounded
+ : Icons.keyboard_arrow_down_rounded,
+ )
: const Offstage()
],
),
diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart
index 7540f7662..bbe2b28be 100644
--- a/flutter/lib/desktop/pages/file_manager_tab_page.dart
+++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart
@@ -86,18 +86,14 @@ class _FileManagerTabPageState extends State {
@override
Widget build(BuildContext context) {
- final tabWidget = Container(
- decoration: BoxDecoration(
- border: Border.all(color: MyTheme.color(context).border!)),
- child: Scaffold(
- backgroundColor: Theme.of(context).backgroundColor,
- body: DesktopTab(
- controller: tabController,
- onWindowCloseButton: handleWindowCloseButton,
- tail: const AddButton().paddingOnly(left: 10),
- labelGetter: DesktopTab.labelGetterAlias,
- )),
- );
+ final tabWidget = Scaffold(
+ backgroundColor: Theme.of(context).cardColor,
+ body: DesktopTab(
+ controller: tabController,
+ onWindowCloseButton: handleWindowCloseButton,
+ tail: const AddButton().paddingOnly(left: 10),
+ labelGetter: DesktopTab.labelGetterAlias,
+ ));
return Platform.isMacOS
? tabWidget
: SubWindowDragToResizeArea(
diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart
index 96cc9fa9b..df2c48ab4 100644
--- a/flutter/lib/desktop/widgets/menu_button.dart
+++ b/flutter/lib/desktop/widgets/menu_button.dart
@@ -27,6 +27,7 @@ class MenuButton extends StatefulWidget {
class _MenuButtonState extends State {
bool _isHover = false;
+ final double _borderRadius = 8.0;
@override
Widget build(BuildContext context) {
@@ -38,16 +39,17 @@ class _MenuButtonState extends State {
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(5),
+ borderRadius: BorderRadius.circular(_borderRadius),
color: _isHover ? widget.hoverColor : widget.color,
),
child: InkWell(
+ hoverColor: widget.hoverColor,
onHover: (val) {
setState(() {
_isHover = val;
});
},
- borderRadius: BorderRadius.circular(5),
+ borderRadius: BorderRadius.circular(_borderRadius),
splashColor: widget.splashColor,
enableFeedback: widget.enableFeedback,
onTap: widget.onPressed,
diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock
index e6ec0454d..a07df9c2e 100644
--- a/flutter/pubspec.lock
+++ b/flutter/pubspec.lock
@@ -325,8 +325,8 @@ packages:
dependency: "direct main"
description:
path: "."
- ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8
- resolved-ref: bc8604a88e52b2b6e64d2661ae49a71450a47af8
+ ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
+ resolved-ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
url: "https://github.com/Kingtous/rustdesk_desktop_multi_window"
source: git
version: "0.1.0"
@@ -970,6 +970,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.11.1"
+ percent_indicator:
+ dependency: "direct main"
+ description:
+ name: percent_indicator
+ sha256: cec41f67181fbd5322aa68b355621d1a4eea827426b8eeb613f6cbe195ff7b4a
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.2"
petitparser:
dependency: transitive
description:
@@ -1216,6 +1224,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
+ texture_rgba_renderer:
+ dependency: "direct main"
+ description:
+ name: texture_rgba_renderer
+ sha256: fbb09b2c6b4ce71261927f9e7e4ea339af3e2f3f2b175f6fb921de1c66ec848d
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.0.8"
timing:
dependency: transitive
description:
diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml
index e009ea890..572b3e20a 100644
--- a/flutter/pubspec.yaml
+++ b/flutter/pubspec.yaml
@@ -19,156 +19,153 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.2.0
environment:
- sdk: ">=2.17.0"
+ sdk: ">=2.17.0"
dependencies:
- flutter:
- sdk: flutter
- flutter_localizations:
- sdk: flutter
-
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^1.0.3
- ffi: ^2.0.1
- path_provider: ^2.0.12
- external_path: ^1.0.1
- provider: ^6.0.3
- tuple: ^2.0.0
- wakelock: ^0.6.2
- device_info_plus: ^4.1.2
- #firebase_analytics: ^9.1.5
- package_info_plus: ^1.4.2
- url_launcher: ^6.0.9
- toggle_switch: ^1.4.0
- dash_chat_2: ^0.0.14
- draggable_float_widget: ^0.0.2
- settings_ui: ^2.0.2
- flutter_breadcrumb: ^1.0.1
- http: ^0.13.4
- qr_code_scanner: ^1.0.0
- zxing2: ^0.1.0
- image_picker: ^0.8.5
- image: ^3.1.3
- back_button_interceptor: ^6.0.1
- flutter_rust_bridge: ^1.61.1
- window_manager:
- git:
- url: https://github.com/Kingtous/rustdesk_window_manager
- ref: 32b24c66151b72bba033ef8b954486aa9351d97b
- desktop_multi_window:
- git:
- url: https://github.com/Kingtous/rustdesk_desktop_multi_window
- ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
- freezed_annotation: ^2.0.3
- flutter_custom_cursor: ^0.0.4
- window_size:
- git:
- url: https://github.com/google/flutter-desktop-embedding.git
- path: plugins/window_size
- ref: a738913c8ce2c9f47515382d40827e794a334274
- get: ^4.6.5
- visibility_detector: ^0.3.3
- contextmenu: ^3.0.0
- desktop_drop: ^0.3.3
- scroll_pos: ^0.3.0
- debounce_throttle: ^2.0.0
- file_picker: ^5.1.0
- flutter_svg: ^1.1.5
- flutter_improved_scrolling:
- # currently, we use flutter 3.0.5 for windows build, latest for other builds.
- #
- # for flutter 3.0.5, please use official version(just comment code below).
- # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below).
- git:
- url: https://github.com/Kingtous/flutter_improved_scrolling
- ref: 62f09545149f320616467c306c8c5f71714a18e6
- uni_links: ^0.5.1
- uni_links_desktop: ^0.1.4
- path: ^1.8.1
- auto_size_text: ^3.0.0
- bot_toast: ^4.0.3
- win32: any
- password_strength: ^0.2.0
- flutter_launcher_icons: ^0.11.0
- flutter_keyboard_visibility: ^5.4.0
- texture_rgba_renderer: ^0.0.8
+ flutter:
+ sdk: flutter
+ flutter_localizations:
+ sdk: flutter
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.3
+ ffi: ^2.0.1
+ path_provider: ^2.0.12
+ external_path: ^1.0.1
+ provider: ^6.0.3
+ tuple: ^2.0.0
+ wakelock: ^0.6.2
+ device_info_plus: ^4.1.2
+ #firebase_analytics: ^9.1.5
+ package_info_plus: ^1.4.2
+ url_launcher: ^6.0.9
+ toggle_switch: ^1.4.0
+ dash_chat_2: ^0.0.14
+ draggable_float_widget: ^0.0.2
+ settings_ui: ^2.0.2
+ flutter_breadcrumb: ^1.0.1
+ http: ^0.13.4
+ qr_code_scanner: ^1.0.0
+ zxing2: ^0.1.0
+ image_picker: ^0.8.5
+ image: ^3.1.3
+ back_button_interceptor: ^6.0.1
+ flutter_rust_bridge: ^1.61.1
+ window_manager:
+ git:
+ url: https://github.com/Kingtous/rustdesk_window_manager
+ ref: 32b24c66151b72bba033ef8b954486aa9351d97b
+ desktop_multi_window:
+ git:
+ url: https://github.com/Kingtous/rustdesk_desktop_multi_window
+ ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a
+ freezed_annotation: ^2.0.3
+ flutter_custom_cursor: ^0.0.4
+ window_size:
+ git:
+ url: https://github.com/google/flutter-desktop-embedding.git
+ path: plugins/window_size
+ ref: a738913c8ce2c9f47515382d40827e794a334274
+ get: ^4.6.5
+ visibility_detector: ^0.3.3
+ contextmenu: ^3.0.0
+ desktop_drop: ^0.3.3
+ scroll_pos: ^0.3.0
+ debounce_throttle: ^2.0.0
+ file_picker: ^5.1.0
+ flutter_svg: ^1.1.5
+ flutter_improved_scrolling:
+ # currently, we use flutter 3.0.5 for windows build, latest for other builds.
+ #
+ # for flutter 3.0.5, please use official version(just comment code below).
+ # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below).
+ git:
+ url: https://github.com/Kingtous/flutter_improved_scrolling
+ ref: 62f09545149f320616467c306c8c5f71714a18e6
+ uni_links: ^0.5.1
+ uni_links_desktop: ^0.1.4
+ path: ^1.8.1
+ auto_size_text: ^3.0.0
+ bot_toast: ^4.0.3
+ win32: any
+ password_strength: ^0.2.0
+ flutter_launcher_icons: ^0.11.0
+ flutter_keyboard_visibility: ^5.4.0
+ texture_rgba_renderer: ^0.0.8
+ percent_indicator: ^4.2.2
dev_dependencies:
- icons_launcher: ^2.0.4
- #flutter_test:
- #sdk: flutter
- build_runner: ^2.1.11
- freezed: ^2.0.3
- flutter_lints: ^2.0.0
- ffigen: ^7.2.4
+ icons_launcher: ^2.0.4
+ #flutter_test:
+ #sdk: flutter
+ build_runner: ^2.1.11
+ freezed: ^2.0.3
+ flutter_lints: ^2.0.0
+ ffigen: ^7.2.4
# rerun: flutter pub run flutter_launcher_icons
flutter_icons:
- image_path: "../res/icon.png"
- remove_alpha_ios: true
- android: true
- ios: true
- windows:
- generate: true
- macos:
- image_path: "../res/mac-icon.png"
- generate: true
- linux: true
- web:
- generate: true
-
+ image_path: "../res/icon.png"
+ remove_alpha_ios: true
+ android: true
+ ios: true
+ windows:
+ generate: true
+ macos:
+ image_path: "../res/mac-icon.png"
+ generate: true
+ linux: true
+ web:
+ generate: true
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
- # The following line ensures that the Material Icons font is
- # included with your application, so that you can use the icons in
- # the material Icons class.
- uses-material-design: true
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
- # To add assets to your application, add an assets section, like this:
- assets:
- - assets/
+ # To add assets to your application, add an assets section, like this:
+ assets:
+ - assets/
- fonts:
- - family: GestureIcons
- fonts:
- - asset: assets/gestures.ttf
- - family: Tabbar
- fonts:
- - asset: assets/tabbar.ttf
- - family: PeerSearchbar
- fonts:
- - asset: assets/peer_searchbar.ttf
+ fonts:
+ - family: GestureIcons
+ fonts:
+ - asset: assets/gestures.ttf
+ - family: Tabbar
+ fonts:
+ - asset: assets/tabbar.ttf
+ - family: PeerSearchbar
+ fonts:
+ - asset: assets/peer_searchbar.ttf
-
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware.
- # An image asset can refer to one or more resolution-specific "variants", see
- # https://flutter.dev/assets-and-images/#resolution-aware.
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
- # For details regarding adding assets from package dependencies, see
- # https://flutter.dev/assets-and-images/#from-packages
-
- # To add custom fonts to your application, add a fonts section here,
- # in this "flutter" section. Each entry in this list should have a
- # "family" key with the font family name, and a "fonts" key with a
- # list giving the asset and other descriptors for the font. For
- # example:
- # fonts:
- # - family: Schyler
- # fonts:
- # - asset: fonts/Schyler-Regular.ttf
- # - asset: fonts/Schyler-Italic.ttf
- # style: italic
- # - family: Trajan Pro
- # fonts:
- # - asset: fonts/TrajanPro.ttf
- # - asset: fonts/TrajanPro_Bold.ttf
- # weight: 700
- #
- # For details regarding fonts from package dependencies,
- # see https://flutter.dev/custom-fonts/#from-packages
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages