Skip to content

Commit 335ee8a

Browse files
committed
桌面版页面开发
1 parent c004d65 commit 335ee8a

Some content is hidden

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

46 files changed

+823
-148
lines changed

README.en.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
flutter视频下载工具
55

66
### generate icons command
7+
`flutter pub run flutter_launcher_icons:main`
78

8-
# flutter pub run flutter_launcher_icons:main
9+
### fix 无法打开‘iproxy’ 因为无法验证开发者
10+
`sudo xattr -d com.apple.quarantine /Users/Waiting/Library/flutter/bin/cache/artifacts/usbmuxd/iproxy`
11+
`sudo xattr -d com.apple.quarantine /Users/Waiting/Library/flutter-2.10.0/bin/cache/artifacts/usbmuxd/iproxy`

README.md

+12-21
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,18 @@ TubeSavely - Video downloader 支持tiktok、 抖音快手、小红书
1212
Free downloader to fast download all videos from social webs.
1313

1414
#应用介绍:
15-
最简单的视频下载,支持99%短视频平台一键解析下载。
16-
您可以在手机图库中保存TikTok视频,并随时离线查看。我们根本不使用TikTok API,因此您不必担心提供登录详细信息,这是一个专门的TikToks视频保护程序和照片保护程序
17-
他们的应用程序上有3亿以上的用户,这些用户每天都在创作美丽的音乐视频。像该应用程序这样的抖音视频创作社交网络允许你浏览短视频笑话和搞笑视频、喜剧视频、音乐、娱乐和标签,但你不能下载没有水印的抖音。
18-
该应用程序的功能:-
19-
-下载无水印的抖音视频。
20-
-从您的任何TikTok视频中删除水印。
21-
-通过复制URL下载音乐视频
22-
-粘贴链接到抖音视频下载
23-
-安全轻便的抖音下载器
24-
-高清快速抖音视频下载
25-
-超快速保存视频。支持下载速度提升。
26-
-这是一个用于TikTok视频下载的工具。
27-
-非常简单快速保存TikTok视频
28-
图片去水印、视频剪辑、视频变速、视频转GIF、最佳短视频创作软件
29-
根据TikTok和Vine用户版权程序,如果你想转发它们,你需要获得所有者的许可。
30-
31-
免责声明:
32-
*在转发视频或照片之前,请获得所有者的许可。
33-
*我们不对因未经授权转发视频或照片而导致的任何侵犯知识产权行为负责。
34-
*我们尊重TikTok的权利。
35-
*此应用程序未与TikTok关联。
15+
【海量平台,一网打尽】
16+
TubeSavely自豪地支持超过1800个国内外主流及小众视频平台,覆盖YouTube、Instagram、TikTok、Bilibili、Vimeo等热门站点,甚至是那些鲜为人知的专业领域平台。无论您钟情于哪个角落的精彩,TubeSavely都能成为您的专属桥梁,一键下载,轻松收藏。
17+
【高清画质,随心选择】
18+
质量决定体验,TubeSavely深谙其道。我们提供从标清到超高清的多种分辨率选择,满足不同场景下的观看需求。不论是手机小屏的便捷浏览,还是大屏电视的沉浸享受,TubeSavely都能确保您下载的每一帧都清晰流畅,视觉享受不受限。
19+
【高速下载,省时省心】
20+
采用先进的多线程下载技术,TubeSavely极大地缩短了下载时间,即使面对超大体积的视频文件也能迅速完成。告别漫长等待,让精彩内容即刻呈现,享受即下即看的畅快体验。
21+
【界面友好,操作简便】
22+
TubeSavely的设计理念在于简化操作,提升效率。简洁直观的用户界面,即便是初次接触的用户也能迅速上手。只需复制视频链接,粘贴到TubeSavely,剩下的交给我们的智能解析引擎,一键启动下载,轻松到不可思议。
23+
【安全无忧,尊重版权】
24+
我们深知版权的重要性,TubeSavely严格遵守各平台的使用条款,确保所有下载行为合法合规。同时,我们重视用户隐私,不会保存或传输任何个人数据,让您在享受便利的同时,也能安心无忧。
25+
【跨平台支持,随时随地】
26+
无论是Windows、macOS,还是Android、iOS,TubeSavely都致力于提供全面的平台支持,确保您在任意设备上都能享受到一致的优质服务。无论在家、办公室,还是旅途之中,精彩视频随身携带,灵感和欢乐永不间断。
3627

3728
#应用一句话简介:
3829
视频下载器-无水印、高清、免费!

android/local.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
sdk.dir=/Users/Waiting/Library/Android/sdk
22
flutter.sdk=/Users/Waiting/Library/flutter
3-
flutter.buildMode=debug
3+
flutter.buildMode=release
44
flutter.versionName=1.0.0
5-
flutter.versionCode=1
5+
flutter.versionCode=3

assets/ic_logo_216.png

10.1 KB
Loading

lib/downloader/downloader.dart

+27-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:image_gallery_saver/image_gallery_saver.dart';
1212
import 'package:open_file/open_file.dart';
1313
import 'package:path/path.dart' as path;
1414
import 'package:path_provider/path_provider.dart';
15+
import 'package:tubesavely/utils/platform_util.dart';
1516
import 'package:tubesavely/utils/toast_util.dart';
1617

1718
class Downloader {
@@ -114,7 +115,8 @@ class Downloader {
114115
final task = DownloadTask(
115116
url: url ?? '',
116117
filename: fileName,
117-
directory: 'TubeSavely/Files',
118+
// directory: 'TubeSavely/Files',
119+
directory: (await getDownloadsDirectory())?.path ?? '',
118120
baseDirectory: BaseDirectory.temporary,
119121
updates: Updates.statusAndProgress,
120122
requiresWiFi: false,
@@ -170,7 +172,9 @@ class Downloader {
170172
final task = DownloadTask(
171173
url: url ?? '',
172174
filename: '$fileName.mp4',
173-
directory: 'TubeSavely/Files',
175+
// directory: 'TubeSavely/Files',
176+
// baseDirectory: BaseDirectory.applicationDocuments,
177+
directory: (await getDownloadsDirectory())?.path ?? '',
174178
updates: Updates.statusAndProgress,
175179
requiresWiFi: false,
176180
retries: 5,
@@ -184,11 +188,27 @@ class Downloader {
184188

185189
switch (result.status) {
186190
case TaskStatus.complete:
187-
var result = await ImageGallerySaver.saveFile(await task.filePath(), name: fileName, isReturnPathOfIOS: true);
188-
if (result['isSuccess']) {
189-
ToastUtil.success('Download Success');
190-
} else {
191-
ToastUtil.error(result['errorMessage']);
191+
if (PlatformUtils.isMacOS) {
192+
try {
193+
// 获取文档目录路径
194+
Directory? appDocDir = await getDownloadsDirectory();
195+
196+
// 文件名和路径
197+
String filePath = await task.filePath();
198+
199+
print('文件名: $fileName');
200+
print('文件已保存至: $filePath');
201+
} catch (e) {
202+
print('保存文件时发生错误: $e');
203+
}
204+
}
205+
if (PlatformUtils.isMobile) {
206+
var result = await ImageGallerySaver.saveFile(await task.filePath(), name: fileName, isReturnPathOfIOS: true);
207+
if (result['isSuccess']) {
208+
ToastUtil.success('Download Success');
209+
} else {
210+
ToastUtil.error(result['errorMessage']);
211+
}
192212
}
193213
case TaskStatus.canceled:
194214
debugPrint('Download was canceled');

lib/main.dart

+33-17
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,45 @@
1-
import 'dart:ui';
2-
31
import 'package:flutter/material.dart';
42
import 'package:flutter/services.dart';
3+
import 'package:flutter_easyloading/flutter_easyloading.dart';
54
import 'package:flutter_screenutil/flutter_screenutil.dart';
65
import 'package:media_kit/media_kit.dart';
7-
import 'package:tubesavely/pages/feedback_page.dart';
8-
import 'package:tubesavely/pages/history_page.dart';
9-
import 'package:tubesavely/pages/home_page.dart';
10-
import 'package:tubesavely/pages/more_page.dart';
11-
import 'package:tubesavely/pages/splash_page.dart';
12-
import 'package:tubesavely/pages/task_page.dart';
6+
import 'package:tubesavely/screen/desktop/main.dart';
7+
import 'package:tubesavely/screen/mobile/pages/feedback_page.dart';
8+
import 'package:tubesavely/screen/mobile/pages/history_page.dart';
9+
import 'package:tubesavely/screen/mobile/pages/home_page.dart';
10+
import 'package:tubesavely/screen/mobile/pages/more_page.dart';
11+
import 'package:tubesavely/screen/mobile/pages/splash_page.dart';
12+
import 'package:tubesavely/screen/mobile/pages/task_page.dart';
1313
import 'package:tubesavely/theme/app_theme.dart';
14+
import 'package:tubesavely/utils/platform_util.dart';
1415
import 'package:tubesavely/widget/drawer_controller.dart';
1516
import 'package:tubesavely/widget/slide_drawer.dart';
17+
import 'package:window_manager/window_manager.dart';
1618

1719
void main() async {
18-
await ScreenUtil.ensureScreenSize();
19-
_loadShader();
20-
MediaKit.ensureInitialized();
21-
runApp(const MyApp());
22-
}
20+
WidgetsFlutterBinding.ensureInitialized();
2321

24-
Future<void> _loadShader() async {
25-
return FragmentProgram.fromAsset('assets/shaders/shader.frag').then((FragmentProgram prgm) {
26-
SplashPage.shader = prgm.fragmentShader();
27-
}, onError: (Object error, StackTrace stackTrace) {});
22+
if (PlatformUtils.isMobile) {
23+
await ScreenUtil.ensureScreenSize();
24+
MediaKit.ensureInitialized();
25+
runApp(const MyApp());
26+
} else {
27+
windowManager.ensureInitialized();
28+
WindowOptions windowOptions = const WindowOptions(
29+
size: Size(950, 650),
30+
minimumSize: Size(800, 550),
31+
center: true,
32+
backgroundColor: Colors.transparent,
33+
windowButtonVisibility: true,
34+
skipTaskbar: false,
35+
titleBarStyle: TitleBarStyle.hidden,
36+
);
37+
windowManager.waitUntilReadyToShow(windowOptions, () async {
38+
await windowManager.show();
39+
await windowManager.focus();
40+
});
41+
runApp(const DesktopApp());
42+
}
2843
}
2944

3045
class MyApp extends StatefulWidget {
@@ -47,6 +62,7 @@ class _MyAppState extends State<MyApp> {
4762
useMaterial3: true,
4863
),
4964
home: const SplashPage(),
65+
builder: EasyLoading.init(),
5066
);
5167
}
5268
}
File renamed without changes.
File renamed without changes.

lib/screen/desktop/main.dart

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_easyloading/flutter_easyloading.dart';
3+
import 'package:tubesavely/screen/desktop/pages/home_page.dart';
4+
5+
class DesktopApp extends StatefulWidget {
6+
const DesktopApp({super.key});
7+
8+
@override
9+
State<StatefulWidget> createState() => _DesktopAppState();
10+
}
11+
12+
class _DesktopAppState extends State<DesktopApp> {
13+
@override
14+
Widget build(BuildContext context) {
15+
return MaterialApp(
16+
debugShowCheckedModeBanner: false,
17+
color: Colors.black,
18+
// builder: (BuildContext context, Widget? child) {
19+
// return const HomePage();
20+
// },
21+
builder: EasyLoading.init(),
22+
home: const HomePage(),
23+
);
24+
}
25+
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:package_info_plus/package_info_plus.dart';
3+
4+
class AboutPage extends StatelessWidget {
5+
const AboutPage({super.key});
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
return Center(
10+
child: Container(
11+
// width: 450,
12+
// padding: const EdgeInsets.all(20),
13+
child: Column(
14+
children: [
15+
const SizedBox(width: 150, height: 100, child: Image(image: AssetImage('assets/ic_logo.png'))),
16+
const Text(
17+
'TubeSavely',
18+
style: TextStyle(fontSize: 20),
19+
),
20+
FutureBuilder<PackageInfo>(
21+
future: PackageInfo.fromPlatform(),
22+
builder: (context, snapshot) {
23+
return Text(
24+
'Version ${snapshot.data?.version}',
25+
style: const TextStyle(fontSize: 12, color: Colors.black45),
26+
);
27+
}),
28+
const SizedBox(height: 10),
29+
const Text(
30+
'这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍这是App介绍,很长的一段介绍',
31+
style: TextStyle(fontSize: 12, color: Colors.black45),
32+
),
33+
const SizedBox(height: 5),
34+
const Text(
35+
'Copyright © 2023 TubeSavely. All rights reserved.',
36+
style: TextStyle(fontSize: 10),
37+
),
38+
],
39+
),
40+
));
41+
}
42+
}
+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:flutter/material.dart';
2+
3+
class ConvertPage extends StatefulWidget {
4+
const ConvertPage({super.key});
5+
6+
@override
7+
State<StatefulWidget> createState() => _ConvertPageState();
8+
}
9+
10+
class _ConvertPageState extends State<ConvertPage> with AutomaticKeepAliveClientMixin<ConvertPage> {
11+
@override
12+
Widget build(BuildContext context) {
13+
super.build(context);
14+
return Column(
15+
children: [
16+
Row(
17+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
18+
children: [
19+
TextButton(
20+
onPressed: () {},
21+
child: const Text(
22+
'添加视频',
23+
style: TextStyle(color: Colors.blue),
24+
),
25+
),
26+
TextButton(
27+
onPressed: () {},
28+
child: const Text('转换格式'),
29+
)
30+
],
31+
),
32+
Expanded(
33+
child: Container(
34+
margin: const EdgeInsets.only(top: 10, bottom: 20),
35+
padding: const EdgeInsets.symmetric(vertical: 10),
36+
decoration: BoxDecoration(
37+
color: Colors.white,
38+
border: Border.all(color: Colors.black45),
39+
borderRadius: BorderRadius.circular(8),
40+
),
41+
// height: 500,
42+
width: double.infinity,
43+
child: Expanded(
44+
child: Center(
45+
child: TextButton(onPressed: () {}, child: const Text('选择视频')),
46+
))
47+
// ListView.builder(itemBuilder: (context, index) {
48+
// return _buildItem();
49+
// })
50+
,
51+
))
52+
],
53+
);
54+
}
55+
56+
_buildItem() {
57+
return Container(
58+
padding: const EdgeInsets.symmetric(vertical: 10),
59+
margin: const EdgeInsets.only(bottom: 10, left: 10, right: 10),
60+
width: double.infinity,
61+
decoration: BoxDecoration(
62+
color: Colors.white,
63+
border: Border.all(color: Colors.black26),
64+
borderRadius: BorderRadius.circular(4),
65+
),
66+
child: Row(
67+
children: [
68+
const SizedBox(width: 100, height: 60, child: Image(image: AssetImage('assets/ic_logo.png'))),
69+
const Expanded(
70+
child: Column(
71+
mainAxisAlignment: MainAxisAlignment.start,
72+
crossAxisAlignment: CrossAxisAlignment.start,
73+
children: [Text('标题'), Text('https://www.facebook.com/100000124835838/videos/329176782997696/')],
74+
)),
75+
Row(
76+
children: [
77+
IconButton(onPressed: () {}, icon: Icon(Icons.save_alt)),
78+
IconButton(onPressed: () {}, icon: Icon(Icons.folder_open)),
79+
IconButton(onPressed: () {}, icon: Icon(Icons.delete)),
80+
],
81+
)
82+
],
83+
),
84+
);
85+
}
86+
87+
@override
88+
bool get wantKeepAlive => true;
89+
}

0 commit comments

Comments
 (0)