Skip to content

Commit

Permalink
windows: Handle magnet links & torrent files
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Ray committed Jan 11, 2025
1 parent 24d3841 commit cf38f37
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 23 deletions.
3 changes: 3 additions & 0 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:pikatorrent/models/session.dart';
import 'package:pikatorrent/models/torrents.dart';
import 'package:pikatorrent/navigation/router.dart';
import 'package:pikatorrent/platforms/android/foreground_service.dart';
import 'package:pikatorrent/platforms/windows/register_app.dart';
import 'package:pikatorrent/utils/device.dart';
import 'package:provider/provider.dart';
import 'package:window_manager/window_manager.dart';
Expand Down Expand Up @@ -84,6 +85,8 @@ void main() async {
// when live reloading.
debugPrint(e.toString());
}
} else if (Platform.isWindows) {
registerAppInRegistry();
}

runApp(const PikaTorrent());
Expand Down
4 changes: 3 additions & 1 deletion app/lib/navigation/app_shell_route.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'package:pikatorrent/dialogs/add_torrent.dart';
Expand Down Expand Up @@ -44,7 +46,7 @@ class _AppShellRouteState extends State<AppShellRoute> {
} else if (uriString.startsWith(appUri)) {
// App URI
_openAddTorrentDialog(getTorrentLink(uriString), null);
} else if (uriString.startsWith('/')) {
} else if (File(uriString).existsSync()) {
// Filesystem path
_openAddTorrentDialog(null, uriString);
}
Expand Down
69 changes: 69 additions & 0 deletions app/lib/platforms/windows/register_app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'dart:io';

import 'package:win32_registry/win32_registry.dart';

const String appName = 'PikaTorrent';
const String appCapabilityPath = 'Software\\$appName\\Capabilities';

Future<void> registerAppInRegistry() async {
await registerAppCmd();
await registerApp();
await registerCapabilities();
}

Future<void> registerAppCmd() async {
String appPath = Platform.resolvedExecutable;

String protocolRegKey = 'Software\\Classes\\$appName';
String protocolCmdRegKey = 'shell\\open\\command';
RegistryValue protocolCmdRegValue = RegistryValue(
'',
RegistryValueType.string,
'"$appPath" "%1"',
);

final regKey = Registry.currentUser.createKey(protocolRegKey);
regKey.createKey(protocolCmdRegKey).createValue(protocolCmdRegValue);
}

Future<void> registerApp() async {
String appRegKey = 'Software\\RegisteredApplications';
RegistryValue appCapability = const RegistryValue(
appName,
RegistryValueType.string,
appCapabilityPath,
);

final regKey = Registry.currentUser.createKey(appRegKey);
regKey.createValue(appCapability);
}

Future<void> registerCapabilities() async {
final regKey = Registry.currentUser.createKey('Software\\$appName\\Capabilities');
regKey.createValue(const RegistryValue(
'ApplicationDescription',
RegistryValueType.string,
'BitTorrent software',
));

final fileRegKey = Registry.currentUser.createKey('Software\\$appName\\Capabilities\\FILEAssociations');
fileRegKey.createValue(const RegistryValue(
'.torrent',
RegistryValueType.string,
appName,
));

final mimeRegKey = Registry.currentUser.createKey('Software\\$appName\\Capabilities\\MIMEAssociations');
mimeRegKey.createValue(const RegistryValue(
'application/x-bittorrent',
RegistryValueType.string,
appName,
));

final urlRegKey = Registry.currentUser.createKey('Software\\$appName\\Capabilities\\URLAssociations');
urlRegKey.createValue(const RegistryValue(
'magnet',
RegistryValueType.string,
appName,
));
}
43 changes: 22 additions & 21 deletions app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ packages:
app_links:
dependency: "direct main"
description:
name: app_links
sha256: ad1a6d598e7e39b46a34f746f9a8b011ee147e4c275d407fa457e7a62f84dd99
url: "https://pub.dev"
source: hosted
version: "6.3.2"
path: app_links
ref: d1aa2be128708e976dc88154854355217a3ff9c4
resolved-ref: d1aa2be128708e976dc88154854355217a3ff9c4
url: "https://github.com/G-Ray/app_links"
source: git
version: "6.4.0"
app_links_linux:
dependency: transitive
description:
Expand Down Expand Up @@ -109,10 +110,10 @@ packages:
dependency: "direct main"
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.dev"
source: hosted
version: "1.18.0"
version: "1.19.0"
content_resolver:
dependency: "direct main"
description:
Expand Down Expand Up @@ -397,18 +398,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.7"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.8"
leak_tracker_testing:
dependency: transitive
description:
Expand Down Expand Up @@ -845,7 +846,7 @@ packages:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
version: "0.0.0"
source_span:
dependency: transitive
description:
Expand All @@ -866,10 +867,10 @@ packages:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
version: "1.12.0"
stream_channel:
dependency: transitive
description:
Expand All @@ -882,10 +883,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.3.0"
term_glyph:
dependency: transitive
description:
Expand All @@ -898,10 +899,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.3"
timezone:
dependency: transitive
description:
Expand Down Expand Up @@ -1026,10 +1027,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
url: "https://pub.dev"
source: hosted
version: "14.2.5"
version: "14.3.0"
web:
dependency: transitive
description:
Expand All @@ -1047,7 +1048,7 @@ packages:
source: hosted
version: "5.7.2"
win32_registry:
dependency: transitive
dependency: "direct main"
description:
name: win32_registry
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
Expand Down
7 changes: 6 additions & 1 deletion app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ dependencies:
handy_window: ^0.4.0
fuzzywuzzy: ^1.2.0
flutter_local_notifications: ^18.0.1
app_links: ^6.3.2
app_links:
git:
url: "https://github.com/G-Ray/app_links"
path: app_links
ref: d1aa2be128708e976dc88154854355217a3ff9c4
content_resolver: ^0.3.2
permission_handler: ^11.3.1
external_path: ^2.0.1
Expand All @@ -67,6 +71,7 @@ dependencies:
window_manager: ^0.4.3
pub_semver: ^2.1.5
http: ^1.2.2
win32_registry: ^1.1.5

dev_dependencies:
flutter_test:
Expand Down
39 changes: 39 additions & 0 deletions app/windows/runner/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,48 @@

#include "flutter_window.h"
#include "utils.h"
#include "app_links/app_links_plugin_c_api.h"

bool SendAppLinkToInstance(const std::wstring& title) {
// Find our exact window
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", title.c_str());

if (hwnd) {
// Dispatch new link to current window
SendAppLink(hwnd);

// (Optional) Restore our window to front in same state
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement(hwnd, &place);

switch(place.showCmd) {
case SW_SHOWMAXIMIZED:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(hwnd, SW_RESTORE);
break;
default:
ShowWindow(hwnd, SW_NORMAL);
break;
}

SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(hwnd);
// END (Optional) Restore

// Window has been found, don't create another one.
return true;
}

return false;
}

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) {
if (SendAppLinkToInstance(L"PikaTorrent")) {
return EXIT_SUCCESS;
}
// Attach to console when present (e.g., 'flutter run') or create a
// new console when running with a debugger.
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
Expand Down

0 comments on commit cf38f37

Please sign in to comment.