feat: register as android download handler for browser integration (#1251)

This commit is contained in:
Copilot authored and GitHub committed 2026-01-22 18:33:23 +08:00
1 parent 8d33e1a5b3
commit a3c1f84c2c
2 files changed
+71 -42

No files matched your search

@@ -5,8 +5,10 @@
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<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.WRITE_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.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
@@ -69,6 +71,19 @@
<data
android:scheme="magnet" />
</intent-filter>
<!-- Handle http/https URLs with common downloadable mimeTypes -->
<intent-filter android:label="Gopeed">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW_DOWNLOADS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
@@ -91,7 +106,7 @@
</activity>
<!-- Add android:stopWithTask option only when necessary. -->
<service
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="dataSync"
android:exported="false" />
@@ -102,4 +117,4 @@
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
</manifest>
@@ -225,18 +225,25 @@ class BuildTaskListView extends GetView {
// Get ETA text, e.g. "00:05:30"
String getEtaText() {
if (isDone()) return "";
if (!isRunning()) return "";
final total = task.meta.res?.size ?? 0;
final downloaded = task.progress.downloaded;
final speed = task.progress.speed;
// If speed is 0 or file is downloaded, don't show time
if (total <= 0 || speed <= 0 || downloaded >= total) {
// If speed is 0 or total unknown, don't show time
if (total <= 0 || speed <= 0) {
return "";
}
final remainingBytes = total - downloaded;
final remainingSeconds = remainingBytes ~/ speed;
// If remaining bytes <= 0, download is essentially complete
if (remainingBytes <= 0) {
return "";
}
// Use ceiling division to avoid showing 0 seconds when there's still data remaining
final remainingSeconds = (remainingBytes + speed - 1) ~/ speed;
// If time is too long (e.g. > 1 day), return > 1d
if (remainingSeconds > 86400) return "> 1d";
@@ -347,44 +354,51 @@ class BuildTaskListView extends GetView {
children: [
// Left side: Progress text + Percentage
Expanded(
flex: 1,
child: Row(
children: [
Text(
getProgressText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
),
const SizedBox(width: 8),
Text(
getPercentText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
),
],
).padding(left: 18)),
children: [
Flexible(
child: Text(
getProgressText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
overflow: TextOverflow.ellipsis,
),
),
// Hide percentage on mobile
if (!Util.isMobile() &&
getPercentText().isNotEmpty) ...[
const SizedBox(width: 4),
Text(
getPercentText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
),
],
],
).padding(left: 18)),
// Right side: ETA + Speed + Actions
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
getEtaText(),
style: Get.textTheme.titleSmall,
Row(
mainAxisSize: MainAxisSize.min,
children: [
// Only show ETA on wider screens
if (!Util.isMobile() && getEtaText().isNotEmpty) ...[
Text(
getEtaText(),
style: Get.textTheme.titleSmall,
),
Text(
" | ",
style: Get.textTheme.titleSmall?.copyWith(
color: Get.theme.disabledColor,
fontWeight: FontWeight.w300,
),
Text(
" | ",
style: Get.textTheme.titleSmall?.copyWith(
color: Get.theme.disabledColor,
fontWeight: FontWeight.w300,
),
).padding(horizontal: 4),
Text("${Util.fmtByte(task.progress.speed)} / s",
style: Get.textTheme.titleSmall),
...buildActions()
],
)),
).padding(horizontal: 4),
],
Text("${Util.fmtByte(task.progress.speed)}/s",
style: Get.textTheme.titleSmall),
...buildActions()
],
),
],
),
isDone()