Compare commits

..
Author SHA1 Message Date
liwei ab371d21f9 ci: fix 2025-01-31 19:58:59 +08:00
liwei 4fc67a676e windows debug extension id 2025-01-29 09:37:34 +08:00
Levi 864e6b0477 fix 2025-01-28 22:24:52 +08:00
Levi 0b1d6ca1f6 fix 2025-01-28 19:28:19 +08:00
Levi c2049806a5 fix mac 2025-01-28 19:13:55 +08:00
Levi a58738f910 fix 2025-01-28 18:25:13 +08:00
Levi 606f93e885 auto install host 2025-01-28 17:51:19 +08:00
Levi 509e5c9f5e extension host integration 2025-01-26 12:03:26 +08:00
Levi fb38253045 revert pub 2025-01-25 12:02:13 +08:00
Levi 782205ef27 所有平台统一包名 2025-01-25 11:47:04 +08:00
8 changed files with 58 additions and 72 deletions

No files matched your search

+2 -2
View File
@@ -177,7 +177,7 @@ jobs:
run: | run: |
python3 -m pip install setuptools --break-system-packages python3 -m pip install setuptools --break-system-packages
npm install -g appdmg npm install -g appdmg
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v3
with: with:
name: macos-arm64-lib name: macos-arm64-lib
path: ui/flutter/lib-arm64 path: ui/flutter/lib-arm64
@@ -526,7 +526,7 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: "3.8.18" python-version: "3.8.18"
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v3
with: with:
name: web-dist name: web-dist
path: dist/zip/ path: dist/zip/
+1 -1
View File
@@ -48,7 +48,7 @@ android {
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 29
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }
@@ -7,8 +7,6 @@
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application <application
@@ -93,8 +91,7 @@
<!-- Add android:stopWithTask option only when necessary. --> <!-- Add android:stopWithTask option only when necessary. -->
<service <service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService" android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="dataSync" android:stopWithTask="true" />
android:exported="false" />
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
@@ -82,7 +82,16 @@ class CreateView extends GetView<CreateController> {
_urlController.text = url; _urlController.text = url;
_urlController.selection = TextSelection.fromPosition( _urlController.selection = TextSelection.fromPosition(
TextPosition(offset: _urlController.text.length)); TextPosition(offset: _urlController.text.length));
final protocol = parseProtocol(url); final uppercaseUrl = url.toUpperCase();
Protocol? protocol;
if (uppercaseUrl.startsWith("HTTP:") ||
uppercaseUrl.startsWith("HTTPS:")) {
protocol = Protocol.http;
}
if (uppercaseUrl.startsWith("MAGNET:") ||
uppercaseUrl.endsWith(".TORRENT")) {
protocol = Protocol.bt;
}
if (protocol != null) { if (protocol != null) {
final extraHandlers = { final extraHandlers = {
Protocol.http: () { Protocol.http: () {
@@ -663,20 +672,6 @@ class CreateView extends GetView<CreateController> {
); );
} }
// parse protocol from url
parseProtocol(String url) {
final uppercaseUrl = url.toUpperCase();
Protocol? protocol;
if (uppercaseUrl.startsWith("HTTP:") || uppercaseUrl.startsWith("HTTPS:")) {
protocol = Protocol.http;
}
if (uppercaseUrl.startsWith("MAGNET:") ||
uppercaseUrl.endsWith(".TORRENT")) {
protocol = Protocol.bt;
}
return protocol;
}
// recognize magnet uri, if length == 40, auto add magnet prefix // recognize magnet uri, if length == 40, auto add magnet prefix
recognizeMagnetUri(String text) { recognizeMagnetUri(String text) {
if (text.length != 40) { if (text.length != 40) {
@@ -769,23 +764,24 @@ class CreateView extends GetView<CreateController> {
Object? parseReqExtra(String url) { Object? parseReqExtra(String url) {
Object? reqExtra; Object? reqExtra;
final protocol = parseProtocol(url); if (controller.showAdvanced.value) {
switch (protocol) { switch (controller.advancedTabController.index) {
case Protocol.http: case 0:
final header = Map<String, String>.fromEntries(_httpHeaderControllers final header = Map<String, String>.fromEntries(_httpHeaderControllers
.map((e) => MapEntry(e.name.text, e.value.text))); .map((e) => MapEntry(e.name.text, e.value.text)));
header.removeWhere( header.removeWhere(
(key, value) => key.trim().isEmpty || value.trim().isEmpty); (key, value) => key.trim().isEmpty || value.trim().isEmpty);
if (header.isNotEmpty) { if (header.isNotEmpty) {
reqExtra = ReqExtraHttp()..header = header; reqExtra = ReqExtraHttp()..header = header;
} }
break; break;
case Protocol.bt: case 1:
if (_btTrackerController.text.trim().isNotEmpty) { if (_btTrackerController.text.trim().isNotEmpty) {
reqExtra = ReqExtraBt() reqExtra = ReqExtraBt()
..trackers = Util.textToLines(_btTrackerController.text); ..trackers = Util.textToLines(_btTrackerController.text);
} }
break; break;
}
} }
return reqExtra; return reqExtra;
} }
@@ -762,7 +762,7 @@ class SettingView extends GetView<SettingController> {
width: 80, width: 80,
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: startCfg.value.network, value: startCfg.value.network,
onChanged: Util.isDesktop() || Util.isAndroid() onChanged: Util.isDesktop()
? (value) async { ? (value) async {
startCfg.update((val) { startCfg.update((val) {
val!.network = value!; val!.network = value!;
@@ -786,8 +786,7 @@ class SettingView extends GetView<SettingController> {
), ),
) )
]; ];
if ((Util.isDesktop() || Util.isAndroid()) && if (Util.isDesktop() && startCfg.value.network == 'tcp') {
startCfg.value.network == 'tcp') {
final arr = startCfg.value.address.split(':'); final arr = startCfg.value.address.split(':');
var ip = '127.0.0.1'; var ip = '127.0.0.1';
var port = '0'; var port = '0';
-2
View File
@@ -1,7 +1,6 @@
import 'package:args/args.dart'; import 'package:args/args.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
@@ -41,7 +40,6 @@ void main(List<String> arguments) async {
Future<void> init(Args args) async { Future<void> init(Args args) async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
FlutterForegroundTask.initCommunicationPort();
await Util.initStorageDir(); await Util.initStorageDir();
await Database.instance.init(); await Database.instance.init();
if (Util.isDesktop()) { if (Util.isDesktop()) {
@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:win32_registry/win32_registry.dart'; import 'package:win32_registry/win32_registry.dart';
import '../../win32.dart'; import '../../win32.dart';
@@ -26,7 +27,8 @@ const _firefoxNativeHostsKey = r'Software\Mozilla\NativeMessagingHosts';
/// Install host binary for browser extension /// Install host binary for browser extension
Future<void> doInstallHost() async { Future<void> doInstallHost() async {
final hostPath = _joinExePath(_hostExecName); final hostPath =
path.join((await getApplicationSupportDirectory()).path, _hostExecName);
Future<List<int>> getHostAssetData() async { Future<List<int>> getHostAssetData() async {
final hostAsset = await rootBundle.load('assets/host/$_hostExecName'); final hostAsset = await rootBundle.load('assets/host/$_hostExecName');
@@ -100,7 +102,7 @@ Future<bool> doCheckManifestInstalled(Browser browser) async {
} }
final existingContent = await File(manifestPath).readAsString(); final existingContent = await File(manifestPath).readAsString();
final expectedContent = await _getManifestContent(browser); final expectedContent = await _getManifestContent();
return existingContent == expectedContent; return existingContent == expectedContent;
} }
@@ -110,7 +112,7 @@ Future<void> doInstallManifest(Browser browser) async {
if (await checkManifestInstalled(browser)) return; if (await checkManifestInstalled(browser)) return;
final manifestPath = _getManifestPath(browser)!; final manifestPath = _getManifestPath(browser)!;
final manifestContent = await _getManifestContent(browser); final manifestContent = await _getManifestContent();
final manifestDir = path.dirname(manifestPath); final manifestDir = path.dirname(manifestPath);
await Directory(manifestDir).create(recursive: true); await Directory(manifestDir).create(recursive: true);
await File(manifestPath).writeAsString(manifestContent); await File(manifestPath).writeAsString(manifestContent);
@@ -233,10 +235,10 @@ List<String> _getUnixExecutablePaths(Browser browser) {
} }
String? _getManifestPath(Browser browser) { String? _getManifestPath(Browser browser) {
final manifestName =
browser == Browser.firefox ? '$_hostName.moz.json' : '$_hostName.json';
if (Platform.isWindows) { if (Platform.isWindows) {
return _joinExePath(manifestName); final execPath = Platform.resolvedExecutable;
final execDir = path.dirname(execPath);
return path.join(execDir, '$_hostName.json');
} }
final home = final home =
@@ -247,25 +249,25 @@ String? _getManifestPath(Browser browser) {
switch (browser) { switch (browser) {
case Browser.chrome: case Browser.chrome:
return path.join(home, 'Library', 'Application Support', 'Google', return path.join(home, 'Library', 'Application Support', 'Google',
'Chrome', 'NativeMessagingHosts', manifestName); 'Chrome', 'NativeMessagingHosts', '$_hostName.json');
case Browser.edge: case Browser.edge:
return path.join(home, 'Library', 'Application Support', return path.join(home, 'Library', 'Application Support',
'Microsoft Edge', 'NativeMessagingHosts', manifestName); 'Microsoft Edge', 'NativeMessagingHosts', '$_hostName.json');
case Browser.firefox: case Browser.firefox:
return path.join(home, 'Library', 'Application Support', 'Mozilla', return path.join(home, 'Library', 'Application Support', 'Mozilla',
'NativeMessagingHosts', manifestName); 'NativeMessagingHosts', '$_hostName.json');
} }
} else if (Platform.isLinux) { } else if (Platform.isLinux) {
switch (browser) { switch (browser) {
case Browser.chrome: case Browser.chrome:
return path.join(home, '.config', 'google-chrome', return path.join(home, '.config', 'google-chrome',
'NativeMessagingHosts', manifestName); 'NativeMessagingHosts', '$_hostName.json');
case Browser.edge: case Browser.edge:
return path.join(home, '.config', 'microsoft-edge', return path.join(home, '.config', 'microsoft-edge',
'NativeMessagingHosts', manifestName); 'NativeMessagingHosts', '$_hostName.json');
case Browser.firefox: case Browser.firefox:
return path.join( return path.join(
home, '.mozilla', 'native-messaging-hosts', manifestName); home, '.mozilla', 'native-messaging-hosts', '$_hostName.json');
} }
} }
return null; return null;
@@ -281,20 +283,20 @@ Future<bool> _checkWindowsRegistry(String keyPath) async {
} }
} }
Future<String> _getManifestContent(Browser browser) async { Future<String> _getManifestContent() async {
final hostPath = _joinExePath(_hostExecName); final hostPath =
path.join((await getApplicationSupportDirectory()).path, _hostExecName);
final manifest = { final manifest = {
'name': _hostName, 'name': _hostName,
'description': 'Gopeed browser extension host', 'description': 'Gopeed browser extension host',
'path': hostPath, 'path': hostPath,
'type': 'stdio', 'type': 'stdio',
if (browser != Browser.firefox) 'allowed_origins': [
'allowed_origins': [ 'chrome-extension://$_chromeExtensionId/',
'chrome-extension://$_chromeExtensionId/', 'chrome-extension://$_edgeExtensionId/',
'chrome-extension://$_edgeExtensionId/', ..._debugExtensionIds.map((id) => 'chrome-extension://$id/'),
..._debugExtensionIds.map((id) => 'chrome-extension://$id/'), ],
], 'allowed_extensions': [_firefoxExtensionId],
if (browser == Browser.firefox) 'allowed_extensions': [_firefoxExtensionId],
}; };
return const JsonEncoder.withIndent(' ').convert(manifest); return const JsonEncoder.withIndent(' ').convert(manifest);
} }
@@ -309,9 +311,3 @@ String _getWindowsRegistryKey(Browser browser) {
return _firefoxNativeHostsKey; return _firefoxNativeHostsKey;
} }
} }
String _joinExePath(String fileName) {
final execPath = Platform.resolvedExecutable;
final execDir = path.dirname(execPath);
return path.join(execDir, fileName);
}
+1 -1
View File
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.6.9+1 version: 1.6.7+1
environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"