mirror of
https://github.com/madari-media/madari-oss.git
synced 2026-03-11 21:26:56 +00:00
Project import generated by Copybara.
GitOrigin-RevId: dc6df4683dd1ae55904108f04a26dbf68fed5e3c
This commit is contained in:
parent
0891e8eddf
commit
f7c6cdb209
8 changed files with 64 additions and 248 deletions
|
|
@ -6,8 +6,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:madari_client/features/connection/types/stremio.dart';
|
||||
import 'package:madari_client/features/connections/service/base_connection_service.dart';
|
||||
import 'package:madari_client/features/doc_viewer/container/doc_viewer.dart';
|
||||
import 'package:madari_client/utils/external_player.dart';
|
||||
|
||||
import '../../../../utils/external_player.dart';
|
||||
import '../../../../utils/load_language.dart';
|
||||
import '../../../doc_viewer/types/doc_source.dart';
|
||||
import '../../../downloads/service/service.dart';
|
||||
|
|
|
|||
|
|
@ -274,16 +274,10 @@ class _StremioItemViewerState extends State<StremioItemViewer> {
|
|||
if (widget.original != null &&
|
||||
widget.original?.type == "series" &&
|
||||
widget.original?.videos?.isNotEmpty == true)
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isWideScreen ? (screenWidth - contentWidth) / 2 : 0,
|
||||
vertical: 0,
|
||||
),
|
||||
sliver: StremioItemSeasonSelector(
|
||||
meta: item!,
|
||||
library: widget.library,
|
||||
service: widget.service,
|
||||
),
|
||||
StremioItemSeasonSelector(
|
||||
meta: item!,
|
||||
library: widget.library,
|
||||
service: widget.service,
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
|
|
|
|||
|
|
@ -165,56 +165,62 @@ class _StremioItemSeasonSelectorState extends State<StremioItemSeasonSelector>
|
|||
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 320),
|
||||
child: ElevatedButton.icon(
|
||||
icon: const Icon(Icons.shuffle),
|
||||
label: const Text("Random Episode"),
|
||||
onPressed: () {
|
||||
Random random = Random();
|
||||
int randomIndex = random.nextInt(
|
||||
widget.meta.videos!.length,
|
||||
);
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isWideScreen ? (screenWidth - contentWidth) / 2 : 8,
|
||||
),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 320),
|
||||
child: ElevatedButton.icon(
|
||||
icon: const Icon(Icons.shuffle),
|
||||
label: const Text("Random Episode"),
|
||||
onPressed: () {
|
||||
Random random = Random();
|
||||
int randomIndex = random.nextInt(
|
||||
widget.meta.videos!.length,
|
||||
);
|
||||
|
||||
openEpisode(
|
||||
currentSeason: widget.meta.videos![randomIndex].season,
|
||||
episode: widget.meta.videos![randomIndex],
|
||||
);
|
||||
},
|
||||
openEpisode(
|
||||
currentSeason:
|
||||
widget.meta.videos![randomIndex].season,
|
||||
episode: widget.meta.videos![randomIndex],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: TabBar(
|
||||
tabAlignment: TabAlignment.start,
|
||||
dividerColor: Colors.transparent,
|
||||
controller: _tabController,
|
||||
isScrollable: true,
|
||||
splashBorderRadius: BorderRadius.circular(8),
|
||||
padding: const EdgeInsets.all(4),
|
||||
tabs: seasons.map((season) {
|
||||
return Tab(
|
||||
text: season == 0 ? "Specials" : 'Season $season',
|
||||
height: 40,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
tabAlignment: TabAlignment.start,
|
||||
dividerColor: Colors.transparent,
|
||||
controller: _tabController,
|
||||
isScrollable: true,
|
||||
splashBorderRadius: BorderRadius.circular(8),
|
||||
padding: const EdgeInsets.all(4),
|
||||
tabs: seasons.map((season) {
|
||||
return Tab(
|
||||
text: season == 0 ? "Specials" : 'Season $season',
|
||||
height: 40,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import 'package:madari_client/engine/engine.dart';
|
|||
import 'package:pdfrx/pdfrx.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class MagicShowMarkdown extends StatefulWidget {
|
||||
final RecordModel record;
|
||||
|
|
@ -141,8 +140,6 @@ class _MagicShowMarkdownState extends State<MagicShowMarkdown> {
|
|||
}
|
||||
}
|
||||
|
||||
// Add the mermaid diagram
|
||||
contentWidgets.add(_buildMermaidDiagram(match.group(1)!));
|
||||
lastEnd = match.end;
|
||||
}
|
||||
|
||||
|
|
@ -173,17 +170,6 @@ class _MagicShowMarkdownState extends State<MagicShowMarkdown> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildMermaidDiagram(String mermaidCode) {
|
||||
return Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 300,
|
||||
),
|
||||
child: MermaidRenderer(
|
||||
html: mermaidCode,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
@ -339,143 +325,3 @@ class _MagicShowMarkdownState extends State<MagicShowMarkdown> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MermaidRenderer extends StatefulWidget {
|
||||
final String html;
|
||||
|
||||
const MermaidRenderer({
|
||||
super.key,
|
||||
required this.html,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MermaidRenderer> createState() => _MermaidRendererState();
|
||||
}
|
||||
|
||||
class _MermaidRendererState extends State<MermaidRenderer> {
|
||||
late WebViewController controller;
|
||||
bool isFullScreen = false;
|
||||
bool hasError = false;
|
||||
|
||||
String get html => """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
startOnLoad: true,
|
||||
theme: 'default'
|
||||
});
|
||||
|
||||
window.onerror = function(msg, url, lineNo, columnNo, error) {
|
||||
window.flutter_inappwebview.callHandler('onError', msg);
|
||||
return false;
|
||||
};
|
||||
|
||||
mermaid.parseError = function(err) {
|
||||
window.flutter_inappwebview.callHandler('onError', err);
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="mermaid">
|
||||
${widget.html}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..addJavaScriptChannel(
|
||||
'flutter_inappwebview',
|
||||
onMessageReceived: (message) {
|
||||
setState(() {
|
||||
hasError = true;
|
||||
});
|
||||
},
|
||||
)
|
||||
..loadHtmlString(html);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (hasError) {
|
||||
return Container(
|
||||
height: 100,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.red),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'Unable to render diagram.\nPlease check the syntax.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
isFullScreen ? BorderRadius.zero : BorderRadius.circular(10),
|
||||
child: WebViewWidget(
|
||||
controller: controller,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 8,
|
||||
right: 8,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen,
|
||||
color: Colors.grey[800],
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isFullScreen = !isFullScreen;
|
||||
});
|
||||
if (isFullScreen) {
|
||||
final controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..loadHtmlString(html);
|
||||
|
||||
Navigator.of(context)
|
||||
.push(
|
||||
MaterialPageRoute(
|
||||
fullscreenDialog: true,
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: const Text("Diagram"),
|
||||
),
|
||||
body: WebViewWidget(controller: controller),
|
||||
),
|
||||
),
|
||||
)
|
||||
.then((_) {
|
||||
setState(() {
|
||||
isFullScreen = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,10 +38,16 @@ PlaybackConfig getPlaybackConfig() {
|
|||
|
||||
@JsonSerializable()
|
||||
class PlaybackConfig {
|
||||
@JsonKey(defaultValue: true)
|
||||
final bool autoPlay;
|
||||
@JsonKey(defaultValue: 1.0)
|
||||
final double playbackSpeed;
|
||||
@JsonKey(defaultValue: "eng")
|
||||
final String defaultAudioTrack;
|
||||
@JsonKey(defaultValue: "eng")
|
||||
final String defaultSubtitleTrack;
|
||||
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool externalPlayer;
|
||||
final Map<String, String>? externalPlayerId;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import sqflite_darwin
|
|||
import sqlite3_flutter_libs
|
||||
import url_launcher_macos
|
||||
import wakelock_plus
|
||||
import webview_flutter_wkwebview
|
||||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
|
|
@ -37,6 +36,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||
FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin"))
|
||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||
}
|
||||
|
|
|
|||
34
pubspec.lock
34
pubspec.lock
|
|
@ -1812,38 +1812,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.0"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: "285cedfd9441267f6cca8843458620b5fda1af75b04f5818d0441acda5d7df19"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_platform_interface
|
||||
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.0"
|
||||
webview_flutter_wkwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: b7e92f129482460951d96ef9a46b49db34bd2e1621685de26e9eaafd9674e7eb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.16.3"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1869,7 +1837,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
|
|
|
|||
|
|
@ -44,12 +44,10 @@ dependencies:
|
|||
flutter_dotenv: ^5.2.1
|
||||
intl: ^0.20.1
|
||||
simple_animations: ^5.0.0+3
|
||||
webview_flutter: ^4.10.0
|
||||
pdfrx: ^1.0.93
|
||||
photo_view: ^0.15.0
|
||||
window_manager: ^0.4.2
|
||||
background_downloader: ^8.8.0
|
||||
xml: ^6.5.0
|
||||
file_picker: ^8.1.4
|
||||
flutter_inappwebview: ^6.1.5
|
||||
drift: ^2.22.1
|
||||
|
|
|
|||
Loading…
Reference in a new issue