improve download handling
This commit is contained in:
+11
@@ -26,7 +26,9 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
|
||||
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.toPigeonDownloadState
|
||||
import eu.weblibre.flutter_mozilla_components.feature.BrowserHandlingScrollFeature
|
||||
import eu.weblibre.flutter_mozilla_components.feature.KeyboardVisibilityFeature
|
||||
import eu.weblibre.flutter_mozilla_components.feature.ReadabilityExtractFeature
|
||||
@@ -320,6 +322,15 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
|
||||
fragmentManager = childFragmentManager,
|
||||
onDownloadStopped = { download, id, 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(
|
||||
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.ShareResourceAction
|
||||
import mozilla.components.browser.state.state.content.ShareResourceState
|
||||
import mozilla.components.support.utils.DefaultDownloadFileUtils
|
||||
import java.util.UUID
|
||||
|
||||
class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
||||
@@ -39,6 +40,23 @@ class GeckoDownloadsApiImpl : GeckoDownloadsApi {
|
||||
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 {
|
||||
return ShareResourceState.InternetResource(
|
||||
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)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
@@ -10537,6 +10554,7 @@ interface GeckoDownloadsApi {
|
||||
fun requestDownload(tabId: String, state: DownloadState)
|
||||
fun copyInternetResource(tabId: String, state: ShareInternetResourceState)
|
||||
fun shareInternetResource(tabId: String, state: ShareInternetResourceState)
|
||||
fun openDownloadedFile(fileName: String, directoryPath: String, contentType: String?): Boolean
|
||||
|
||||
companion object {
|
||||
/** The codec used by GeckoDownloadsApi. */
|
||||
@@ -10604,6 +10622,25 @@ interface GeckoDownloadsApi {
|
||||
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,
|
||||
DohSettings,
|
||||
DohSettingsMode,
|
||||
DownloadState,
|
||||
DownloadStatus,
|
||||
EmailHitResult,
|
||||
FrecencyThresholdOption,
|
||||
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 TabTranslationEvent = ({String tabId, TabTranslationStateData state});
|
||||
typedef TranslationEngineEvent = TranslationEngineStateData;
|
||||
typedef DownloadStoppedEvent = DownloadState;
|
||||
|
||||
class GeckoEventService extends GeckoStateEvents {
|
||||
// Stream controllers
|
||||
@@ -48,6 +49,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
|
||||
final _tabAddedSubject = PublishSubject<String>();
|
||||
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
||||
final _downloadStoppedSubject = PublishSubject<DownloadStoppedEvent>();
|
||||
final _manifestUpdateSubject = PublishSubject<ManifestUpdateEvent>();
|
||||
final _translationEngineSubject = BehaviorSubject<TranslationEngineEvent>();
|
||||
final _tabTranslationSubject = ReplaySubject<TabTranslationEvent>();
|
||||
@@ -77,6 +79,8 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
|
||||
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
||||
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
||||
Stream<DownloadStoppedEvent> get downloadStoppedEvents =>
|
||||
_downloadStoppedSubject.stream;
|
||||
Stream<ManifestUpdateEvent> get manifestUpdateEvents =>
|
||||
_manifestUpdateSubject.stream;
|
||||
ValueStream<TranslationEngineEvent> get translationEngineEvents =>
|
||||
@@ -218,6 +222,11 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
_mlProgressSubject.addWhenMoreRecent(sequence, null, progress);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDownloadStopped(int sequence, DownloadState state) {
|
||||
_downloadStoppedSubject.addWhenMoreRecent(sequence, state.id, state);
|
||||
}
|
||||
|
||||
@override
|
||||
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest) {
|
||||
_manifestUpdateSubject.addWhenMoreRecent(sequence, tabId, (
|
||||
@@ -276,6 +285,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
await _siteAssignementSubject.close();
|
||||
await _proxyLoadErrorSubject.close();
|
||||
await _mlProgressSubject.close();
|
||||
await _downloadStoppedSubject.close();
|
||||
await _manifestUpdateSubject.close();
|
||||
await _translationEngineSubject.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 onDownloadStopped(int sequence, DownloadState state);
|
||||
|
||||
void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest);
|
||||
|
||||
void onTranslationEngineStateChange(
|
||||
@@ -2301,6 +2303,11 @@ abstract class GeckoDownloadsApi {
|
||||
void requestDownload(String tabId, DownloadState state);
|
||||
void copyInternetResource(String tabId, ShareInternetResourceState state);
|
||||
void shareInternetResource(String tabId, ShareInternetResourceState state);
|
||||
bool openDownloadedFile(
|
||||
String fileName,
|
||||
String directoryPath,
|
||||
String? contentType,
|
||||
);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
|
||||
Reference in New Issue
Block a user