✨ Basic post item
This commit is contained in:
parent
bac90aad23
commit
07b8ec6e96
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
description: This file stores settings for Dart & Flutter DevTools.
|
||||||
|
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||||
|
extensions:
|
@ -13,6 +13,11 @@ PODS:
|
|||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- sqflite_darwin (0.0.4):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
|
||||||
@ -21,6 +26,8 @@ DEPENDENCIES:
|
|||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
@ -35,6 +42,10 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
sqflite_darwin:
|
||||||
|
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus: 4c41c08fc6d7c91f63bc7aec70ffe3730b04f563
|
connectivity_plus: 4c41c08fc6d7c91f63bc7aec70ffe3730b04f563
|
||||||
@ -43,6 +54,8 @@ SPEC CHECKSUMS:
|
|||||||
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
||||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||||
|
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||||
|
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||||
|
|
||||||
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
|
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:easy_localization_loader/easy_localization_loader.dart';
|
import 'package:easy_localization_loader/easy_localization_loader.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:responsive_framework/responsive_framework.dart';
|
import 'package:responsive_framework/responsive_framework.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/providers/theme.dart';
|
import 'package:surface/providers/theme.dart';
|
||||||
@ -40,7 +41,10 @@ class SolianApp extends StatelessWidget {
|
|||||||
darkTheme: th.theme.dark,
|
darkTheme: th.theme.dark,
|
||||||
locale: context.locale,
|
locale: context.locale,
|
||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
localizationsDelegates: context.localizationDelegates,
|
localizationsDelegates: [
|
||||||
|
RelativeTimeLocalizations.delegate,
|
||||||
|
...context.localizationDelegates,
|
||||||
|
],
|
||||||
routerConfig: appRouter,
|
routerConfig: appRouter,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
@ -27,9 +27,14 @@ class SnNetworkProvider {
|
|||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!kIsWeb && Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS)) {
|
||||||
// Switch to native implementation if possible
|
// Switch to native implementation if possible
|
||||||
client.httpClientAdapter = NativeAdapter();
|
client.httpClientAdapter = NativeAdapter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getAttachmentUrl(String ky) {
|
||||||
|
if (ky.startsWith("http://")) return ky;
|
||||||
|
return '${client.options.baseUrl}/cgi/uc/attachments/$ky';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/types/post.dart';
|
import 'package:surface/types/post.dart';
|
||||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||||
|
import 'package:surface/widgets/post/post_item.dart';
|
||||||
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||||
|
|
||||||
class ExploreScreen extends StatefulWidget {
|
class ExploreScreen extends StatefulWidget {
|
||||||
@ -17,16 +18,17 @@ class _ExploreScreenState extends State<ExploreScreen> {
|
|||||||
bool _isBusy = true;
|
bool _isBusy = true;
|
||||||
|
|
||||||
final List<SnPost> _posts = List.empty(growable: true);
|
final List<SnPost> _posts = List.empty(growable: true);
|
||||||
int _postCount = 0;
|
int? _postCount;
|
||||||
|
|
||||||
void _fetchPosts() async {
|
void _fetchPosts() async {
|
||||||
|
if (_postCount != null && _posts.length >= _postCount!) return;
|
||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
|
||||||
final resp = await sn.client.get('/cgi/co/posts', queryParameters: {
|
final resp = await sn.client.get('/cgi/co/posts', queryParameters: {
|
||||||
'take': 10,
|
'take': 10,
|
||||||
'offset': 0,
|
'offset': _posts.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
_postCount = resp.data['count'];
|
_postCount = resp.data['count'];
|
||||||
@ -51,10 +53,12 @@ class _ExploreScreenState extends State<ExploreScreen> {
|
|||||||
body: InfiniteList(
|
body: InfiniteList(
|
||||||
itemCount: _posts.length,
|
itemCount: _posts.length,
|
||||||
isLoading: _isBusy,
|
isLoading: _isBusy,
|
||||||
|
hasReachedMax: _postCount != null && _posts.length >= _postCount!,
|
||||||
onFetchData: _fetchPosts,
|
onFetchData: _fetchPosts,
|
||||||
itemBuilder: (context, idx) {
|
itemBuilder: (context, idx) {
|
||||||
return Text(_posts[idx].toString());
|
return PostItem(data: _posts[idx]);
|
||||||
},
|
},
|
||||||
|
separatorBuilder: (context, index) => const Divider(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
49
lib/widgets/account/account_image.dart
Normal file
49
lib/widgets/account/account_image.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:surface/providers/sn_network.dart';
|
||||||
|
import 'package:surface/widgets/universal_image.dart';
|
||||||
|
|
||||||
|
class AccountImage extends StatelessWidget {
|
||||||
|
final String content;
|
||||||
|
final Color? backgroundColor;
|
||||||
|
final Color? foregroundColor;
|
||||||
|
final double? radius;
|
||||||
|
final Widget? fallbackWidget;
|
||||||
|
|
||||||
|
const AccountImage({
|
||||||
|
super.key,
|
||||||
|
required this.content,
|
||||||
|
this.backgroundColor,
|
||||||
|
this.foregroundColor,
|
||||||
|
this.radius,
|
||||||
|
this.fallbackWidget,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
final url = sn.getAttachmentUrl(content);
|
||||||
|
|
||||||
|
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||||
|
return CircleAvatar(
|
||||||
|
key: Key('attachment-${content.hashCode}'),
|
||||||
|
radius: radius,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
backgroundImage: content.isNotEmpty
|
||||||
|
? ResizeImage(
|
||||||
|
UniversalImage.provider(url),
|
||||||
|
width: ((radius ?? 20) * devicePixelRatio * 2).round(),
|
||||||
|
height: ((radius ?? 20) * devicePixelRatio * 2).round(),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
child: content.isEmpty
|
||||||
|
? (fallbackWidget ??
|
||||||
|
Icon(
|
||||||
|
Icons.account_circle,
|
||||||
|
size: radius != null ? radius! * 1.2 : 24,
|
||||||
|
color: foregroundColor,
|
||||||
|
))
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
183
lib/widgets/markdown_content.dart
Normal file
183
lib/widgets/markdown_content.dart
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:markdown/markdown.dart' as markdown;
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:surface/widgets/universal_image.dart';
|
||||||
|
import 'package:syntax_highlight/syntax_highlight.dart';
|
||||||
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
|
||||||
|
class MarkdownTextContent extends StatefulWidget {
|
||||||
|
final String content;
|
||||||
|
final bool isSelectable;
|
||||||
|
final bool isLargeText;
|
||||||
|
final bool isAutoWarp;
|
||||||
|
|
||||||
|
const MarkdownTextContent({
|
||||||
|
super.key,
|
||||||
|
required this.content,
|
||||||
|
this.isSelectable = false,
|
||||||
|
this.isLargeText = false,
|
||||||
|
this.isAutoWarp = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MarkdownTextContent> createState() => _MarkdownTextContentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MarkdownTextContentState extends State<MarkdownTextContent> {
|
||||||
|
Widget _buildContent(BuildContext context) {
|
||||||
|
return Markdown(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
data: widget.content,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
styleSheet: MarkdownStyleSheet.fromTheme(
|
||||||
|
Theme.of(context),
|
||||||
|
).copyWith(
|
||||||
|
textScaler: TextScaler.linear(widget.isLargeText ? 1.1 : 1),
|
||||||
|
blockquote: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
blockquoteDecoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
),
|
||||||
|
horizontalRuleDecoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
width: 1.0,
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
codeblockDecoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 0.3,
|
||||||
|
),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
color: Theme.of(context).colorScheme.surface.withOpacity(0.5),
|
||||||
|
)),
|
||||||
|
builders: {
|
||||||
|
'code': _MarkdownTextCodeElement(),
|
||||||
|
},
|
||||||
|
softLineBreak: true,
|
||||||
|
extensionSet: markdown.ExtensionSet(
|
||||||
|
<markdown.BlockSyntax>[
|
||||||
|
markdown.CodeBlockSyntax(),
|
||||||
|
...markdown.ExtensionSet.commonMark.blockSyntaxes,
|
||||||
|
...markdown.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||||
|
],
|
||||||
|
<markdown.InlineSyntax>[
|
||||||
|
if (widget.isAutoWarp) markdown.LineBreakSyntax(),
|
||||||
|
_UserNameCardInlineSyntax(),
|
||||||
|
markdown.AutolinkSyntax(),
|
||||||
|
markdown.AutolinkExtensionSyntax(),
|
||||||
|
markdown.CodeSyntax(),
|
||||||
|
...markdown.ExtensionSet.commonMark.inlineSyntaxes,
|
||||||
|
...markdown.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTapLink: (text, href, title) async {
|
||||||
|
if (href == null) return;
|
||||||
|
if (href.startsWith('solink://')) {
|
||||||
|
// final segments = href.replaceFirst('solink://', '').split('/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await launchUrlString(
|
||||||
|
href,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
imageBuilder: (uri, title, alt) {
|
||||||
|
var url = uri.toString();
|
||||||
|
double? width, height;
|
||||||
|
BoxFit? fit;
|
||||||
|
if (url.startsWith('solink://')) {
|
||||||
|
// final segments = url.replaceFirst('solink://', '').split('/');
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return UniversalImage(
|
||||||
|
url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (widget.isSelectable) {
|
||||||
|
return SelectionArea(child: _buildContent(context));
|
||||||
|
}
|
||||||
|
return _buildContent(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserNameCardInlineSyntax extends markdown.InlineSyntax {
|
||||||
|
_UserNameCardInlineSyntax() : super(r'@[a-zA-Z0-9_]+');
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool onMatch(markdown.InlineParser parser, Match match) {
|
||||||
|
final alias = match[0]!;
|
||||||
|
final anchor = markdown.Element.text('a', alias)
|
||||||
|
..attributes['href'] = Uri.encodeFull(
|
||||||
|
'solink://users/${alias.substring(1)}',
|
||||||
|
);
|
||||||
|
parser.addNode(anchor);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MarkdownTextCodeElement extends MarkdownElementBuilder {
|
||||||
|
@override
|
||||||
|
Widget? visitElementAfter(
|
||||||
|
markdown.Element element,
|
||||||
|
TextStyle? preferredStyle,
|
||||||
|
) {
|
||||||
|
var language = '';
|
||||||
|
|
||||||
|
if (element.attributes['class'] != null) {
|
||||||
|
String lg = element.attributes['class'] as String;
|
||||||
|
language = lg.substring(9).trim();
|
||||||
|
}
|
||||||
|
return SizedBox(
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: (() async {
|
||||||
|
final docPath = '../../../';
|
||||||
|
final highlightingPath =
|
||||||
|
join(docPath, 'assets/highlighting', language);
|
||||||
|
await Highlighter.initialize([highlightingPath]);
|
||||||
|
return Highlighter(
|
||||||
|
language: highlightingPath,
|
||||||
|
theme: PlatformDispatcher.instance.platformBrightness ==
|
||||||
|
Brightness.light
|
||||||
|
? await HighlighterTheme.loadLightTheme()
|
||||||
|
: await HighlighterTheme.loadDarkTheme(),
|
||||||
|
);
|
||||||
|
})(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
final highlighter = snapshot.data!;
|
||||||
|
return Text.rich(
|
||||||
|
highlighter.highlight(element.textContent.trim()),
|
||||||
|
style: GoogleFonts.robotoMono(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Text(
|
||||||
|
element.textContent.trim(),
|
||||||
|
style: GoogleFonts.robotoMono(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).padding(all: 8);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:relative_time/relative_time.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/types/post.dart';
|
import 'package:surface/types/post.dart';
|
||||||
|
import 'package:surface/widgets/account/account_image.dart';
|
||||||
|
import 'package:surface/widgets/markdown_content.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
|
||||||
class PostItem extends StatelessWidget {
|
class PostItem extends StatelessWidget {
|
||||||
final SnPost data;
|
final SnPost data;
|
||||||
@ -8,16 +14,61 @@ class PostItem extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [],
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_PostContentHeader(data: data),
|
||||||
|
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostContentPublisher extends StatelessWidget {
|
class _PostContentHeader extends StatelessWidget {
|
||||||
const _PostContentPublisher({super.key});
|
final SnPost data;
|
||||||
|
const _PostContentHeader({required this.data});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Placeholder();
|
return Row(
|
||||||
|
children: [
|
||||||
|
AccountImage(content: data.publisher.avatar),
|
||||||
|
const Gap(12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(data.publisher.nick).bold(),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('@${data.publisher.name}').fontSize(13),
|
||||||
|
const Gap(4),
|
||||||
|
Text(RelativeTime(context).format(data.publishedAt))
|
||||||
|
.fontSize(13),
|
||||||
|
],
|
||||||
|
).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
|
||||||
|
icon: const Icon(
|
||||||
|
Symbols.more_horiz,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 12, vertical: 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostContentBody extends StatelessWidget {
|
||||||
|
final dynamic data;
|
||||||
|
const _PostContentBody({this.data});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (data['content'] == null) return const SizedBox.shrink();
|
||||||
|
return MarkdownTextContent(content: data['content']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
147
lib/widgets/universal_image.dart
Normal file
147
lib/widgets/universal_image.dart
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
|
|
||||||
|
class UniversalImage extends StatelessWidget {
|
||||||
|
final String url;
|
||||||
|
final double? width, height;
|
||||||
|
final BoxFit? fit;
|
||||||
|
final bool noProgressIndicator;
|
||||||
|
final bool noErrorWidget;
|
||||||
|
final double? cacheWidth, cacheHeight;
|
||||||
|
|
||||||
|
const UniversalImage(
|
||||||
|
this.url, {
|
||||||
|
super.key,
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
|
this.fit,
|
||||||
|
this.noProgressIndicator = false,
|
||||||
|
this.noErrorWidget = false,
|
||||||
|
this.cacheWidth,
|
||||||
|
this.cacheHeight,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||||
|
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS)) {
|
||||||
|
return CachedNetworkImage(
|
||||||
|
imageUrl: url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
memCacheHeight: cacheHeight != null
|
||||||
|
? (cacheHeight! * devicePixelRatio).round()
|
||||||
|
: null,
|
||||||
|
memCacheWidth: cacheWidth != null
|
||||||
|
? (cacheWidth! * devicePixelRatio).round()
|
||||||
|
: null,
|
||||||
|
progressIndicatorBuilder: noProgressIndicator
|
||||||
|
? null
|
||||||
|
: (context, url, downloadProgress) => Center(
|
||||||
|
child: TweenAnimationBuilder(
|
||||||
|
tween: Tween(
|
||||||
|
begin: 0,
|
||||||
|
end: downloadProgress.progress ?? 0,
|
||||||
|
),
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
builder: (context, value, _) => CircularProgressIndicator(
|
||||||
|
value: downloadProgress.progress != null
|
||||||
|
? value.toDouble()
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
errorWidget: noErrorWidget
|
||||||
|
? null
|
||||||
|
: (context, url, error) {
|
||||||
|
return Container(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
AnimateWidgetExtensions(Icon(Icons.close, size: 24))
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
Text(
|
||||||
|
error.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).center(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Image.network(
|
||||||
|
url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
cacheHeight: cacheHeight != null
|
||||||
|
? (cacheHeight! * devicePixelRatio).round()
|
||||||
|
: null,
|
||||||
|
cacheWidth:
|
||||||
|
cacheWidth != null ? (cacheWidth! * devicePixelRatio).round() : null,
|
||||||
|
loadingBuilder: noProgressIndicator
|
||||||
|
? null
|
||||||
|
: (BuildContext context, Widget child,
|
||||||
|
ImageChunkEvent? loadingProgress) {
|
||||||
|
if (loadingProgress == null) return child;
|
||||||
|
return Center(
|
||||||
|
child: TweenAnimationBuilder(
|
||||||
|
tween: Tween(
|
||||||
|
begin: 0,
|
||||||
|
end: loadingProgress.expectedTotalBytes != null
|
||||||
|
? loadingProgress.cumulativeBytesLoaded /
|
||||||
|
loadingProgress.expectedTotalBytes!
|
||||||
|
: 0,
|
||||||
|
),
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
builder: (context, value, _) => CircularProgressIndicator(
|
||||||
|
value: loadingProgress.expectedTotalBytes != null
|
||||||
|
? value.toDouble()
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
errorBuilder: noErrorWidget
|
||||||
|
? null
|
||||||
|
: (context, error, stackTrace) {
|
||||||
|
return Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
AnimateWidgetExtensions(Icon(Icons.close, size: 24))
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
Text(
|
||||||
|
error.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).center(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImageProvider provider(String url) {
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS)) {
|
||||||
|
return CachedNetworkImageProvider(url);
|
||||||
|
}
|
||||||
|
return NetworkImage(url);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
@ -8,9 +8,13 @@ import Foundation
|
|||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
|
import sqflite_darwin
|
||||||
|
import url_launcher_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
}
|
}
|
||||||
|
238
pubspec.lock
238
pubspec.lock
@ -134,6 +134,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.9.2"
|
version: "8.9.2"
|
||||||
|
cached_network_image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cached_network_image
|
||||||
|
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
|
cached_network_image_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cached_network_image_platform_interface
|
||||||
|
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.1"
|
||||||
|
cached_network_image_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cached_network_image_web
|
||||||
|
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -347,6 +371,22 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_animate:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_animate
|
||||||
|
sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.0"
|
||||||
|
flutter_cache_manager:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_cache_manager
|
||||||
|
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -360,6 +400,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_markdown:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_markdown
|
||||||
|
sha256: f0e599ba89c9946c8e051780f0ec99aba4ba15895e0380a7ab68f420046fc44e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.4+1"
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -368,6 +416,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.4.2"
|
||||||
|
flutter_shaders:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_shaders
|
||||||
|
sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -426,6 +482,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.4.1"
|
version: "14.4.1"
|
||||||
|
google_fonts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_fonts
|
||||||
|
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.2.1"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -594,6 +658,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3-main.0"
|
version: "0.1.3-main.0"
|
||||||
|
markdown:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: markdown
|
||||||
|
sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.2.2"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -614,10 +686,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: material_symbols_icons
|
name: material_symbols_icons
|
||||||
sha256: "7626ce90395bc6dc2ecb7bdd84c04a97f3f084a4e923ff73791c3c409af02804"
|
sha256: "7b723abea4ad37e16fe921f1f1971cbb9b0f66d223a8c99981168a2306416b98"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2789.0"
|
version: "4.2791.1"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -658,6 +730,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.0"
|
||||||
|
octo_image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: octo_image
|
||||||
|
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -667,7 +747,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||||
@ -778,6 +858,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
|
relative_time:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: relative_time
|
||||||
|
sha256: "4e6c3b27d98ff6af5061b6dbaca178b5aa2607b7a7c2a77e6cae1d32b2759893"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.0"
|
||||||
responsive_framework:
|
responsive_framework:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -786,6 +874,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
|
rxdart:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: rxdart
|
||||||
|
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.28.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -887,6 +983,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.10.0"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
|
sqflite:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite
|
||||||
|
sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
sqflite_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_android
|
||||||
|
sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
|
sqflite_common:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_common
|
||||||
|
sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.4+5"
|
||||||
|
sqflite_darwin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_darwin
|
||||||
|
sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
sqflite_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_platform_interface
|
||||||
|
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -927,6 +1071,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.1"
|
version: "0.4.1"
|
||||||
|
synchronized:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: synchronized
|
||||||
|
sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.3.0+3"
|
||||||
|
syntax_highlight:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: syntax_highlight
|
||||||
|
sha256: ee33b6aa82cc722bb9b40152a792181dee222353b486c0255fde666a3e3a4997
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.0"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -967,6 +1127,78 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.2"
|
||||||
|
url_launcher:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: url_launcher
|
||||||
|
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.1"
|
||||||
|
url_launcher_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_android
|
||||||
|
sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.14"
|
||||||
|
url_launcher_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_ios
|
||||||
|
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.1"
|
||||||
|
url_launcher_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_linux
|
||||||
|
sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.0"
|
||||||
|
url_launcher_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_macos
|
||||||
|
sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
|
url_launcher_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_platform_interface
|
||||||
|
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
url_launcher_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_web
|
||||||
|
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.3"
|
||||||
|
url_launcher_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: url_launcher_windows
|
||||||
|
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -49,6 +49,15 @@ dependencies:
|
|||||||
freezed_annotation: ^2.4.4
|
freezed_annotation: ^2.4.4
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
gap: ^3.0.1
|
gap: ^3.0.1
|
||||||
|
markdown: ^7.2.2
|
||||||
|
flutter_markdown: ^0.7.4+1
|
||||||
|
url_launcher: ^6.3.1
|
||||||
|
cached_network_image: ^3.4.1
|
||||||
|
flutter_animate: ^4.5.0
|
||||||
|
syntax_highlight: ^0.4.0
|
||||||
|
google_fonts: ^6.2.1
|
||||||
|
path: ^1.9.0
|
||||||
|
relative_time: ^5.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -7,8 +7,11 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
connectivity_plus
|
connectivity_plus
|
||||||
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
Loading…
Reference in New Issue
Block a user