diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 803c22d..bcfa22b 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -19,6 +19,10 @@
android:icon="@mipmap/ic_launcher"
android:enableOnBackInvokedCallback="true"
android:requestLegacyExternalStorage="true">
+
+
6.0.3)
+ - flutter_inappwebview_ios/Core (0.0.1):
+ - Flutter
+ - OrderedSet (~> 6.0.3)
- flutter_native_splash (2.4.3):
- Flutter
- flutter_udid (0.0.1):
@@ -188,6 +195,7 @@ PODS:
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
+ - OrderedSet (6.0.3)
- package_info_plus (0.4.5):
- Flutter
- pasteboard (0.0.1):
@@ -239,6 +247,7 @@ DEPENDENCIES:
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
+ - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
@@ -282,6 +291,7 @@ SPEC REPOS:
- GoogleUtilities
- Kingfisher
- nanopb
+ - OrderedSet
- PromisesObjC
- SAMKeychain
- SDWebImage
@@ -309,6 +319,8 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_app_update:
:path: ".symlinks/plugins/flutter_app_update/ios"
+ flutter_inappwebview_ios:
+ :path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_udid:
@@ -380,6 +392,7 @@ SPEC CHECKSUMS:
FirebaseMessaging: e1aca1fcc23e8b9eddb0e33f375ff90944623021
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_app_update: 65f61da626cb111d1b24674abc4b01728d7723bc
+ flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a
flutter_udid: b2417673f287ee62817a1de3d1643f47b9f508ab
flutter_webrtc: 90260f83024b1b96d239a575ea4e3708e79344d1
@@ -396,6 +409,7 @@ SPEC CHECKSUMS:
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
+ OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
pasteboard: 982969ebaa7c78af3e6cc7761e8f5e77565d9ce0
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
diff --git a/lib/providers/navigation.dart b/lib/providers/navigation.dart
index 72e0bca..e9f82a1 100644
--- a/lib/providers/navigation.dart
+++ b/lib/providers/navigation.dart
@@ -58,6 +58,11 @@ class NavigationProvider extends ChangeNotifier {
screen: 'realm',
label: 'screenRealm',
),
+ AppNavDestination(
+ icon: Icon(Symbols.newspaper, weight: 400, opticalSize: 20),
+ screen: 'news',
+ label: 'screenNews',
+ ),
AppNavDestination(
icon: Icon(Symbols.photo_library, weight: 400, opticalSize: 20),
screen: 'album',
@@ -83,8 +88,7 @@ class NavigationProvider extends ChangeNotifier {
List destinations = [];
- int get pinnedDestinationCount =>
- destinations.where((ele) => ele.isPinned).length;
+ int get pinnedDestinationCount => destinations.where((ele) => ele.isPinned).length;
NavigationProvider() {
buildDestinations(kDefaultPinnedDestination);
@@ -113,17 +117,13 @@ class NavigationProvider extends ChangeNotifier {
}
bool isIndexInRange(int min, int max) {
- return _currentIndex != null &&
- _currentIndex! >= min &&
- _currentIndex! < max;
+ return _currentIndex != null && _currentIndex! >= min && _currentIndex! < max;
}
void autoDetectIndex(GoRouter? state) {
if (state == null) return;
final idx = destinations.indexWhere(
- (ele) =>
- ele.screen ==
- state.routerDelegate.currentConfiguration.last.route.name,
+ (ele) => ele.screen == state.routerDelegate.currentConfiguration.last.route.name,
);
_currentIndex = idx == -1 ? null : idx;
notifyListeners();
diff --git a/lib/router.dart b/lib/router.dart
index 4ed1091..b7cca2b 100644
--- a/lib/router.dart
+++ b/lib/router.dart
@@ -19,6 +19,8 @@ import 'package:surface/screens/chat/room.dart';
import 'package:surface/screens/explore.dart';
import 'package:surface/screens/friend.dart';
import 'package:surface/screens/home.dart';
+import 'package:surface/screens/news/news_detail.dart';
+import 'package:surface/screens/news/news_list.dart';
import 'package:surface/screens/notification.dart';
import 'package:surface/screens/post/post_detail.dart';
import 'package:surface/screens/post/post_editor.dart';
@@ -31,7 +33,6 @@ import 'package:surface/screens/settings.dart';
import 'package:surface/screens/sharing.dart';
import 'package:surface/types/post.dart';
import 'package:surface/widgets/about.dart';
-import 'package:surface/widgets/navigation/app_background.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
Widget _fadeThroughTransition(
@@ -48,18 +49,12 @@ final _appRoutes = [
GoRoute(
path: '/',
name: 'home',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: const HomeScreen(),
- ),
+ builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/posts',
name: 'explore',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: const ExploreScreen(),
- ),
+ builder: (context, state) => const ExploreScreen(),
routes: [
GoRoute(
path: '/write/:mode',
@@ -104,64 +99,42 @@ final _appRoutes = [
GoRoute(
path: '/account',
name: 'account',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: const AccountScreen(),
- ),
+ builder: (context, state) => const AccountScreen(),
),
GoRoute(
path: '/chat',
name: 'chat',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: const ChatScreen(),
- ),
+ builder: (context, state) => const ChatScreen(),
routes: [
GoRoute(
path: '/:scope/:alias',
name: 'chatRoom',
- builder: (context, state) => AppBackground(
- child: ChatRoomScreen(
- scope: state.pathParameters['scope']!,
- alias: state.pathParameters['alias']!,
- ),
+ builder: (context, state) => ChatRoomScreen(
+ scope: state.pathParameters['scope']!,
+ alias: state.pathParameters['alias']!,
),
),
GoRoute(
path: '/:scope/:alias/call',
name: 'chatCallRoom',
- builder: (context, state) => AppBackground(
- child: CallRoomScreen(
- scope: state.pathParameters['scope']!,
- alias: state.pathParameters['alias']!,
- ),
+ builder: (context, state) => CallRoomScreen(
+ scope: state.pathParameters['scope']!,
+ alias: state.pathParameters['alias']!,
),
),
GoRoute(
path: '/:scope/:alias/detail',
name: 'channelDetail',
- builder: (context, state) => AppBackground(
- child: ChannelDetailScreen(
- scope: state.pathParameters['scope']!,
- alias: state.pathParameters['alias']!,
- ),
+ builder: (context, state) => ChannelDetailScreen(
+ scope: state.pathParameters['scope']!,
+ alias: state.pathParameters['alias']!,
),
),
GoRoute(
path: '/manage',
name: 'chatManage',
- pageBuilder: (context, state) => CustomTransitionPage(
- child: ChatManageScreen(
- editingChannelAlias: state.uri.queryParameters['editing'],
- ),
- transitionsBuilder: (context, animation, secondaryAnimation, child) {
- return FadeThroughTransition(
- animation: animation,
- secondaryAnimation: secondaryAnimation,
- fillColor: Colors.transparent,
- child: child,
- );
- },
+ builder: (context, state) => ChatManageScreen(
+ editingChannelAlias: state.uri.queryParameters['editing'],
),
),
],
@@ -182,36 +155,40 @@ final _appRoutes = [
GoRoute(
path: '/manage',
name: 'realmManage',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: RealmManageScreen(
- editingRealmAlias: state.uri.queryParameters['editing'],
- ),
+ builder: (context, state) => RealmManageScreen(
+ editingRealmAlias: state.uri.queryParameters['editing'],
),
),
],
),
+ GoRoute(
+ path: '/news',
+ name: 'news',
+ builder: (context, state) => const NewsScreen(),
+ routes: [
+ GoRoute(
+ path: '/:hash',
+ name: 'newsDetail',
+ builder: (context, state) => NewsDetailScreen(
+ hash: state.pathParameters['hash']!,
+ ),
+ ),
+ ]
+ ),
GoRoute(
path: '/album',
name: 'album',
- pageBuilder: (context, state) => CustomTransitionPage(
- transitionsBuilder: _fadeThroughTransition,
- child: const AlbumScreen(),
- ),
+ builder: (context, state) => const AlbumScreen(),
),
GoRoute(
path: '/friend',
name: 'friend',
- pageBuilder: (context, state) => NoTransitionPage(
- child: const FriendScreen(),
- ),
+ builder: (context, state) => const FriendScreen(),
),
GoRoute(
path: '/notification',
name: 'notification',
- pageBuilder: (context, state) => NoTransitionPage(
- child: const NotificationScreen(),
- ),
+ builder: (context, state) => const NotificationScreen(),
),
GoRoute(
path: '/auth/login',
diff --git a/lib/screens/news/news_detail.dart b/lib/screens/news/news_detail.dart
new file mode 100644
index 0000000..6e440e2
--- /dev/null
+++ b/lib/screens/news/news_detail.dart
@@ -0,0 +1,113 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:surface/providers/sn_network.dart';
+import 'package:surface/types/news.dart';
+import 'package:surface/widgets/dialog.dart';
+import 'package:surface/widgets/navigation/app_scaffold.dart';
+import 'package:flutter_inappwebview/flutter_inappwebview.dart';
+
+class NewsDetailScreen extends StatefulWidget {
+ final String hash;
+
+ const NewsDetailScreen({super.key, required this.hash});
+
+ @override
+ State createState() => _NewsDetailScreenState();
+}
+
+class _NewsDetailScreenState extends State {
+ SnNewsArticle? _article;
+
+ Future _fetchArticle() async {
+ try {
+ final sn = context.read();
+ final resp = await sn.client.get('/cgi/re/news/${widget.hash}');
+ _article = SnNewsArticle.fromJson(resp.data);
+ } catch (err) {
+ if (!mounted) return;
+ context.showErrorDialog(err).then((_) {
+ if (!mounted) return;
+ Navigator.pop(context);
+ });
+ } finally {
+ setState(() {});
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _fetchArticle();
+ }
+
+ bool _isReadingFromReader = true;
+
+ String get _htmlContent => """
+
+
+
+
+
+
+ ${_article?.content ?? ''}
+
+
+ """;
+
+ InAppWebViewController? _webViewController;
+
+ @override
+ Widget build(BuildContext context) {
+ return AppScaffold(
+ appBar: AppBar(
+ leading: const PageBackButton(),
+ title: Text(_article?.title ?? 'loading'.tr()),
+ ),
+ body: Column(
+ children: [
+ MaterialBanner(
+ dividerColor: Colors.transparent,
+ leading: const Icon(Icons.info),
+ content: Text(_isReadingFromReader ? 'newsReadingFromReader'.tr() : 'newsReadingFromOriginal'.tr()),
+ actions: [
+ TextButton(
+ child: Text('newsReadingProviderSwap').tr(),
+ onPressed: () {
+ setState(() => _isReadingFromReader = !_isReadingFromReader);
+ if (!_isReadingFromReader) {
+ _webViewController?.goTo(historyItem: WebHistoryItem(url: WebUri(_article!.url)));
+ } else {
+ _webViewController?.goBack();
+ }
+ },
+ ),
+ ],
+ ),
+ Expanded(
+ child: InAppWebView(
+ key: Key('news-detail-webview-${widget.hash}-$_isReadingFromReader'),
+ onWebViewCreated: (controller) {
+ _webViewController = controller;
+ },
+ initialUrlRequest: URLRequest(url: WebUri(_article!.url)),
+ onLoadStop: (controller, url) {
+ print("Loaded: $url");
+ },
+ onLoadError: (controller, url, code, message) {
+ print("Error loading $url: $message ($code)");
+ },
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/screens/news/news_list.dart b/lib/screens/news/news_list.dart
new file mode 100644
index 0000000..7efa1a6
--- /dev/null
+++ b/lib/screens/news/news_list.dart
@@ -0,0 +1,189 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:gap/gap.dart';
+import 'package:go_router/go_router.dart';
+import 'package:provider/provider.dart';
+import 'package:styled_widget/styled_widget.dart';
+import 'package:surface/providers/sn_network.dart';
+import 'package:surface/types/news.dart';
+import 'package:surface/widgets/app_bar_leading.dart';
+import 'package:surface/widgets/dialog.dart';
+import 'package:surface/widgets/navigation/app_scaffold.dart';
+import 'package:surface/widgets/universal_image.dart';
+import 'package:very_good_infinite_list/very_good_infinite_list.dart';
+
+class NewsScreen extends StatefulWidget {
+ const NewsScreen({super.key});
+
+ @override
+ State createState() => _NewsScreenState();
+}
+
+class _NewsScreenState extends State {
+ List? _sources;
+
+ @override
+ initState() {
+ super.initState();
+ _fetchSources();
+ }
+
+ Future _fetchSources() async {
+ try {
+ final sn = context.read();
+ final resp = await sn.client.get('/cgi/re/well-known/sources');
+ _sources = List.from(
+ resp.data?.map((e) => SnNewsSource.fromJson(e)) ?? [],
+ );
+ } catch (err) {
+ if (!mounted) return;
+ context.showErrorDialog(err);
+ } finally {
+ setState(() {});
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ if (_sources == null) {
+ return AppScaffold(
+ appBar: AppBar(
+ leading: AutoAppBarLeading(),
+ title: Text('screenNews').tr(),
+ ),
+ body: Center(
+ child: CircularProgressIndicator(),
+ ),
+ );
+ }
+
+ return DefaultTabController(
+ length: _sources!.length + 1,
+ child: AppScaffold(
+ body: NestedScrollView(
+ headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
+ return [
+ SliverOverlapAbsorber(
+ handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
+ sliver: SliverAppBar(
+ leading: AutoAppBarLeading(),
+ title: Text('screenNews').tr(),
+ bottom: TabBar(
+ isScrollable: true,
+ tabs: [
+ Tab(child: Text('newsAllSources'.tr())),
+ for (final source in _sources!) Tab(child: Text(source.label)),
+ ],
+ ),
+ ),
+ ),
+ ];
+ },
+ body: TabBarView(
+ children: [
+ _NewsArticleListWidget(),
+ for (final source in _sources!) _NewsArticleListWidget(source: source.id),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
+
+class _NewsArticleListWidget extends StatefulWidget {
+ final String? source;
+
+ const _NewsArticleListWidget({this.source});
+
+ @override
+ State<_NewsArticleListWidget> createState() => _NewsArticleListWidgetState();
+}
+
+class _NewsArticleListWidgetState extends State<_NewsArticleListWidget> {
+ bool _isBusy = false;
+
+ int? _totalCount;
+ final List _articles = List.empty(growable: true);
+
+ Future _fetchArticles() async {
+ setState(() => _isBusy = true);
+
+ try {
+ final sn = context.read();
+ final resp = await sn.client.get('/cgi/re/news', queryParameters: {
+ 'take': 10,
+ 'offset': _articles.length,
+ if (widget.source != null) 'source': widget.source,
+ });
+ _totalCount = resp.data['count'];
+ _articles.addAll(List.from(
+ resp.data['data']?.map((e) => SnNewsArticle.fromJson(e)) ?? [],
+ ));
+ } catch (err) {
+ if (!mounted) return;
+ context.showErrorDialog(err);
+ } finally {
+ setState(() => _isBusy = false);
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _fetchArticles();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return MediaQuery.removePadding(
+ context: context,
+ removeTop: true,
+ child: RefreshIndicator(
+ onRefresh: _fetchArticles,
+ child: InfiniteList(
+ isLoading: _isBusy,
+ itemCount: _articles.length,
+ hasReachedMax: _totalCount != null && _articles.length >= _totalCount!,
+ onFetchData: () {
+ _fetchArticles();
+ },
+ itemBuilder: (context, index) {
+ final article = _articles[index];
+
+ final baseUri = Uri.parse(article.url);
+ final baseUrl = '${baseUri.scheme}://${baseUri.host}';
+
+ return Card(
+ child: InkWell(
+ radius: 8,
+ onTap: () {
+ GoRouter.of(context).pushNamed(
+ 'newsDetail',
+ pathParameters: {'hash': article.hash},
+ );
+ },
+ child: Column(
+ children: [
+ if (article.thumbnail.isNotEmpty && !article.thumbnail.endsWith('.svg'))
+ ClipRRect(
+ borderRadius: BorderRadius.all(Radius.circular(8)),
+ child: AspectRatio(
+ aspectRatio: 16 / 9,
+ child: AutoResizeUniversalImage('$baseUrl/${article.thumbnail}'),
+ ),
+ ),
+ Text(article.title).textStyle(Theme.of(context).textTheme.titleLarge!),
+ Text(article.description).textStyle(Theme.of(context).textTheme.bodyMedium!),
+ const Gap(8),
+ Text(article.source).textStyle(Theme.of(context).textTheme.bodySmall!),
+ ],
+ ).padding(all: 8),
+ ),
+ );
+ },
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/types/news.dart b/lib/types/news.dart
new file mode 100644
index 0000000..1181022
--- /dev/null
+++ b/lib/types/news.dart
@@ -0,0 +1,38 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'news.freezed.dart';
+part 'news.g.dart';
+
+@freezed
+class SnNewsSource with _$SnNewsSource {
+ const factory SnNewsSource({
+ required String id,
+ required String label,
+ required String type,
+ required String source,
+ required int depth,
+ required bool enabled,
+ }) = _SnNewsSource;
+
+ factory SnNewsSource.fromJson(Map json) => _$SnNewsSourceFromJson(json);
+}
+
+@freezed
+class SnNewsArticle with _$SnNewsArticle {
+ const factory SnNewsArticle({
+ required int id,
+ required DateTime createdAt,
+ required DateTime updatedAt,
+ required dynamic deletedAt,
+ required String thumbnail,
+ required String title,
+ required String description,
+ required String content,
+ required String url,
+ required String hash,
+ required String source,
+ required dynamic publishedAt,
+ }) = _SnNewsArticle;
+
+ factory SnNewsArticle.fromJson(Map json) => _$SnNewsArticleFromJson(json);
+}
diff --git a/lib/types/news.freezed.dart b/lib/types/news.freezed.dart
new file mode 100644
index 0000000..a157a42
--- /dev/null
+++ b/lib/types/news.freezed.dart
@@ -0,0 +1,660 @@
+// coverage:ignore-file
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of 'news.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity(T value) => value;
+
+final _privateConstructorUsedError = UnsupportedError(
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+
+SnNewsSource _$SnNewsSourceFromJson(Map json) {
+ return _SnNewsSource.fromJson(json);
+}
+
+/// @nodoc
+mixin _$SnNewsSource {
+ String get id => throw _privateConstructorUsedError;
+ String get label => throw _privateConstructorUsedError;
+ String get type => throw _privateConstructorUsedError;
+ String get source => throw _privateConstructorUsedError;
+ int get depth => throw _privateConstructorUsedError;
+ bool get enabled => throw _privateConstructorUsedError;
+
+ /// Serializes this SnNewsSource to a JSON map.
+ Map toJson() => throw _privateConstructorUsedError;
+
+ /// Create a copy of SnNewsSource
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ $SnNewsSourceCopyWith get copyWith =>
+ throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $SnNewsSourceCopyWith<$Res> {
+ factory $SnNewsSourceCopyWith(
+ SnNewsSource value, $Res Function(SnNewsSource) then) =
+ _$SnNewsSourceCopyWithImpl<$Res, SnNewsSource>;
+ @useResult
+ $Res call(
+ {String id,
+ String label,
+ String type,
+ String source,
+ int depth,
+ bool enabled});
+}
+
+/// @nodoc
+class _$SnNewsSourceCopyWithImpl<$Res, $Val extends SnNewsSource>
+ implements $SnNewsSourceCopyWith<$Res> {
+ _$SnNewsSourceCopyWithImpl(this._value, this._then);
+
+ // ignore: unused_field
+ final $Val _value;
+ // ignore: unused_field
+ final $Res Function($Val) _then;
+
+ /// Create a copy of SnNewsSource
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? id = null,
+ Object? label = null,
+ Object? type = null,
+ Object? source = null,
+ Object? depth = null,
+ Object? enabled = null,
+ }) {
+ return _then(_value.copyWith(
+ id: null == id
+ ? _value.id
+ : id // ignore: cast_nullable_to_non_nullable
+ as String,
+ label: null == label
+ ? _value.label
+ : label // ignore: cast_nullable_to_non_nullable
+ as String,
+ type: null == type
+ ? _value.type
+ : type // ignore: cast_nullable_to_non_nullable
+ as String,
+ source: null == source
+ ? _value.source
+ : source // ignore: cast_nullable_to_non_nullable
+ as String,
+ depth: null == depth
+ ? _value.depth
+ : depth // ignore: cast_nullable_to_non_nullable
+ as int,
+ enabled: null == enabled
+ ? _value.enabled
+ : enabled // ignore: cast_nullable_to_non_nullable
+ as bool,
+ ) as $Val);
+ }
+}
+
+/// @nodoc
+abstract class _$$SnNewsSourceImplCopyWith<$Res>
+ implements $SnNewsSourceCopyWith<$Res> {
+ factory _$$SnNewsSourceImplCopyWith(
+ _$SnNewsSourceImpl value, $Res Function(_$SnNewsSourceImpl) then) =
+ __$$SnNewsSourceImplCopyWithImpl<$Res>;
+ @override
+ @useResult
+ $Res call(
+ {String id,
+ String label,
+ String type,
+ String source,
+ int depth,
+ bool enabled});
+}
+
+/// @nodoc
+class __$$SnNewsSourceImplCopyWithImpl<$Res>
+ extends _$SnNewsSourceCopyWithImpl<$Res, _$SnNewsSourceImpl>
+ implements _$$SnNewsSourceImplCopyWith<$Res> {
+ __$$SnNewsSourceImplCopyWithImpl(
+ _$SnNewsSourceImpl _value, $Res Function(_$SnNewsSourceImpl) _then)
+ : super(_value, _then);
+
+ /// Create a copy of SnNewsSource
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? id = null,
+ Object? label = null,
+ Object? type = null,
+ Object? source = null,
+ Object? depth = null,
+ Object? enabled = null,
+ }) {
+ return _then(_$SnNewsSourceImpl(
+ id: null == id
+ ? _value.id
+ : id // ignore: cast_nullable_to_non_nullable
+ as String,
+ label: null == label
+ ? _value.label
+ : label // ignore: cast_nullable_to_non_nullable
+ as String,
+ type: null == type
+ ? _value.type
+ : type // ignore: cast_nullable_to_non_nullable
+ as String,
+ source: null == source
+ ? _value.source
+ : source // ignore: cast_nullable_to_non_nullable
+ as String,
+ depth: null == depth
+ ? _value.depth
+ : depth // ignore: cast_nullable_to_non_nullable
+ as int,
+ enabled: null == enabled
+ ? _value.enabled
+ : enabled // ignore: cast_nullable_to_non_nullable
+ as bool,
+ ));
+ }
+}
+
+/// @nodoc
+@JsonSerializable()
+class _$SnNewsSourceImpl implements _SnNewsSource {
+ const _$SnNewsSourceImpl(
+ {required this.id,
+ required this.label,
+ required this.type,
+ required this.source,
+ required this.depth,
+ required this.enabled});
+
+ factory _$SnNewsSourceImpl.fromJson(Map json) =>
+ _$$SnNewsSourceImplFromJson(json);
+
+ @override
+ final String id;
+ @override
+ final String label;
+ @override
+ final String type;
+ @override
+ final String source;
+ @override
+ final int depth;
+ @override
+ final bool enabled;
+
+ @override
+ String toString() {
+ return 'SnNewsSource(id: $id, label: $label, type: $type, source: $source, depth: $depth, enabled: $enabled)';
+ }
+
+ @override
+ bool operator ==(Object other) {
+ return identical(this, other) ||
+ (other.runtimeType == runtimeType &&
+ other is _$SnNewsSourceImpl &&
+ (identical(other.id, id) || other.id == id) &&
+ (identical(other.label, label) || other.label == label) &&
+ (identical(other.type, type) || other.type == type) &&
+ (identical(other.source, source) || other.source == source) &&
+ (identical(other.depth, depth) || other.depth == depth) &&
+ (identical(other.enabled, enabled) || other.enabled == enabled));
+ }
+
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ int get hashCode =>
+ Object.hash(runtimeType, id, label, type, source, depth, enabled);
+
+ /// Create a copy of SnNewsSource
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ @pragma('vm:prefer-inline')
+ _$$SnNewsSourceImplCopyWith<_$SnNewsSourceImpl> get copyWith =>
+ __$$SnNewsSourceImplCopyWithImpl<_$SnNewsSourceImpl>(this, _$identity);
+
+ @override
+ Map toJson() {
+ return _$$SnNewsSourceImplToJson(
+ this,
+ );
+ }
+}
+
+abstract class _SnNewsSource implements SnNewsSource {
+ const factory _SnNewsSource(
+ {required final String id,
+ required final String label,
+ required final String type,
+ required final String source,
+ required final int depth,
+ required final bool enabled}) = _$SnNewsSourceImpl;
+
+ factory _SnNewsSource.fromJson(Map json) =
+ _$SnNewsSourceImpl.fromJson;
+
+ @override
+ String get id;
+ @override
+ String get label;
+ @override
+ String get type;
+ @override
+ String get source;
+ @override
+ int get depth;
+ @override
+ bool get enabled;
+
+ /// Create a copy of SnNewsSource
+ /// with the given fields replaced by the non-null parameter values.
+ @override
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ _$$SnNewsSourceImplCopyWith<_$SnNewsSourceImpl> get copyWith =>
+ throw _privateConstructorUsedError;
+}
+
+SnNewsArticle _$SnNewsArticleFromJson(Map json) {
+ return _SnNewsArticle.fromJson(json);
+}
+
+/// @nodoc
+mixin _$SnNewsArticle {
+ int get id => throw _privateConstructorUsedError;
+ DateTime get createdAt => throw _privateConstructorUsedError;
+ DateTime get updatedAt => throw _privateConstructorUsedError;
+ dynamic get deletedAt => throw _privateConstructorUsedError;
+ String get thumbnail => throw _privateConstructorUsedError;
+ String get title => throw _privateConstructorUsedError;
+ String get description => throw _privateConstructorUsedError;
+ String get content => throw _privateConstructorUsedError;
+ String get url => throw _privateConstructorUsedError;
+ String get hash => throw _privateConstructorUsedError;
+ String get source => throw _privateConstructorUsedError;
+ dynamic get publishedAt => throw _privateConstructorUsedError;
+
+ /// Serializes this SnNewsArticle to a JSON map.
+ Map toJson() => throw _privateConstructorUsedError;
+
+ /// Create a copy of SnNewsArticle
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ $SnNewsArticleCopyWith get copyWith =>
+ throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $SnNewsArticleCopyWith<$Res> {
+ factory $SnNewsArticleCopyWith(
+ SnNewsArticle value, $Res Function(SnNewsArticle) then) =
+ _$SnNewsArticleCopyWithImpl<$Res, SnNewsArticle>;
+ @useResult
+ $Res call(
+ {int id,
+ DateTime createdAt,
+ DateTime updatedAt,
+ dynamic deletedAt,
+ String thumbnail,
+ String title,
+ String description,
+ String content,
+ String url,
+ String hash,
+ String source,
+ dynamic publishedAt});
+}
+
+/// @nodoc
+class _$SnNewsArticleCopyWithImpl<$Res, $Val extends SnNewsArticle>
+ implements $SnNewsArticleCopyWith<$Res> {
+ _$SnNewsArticleCopyWithImpl(this._value, this._then);
+
+ // ignore: unused_field
+ final $Val _value;
+ // ignore: unused_field
+ final $Res Function($Val) _then;
+
+ /// Create a copy of SnNewsArticle
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? id = null,
+ Object? createdAt = null,
+ Object? updatedAt = null,
+ Object? deletedAt = freezed,
+ Object? thumbnail = null,
+ Object? title = null,
+ Object? description = null,
+ Object? content = null,
+ Object? url = null,
+ Object? hash = null,
+ Object? source = null,
+ Object? publishedAt = freezed,
+ }) {
+ return _then(_value.copyWith(
+ id: null == id
+ ? _value.id
+ : id // ignore: cast_nullable_to_non_nullable
+ as int,
+ createdAt: null == createdAt
+ ? _value.createdAt
+ : createdAt // ignore: cast_nullable_to_non_nullable
+ as DateTime,
+ updatedAt: null == updatedAt
+ ? _value.updatedAt
+ : updatedAt // ignore: cast_nullable_to_non_nullable
+ as DateTime,
+ deletedAt: freezed == deletedAt
+ ? _value.deletedAt
+ : deletedAt // ignore: cast_nullable_to_non_nullable
+ as dynamic,
+ thumbnail: null == thumbnail
+ ? _value.thumbnail
+ : thumbnail // ignore: cast_nullable_to_non_nullable
+ as String,
+ title: null == title
+ ? _value.title
+ : title // ignore: cast_nullable_to_non_nullable
+ as String,
+ description: null == description
+ ? _value.description
+ : description // ignore: cast_nullable_to_non_nullable
+ as String,
+ content: null == content
+ ? _value.content
+ : content // ignore: cast_nullable_to_non_nullable
+ as String,
+ url: null == url
+ ? _value.url
+ : url // ignore: cast_nullable_to_non_nullable
+ as String,
+ hash: null == hash
+ ? _value.hash
+ : hash // ignore: cast_nullable_to_non_nullable
+ as String,
+ source: null == source
+ ? _value.source
+ : source // ignore: cast_nullable_to_non_nullable
+ as String,
+ publishedAt: freezed == publishedAt
+ ? _value.publishedAt
+ : publishedAt // ignore: cast_nullable_to_non_nullable
+ as dynamic,
+ ) as $Val);
+ }
+}
+
+/// @nodoc
+abstract class _$$SnNewsArticleImplCopyWith<$Res>
+ implements $SnNewsArticleCopyWith<$Res> {
+ factory _$$SnNewsArticleImplCopyWith(
+ _$SnNewsArticleImpl value, $Res Function(_$SnNewsArticleImpl) then) =
+ __$$SnNewsArticleImplCopyWithImpl<$Res>;
+ @override
+ @useResult
+ $Res call(
+ {int id,
+ DateTime createdAt,
+ DateTime updatedAt,
+ dynamic deletedAt,
+ String thumbnail,
+ String title,
+ String description,
+ String content,
+ String url,
+ String hash,
+ String source,
+ dynamic publishedAt});
+}
+
+/// @nodoc
+class __$$SnNewsArticleImplCopyWithImpl<$Res>
+ extends _$SnNewsArticleCopyWithImpl<$Res, _$SnNewsArticleImpl>
+ implements _$$SnNewsArticleImplCopyWith<$Res> {
+ __$$SnNewsArticleImplCopyWithImpl(
+ _$SnNewsArticleImpl _value, $Res Function(_$SnNewsArticleImpl) _then)
+ : super(_value, _then);
+
+ /// Create a copy of SnNewsArticle
+ /// with the given fields replaced by the non-null parameter values.
+ @pragma('vm:prefer-inline')
+ @override
+ $Res call({
+ Object? id = null,
+ Object? createdAt = null,
+ Object? updatedAt = null,
+ Object? deletedAt = freezed,
+ Object? thumbnail = null,
+ Object? title = null,
+ Object? description = null,
+ Object? content = null,
+ Object? url = null,
+ Object? hash = null,
+ Object? source = null,
+ Object? publishedAt = freezed,
+ }) {
+ return _then(_$SnNewsArticleImpl(
+ id: null == id
+ ? _value.id
+ : id // ignore: cast_nullable_to_non_nullable
+ as int,
+ createdAt: null == createdAt
+ ? _value.createdAt
+ : createdAt // ignore: cast_nullable_to_non_nullable
+ as DateTime,
+ updatedAt: null == updatedAt
+ ? _value.updatedAt
+ : updatedAt // ignore: cast_nullable_to_non_nullable
+ as DateTime,
+ deletedAt: freezed == deletedAt
+ ? _value.deletedAt
+ : deletedAt // ignore: cast_nullable_to_non_nullable
+ as dynamic,
+ thumbnail: null == thumbnail
+ ? _value.thumbnail
+ : thumbnail // ignore: cast_nullable_to_non_nullable
+ as String,
+ title: null == title
+ ? _value.title
+ : title // ignore: cast_nullable_to_non_nullable
+ as String,
+ description: null == description
+ ? _value.description
+ : description // ignore: cast_nullable_to_non_nullable
+ as String,
+ content: null == content
+ ? _value.content
+ : content // ignore: cast_nullable_to_non_nullable
+ as String,
+ url: null == url
+ ? _value.url
+ : url // ignore: cast_nullable_to_non_nullable
+ as String,
+ hash: null == hash
+ ? _value.hash
+ : hash // ignore: cast_nullable_to_non_nullable
+ as String,
+ source: null == source
+ ? _value.source
+ : source // ignore: cast_nullable_to_non_nullable
+ as String,
+ publishedAt: freezed == publishedAt
+ ? _value.publishedAt
+ : publishedAt // ignore: cast_nullable_to_non_nullable
+ as dynamic,
+ ));
+ }
+}
+
+/// @nodoc
+@JsonSerializable()
+class _$SnNewsArticleImpl implements _SnNewsArticle {
+ const _$SnNewsArticleImpl(
+ {required this.id,
+ required this.createdAt,
+ required this.updatedAt,
+ required this.deletedAt,
+ required this.thumbnail,
+ required this.title,
+ required this.description,
+ required this.content,
+ required this.url,
+ required this.hash,
+ required this.source,
+ required this.publishedAt});
+
+ factory _$SnNewsArticleImpl.fromJson(Map json) =>
+ _$$SnNewsArticleImplFromJson(json);
+
+ @override
+ final int id;
+ @override
+ final DateTime createdAt;
+ @override
+ final DateTime updatedAt;
+ @override
+ final dynamic deletedAt;
+ @override
+ final String thumbnail;
+ @override
+ final String title;
+ @override
+ final String description;
+ @override
+ final String content;
+ @override
+ final String url;
+ @override
+ final String hash;
+ @override
+ final String source;
+ @override
+ final dynamic publishedAt;
+
+ @override
+ String toString() {
+ return 'SnNewsArticle(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, thumbnail: $thumbnail, title: $title, description: $description, content: $content, url: $url, hash: $hash, source: $source, publishedAt: $publishedAt)';
+ }
+
+ @override
+ bool operator ==(Object other) {
+ return identical(this, other) ||
+ (other.runtimeType == runtimeType &&
+ other is _$SnNewsArticleImpl &&
+ (identical(other.id, id) || other.id == id) &&
+ (identical(other.createdAt, createdAt) ||
+ other.createdAt == createdAt) &&
+ (identical(other.updatedAt, updatedAt) ||
+ other.updatedAt == updatedAt) &&
+ const DeepCollectionEquality().equals(other.deletedAt, deletedAt) &&
+ (identical(other.thumbnail, thumbnail) ||
+ other.thumbnail == thumbnail) &&
+ (identical(other.title, title) || other.title == title) &&
+ (identical(other.description, description) ||
+ other.description == description) &&
+ (identical(other.content, content) || other.content == content) &&
+ (identical(other.url, url) || other.url == url) &&
+ (identical(other.hash, hash) || other.hash == hash) &&
+ (identical(other.source, source) || other.source == source) &&
+ const DeepCollectionEquality()
+ .equals(other.publishedAt, publishedAt));
+ }
+
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ int get hashCode => Object.hash(
+ runtimeType,
+ id,
+ createdAt,
+ updatedAt,
+ const DeepCollectionEquality().hash(deletedAt),
+ thumbnail,
+ title,
+ description,
+ content,
+ url,
+ hash,
+ source,
+ const DeepCollectionEquality().hash(publishedAt));
+
+ /// Create a copy of SnNewsArticle
+ /// with the given fields replaced by the non-null parameter values.
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ @override
+ @pragma('vm:prefer-inline')
+ _$$SnNewsArticleImplCopyWith<_$SnNewsArticleImpl> get copyWith =>
+ __$$SnNewsArticleImplCopyWithImpl<_$SnNewsArticleImpl>(this, _$identity);
+
+ @override
+ Map toJson() {
+ return _$$SnNewsArticleImplToJson(
+ this,
+ );
+ }
+}
+
+abstract class _SnNewsArticle implements SnNewsArticle {
+ const factory _SnNewsArticle(
+ {required final int id,
+ required final DateTime createdAt,
+ required final DateTime updatedAt,
+ required final dynamic deletedAt,
+ required final String thumbnail,
+ required final String title,
+ required final String description,
+ required final String content,
+ required final String url,
+ required final String hash,
+ required final String source,
+ required final dynamic publishedAt}) = _$SnNewsArticleImpl;
+
+ factory _SnNewsArticle.fromJson(Map json) =
+ _$SnNewsArticleImpl.fromJson;
+
+ @override
+ int get id;
+ @override
+ DateTime get createdAt;
+ @override
+ DateTime get updatedAt;
+ @override
+ dynamic get deletedAt;
+ @override
+ String get thumbnail;
+ @override
+ String get title;
+ @override
+ String get description;
+ @override
+ String get content;
+ @override
+ String get url;
+ @override
+ String get hash;
+ @override
+ String get source;
+ @override
+ dynamic get publishedAt;
+
+ /// Create a copy of SnNewsArticle
+ /// with the given fields replaced by the non-null parameter values.
+ @override
+ @JsonKey(includeFromJson: false, includeToJson: false)
+ _$$SnNewsArticleImplCopyWith<_$SnNewsArticleImpl> get copyWith =>
+ throw _privateConstructorUsedError;
+}
diff --git a/lib/types/news.g.dart b/lib/types/news.g.dart
new file mode 100644
index 0000000..2c7f788
--- /dev/null
+++ b/lib/types/news.g.dart
@@ -0,0 +1,59 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'news.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_$SnNewsSourceImpl _$$SnNewsSourceImplFromJson(Map json) =>
+ _$SnNewsSourceImpl(
+ id: json['id'] as String,
+ label: json['label'] as String,
+ type: json['type'] as String,
+ source: json['source'] as String,
+ depth: (json['depth'] as num).toInt(),
+ enabled: json['enabled'] as bool,
+ );
+
+Map _$$SnNewsSourceImplToJson(_$SnNewsSourceImpl instance) =>
+ {
+ 'id': instance.id,
+ 'label': instance.label,
+ 'type': instance.type,
+ 'source': instance.source,
+ 'depth': instance.depth,
+ 'enabled': instance.enabled,
+ };
+
+_$SnNewsArticleImpl _$$SnNewsArticleImplFromJson(Map json) =>
+ _$SnNewsArticleImpl(
+ id: (json['id'] as num).toInt(),
+ createdAt: DateTime.parse(json['created_at'] as String),
+ updatedAt: DateTime.parse(json['updated_at'] as String),
+ deletedAt: json['deleted_at'],
+ thumbnail: json['thumbnail'] as String,
+ title: json['title'] as String,
+ description: json['description'] as String,
+ content: json['content'] as String,
+ url: json['url'] as String,
+ hash: json['hash'] as String,
+ source: json['source'] as String,
+ publishedAt: json['published_at'],
+ );
+
+Map _$$SnNewsArticleImplToJson(_$SnNewsArticleImpl instance) =>
+ {
+ 'id': instance.id,
+ 'created_at': instance.createdAt.toIso8601String(),
+ 'updated_at': instance.updatedAt.toIso8601String(),
+ 'deleted_at': instance.deletedAt,
+ 'thumbnail': instance.thumbnail,
+ 'title': instance.title,
+ 'description': instance.description,
+ 'content': instance.content,
+ 'url': instance.url,
+ 'hash': instance.hash,
+ 'source': instance.source,
+ 'published_at': instance.publishedAt,
+ };
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 9cdba3d..d187442 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -13,6 +13,7 @@ import file_selector_macos
import firebase_analytics
import firebase_core
import firebase_messaging
+import flutter_inappwebview_macos
import flutter_udid
import flutter_webrtc
import gal
@@ -40,6 +41,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
+ InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index 317faac..2ac2676 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -675,6 +675,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.0"
+ flutter_inappwebview:
+ dependency: "direct main"
+ description:
+ name: flutter_inappwebview
+ sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.5"
+ flutter_inappwebview_android:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_android
+ sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.3"
+ flutter_inappwebview_internal_annotations:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_internal_annotations
+ sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ flutter_inappwebview_ios:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_ios
+ sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ flutter_inappwebview_macos:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_macos
+ sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ flutter_inappwebview_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_platform_interface
+ sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0+1"
+ flutter_inappwebview_web:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_web
+ sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ flutter_inappwebview_windows:
+ dependency: transitive
+ description:
+ name: flutter_inappwebview_windows
+ sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.0"
flutter_launcher_icons:
dependency: "direct dev"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 187da15..af6ffc2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -115,6 +115,7 @@ dependencies:
slide_countdown: ^2.0.2
video_compress: ^3.1.3
cached_network_image: ^3.4.1
+ flutter_inappwebview: ^6.1.5
dev_dependencies:
flutter_test:
diff --git a/web/index.html b/web/index.html
index 1734104..82f4e82 100644
--- a/web/index.html
+++ b/web/index.html
@@ -16,6 +16,8 @@
-->
+
+
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index e1dd346..8bcf9ef 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -34,6 +35,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FileSelectorWindows"));
FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
+ FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
FlutterUdidPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
FlutterWebRTCPluginRegisterWithRegistrar(
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index e9cb10e..ac4942c 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
file_saver
file_selector_windows
firebase_core
+ flutter_inappwebview_windows
flutter_udid
flutter_webrtc
gal