mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: custom piped & invidious instance support
This commit is contained in:
parent
c3bbc129ad
commit
91871d0d26
@ -8,6 +8,7 @@ class AdaptiveSelectTile<T> extends HookWidget {
|
|||||||
final Widget title;
|
final Widget title;
|
||||||
final Widget? subtitle;
|
final Widget? subtitle;
|
||||||
final Widget? secondary;
|
final Widget? secondary;
|
||||||
|
final List<Widget>? trailing;
|
||||||
final ListTileControlAffinity? controlAffinity;
|
final ListTileControlAffinity? controlAffinity;
|
||||||
final T value;
|
final T value;
|
||||||
final ValueChanged<T?>? onChanged;
|
final ValueChanged<T?>? onChanged;
|
||||||
@ -34,6 +35,7 @@ class AdaptiveSelectTile<T> extends HookWidget {
|
|||||||
this.controlAffinity = ListTileControlAffinity.trailing,
|
this.controlAffinity = ListTileControlAffinity.trailing,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
|
this.trailing,
|
||||||
this.breakLayout,
|
this.breakLayout,
|
||||||
this.showValueWhenUnfolded = true,
|
this.showValueWhenUnfolded = true,
|
||||||
super.key,
|
super.key,
|
||||||
@ -54,8 +56,10 @@ class AdaptiveSelectTile<T> extends HookWidget {
|
|||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
popupConstraints: popupConstraints ?? const BoxConstraints(maxWidth: 200),
|
popupConstraints: popupConstraints ?? const BoxConstraints(maxWidth: 200),
|
||||||
popupWidthConstraint: popupWidthConstraint ?? PopoverConstraint.flexible,
|
popupWidthConstraint: popupWidthConstraint ?? PopoverConstraint.flexible,
|
||||||
|
autoClosePopover: true,
|
||||||
popup: (context) {
|
popup: (context) {
|
||||||
return SelectPopup(
|
return SelectPopup(
|
||||||
|
autoClose: true,
|
||||||
items: SelectItemBuilder(
|
items: SelectItemBuilder(
|
||||||
childCount: options.length,
|
childCount: options.length,
|
||||||
builder: (context, index) {
|
builder: (context, index) {
|
||||||
@ -82,9 +86,20 @@ class AdaptiveSelectTile<T> extends HookWidget {
|
|||||||
leading: controlAffinity != ListTileControlAffinity.leading
|
leading: controlAffinity != ListTileControlAffinity.leading
|
||||||
? secondary
|
? secondary
|
||||||
: control,
|
: control,
|
||||||
trailing: controlAffinity == ListTileControlAffinity.leading
|
trailing: Row(
|
||||||
? secondary
|
mainAxisSize: MainAxisSize.min,
|
||||||
: control,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
spacing: 5,
|
||||||
|
children: [
|
||||||
|
...?trailing,
|
||||||
|
if (controlAffinity == ListTileControlAffinity.leading &&
|
||||||
|
secondary != null)
|
||||||
|
secondary!
|
||||||
|
else if (controlAffinity == ListTileControlAffinity.trailing &&
|
||||||
|
control != null)
|
||||||
|
control,
|
||||||
|
],
|
||||||
|
),
|
||||||
onTap: breakLayout ?? mediaQuery.mdAndUp
|
onTap: breakLayout ?? mediaQuery.mdAndUp
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
|
@ -422,5 +422,7 @@
|
|||||||
"youtube_engine_set_path": "Make sure it's available in the PATH variable or\nset the absolute path to the {engine} executable below",
|
"youtube_engine_set_path": "Make sure it's available in the PATH variable or\nset the absolute path to the {engine} executable below",
|
||||||
"youtube_engine_unix_issue_message": "In macOS/Linux/unix like OS's, setting path on .zshrc/.bashrc/.bash_profile etc. won't work.\nYou need to set the path in the shell configuration file",
|
"youtube_engine_unix_issue_message": "In macOS/Linux/unix like OS's, setting path on .zshrc/.bashrc/.bash_profile etc. won't work.\nYou need to set the path in the shell configuration file",
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"file_not_found": "File not found"
|
"file_not_found": "File not found",
|
||||||
|
"custom": "Custom",
|
||||||
|
"add_custom_url": "Add custom URL"
|
||||||
}
|
}
|
@ -4,6 +4,9 @@ import 'package:auto_route/auto_route.dart';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart' show ListTile;
|
import 'package:flutter/material.dart' show ListTile;
|
||||||
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||||
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -11,6 +14,8 @@ import 'package:piped_client/piped_client.dart';
|
|||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
import 'package:spotube/collections/routes.gr.dart';
|
import 'package:spotube/collections/routes.gr.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
|
import 'package:spotube/components/form/text_form_field.dart';
|
||||||
|
import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dart';
|
||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.dart';
|
||||||
import 'package:spotube/modules/settings/section_card_with_heading.dart';
|
import 'package:spotube/modules/settings/section_card_with_heading.dart';
|
||||||
import 'package:spotube/components/adaptive/adaptive_select_tile.dart';
|
import 'package:spotube/components/adaptive/adaptive_select_tile.dart';
|
||||||
@ -97,10 +102,106 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
value: preferences.pipedInstance,
|
value: preferences.pipedInstance,
|
||||||
showValueWhenUnfolded: false,
|
showValueWhenUnfolded: false,
|
||||||
options: data
|
trailing: [
|
||||||
.sortedBy((e) => e.name)
|
Tooltip(
|
||||||
.map(
|
tooltip: TooltipContainer(
|
||||||
(e) => SelectItemButton(
|
child: Text(context.l10n.add_custom_url),
|
||||||
|
),
|
||||||
|
child: IconButton.outline(
|
||||||
|
icon: const Icon(SpotubeIcons.edit),
|
||||||
|
size: ButtonSize.small,
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierColor: Colors.black.withValues(alpha: 0.5),
|
||||||
|
builder: (context) => HookBuilder(
|
||||||
|
builder: (context) {
|
||||||
|
final controller =
|
||||||
|
useShadcnTextEditingController(
|
||||||
|
text: preferences.pipedInstance,
|
||||||
|
);
|
||||||
|
final formKey = useMemoized(
|
||||||
|
() => GlobalKey<FormBuilderState>(), []);
|
||||||
|
|
||||||
|
return Alert(
|
||||||
|
title:
|
||||||
|
Text(context.l10n.piped_instance).h4(),
|
||||||
|
content: FormBuilder(
|
||||||
|
key: formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Gap(10),
|
||||||
|
TextFormBuilderField(
|
||||||
|
name: "url",
|
||||||
|
controller: controller,
|
||||||
|
placeholder: Text(
|
||||||
|
context.l10n.piped_instance),
|
||||||
|
validator:
|
||||||
|
FormBuilderValidators.url(),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Button.secondary(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Text(context.l10n.cancel),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
Expanded(
|
||||||
|
child: Button.primary(
|
||||||
|
onPressed: () {
|
||||||
|
if (!formKey.currentState!
|
||||||
|
.saveAndValidate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
preferencesNotifier
|
||||||
|
.setPipedInstance(
|
||||||
|
controller.text,
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Text(context.l10n.save),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
options: [
|
||||||
|
if (data
|
||||||
|
.none((e) => e.apiUrl == preferences.pipedInstance))
|
||||||
|
SelectItemButton(
|
||||||
|
value: preferences.pipedInstance,
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: theme.typography.xSmall.copyWith(
|
||||||
|
color: theme.colorScheme.foreground,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(text: context.l10n.custom),
|
||||||
|
const TextSpan(text: "\n"),
|
||||||
|
TextSpan(text: preferences.pipedInstance),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final e in data.sortedBy((e) => e.name))
|
||||||
|
SelectItemButton(
|
||||||
value: e.apiUrl,
|
value: e.apiUrl,
|
||||||
child: RichText(
|
child: RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
@ -121,8 +222,7 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
.toList(),
|
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
preferencesNotifier.setPipedInstance(value);
|
preferencesNotifier.setPipedInstance(value);
|
||||||
@ -157,12 +257,108 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
"${context.l10n.invidious_description}\n"
|
"${context.l10n.invidious_description}\n"
|
||||||
"${context.l10n.invidious_warning}",
|
"${context.l10n.invidious_warning}",
|
||||||
),
|
),
|
||||||
|
trailing: [
|
||||||
|
Tooltip(
|
||||||
|
tooltip: TooltipContainer(
|
||||||
|
child: Text(context.l10n.add_custom_url),
|
||||||
|
),
|
||||||
|
child: IconButton.outline(
|
||||||
|
icon: const Icon(SpotubeIcons.edit),
|
||||||
|
size: ButtonSize.small,
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierColor: Colors.black.withValues(alpha: 0.5),
|
||||||
|
builder: (context) => HookBuilder(
|
||||||
|
builder: (context) {
|
||||||
|
final controller =
|
||||||
|
useShadcnTextEditingController(
|
||||||
|
text: preferences.invidiousInstance,
|
||||||
|
);
|
||||||
|
final formKey = useMemoized(
|
||||||
|
() => GlobalKey<FormBuilderState>(), []);
|
||||||
|
|
||||||
|
return Alert(
|
||||||
|
title: Text(context.l10n.invidious_instance)
|
||||||
|
.h4(),
|
||||||
|
content: FormBuilder(
|
||||||
|
key: formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Gap(10),
|
||||||
|
TextFormBuilderField(
|
||||||
|
name: "url",
|
||||||
|
controller: controller,
|
||||||
|
placeholder: Text(context
|
||||||
|
.l10n.invidious_instance),
|
||||||
|
validator:
|
||||||
|
FormBuilderValidators.url(),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Button.secondary(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Text(context.l10n.cancel),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
Expanded(
|
||||||
|
child: Button.primary(
|
||||||
|
onPressed: () {
|
||||||
|
if (!formKey.currentState!
|
||||||
|
.saveAndValidate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
preferencesNotifier
|
||||||
|
.setInvidiousInstance(
|
||||||
|
controller.text,
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
Text(context.l10n.save),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
value: preferences.invidiousInstance,
|
value: preferences.invidiousInstance,
|
||||||
showValueWhenUnfolded: false,
|
showValueWhenUnfolded: false,
|
||||||
options: data
|
options: [
|
||||||
.sortedBy((e) => e.name)
|
if (data.none((e) =>
|
||||||
.map(
|
e.details.uri == preferences.invidiousInstance))
|
||||||
(e) => SelectItemButton(
|
SelectItemButton(
|
||||||
|
value: preferences.invidiousInstance,
|
||||||
|
child: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: theme.typography.xSmall.copyWith(
|
||||||
|
color: theme.colorScheme.foreground,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(text: context.l10n.custom),
|
||||||
|
const TextSpan(text: "\n"),
|
||||||
|
TextSpan(text: preferences.invidiousInstance),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final e in data.sortedBy((e) => e.name))
|
||||||
|
SelectItemButton(
|
||||||
value: e.details.uri,
|
value: e.details.uri,
|
||||||
child: RichText(
|
child: RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
@ -183,8 +379,7 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
.toList(),
|
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
preferencesNotifier.setInvidiousInstance(value);
|
preferencesNotifier.setInvidiousInstance(value);
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"bn": [
|
"bn": [
|
||||||
@ -48,7 +50,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ca": [
|
"ca": [
|
||||||
@ -74,7 +78,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"cs": [
|
"cs": [
|
||||||
@ -100,7 +106,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"de": [
|
"de": [
|
||||||
@ -126,7 +134,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"es": [
|
"es": [
|
||||||
@ -152,7 +162,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"eu": [
|
"eu": [
|
||||||
@ -178,7 +190,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"fa": [
|
"fa": [
|
||||||
@ -204,7 +218,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"fi": [
|
"fi": [
|
||||||
@ -230,7 +246,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"fr": [
|
"fr": [
|
||||||
@ -256,7 +274,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"hi": [
|
"hi": [
|
||||||
@ -282,7 +302,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"id": [
|
"id": [
|
||||||
@ -308,7 +330,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"it": [
|
"it": [
|
||||||
@ -334,7 +358,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ja": [
|
"ja": [
|
||||||
@ -360,7 +386,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ka": [
|
"ka": [
|
||||||
@ -386,7 +414,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ko": [
|
"ko": [
|
||||||
@ -412,7 +442,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ne": [
|
"ne": [
|
||||||
@ -438,7 +470,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"nl": [
|
"nl": [
|
||||||
@ -464,7 +498,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"pl": [
|
"pl": [
|
||||||
@ -490,7 +526,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"pt": [
|
"pt": [
|
||||||
@ -516,7 +554,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ru": [
|
"ru": [
|
||||||
@ -542,7 +582,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"th": [
|
"th": [
|
||||||
@ -568,7 +610,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"tr": [
|
"tr": [
|
||||||
@ -594,7 +638,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"uk": [
|
"uk": [
|
||||||
@ -620,7 +666,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"vi": [
|
"vi": [
|
||||||
@ -646,7 +694,9 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
],
|
],
|
||||||
|
|
||||||
"zh": [
|
"zh": [
|
||||||
@ -672,6 +722,8 @@
|
|||||||
"youtube_engine_set_path",
|
"youtube_engine_set_path",
|
||||||
"youtube_engine_unix_issue_message",
|
"youtube_engine_unix_issue_message",
|
||||||
"download",
|
"download",
|
||||||
"file_not_found"
|
"file_not_found",
|
||||||
|
"custom",
|
||||||
|
"add_custom_url"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user