mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-21 07:41:58 +00:00
added screenshot option to player view
This commit is contained in:
parent
17c18bd79a
commit
95619437a1
3 changed files with 221 additions and 0 deletions
|
|
@ -89,6 +89,7 @@
|
|||
"appearance_subtitle": "Thema, Datum- & Zeitformat",
|
||||
"theme": "Thema",
|
||||
"dark_mode": "Dunkler Modus",
|
||||
"follow_system_theme": "System Hell/Dunkel-Modus folgen",
|
||||
"on": "An",
|
||||
"off": "Aus",
|
||||
"pure_black_dark_mode": "Rein schwarzer Dunkler Modus",
|
||||
|
|
@ -375,6 +376,7 @@
|
|||
"save": "Speichern",
|
||||
"picture_saved": "Bild gespeichert",
|
||||
"cover_updated": "Cover aktualisiert",
|
||||
"include_subtitles": "Mit Untertiteln speichern",
|
||||
"blend_mode_default": "Standard",
|
||||
"blend_mode_multiply": "Multiplizieren",
|
||||
"blend_mode_screen": "Bildschirm",
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
"appearance_subtitle": "Theme, date & time format",
|
||||
"theme": "Theme",
|
||||
"dark_mode": "Dark mode",
|
||||
"follow_system_theme": "Follow system theme",
|
||||
"on": "On",
|
||||
"off": "Off",
|
||||
"pure_black_dark_mode": "Pure black dark mode",
|
||||
|
|
@ -379,6 +380,7 @@
|
|||
"save": "Save",
|
||||
"picture_saved": "Picture saved",
|
||||
"cover_updated": "Cover updated",
|
||||
"include_subtitles": "Include subtitles",
|
||||
"blend_mode_default": "Default",
|
||||
"blend_mode_multiply": "Multiply",
|
||||
"blend_mode_screen": "Screen",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart' as riv;
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/changed.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/video.dart' as vid;
|
||||
import 'package:mangayomi/modules/anime/providers/anime_player_controller_provider.dart';
|
||||
import 'package:mangayomi/modules/anime/widgets/aniskip_countdown_btn.dart';
|
||||
|
|
@ -19,9 +21,11 @@ import 'package:mangayomi/modules/anime/widgets/subtitle_view.dart';
|
|||
import 'package:mangayomi/modules/anime/widgets/subtitle_setting_widget.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
||||
import 'package:mangayomi/modules/more/settings/player/providers/player_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
|
||||
import 'package:mangayomi/modules/widgets/progress_center.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/services/aniskip.dart';
|
||||
import 'package:mangayomi/services/get_video_list.dart';
|
||||
import 'package:mangayomi/services/torrent_server.dart';
|
||||
|
|
@ -30,8 +34,11 @@ import 'package:mangayomi/utils/language.dart';
|
|||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:media_kit_video/media_kit_video_controls/src/controls/extensions/duration.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
|
||||
bool _isDesktop = Platform.isMacOS || Platform.isLinux || Platform.isWindows;
|
||||
|
||||
|
|
@ -209,6 +216,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
bool _hasOpeningSkip = false;
|
||||
bool _hasEndingSkip = false;
|
||||
bool _initSubtitleAndAudio = true;
|
||||
bool _includeSubtitles = false;
|
||||
|
||||
late StreamSubscription<Duration> _currentPositionSub = _player
|
||||
.stream
|
||||
|
|
@ -1174,6 +1182,16 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
}
|
||||
},
|
||||
),
|
||||
btnToShowShareScreenshot(
|
||||
widget.episode,
|
||||
onChanged: (v) {
|
||||
if (v) {
|
||||
_player.play();
|
||||
} else {
|
||||
_player.pause();
|
||||
}
|
||||
},
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
|
|
@ -1373,6 +1391,205 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
);
|
||||
}
|
||||
|
||||
Widget btnToShowShareScreenshot(
|
||||
Chapter episode, {
|
||||
void Function(bool)? onChanged,
|
||||
}) {
|
||||
return IconButton(
|
||||
onPressed: () async {
|
||||
onChanged?.call(false);
|
||||
Widget button(String label, IconData icon, Function() onPressed) =>
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Icon(icon),
|
||||
),
|
||||
Text(label),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
final name =
|
||||
"${episode.manga.value!.name} ${episode.name} - ${_currentPosition.value.toString()}"
|
||||
.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_');
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
constraints: BoxConstraints(maxWidth: context.width(1)),
|
||||
builder: (context) {
|
||||
return SuperListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
),
|
||||
color: context.themeData.scaffoldBackgroundColor,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
height: 7,
|
||||
width: 35,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
color: context.secondaryColor.withValues(
|
||||
alpha: 0.4,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
button(
|
||||
context.l10n.set_as_cover,
|
||||
Icons.image_outlined,
|
||||
() async {
|
||||
final imageBytes = await _player.screenshot(
|
||||
format: "image/png",
|
||||
includeLibassSubtitles: _includeSubtitles,
|
||||
);
|
||||
if (context.mounted) {
|
||||
final res = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
context.l10n.use_this_as_cover_art,
|
||||
),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(context.l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final manga =
|
||||
episode.manga.value!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(
|
||||
manga
|
||||
..customCoverImage =
|
||||
imageBytes,
|
||||
);
|
||||
ref
|
||||
.read(
|
||||
synchingProvider(
|
||||
syncId: 1,
|
||||
).notifier,
|
||||
)
|
||||
.addChangedPart(
|
||||
ActionType.updateItem,
|
||||
manga.id,
|
||||
manga.toJson(),
|
||||
false,
|
||||
);
|
||||
});
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context, "ok");
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.ok),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
if (res != null &&
|
||||
res == "ok" &&
|
||||
context.mounted) {
|
||||
Navigator.pop(context);
|
||||
botToast(
|
||||
context.l10n.cover_updated,
|
||||
second: 3,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
button(
|
||||
context.l10n.share,
|
||||
Icons.share_outlined,
|
||||
() async {
|
||||
final imageBytes = await _player.screenshot(
|
||||
format: "image/png",
|
||||
includeLibassSubtitles: _includeSubtitles,
|
||||
);
|
||||
await Share.shareXFiles([
|
||||
XFile.fromData(
|
||||
imageBytes!,
|
||||
name: name,
|
||||
mimeType: 'image/png',
|
||||
),
|
||||
]);
|
||||
},
|
||||
),
|
||||
button(
|
||||
context.l10n.save,
|
||||
Icons.save_outlined,
|
||||
() async {
|
||||
final imageBytes = await _player.screenshot(
|
||||
format: "image/png",
|
||||
includeLibassSubtitles: _includeSubtitles,
|
||||
);
|
||||
final dir =
|
||||
await StorageProvider().getGalleryDirectory();
|
||||
final file = File(p.join(dir!.path, "$name.png"));
|
||||
file.writeAsBytesSync(imageBytes!);
|
||||
if (context.mounted) {
|
||||
botToast(context.l10n.picture_saved, second: 3);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SwitchListTile(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_includeSubtitles = value;
|
||||
});
|
||||
},
|
||||
title: Text(context.l10n.include_subtitles),
|
||||
value: _includeSubtitles,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
onChanged?.call(true);
|
||||
},
|
||||
icon: Icon(Icons.adaptive.share),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: _videoPlayer(context));
|
||||
|
|
|
|||
Loading…
Reference in a new issue