diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c2083ad9e..1e01e7208 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -108,5 +108,9 @@
+
+
+
+
diff --git a/android/app/src/main/kotlin/nl/jknaapen/fladder/MainActivity.kt b/android/app/src/main/kotlin/nl/jknaapen/fladder/MainActivity.kt
index 5c630841e..98964c4eb 100644
--- a/android/app/src/main/kotlin/nl/jknaapen/fladder/MainActivity.kt
+++ b/android/app/src/main/kotlin/nl/jknaapen/fladder/MainActivity.kt
@@ -1,6 +1,7 @@
package nl.jknaapen.fladder
import BatteryOptimizationPigeon
+import FlutterError
import NativeVideoActivity
import PlayerSettingsPigeon
import StartResult
@@ -17,6 +18,7 @@ import android.provider.Settings
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.ui.platform.LocalContext
+import androidx.core.content.FileProvider
import com.ryanheise.audioservice.AudioServiceFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import nl.jknaapen.fladder.objects.PlayerSettingsObject
@@ -24,6 +26,12 @@ import nl.jknaapen.fladder.objects.TranslationsMessenger
import nl.jknaapen.fladder.objects.VideoPlayerObject
import nl.jknaapen.fladder.utility.leanBackEnabled
import androidx.core.net.toUri
+import nl.jknaapen.fladder.wallpaper.WallpaperApi
+import nl.jknaapen.fladder.wallpaper.WallpaperApiUtility
+import java.io.File
+import java.util.Objects
+
+class WallpaperFileProvider : FileProvider()
class MainActivity : AudioServiceFragmentActivity(), NativeVideoActivity {
private lateinit var videoPlayerLauncher: ActivityResultLauncher
@@ -37,6 +45,10 @@ class MainActivity : AudioServiceFragmentActivity(), NativeVideoActivity {
flutterEngine.dartExecutor.binaryMessenger,
this
)
+ WallpaperApi.setUp(
+ flutterEngine.dartExecutor.binaryMessenger,
+ WallpaperApiUtility(this, wallpaperLauncher)
+ )
VideoPlayerApi.setUp(
flutterEngine.dartExecutor.binaryMessenger,
videoPlayerHost.implementation
@@ -93,6 +105,12 @@ class MainActivity : AudioServiceFragmentActivity(), NativeVideoActivity {
setIntent(intent)
}
+ private val wallpaperLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ // Handle the result of the wallpaper intent if needed
+ }
+
override fun launchActivity(callback: (Result) -> Unit) {
try {
videoPlayerCallback = callback
diff --git a/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApi.g.kt b/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApi.g.kt
new file mode 100644
index 000000000..5118e94db
--- /dev/null
+++ b/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApi.g.kt
@@ -0,0 +1,97 @@
+// Autogenerated from Pigeon (v26.1.0), do not edit directly.
+// See also: https://pub.dev/packages/pigeon
+@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
+
+package nl.jknaapen.fladder.wallpaper
+
+import FlutterError
+import android.util.Log
+import io.flutter.plugin.common.BasicMessageChannel
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.EventChannel
+import io.flutter.plugin.common.MessageCodec
+import io.flutter.plugin.common.StandardMethodCodec
+import io.flutter.plugin.common.StandardMessageCodec
+import java.io.ByteArrayOutputStream
+import java.nio.ByteBuffer
+
+private object WallpaperApiPigeonUtils {
+
+ fun wrapResult(result: Any?): List {
+ return listOf(result)
+ }
+
+ fun wrapError(exception: Throwable): List {
+ return if (exception is FlutterError) {
+ listOf(
+ exception.code,
+ exception.message,
+ exception.details
+ )
+ } else {
+ listOf(
+ exception.javaClass.simpleName,
+ exception.toString(),
+ "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
+ )
+ }
+ }
+}
+
+private open class WallpaperApiPigeonCodec : StandardMessageCodec() {
+ override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
+ return super.readValueOfType(type, buffer)
+ }
+
+ override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
+ super.writeValue(stream, value)
+ }
+}
+
+
+/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
+interface WallpaperApi {
+ fun openWallpaperPopup(filePath: String, callback: (Result) -> Unit)
+
+ companion object {
+ /** The codec used by WallpaperApi. */
+ val codec: MessageCodec by lazy {
+ WallpaperApiPigeonCodec()
+ }
+
+ /** Sets up an instance of `WallpaperApi` to handle messages through the `binaryMessenger`. */
+ @JvmOverloads
+ fun setUp(
+ binaryMessenger: BinaryMessenger,
+ api: WallpaperApi?,
+ messageChannelSuffix: String = ""
+ ) {
+ val separatedMessageChannelSuffix =
+ if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
+ run {
+ val channel = BasicMessageChannel(
+ binaryMessenger,
+ "dev.flutter.pigeon.nl_jknaapen_fladder.wallpaper.WallpaperApi.openWallpaperPopup$separatedMessageChannelSuffix",
+ codec
+ )
+ if (api != null) {
+ channel.setMessageHandler { message, reply ->
+ val args = message as List
+ val filePathArg = args[0] as String
+ api.openWallpaperPopup(filePathArg) { result: Result ->
+ val error = result.exceptionOrNull()
+ if (error != null) {
+ reply.reply(WallpaperApiPigeonUtils.wrapError(error))
+ } else {
+ val data = result.getOrNull()
+ reply.reply(WallpaperApiPigeonUtils.wrapResult(data))
+ }
+ }
+ }
+ } else {
+ channel.setMessageHandler(null)
+ }
+ }
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApiUtility.kt b/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApiUtility.kt
new file mode 100644
index 000000000..fffcfe95c
--- /dev/null
+++ b/android/app/src/main/kotlin/nl/jknaapen/fladder/wallpaper/WallpaperApiUtility.kt
@@ -0,0 +1,45 @@
+package nl.jknaapen.fladder.wallpaper
+
+import FlutterError
+import android.content.Intent
+import androidx.core.content.FileProvider
+import java.io.File
+
+class WallpaperApiUtility(
+ val applicationContext: android.content.Context,
+ private val launcher: androidx.activity.result.ActivityResultLauncher
+) : WallpaperApi {
+ private var pendingCallback: ((Result) -> Unit)? = null
+
+ override fun openWallpaperPopup(filePath: String, callback: (Result) -> Unit) {
+ this.pendingCallback = callback
+
+ try {
+ val file = File(filePath)
+
+ val uri =
+ FileProvider.getUriForFile(
+ applicationContext,
+ "${applicationContext.packageName}.wallpaper_provider",
+ file
+ )
+
+ val intent = Intent(Intent.ACTION_ATTACH_DATA).apply {
+ addCategory(Intent.CATEGORY_DEFAULT)
+ setDataAndType(uri, "image/*")
+ putExtra("mimeType", "image/*")
+ addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ }
+
+ launcher.launch(android.content.Intent.createChooser(intent, "Set wallpaper as:"))
+ } catch (e: Exception) {
+ // Pigeon handles exceptions gracefully and passes them back to Dart
+ throw FlutterError("INTENT_ERROR", "Failed to launch intent: ${e.message}", null)
+ }
+ }
+
+ fun onResult(success: Boolean) {
+ pendingCallback?.invoke(Result.success(success))
+ pendingCallback = null
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/wallpaper_file_paths.xml b/android/app/src/main/res/xml/wallpaper_file_paths.xml
new file mode 100644
index 000000000..9ab682c64
--- /dev/null
+++ b/android/app/src/main/res/xml/wallpaper_file_paths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index d2fa5c6d3..db330a143 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -2764,5 +2764,6 @@
"musicDashboard": "Music Dashboard",
"quiet": "Quiet",
"loud": "Loud",
- "share": "Share"
+ "share": "Share",
+ "setAs": "Set as"
}
\ No newline at end of file
diff --git a/lib/screens/photo_viewer/photo_viewer_screen.dart b/lib/screens/photo_viewer/photo_viewer_screen.dart
index 876737d0a..8f8c24d07 100644
--- a/lib/screens/photo_viewer/photo_viewer_screen.dart
+++ b/lib/screens/photo_viewer/photo_viewer_screen.dart
@@ -9,7 +9,6 @@ import 'package:extended_image/extended_image.dart';
import 'package:flutter_blurhash/flutter_blurhash.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:iconsax_plus/iconsax_plus.dart';
-import 'package:share_plus/share_plus.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/models/items/photos_model.dart';
@@ -484,11 +483,6 @@ class _PhotoViewerScreenState extends ConsumerState with Widg
? IconsaxPlusLinear.filter_remove
: IconsaxPlusLinear.filter,
),
- ElevatedIconButtonLabel(
- label: context.localized.share,
- onPressed: () => sharePhoto(currentPhoto),
- icon: IconsaxPlusLinear.share,
- ),
].addInBetween(const SizedBox(width: 16)),
);
}),
@@ -512,16 +506,6 @@ class _PhotoViewerScreenState extends ConsumerState with Widg
},
);
- Future sharePhoto(PhotoModel photo) async {
- final file = await CustomCacheManager.instance.getSingleFile(photo.downloadPath(ref));
- await SharePlus.instance.share(ShareParams(files: [
- XFile(
- file.path,
- ),
- ]));
- await file.delete();
- }
-
Future markAsFavourite(PhotoModel photo, {bool? value}) async {
await ref.read(userProvider.notifier).setAsFavorite(value ?? !photo.userData.isFavourite, photo.id);
diff --git a/lib/src/wallpaper_api.g.dart b/lib/src/wallpaper_api.g.dart
new file mode 100644
index 000000000..cad40ae76
--- /dev/null
+++ b/lib/src/wallpaper_api.g.dart
@@ -0,0 +1,80 @@
+// Autogenerated from Pigeon (v26.1.0), do not edit directly.
+// See also: https://pub.dev/packages/pigeon
+// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
+
+import 'dart:async';
+import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
+
+import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
+import 'package:flutter/services.dart';
+
+PlatformException _createConnectionError(String channelName) {
+ return PlatformException(
+ code: 'channel-error',
+ message: 'Unable to establish connection on channel: "$channelName".',
+ );
+}
+
+
+class _PigeonCodec extends StandardMessageCodec {
+ const _PigeonCodec();
+ @override
+ void writeValue(WriteBuffer buffer, Object? value) {
+ if (value is int) {
+ buffer.putUint8(4);
+ buffer.putInt64(value);
+ } else {
+ super.writeValue(buffer, value);
+ }
+ }
+
+ @override
+ Object? readValueOfType(int type, ReadBuffer buffer) {
+ switch (type) {
+ default:
+ return super.readValueOfType(type, buffer);
+ }
+ }
+}
+
+class WallpaperApi {
+ /// Constructor for [WallpaperApi]. The [binaryMessenger] named argument is
+ /// available for dependency injection. If it is left null, the default
+ /// BinaryMessenger will be used which routes to the host platform.
+ WallpaperApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
+ : pigeonVar_binaryMessenger = binaryMessenger,
+ pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
+ final BinaryMessenger? pigeonVar_binaryMessenger;
+
+ static const MessageCodec