improve download handling
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
|
|
||||||
<!-- Needed for uploading media files on devices with Android 13 and later. -->
|
<!-- Needed for uploading media files on devices with Android 13 and later. -->
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||||
|
|||||||
+29
@@ -45,6 +45,7 @@ import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
|||||||
import 'package:weblibre/presentation/widgets/failure_widget.dart';
|
import 'package:weblibre/presentation/widgets/failure_widget.dart';
|
||||||
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
|
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
|
||||||
import 'package:weblibre/presentation/widgets/url_icon.dart';
|
import 'package:weblibre/presentation/widgets/url_icon.dart';
|
||||||
|
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
||||||
|
|
||||||
class Section extends MultiSliver {
|
class Section extends MultiSliver {
|
||||||
static final _datePattern = DateFormat.MMMd().addPattern('Hm');
|
static final _datePattern = DateFormat.MMMd().addPattern('Hm');
|
||||||
@@ -499,6 +500,34 @@ class HistoryScreen extends HookConsumerWidget {
|
|||||||
onTap: (item) async {
|
onTap: (item) async {
|
||||||
if (selectedItems.value.isNotEmpty) {
|
if (selectedItems.value.isNotEmpty) {
|
||||||
toggleSelected(item);
|
toggleSelected(item);
|
||||||
|
} else if (isDownloadsMode) {
|
||||||
|
final filePath = item.title;
|
||||||
|
final file = filePath.mapNotNull(File.new);
|
||||||
|
|
||||||
|
if (file == null ||
|
||||||
|
await file.exists() != true) {
|
||||||
|
if (context.mounted) {
|
||||||
|
ui_helper.showErrorMessage(
|
||||||
|
context,
|
||||||
|
'Downloaded file not found',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final opened = await GeckoDownloadsService()
|
||||||
|
.openDownloadedFile(
|
||||||
|
fileName: p.basename(file.path),
|
||||||
|
directoryPath: file.parent.path,
|
||||||
|
contentType: item.previewImageUrl,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!opened && context.mounted) {
|
||||||
|
ui_helper.showErrorMessage(
|
||||||
|
context,
|
||||||
|
'Could not open downloaded file',
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await ref
|
await ref
|
||||||
.read(tabRepositoryProvider.notifier)
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
|||||||
+2
-2
@@ -441,7 +441,7 @@ final class UnifiedPreferenceSettingsRepositoryProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$unifiedPreferenceSettingsRepositoryHash() =>
|
String _$unifiedPreferenceSettingsRepositoryHash() =>
|
||||||
r'c544b5815ec676ddb6cde1ffeb8c9ef4a7dc4469';
|
r'f2153c826e2cba308cf3e8bdfe371e0b6b3e7dbd';
|
||||||
|
|
||||||
final class UnifiedPreferenceSettingsRepositoryFamily extends $Family
|
final class UnifiedPreferenceSettingsRepositoryFamily extends $Family
|
||||||
with
|
with
|
||||||
@@ -554,7 +554,7 @@ final class PreferenceSettingsGroupRepositoryProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$preferenceSettingsGroupRepositoryHash() =>
|
String _$preferenceSettingsGroupRepositoryHash() =>
|
||||||
r'c8335b39c4c9fa95c4d415231b103a2feff97d26';
|
r'ae2b8553b895945d2a5c44a8ed24b8bbb00bb985';
|
||||||
|
|
||||||
final class PreferenceSettingsGroupRepositoryFamily extends $Family
|
final class PreferenceSettingsGroupRepositoryFamily extends $Family
|
||||||
with
|
with
|
||||||
|
|||||||
@@ -18,9 +18,12 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:weblibre/core/providers/router.dart';
|
import 'package:weblibre/core/providers/router.dart';
|
||||||
import 'package:weblibre/domain/services/app_initialization.dart';
|
import 'package:weblibre/domain/services/app_initialization.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/domain/providers.dart';
|
||||||
import 'package:weblibre/features/sync/domain/entities/sync_repository_state.dart';
|
import 'package:weblibre/features/sync/domain/entities/sync_repository_state.dart';
|
||||||
import 'package:weblibre/features/sync/domain/repositories/sync.dart';
|
import 'package:weblibre/features/sync/domain/repositories/sync.dart';
|
||||||
import 'package:weblibre/features/web_search/domain/controllers/sandbox_capture_controller.dart';
|
import 'package:weblibre/features/web_search/domain/controllers/sandbox_capture_controller.dart';
|
||||||
@@ -99,7 +102,9 @@ class MainApp extends HookConsumerWidget {
|
|||||||
disableAnimations: disableAnimations,
|
disableAnimations: disableAnimations,
|
||||||
child: _SyncEventListener(
|
child: _SyncEventListener(
|
||||||
child: _SandboxCaptureErrorListener(
|
child: _SandboxCaptureErrorListener(
|
||||||
child: child ?? const SizedBox.shrink(),
|
child: _DownloadStoppedListener(
|
||||||
|
child: child ?? const SizedBox.shrink(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -142,6 +147,65 @@ class MainApp extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _DownloadStoppedListener extends HookConsumerWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const _DownloadStoppedListener({required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final downloadStoppedEvents = ref.watch(
|
||||||
|
eventServiceProvider.select((service) => service.downloadStoppedEvents),
|
||||||
|
);
|
||||||
|
|
||||||
|
useOnStreamChange(
|
||||||
|
downloadStoppedEvents,
|
||||||
|
onData: (download) {
|
||||||
|
switch (download.status) {
|
||||||
|
case DownloadStatus.completed:
|
||||||
|
ui_helper.showInfoMessage(
|
||||||
|
context,
|
||||||
|
'Download completed',
|
||||||
|
duration: const Duration(seconds: 6),
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: 'Open',
|
||||||
|
onPressed: () async {
|
||||||
|
final opened = await GeckoDownloadsService()
|
||||||
|
.openDownloadedFile(
|
||||||
|
fileName: download.fileName ?? '',
|
||||||
|
directoryPath: download.directoryPath ?? '',
|
||||||
|
contentType: download.contentType,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!opened && context.mounted) {
|
||||||
|
ui_helper.showErrorMessage(
|
||||||
|
context,
|
||||||
|
'Could not open downloaded file',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case DownloadStatus.failed:
|
||||||
|
ui_helper.showErrorMessage(
|
||||||
|
context,
|
||||||
|
'Download failed: ${download.fileName ?? download.url}',
|
||||||
|
persist: true,
|
||||||
|
);
|
||||||
|
case DownloadStatus.initiated:
|
||||||
|
case DownloadStatus.downloading:
|
||||||
|
case DownloadStatus.paused:
|
||||||
|
case DownloadStatus.cancelled:
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MediaQueryData applyAppMediaQueryOverrides({
|
MediaQueryData applyAppMediaQueryOverrides({
|
||||||
required MediaQueryData mediaQuery,
|
required MediaQueryData mediaQuery,
|
||||||
required double uiScaleFactor,
|
required double uiScaleFactor,
|
||||||
|
|||||||
+11
@@ -26,7 +26,9 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
|
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
|
||||||
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
|
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
|
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.toPigeonDownloadState
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.BrowserHandlingScrollFeature
|
import eu.weblibre.flutter_mozilla_components.feature.BrowserHandlingScrollFeature
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.KeyboardVisibilityFeature
|
import eu.weblibre.flutter_mozilla_components.feature.KeyboardVisibilityFeature
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.ReadabilityExtractFeature
|
import eu.weblibre.flutter_mozilla_components.feature.ReadabilityExtractFeature
|
||||||
@@ -320,6 +322,15 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
|||||||
fragmentManager = childFragmentManager,
|
fragmentManager = childFragmentManager,
|
||||||
onDownloadStopped = { download, id, status ->
|
onDownloadStopped = { download, id, status ->
|
||||||
Logger.debug("Download done. ID#$id $download with status $status")
|
Logger.debug("Download done. ID#$id $download with status $status")
|
||||||
|
if (
|
||||||
|
status == mozilla.components.browser.state.state.content.DownloadState.Status.COMPLETED ||
|
||||||
|
status == mozilla.components.browser.state.state.content.DownloadState.Status.FAILED
|
||||||
|
) {
|
||||||
|
components.flutterEvents.onDownloadStopped(
|
||||||
|
EventSequence.next(),
|
||||||
|
download.toPigeonDownloadState(status),
|
||||||
|
) { _ -> }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
downloadFileUtils = DefaultDownloadFileUtils(
|
downloadFileUtils = DefaultDownloadFileUtils(
|
||||||
context = components.profileApplicationContext,
|
context = components.profileApplicationContext,
|
||||||
|
|||||||
+19
-1
@@ -15,6 +15,7 @@ import mozilla.components.browser.state.action.ContentAction
|
|||||||
import mozilla.components.browser.state.action.CopyInternetResourceAction
|
import mozilla.components.browser.state.action.CopyInternetResourceAction
|
||||||
import mozilla.components.browser.state.action.ShareResourceAction
|
import mozilla.components.browser.state.action.ShareResourceAction
|
||||||
import mozilla.components.browser.state.state.content.ShareResourceState
|
import mozilla.components.browser.state.state.content.ShareResourceState
|
||||||
|
import mozilla.components.support.utils.DefaultDownloadFileUtils
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
||||||
@@ -39,6 +40,23 @@ class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
|||||||
components.core.store.dispatch(ShareResourceAction.AddShareAction(tabId, state.toMozillaShareInternetResourceState()))
|
components.core.store.dispatch(ShareResourceAction.AddShareAction(tabId, state.toMozillaShareInternetResourceState()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openDownloadedFile(
|
||||||
|
fileName: String,
|
||||||
|
directoryPath: String,
|
||||||
|
contentType: String?,
|
||||||
|
): Boolean {
|
||||||
|
return DefaultDownloadFileUtils(
|
||||||
|
context = components.profileApplicationContext,
|
||||||
|
downloadLocation = {
|
||||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path
|
||||||
|
},
|
||||||
|
).openFile(
|
||||||
|
fileName = fileName,
|
||||||
|
directoryPath = directoryPath,
|
||||||
|
contentType = contentType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun ShareInternetResourceState.toMozillaShareInternetResourceState(): ShareResourceState.InternetResource {
|
private fun ShareInternetResourceState.toMozillaShareInternetResourceState(): ShareResourceState.InternetResource {
|
||||||
return ShareResourceState.InternetResource(
|
return ShareResourceState.InternetResource(
|
||||||
url = url,
|
url = url,
|
||||||
@@ -84,4 +102,4 @@ class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.weblibre.flutter_mozilla_components.ext
|
||||||
|
|
||||||
|
import eu.weblibre.flutter_mozilla_components.pigeons.DownloadState as PigeonDownloadState
|
||||||
|
import eu.weblibre.flutter_mozilla_components.pigeons.DownloadStatus as PigeonDownloadStatus
|
||||||
|
import mozilla.components.browser.state.state.content.DownloadState as MozillaDownloadState
|
||||||
|
|
||||||
|
fun MozillaDownloadState.toPigeonDownloadState(
|
||||||
|
statusOverride: MozillaDownloadState.Status = status,
|
||||||
|
): PigeonDownloadState =
|
||||||
|
PigeonDownloadState(
|
||||||
|
url = url,
|
||||||
|
fileName = fileName,
|
||||||
|
contentType = contentType,
|
||||||
|
contentLength = contentLength,
|
||||||
|
currentBytesCopied = currentBytesCopied,
|
||||||
|
status = statusOverride.toPigeonDownloadStatus(),
|
||||||
|
userAgent = userAgent,
|
||||||
|
destinationDirectory = null,
|
||||||
|
directoryPath = directoryPath,
|
||||||
|
referrerUrl = referrerUrl,
|
||||||
|
skipConfirmation = skipConfirmation,
|
||||||
|
openInApp = openInApp,
|
||||||
|
id = id,
|
||||||
|
sessionId = sessionId,
|
||||||
|
private = private,
|
||||||
|
createdTime = createdTime,
|
||||||
|
notificationId = notificationId?.toLong(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun MozillaDownloadState.Status.toPigeonDownloadStatus(): PigeonDownloadStatus =
|
||||||
|
when (this) {
|
||||||
|
MozillaDownloadState.Status.INITIATED -> PigeonDownloadStatus.INITIATED
|
||||||
|
MozillaDownloadState.Status.DOWNLOADING -> PigeonDownloadStatus.DOWNLOADING
|
||||||
|
MozillaDownloadState.Status.PAUSED -> PigeonDownloadStatus.PAUSED
|
||||||
|
MozillaDownloadState.Status.CANCELLED -> PigeonDownloadStatus.CANCELLED
|
||||||
|
MozillaDownloadState.Status.FAILED -> PigeonDownloadStatus.FAILED
|
||||||
|
MozillaDownloadState.Status.COMPLETED -> PigeonDownloadStatus.COMPLETED
|
||||||
|
}
|
||||||
+37
@@ -9046,6 +9046,23 @@ class GeckoStateEvents(private val binaryMessenger: BinaryMessenger, private val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun onDownloadStopped(sequenceArg: Long, stateArg: DownloadState, callback: (Result<Unit>) -> Unit)
|
||||||
|
{
|
||||||
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
|
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onDownloadStopped$separatedMessageChannelSuffix"
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||||
|
channel.send(listOf(sequenceArg, stateArg)) {
|
||||||
|
if (it is List<*>) {
|
||||||
|
if (it.size > 1) {
|
||||||
|
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||||
|
} else {
|
||||||
|
callback(Result.success(Unit))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback(Result.failure(GeckoPigeonUtils.createConnectionError(channelName)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fun onManifestUpdate(sequenceArg: Long, tabIdArg: String, manifestArg: PwaManifest?, callback: (Result<Unit>) -> Unit)
|
fun onManifestUpdate(sequenceArg: Long, tabIdArg: String, manifestArg: PwaManifest?, callback: (Result<Unit>) -> Unit)
|
||||||
{
|
{
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
@@ -10537,6 +10554,7 @@ interface GeckoDownloadsApi {
|
|||||||
fun requestDownload(tabId: String, state: DownloadState)
|
fun requestDownload(tabId: String, state: DownloadState)
|
||||||
fun copyInternetResource(tabId: String, state: ShareInternetResourceState)
|
fun copyInternetResource(tabId: String, state: ShareInternetResourceState)
|
||||||
fun shareInternetResource(tabId: String, state: ShareInternetResourceState)
|
fun shareInternetResource(tabId: String, state: ShareInternetResourceState)
|
||||||
|
fun openDownloadedFile(fileName: String, directoryPath: String, contentType: String?): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by GeckoDownloadsApi. */
|
/** The codec used by GeckoDownloadsApi. */
|
||||||
@@ -10604,6 +10622,25 @@ interface GeckoDownloadsApi {
|
|||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.openDownloadedFile$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val fileNameArg = args[0] as String
|
||||||
|
val directoryPathArg = args[1] as String
|
||||||
|
val contentTypeArg = args[2] as String?
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
listOf(api.openDownloadedFile(fileNameArg, directoryPathArg, contentTypeArg))
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
GeckoPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ export 'src/pigeons/gecko.g.dart'
|
|||||||
DocumentType,
|
DocumentType,
|
||||||
DohSettings,
|
DohSettings,
|
||||||
DohSettingsMode,
|
DohSettingsMode,
|
||||||
|
DownloadState,
|
||||||
|
DownloadStatus,
|
||||||
EmailHitResult,
|
EmailHitResult,
|
||||||
FrecencyThresholdOption,
|
FrecencyThresholdOption,
|
||||||
GeckoDeleteBrowsingDataController,
|
GeckoDeleteBrowsingDataController,
|
||||||
|
|||||||
@@ -72,4 +72,12 @@ class GeckoDownloadsService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> openDownloadedFile({
|
||||||
|
required String fileName,
|
||||||
|
required String directoryPath,
|
||||||
|
String? contentType,
|
||||||
|
}) {
|
||||||
|
return _api.openDownloadedFile(fileName, directoryPath, contentType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ typedef ScrollEvent = ({String tabId, int scrollY});
|
|||||||
typedef ManifestUpdateEvent = ({String tabId, PwaManifest? manifest});
|
typedef ManifestUpdateEvent = ({String tabId, PwaManifest? manifest});
|
||||||
typedef TabTranslationEvent = ({String tabId, TabTranslationStateData state});
|
typedef TabTranslationEvent = ({String tabId, TabTranslationStateData state});
|
||||||
typedef TranslationEngineEvent = TranslationEngineStateData;
|
typedef TranslationEngineEvent = TranslationEngineStateData;
|
||||||
|
typedef DownloadStoppedEvent = DownloadState;
|
||||||
|
|
||||||
class GeckoEventService extends GeckoStateEvents {
|
class GeckoEventService extends GeckoStateEvents {
|
||||||
// Stream controllers
|
// Stream controllers
|
||||||
@@ -48,6 +49,7 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
|
|
||||||
final _tabAddedSubject = PublishSubject<String>();
|
final _tabAddedSubject = PublishSubject<String>();
|
||||||
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
||||||
|
final _downloadStoppedSubject = PublishSubject<DownloadStoppedEvent>();
|
||||||
final _manifestUpdateSubject = PublishSubject<ManifestUpdateEvent>();
|
final _manifestUpdateSubject = PublishSubject<ManifestUpdateEvent>();
|
||||||
final _translationEngineSubject = BehaviorSubject<TranslationEngineEvent>();
|
final _translationEngineSubject = BehaviorSubject<TranslationEngineEvent>();
|
||||||
final _tabTranslationSubject = ReplaySubject<TabTranslationEvent>();
|
final _tabTranslationSubject = ReplaySubject<TabTranslationEvent>();
|
||||||
@@ -77,6 +79,8 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
|
|
||||||
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
||||||
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
||||||
|
Stream<DownloadStoppedEvent> get downloadStoppedEvents =>
|
||||||
|
_downloadStoppedSubject.stream;
|
||||||
Stream<ManifestUpdateEvent> get manifestUpdateEvents =>
|
Stream<ManifestUpdateEvent> get manifestUpdateEvents =>
|
||||||
_manifestUpdateSubject.stream;
|
_manifestUpdateSubject.stream;
|
||||||
ValueStream<TranslationEngineEvent> get translationEngineEvents =>
|
ValueStream<TranslationEngineEvent> get translationEngineEvents =>
|
||||||
@@ -218,6 +222,11 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
_mlProgressSubject.addWhenMoreRecent(sequence, null, progress);
|
_mlProgressSubject.addWhenMoreRecent(sequence, null, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onDownloadStopped(int sequence, DownloadState state) {
|
||||||
|
_downloadStoppedSubject.addWhenMoreRecent(sequence, state.id, state);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest) {
|
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest) {
|
||||||
_manifestUpdateSubject.addWhenMoreRecent(sequence, tabId, (
|
_manifestUpdateSubject.addWhenMoreRecent(sequence, tabId, (
|
||||||
@@ -276,6 +285,7 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
await _siteAssignementSubject.close();
|
await _siteAssignementSubject.close();
|
||||||
await _proxyLoadErrorSubject.close();
|
await _proxyLoadErrorSubject.close();
|
||||||
await _mlProgressSubject.close();
|
await _mlProgressSubject.close();
|
||||||
|
await _downloadStoppedSubject.close();
|
||||||
await _manifestUpdateSubject.close();
|
await _manifestUpdateSubject.close();
|
||||||
await _translationEngineSubject.close();
|
await _translationEngineSubject.close();
|
||||||
await _tabTranslationSubject.close();
|
await _tabTranslationSubject.close();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2007,6 +2007,8 @@ abstract class GeckoStateEvents {
|
|||||||
|
|
||||||
void onMlProgress(int sequence, MlProgressData progress);
|
void onMlProgress(int sequence, MlProgressData progress);
|
||||||
|
|
||||||
|
void onDownloadStopped(int sequence, DownloadState state);
|
||||||
|
|
||||||
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest);
|
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest);
|
||||||
|
|
||||||
void onTranslationEngineStateChange(
|
void onTranslationEngineStateChange(
|
||||||
@@ -2301,6 +2303,11 @@ abstract class GeckoDownloadsApi {
|
|||||||
void requestDownload(String tabId, DownloadState state);
|
void requestDownload(String tabId, DownloadState state);
|
||||||
void copyInternetResource(String tabId, ShareInternetResourceState state);
|
void copyInternetResource(String tabId, ShareInternetResourceState state);
|
||||||
void shareInternetResource(String tabId, ShareInternetResourceState state);
|
void shareInternetResource(String tabId, ShareInternetResourceState state);
|
||||||
|
bool openDownloadedFile(
|
||||||
|
String fileName,
|
||||||
|
String directoryPath,
|
||||||
|
String? contentType,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
|
|||||||
Reference in New Issue
Block a user