mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
349 lines
14 KiB
Dart
349 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:isar_community/isar.dart';
|
|
import 'package:mangayomi/eval/model/m_bridge.dart';
|
|
import 'package:mangayomi/eval/model/source_preference.dart';
|
|
import 'package:mangayomi/main.dart';
|
|
import 'package:mangayomi/models/changed.dart';
|
|
import 'package:mangayomi/models/source.dart';
|
|
import 'package:mangayomi/modules/browse/extension/providers/extension_preferences_providers.dart';
|
|
import 'package:mangayomi/modules/browse/extension/widgets/source_preference_widget.dart';
|
|
import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart';
|
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
|
import 'package:mangayomi/services/get_source_preference.dart';
|
|
import 'package:mangayomi/services/http/m_client.dart';
|
|
import 'package:mangayomi/utils/cached_network.dart';
|
|
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
|
import 'package:mangayomi/utils/language.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class ExtensionDetail extends ConsumerStatefulWidget {
|
|
final Source source;
|
|
const ExtensionDetail({super.key, required this.source});
|
|
|
|
@override
|
|
ConsumerState<ExtensionDetail> createState() => _ExtensionDetailState();
|
|
}
|
|
|
|
class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|
late Source source = isar.sources.getSync(widget.source.id!)!;
|
|
late List<SourcePreference>? sourcePreference = () {
|
|
try {
|
|
return getSourcePreference(
|
|
source: source,
|
|
).map((e) => getSourcePreferenceEntry(e.key!, source.id!)).toList();
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}();
|
|
Future<void> _launchInBrowser(Uri url) async {
|
|
if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
|
|
throw 'Could not launch $url';
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = l10nLocalizations(context)!;
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(l10n.extension_detail),
|
|
leading: BackButton(onPressed: () => Navigator.pop(context, source)),
|
|
actions: [
|
|
if (source.repo?.website != null)
|
|
IconButton(
|
|
onPressed: () {
|
|
_launchInBrowser(Uri.parse(source.repo!.website!));
|
|
},
|
|
icon: Icon(Icons.open_in_new_outlined),
|
|
),
|
|
],
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 20),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(
|
|
context,
|
|
).secondaryHeaderColor.withValues(alpha: 0.5),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: widget.source.iconUrl!.isEmpty
|
|
? const Icon(Icons.source_outlined, size: 140)
|
|
: cachedNetworkImage(
|
|
imageUrl: widget.source.iconUrl!,
|
|
fit: BoxFit.contain,
|
|
width: 140,
|
|
height: 140,
|
|
errorWidget: const SizedBox(
|
|
width: 140,
|
|
height: 140,
|
|
child: Center(
|
|
child: Icon(Icons.source_outlined, size: 140),
|
|
),
|
|
),
|
|
headers: {},
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(12),
|
|
child: Text(
|
|
widget.source.name!,
|
|
style: const TextStyle(
|
|
fontSize: 23,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: context.primaryColor.withValues(alpha: 0.2),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Column(
|
|
children: [
|
|
Text(
|
|
widget.source.version!,
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
l10n.version,
|
|
style: const TextStyle(fontSize: 11),
|
|
),
|
|
],
|
|
),
|
|
Column(
|
|
children: [
|
|
Text(
|
|
completeLanguageName(widget.source.lang!),
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Text(
|
|
l10n.language,
|
|
style: const TextStyle(fontSize: 11),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: SizedBox(
|
|
width: context.width(1),
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
padding: const EdgeInsets.all(0),
|
|
backgroundColor: Colors.transparent,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
elevation: 0,
|
|
shadowColor: Colors.transparent,
|
|
),
|
|
onPressed: () async {
|
|
final res = await context.push(
|
|
'/codeEditor',
|
|
extra: source.id,
|
|
);
|
|
if (res != null && mounted) {
|
|
setState(() {
|
|
source = res as Source;
|
|
sourcePreference = getSourcePreference(source: source)
|
|
.map(
|
|
(e) =>
|
|
getSourcePreferenceEntry(e.key!, source.id!),
|
|
)
|
|
.toList();
|
|
});
|
|
}
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
|
child: Text(
|
|
l10n.edit_code,
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
const Icon(Icons.code),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: SizedBox(
|
|
width: context.width(1),
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
padding: const EdgeInsets.all(0),
|
|
backgroundColor: Colors.transparent,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
elevation: 0,
|
|
shadowColor: Colors.transparent,
|
|
),
|
|
onPressed: () async {
|
|
MClient.deleteAllCookies(source.baseUrl ?? "");
|
|
botToast("Cookies deleted!");
|
|
},
|
|
child: const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
|
child: Text(
|
|
"Delete all cookies",
|
|
style: TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: SizedBox(
|
|
width: context.width(1),
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
padding: const EdgeInsets.all(0),
|
|
side: BorderSide(color: context.primaryColor, width: 0.3),
|
|
backgroundColor: Colors.transparent,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
elevation: 0,
|
|
shadowColor: Colors.transparent,
|
|
),
|
|
onPressed: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) {
|
|
return AlertDialog(
|
|
title: Text(widget.source.name!),
|
|
content: Text(
|
|
l10n.uninstall_extension(widget.source.name!),
|
|
),
|
|
actions: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.pop(ctx);
|
|
},
|
|
child: Text(l10n.cancel),
|
|
),
|
|
const SizedBox(width: 15),
|
|
TextButton(
|
|
onPressed: () {
|
|
final sourcePrefsIds = isar
|
|
.sourcePreferences
|
|
.filter()
|
|
.sourceIdEqualTo(source.id!)
|
|
.findAllSync()
|
|
.map((e) => e.id!)
|
|
.toList();
|
|
final sourcePrefsStringIds = isar
|
|
.sourcePreferenceStringValues
|
|
.filter()
|
|
.sourceIdEqualTo(source.id!)
|
|
.findAllSync()
|
|
.map((e) => e.id)
|
|
.toList();
|
|
isar.writeTxnSync(() {
|
|
if (source.isObsolete ?? false) {
|
|
isar.sources.deleteSync(
|
|
widget.source.id!,
|
|
);
|
|
ref
|
|
.read(
|
|
synchingProvider(
|
|
syncId: 1,
|
|
).notifier,
|
|
)
|
|
.addChangedPart(
|
|
ActionType.removeExtension,
|
|
source.id,
|
|
"{}",
|
|
false,
|
|
);
|
|
} else {
|
|
isar.sources.putSync(
|
|
widget.source
|
|
..sourceCode = ""
|
|
..isAdded = false
|
|
..isPinned = false
|
|
..updatedAt = DateTime.now()
|
|
.millisecondsSinceEpoch,
|
|
);
|
|
}
|
|
isar.sourcePreferences.deleteAllSync(
|
|
sourcePrefsIds,
|
|
);
|
|
isar.sourcePreferenceStringValues
|
|
.deleteAllSync(sourcePrefsStringIds);
|
|
});
|
|
|
|
Navigator.pop(ctx);
|
|
Navigator.pop(context);
|
|
},
|
|
child: Text(l10n.ok),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
},
|
|
child: Text(
|
|
l10n.uninstall,
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (sourcePreference != null)
|
|
SourcePreferenceWidget(
|
|
sourcePreference: sourcePreference!,
|
|
source: source,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|