Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: bittorrent playback #44

Merged
merged 5 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README-be.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Miru App

## Спіс задач

- [ ] BT торэнт
- [x] BT торэнт
- [ ] Палепшаныя прылады адладкі
- [ ] Сінхранізацыя дадзеных
- [ ] Аўтаматычны пошук субтытраў
Expand Down
2 changes: 1 addition & 1 deletion README-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Miru App

## Todo

- [ ] BT torrent
- [x] BT torrent
- [ ] Better debugging tools
- [ ] Data synchronization
- [ ] Automatically search for subtitles
Expand Down
2 changes: 1 addition & 1 deletion README-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Miru App

## Todo

- [ ] BTトレント
- [x] BTトレント
- [ ] より良いデバッグツール
- [ ] データの同期
- [ ] 字幕の自動検索
Expand Down
2 changes: 1 addition & 1 deletion README-ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Miru App

## Список задач

- [ ] BT торрент
- [x] BT торрент
- [ ] Улучшенные инструменты отладки
- [ ] Синхронизация данных
- [ ] Автоматический поиск субтитров
Expand Down
2 changes: 1 addition & 1 deletion README-ryu.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Miru App

## Todo

- [ ] BTトレント
- [x] BTトレント
- [ ] ゆりゆたさるデバッグツール
- [ ] データぬちゃーき
- [ ] じまちゅるぬじちゃーきんさく
Expand Down
2 changes: 1 addition & 1 deletion README-uk.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Miru App

## Список завдань

- [ ] BT торент
- [x] BT торент
- [ ] Покращені інструменти налагодження
- [ ] Синхронізація даних
- [ ] Автоматичний пошук субтитрів
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Miru App

## Todo

- [ ] BT 种子播放
- [x] BT 种子播放
- [ ] 更好的调试工具
- [ ] 数据同步
- [ ] 自动搜寻字幕
Expand Down
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ android {
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Expand Down
14 changes: 13 additions & 1 deletion assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
"repo-url-subtitle": "Get the repository URL for extensions",
"tmdb-key": "TMDB API Key",
"tmdb-key-subtitle": "Get API Key for TMDB metadata",
"bt-server": "BT Server",
"bt-server-subtitle": "BT Server is a necessary component for online playback of BT seeds",
"bt-server-manager": "Manager",
"upgrade": "Update Software",
"upgrade-subtitle": "version: {version}",
"upgrade-training": "Check",
Expand Down Expand Up @@ -128,7 +131,8 @@
"subtitle-none": "No Subtitle",
"subtitle": "Subtitle",
"subtitle-change": "Change Subtitle {title}",
"subtitle-file": "Subtitle File"
"subtitle-file": "Subtitle File",
"torrent-downloading": "Torrent downloading"
},

"comic-settings": {
Expand Down Expand Up @@ -191,5 +195,13 @@
"genres": "Genres",
"runtime": "Runtime",
"languages": "Languages"
},

"bt-server": {
"not-installed": "BT-Server not installed",
"running": "BT-Server is running",
"stopped": "BT-Server is stopped",
"version": "Version {version}",
"start": "Start"
}
}
14 changes: 13 additions & 1 deletion assets/i18n/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"repo-url-subtitle": "获取扩展的仓库地址",
"tmdb-key": "TMDB API Key",
"tmdb-key-subtitle": "获取 TMDB 元数据的 API Key",
"bt-server": "BT Server",
"bt-server-subtitle": "在线播放 BT 种子的必要组件",
"bt-server-manager": "管理",
"upgrade": "更新软件",
"upgrade-subtitle": "当前版本:{version}",
"upgrade-training": "检查更新",
Expand Down Expand Up @@ -117,7 +120,8 @@
"subtitle-none": "不使用字幕",
"subtitle": "字幕",
"subtitle-change": "切换字幕 {title}",
"subtitle-file": "选择字幕文件"
"subtitle-file": "选择字幕文件",
"torrent-downloading": "正在下载种子"
},

"reader": {
Expand Down Expand Up @@ -180,5 +184,13 @@
"genres": "类型",
"runtime": "时长",
"languages": "语言"
},

"bt-server": {
"not-installed": "BT-Server 未安装",
"running": "BT-Server 正在运行",
"stopped": "BT-Server 已停止",
"version": "版本 {version}",
"start": "启动"
}
}
35 changes: 35 additions & 0 deletions lib/api/bt_server.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'dart:typed_data';

import 'package:dio/dio.dart';

class BTServerApi {
static const baseApi = "http://localhost:3000";
static final dio = Dio(BaseOptions(
baseUrl: baseApi,
));
static Future<String> getVersion() async {
return (await dio.get<String>("/version")).data!;
}

static Future<String> addTorrent(Uint8List torrent) async {
return (await dio.post<Map<String, dynamic>>("/torrent",
data: torrent,
options: Options(
headers: {
"Content-Type": "application/x-bittorrent",
"Content-Length": torrent.length,
},
)))
.data!["infoHash"];
}

static Future<String> removeTorrent(String infoHash) async {
return (await dio.delete<String>("/torrent/$infoHash")).data!;
}

static Future<List<String>> getFileList(String infoHash) async {
final fileList = (await dio.get<Map<String, dynamic>>("/torrent/$infoHash"))
.data!['files'];
return List<String>.from(fileList);
}
}
2 changes: 1 addition & 1 deletion lib/models/extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ part 'extension.g.dart';

enum ExtensionType { manga, bangumi, fikushon }

enum ExtensionWatchBangumiType { hls, mp4 }
enum ExtensionWatchBangumiType { hls, mp4, torrent }

enum ExtensionLogLevel {
info,
Expand Down
1 change: 1 addition & 0 deletions lib/models/extension.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions lib/pages/bt_dialog/controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:miru_app/pages/main/controller.dart';
import 'package:miru_app/utils/bt_server.dart';
import 'package:miru_app/widgets/messenger.dart';

class BTDialogController extends GetxController {
final isInstalled = false.obs;
final isDownloading = false.obs;
final progress = 0.0.obs;

final _mainController = Get.find<MainController>();
late final isRuning = _mainController.btServerisRunning;
late final version = _mainController.btServerVersion;

@override
void onInit() {
super.onInit();
SchedulerBinding.instance.addPostFrameCallback((_) async {
isInstalled.value = await BTServerUtils.isInstalled();
});
}

downloadOrUpgradeServer(BuildContext context) async {
isDownloading.value = true;
try {
await BTServerUtils.downloadLatestBTServer(
onReceiveProgress: (p0, p1) {
progress.value = p0 / p1;
print(progress.value);
},
);
} catch (e) {
context.mounted &&
showPlatformSnackbar(
context: context,
content: e.toString(),
);
} finally {
isDownloading.value = false;
}
isInstalled.value = await BTServerUtils.isInstalled();
}
}
115 changes: 115 additions & 0 deletions lib/pages/bt_dialog/view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import 'package:flutter/material.dart';
import 'package:fluent_ui/fluent_ui.dart' as fluent;
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:get/get.dart';
import 'package:miru_app/pages/bt_dialog/controller.dart';
import 'package:miru_app/utils/bt_server.dart';
import 'package:miru_app/utils/i18n.dart';
import 'package:miru_app/widgets/button.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress.dart';

class BTDialog extends StatefulWidget {
const BTDialog({Key? key}) : super(key: key);

@override
State<BTDialog> createState() => _BTDialogState();
}

class _BTDialogState extends State<BTDialog> {
final BTDialogController c = Get.put(BTDialogController());

Widget _buildContent(BuildContext context) {
return Obx(() {
if (!c.isInstalled.value) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("bt-server.not-installed".i18n),
const SizedBox(height: 16),
if (c.isDownloading.value)
SizedBox(
width: double.infinity,
child: ProgressBar(value: c.progress.value),
)
else
PlatformFilledButton(
child: Text("common.install".i18n),
onPressed: () {
c.downloadOrUpgradeServer(context);
},
),
],
);
}

return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (c.isRuning.value)
Text("bt-server.running".i18n)
else
Text("bt-server.stopped".i18n),
const SizedBox(height: 16),
if (c.isRuning.value)
Text(
FlutterI18n.translate(
context,
'bt-server.version',
translationParams: {
"version": c.version.value,
},
),
)
else
PlatformFilledButton(
child: Text("bt-server.start".i18n),
onPressed: () {
BTServerUtils.startServer();
},
),
],
);
});
}

Widget _buildAndroid(BuildContext context) {
return AlertDialog(
title: const Text("BT-Server"),
content: _buildContent(context),
actions: [
PlatformTextButton(
child: Text("common.close".i18n),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}

Widget _buildDesktop(BuildContext context) {
return fluent.ContentDialog(
title: const Text("BT-Server"),
content: _buildContent(context),
actions: [
fluent.Button(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("common.close".i18n),
),
],
);
}

@override
Widget build(BuildContext context) {
return PlatformBuildWidget(
androidBuilder: _buildAndroid,
desktopBuilder: _buildDesktop,
);
}
}
2 changes: 1 addition & 1 deletion lib/pages/detail/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import 'package:miru_app/utils/layout.dart';
import 'package:miru_app/widgets/cache_network_image.dart';
import 'package:miru_app/widgets/card_tile.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress_ring.dart';
import 'package:miru_app/widgets/progress.dart';
import 'package:url_launcher/url_launcher.dart';

class DetailPage extends StatefulWidget {
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/extension_repo/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:miru_app/pages/extension_repo/widgets/extension_card.dart';
import 'package:miru_app/utils/i18n.dart';
import 'package:miru_app/widgets/button.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress_ring.dart';
import 'package:miru_app/widgets/progress.dart';

class ExtensionRepoPage extends StatefulWidget {
const ExtensionRepoPage({Key? key}) : super(key: key);
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/extension_repo/widgets/extension_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:miru_app/utils/i18n.dart';
import 'package:miru_app/utils/miru_storage.dart';
import 'package:miru_app/widgets/cache_network_image.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress_ring.dart';
import 'package:miru_app/widgets/progress.dart';

class ExtensionCard extends StatefulWidget {
const ExtensionCard({
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/extension_settings/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import 'package:miru_app/widgets/cache_network_image.dart';
import 'package:miru_app/widgets/card_tile.dart';
import 'package:miru_app/widgets/messenger.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress_ring.dart';
import 'package:miru_app/widgets/progress.dart';
import 'package:miru_app/widgets/settings_input_tile.dart';
import 'package:miru_app/widgets/settings_radios_tile.dart';
import 'package:miru_app/widgets/settings_switch_tile.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/home/pages/favorites_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:miru_app/utils/extension.dart';
import 'package:miru_app/utils/i18n.dart';
import 'package:miru_app/widgets/extension_item_card.dart';
import 'package:miru_app/widgets/platform_widget.dart';
import 'package:miru_app/widgets/progress_ring.dart';
import 'package:miru_app/widgets/progress.dart';

class FavoritesPage extends fluent.StatefulWidget {
const FavoritesPage({Key? key, required this.type}) : super(key: key);
Expand Down
Loading