Compare commits
4 Commits
81a79f9476
...
2.3.2+71
| Author | SHA1 | Date | |
|---|---|---|---|
| 997934f680 | |||
| 26e69d6264 | |||
| 153eabcbf2 | |||
| 6d0145c335 |
1
.github/workflows/nightly.yml
vendored
1
.github/workflows/nightly.yml
vendored
@@ -55,6 +55,7 @@ jobs:
|
|||||||
sudo apt-get install libmpv-dev mpv
|
sudo apt-get install libmpv-dev mpv
|
||||||
sudo apt-get install libayatana-appindicator3-dev
|
sudo apt-get install libayatana-appindicator3-dev
|
||||||
sudo apt-get install keybinder-3.0
|
sudo apt-get install keybinder-3.0
|
||||||
|
sudo apt-get install libnotify-dev
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter build linux
|
- run: flutter build linux
|
||||||
- name: Archive production artifacts
|
- name: Archive production artifacts
|
||||||
|
|||||||
@@ -717,5 +717,6 @@
|
|||||||
"fieldStickerAttachment": "Attachment",
|
"fieldStickerAttachment": "Attachment",
|
||||||
"stickersNew": "New Sticker",
|
"stickersNew": "New Sticker",
|
||||||
"stickersNewDescription": "Create a new sticker belongs to this pack.",
|
"stickersNewDescription": "Create a new sticker belongs to this pack.",
|
||||||
"stickersPackNew": "New Sticker Pack"
|
"stickersPackNew": "New Sticker Pack",
|
||||||
|
"trayMenuShow": "Show"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -715,5 +715,6 @@
|
|||||||
"fieldStickerAttachment": "附件",
|
"fieldStickerAttachment": "附件",
|
||||||
"stickersNew": "新建贴图",
|
"stickersNew": "新建贴图",
|
||||||
"stickersNewDescription": "创建一个新的贴图。",
|
"stickersNewDescription": "创建一个新的贴图。",
|
||||||
"stickersPackNew": "新建贴图包"
|
"stickersPackNew": "新建贴图包",
|
||||||
|
"trayMenuShow": "显示"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import 'package:workmanager/workmanager.dart';
|
|||||||
import 'package:in_app_review/in_app_review.dart';
|
import 'package:in_app_review/in_app_review.dart';
|
||||||
import 'package:image_picker_android/image_picker_android.dart';
|
import 'package:image_picker_android/image_picker_android.dart';
|
||||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||||
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
void appBackgroundDispatcher() {
|
void appBackgroundDispatcher() {
|
||||||
@@ -350,6 +351,10 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
|||||||
disabled: true,
|
disabled: true,
|
||||||
),
|
),
|
||||||
MenuItem.separator(),
|
MenuItem.separator(),
|
||||||
|
MenuItem(
|
||||||
|
key: 'window_show',
|
||||||
|
label: 'trayMenuShow'.tr(),
|
||||||
|
),
|
||||||
MenuItem(
|
MenuItem(
|
||||||
key: 'exit',
|
key: 'exit',
|
||||||
label: 'trayMenuExit'.tr(),
|
label: 'trayMenuExit'.tr(),
|
||||||
@@ -359,6 +364,15 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
|||||||
await trayManager.setContextMenu(menu);
|
await trayManager.setContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _notifyInitialization() async {
|
||||||
|
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
|
||||||
|
|
||||||
|
await localNotifier.setup(
|
||||||
|
appName: 'solian',
|
||||||
|
shortcutPolicy: ShortcutPolicy.requireCreate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
AppLifecycleListener? _appLifecycleListener;
|
AppLifecycleListener? _appLifecycleListener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -373,6 +387,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
|||||||
|
|
||||||
_trayInitialization();
|
_trayInitialization();
|
||||||
_hotkeyInitialization();
|
_hotkeyInitialization();
|
||||||
|
_notifyInitialization();
|
||||||
_initialize().then((_) {
|
_initialize().then((_) {
|
||||||
_postInitialization();
|
_postInitialization();
|
||||||
_tryRequestRating();
|
_tryRequestRating();
|
||||||
@@ -408,6 +423,9 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
|||||||
@override
|
@override
|
||||||
void onTrayMenuItemClick(MenuItem menuItem) {
|
void onTrayMenuItemClick(MenuItem menuItem) {
|
||||||
switch (menuItem.key) {
|
switch (menuItem.key) {
|
||||||
|
case 'window_show':
|
||||||
|
appWindow.show();
|
||||||
|
break;
|
||||||
case 'exit':
|
case 'exit':
|
||||||
_appLifecycleListener?.dispose();
|
_appLifecycleListener?.dispose();
|
||||||
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_udid/flutter_udid.dart';
|
import 'package:flutter_udid/flutter_udid.dart';
|
||||||
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:surface/providers/config.dart';
|
import 'package:surface/providers/config.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
@@ -92,6 +94,20 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
updateTray();
|
updateTray();
|
||||||
final doHaptic = _cfg.prefs.getBool(kAppNotifyWithHaptic) ?? true;
|
final doHaptic = _cfg.prefs.getBool(kAppNotifyWithHaptic) ?? true;
|
||||||
if (doHaptic) HapticFeedback.mediumImpact();
|
if (doHaptic) HapticFeedback.mediumImpact();
|
||||||
|
|
||||||
|
if (!kIsWeb) {
|
||||||
|
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
|
||||||
|
LocalNotification notify = LocalNotification(
|
||||||
|
title: notification.title,
|
||||||
|
subtitle: notification.subtitle,
|
||||||
|
body: notification.body,
|
||||||
|
);
|
||||||
|
notify.onClick = () {
|
||||||
|
appWindow.show();
|
||||||
|
};
|
||||||
|
notify.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,11 +109,13 @@ class ChatMessage extends StatelessWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
showPopover(
|
showPopover(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.surface,
|
||||||
context: context,
|
context: context,
|
||||||
transition: PopoverTransition.other,
|
transition: PopoverTransition.other,
|
||||||
bodyBuilder: (context) => SizedBox(
|
bodyBuilder: (context) => SizedBox(
|
||||||
width: math.min(400, MediaQuery.of(context).size.width - 10),
|
width: math.min(
|
||||||
|
400, MediaQuery.of(context).size.width - 10),
|
||||||
child: AccountPopoverCard(
|
child: AccountPopoverCard(
|
||||||
data: user,
|
data: user,
|
||||||
),
|
),
|
||||||
@@ -144,11 +146,14 @@ class ChatMessage extends StatelessWidget {
|
|||||||
radius: 12,
|
radius: 12,
|
||||||
).padding(right: 8),
|
).padding(right: 8),
|
||||||
Text(
|
Text(
|
||||||
(data.sender.nick?.isNotEmpty ?? false) ? data.sender.nick! : user?.nick ?? 'unknown',
|
(data.sender.nick?.isNotEmpty ?? false)
|
||||||
|
? data.sender.nick!
|
||||||
|
: user?.nick ?? 'unknown',
|
||||||
).bold(),
|
).bold(),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Text(
|
Text(
|
||||||
dateFormatter.format(data.createdAt.toLocal()),
|
dateFormatter
|
||||||
|
.format(data.createdAt.toLocal()),
|
||||||
).fontSize(13),
|
).fontSize(13),
|
||||||
],
|
],
|
||||||
).height(21),
|
).height(21),
|
||||||
@@ -159,7 +164,8 @@ class ChatMessage extends StatelessWidget {
|
|||||||
maxWidth: 480,
|
maxWidth: 480,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(8)),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).dividerColor,
|
||||||
width: 1,
|
width: 1,
|
||||||
@@ -207,9 +213,12 @@ class ChatMessage extends StatelessWidget {
|
|||||||
maxHeight: 560,
|
maxHeight: 560,
|
||||||
maxWidth: 480,
|
maxWidth: 480,
|
||||||
minWidth: 480,
|
minWidth: 480,
|
||||||
padding: padding.copyWith(top: 8),
|
padding: padding.copyWith(top: 8, left: 48 + padding.left),
|
||||||
),
|
),
|
||||||
if (!hasMerged && !isCompact) const Gap(12) else if (!isCompact) const Gap(8),
|
if (!hasMerged && !isCompact)
|
||||||
|
const Gap(12)
|
||||||
|
else if (!isCompact)
|
||||||
|
const Gap(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -223,7 +232,8 @@ class _ChatMessageText extends StatelessWidget {
|
|||||||
final Function(SnChatMessage)? onEdit;
|
final Function(SnChatMessage)? onEdit;
|
||||||
final Function(SnChatMessage)? onDelete;
|
final Function(SnChatMessage)? onDelete;
|
||||||
|
|
||||||
const _ChatMessageText({required this.data, this.onReply, this.onEdit, this.onDelete});
|
const _ChatMessageText(
|
||||||
|
{required this.data, this.onReply, this.onEdit, this.onDelete});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -237,7 +247,8 @@ class _ChatMessageText extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
SelectionArea(
|
SelectionArea(
|
||||||
contextMenuBuilder: (context, editableTextState) {
|
contextMenuBuilder: (context, editableTextState) {
|
||||||
final List<ContextMenuButtonItem> items = editableTextState.contextMenuButtonItems;
|
final List<ContextMenuButtonItem> items =
|
||||||
|
editableTextState.contextMenuButtonItems;
|
||||||
|
|
||||||
if (onReply != null) {
|
if (onReply != null) {
|
||||||
items.insert(
|
items.insert(
|
||||||
@@ -286,6 +297,8 @@ class _ChatMessageText extends StatelessWidget {
|
|||||||
child: MarkdownTextContent(
|
child: MarkdownTextContent(
|
||||||
content: data.body['text'],
|
content: data.body['text'],
|
||||||
isAutoWarp: true,
|
isAutoWarp: true,
|
||||||
|
isEnlargeSticker:
|
||||||
|
RegExp(r"^:([-\w]+):$").hasMatch(data.body['text'] ?? ''),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
Theme.of(context),
|
Theme.of(context),
|
||||||
).copyWith(
|
).copyWith(
|
||||||
textScaler: textScaler,
|
textScaler: textScaler,
|
||||||
p: textColor != null ? Theme.of(context).textTheme.bodyMedium!.copyWith(color: textColor) : null,
|
p: textColor != null
|
||||||
|
? Theme.of(context).textTheme.bodyMedium!.copyWith(color: textColor)
|
||||||
|
: null,
|
||||||
blockquote: TextStyle(
|
blockquote: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
@@ -115,7 +117,7 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
final alias = segments[1];
|
final alias = segments[1];
|
||||||
final st = context.read<SnStickerProvider>();
|
final st = context.read<SnStickerProvider>();
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
final double size = isEnlargeSticker ? 128 : 32;
|
final double size = isEnlargeSticker ? 96 : 32;
|
||||||
return Container(
|
return Container(
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
@@ -131,7 +133,8 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
sn.getAttachmentUrl(snapshot.data!.attachment.rid),
|
sn.getAttachmentUrl(
|
||||||
|
snapshot.data!.attachment.rid),
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
@@ -177,7 +180,9 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: attachment.metadata['ratio'] ??
|
aspectRatio: attachment.metadata['ratio'] ??
|
||||||
switch (attachment.mimetype.split('/').firstOrNull) {
|
switch (attachment.mimetype
|
||||||
|
.split('/')
|
||||||
|
.firstOrNull) {
|
||||||
'audio' => 16 / 9,
|
'audio' => 16 / 9,
|
||||||
'video' => 16 / 9,
|
'video' => 16 / 9,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ class OpenablePostItem extends StatelessWidget {
|
|||||||
openColor: Colors.transparent,
|
openColor: Colors.transparent,
|
||||||
openElevation: 0,
|
openElevation: 0,
|
||||||
transitionType: ContainerTransitionType.fade,
|
transitionType: ContainerTransitionType.fade,
|
||||||
closedColor: Theme.of(context).colorScheme.surfaceContainerLow.withOpacity(
|
closedColor:
|
||||||
|
Theme.of(context).colorScheme.surfaceContainerLow.withOpacity(
|
||||||
cfg.prefs.getBool(kAppBackgroundStoreKey) == true ? 0.75 : 1,
|
cfg.prefs.getBool(kAppBackgroundStoreKey) == true ? 0.75 : 1,
|
||||||
),
|
),
|
||||||
closedShape: const RoundedRectangleBorder(
|
closedShape: const RoundedRectangleBorder(
|
||||||
@@ -135,9 +136,11 @@ class PostItem extends StatelessWidget {
|
|||||||
final box = context.findRenderObject() as RenderBox?;
|
final box = context.findRenderObject() as RenderBox?;
|
||||||
final url = 'https://solsynth.dev/posts/${data.id}';
|
final url = 'https://solsynth.dev/posts/${data.id}';
|
||||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
Share.shareUri(Uri.parse(url), sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
Share.shareUri(Uri.parse(url),
|
||||||
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
||||||
} else {
|
} else {
|
||||||
Share.share(url, sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
Share.share(url,
|
||||||
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +158,8 @@ class PostItem extends StatelessWidget {
|
|||||||
child: MultiProvider(
|
child: MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
Provider<SnNetworkProvider>(create: (_) => context.read()),
|
Provider<SnNetworkProvider>(create: (_) => context.read()),
|
||||||
ChangeNotifierProvider<ConfigProvider>(create: (_) => context.read()),
|
ChangeNotifierProvider<ConfigProvider>(
|
||||||
|
create: (_) => context.read()),
|
||||||
],
|
],
|
||||||
child: ResponsiveBreakpoints.builder(
|
child: ResponsiveBreakpoints.builder(
|
||||||
breakpoints: ResponsiveBreakpoints.of(context).breakpoints,
|
breakpoints: ResponsiveBreakpoints.of(context).breakpoints,
|
||||||
@@ -183,7 +187,8 @@ class PostItem extends StatelessWidget {
|
|||||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await FileSaver.instance.saveFile(name: 'Solar Network Post #${data.id}.png', file: imageFile);
|
await FileSaver.instance.saveFile(
|
||||||
|
name: 'Solar Network Post #${data.id}.png', file: imageFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
await imageFile.delete();
|
await imageFile.delete();
|
||||||
@@ -197,7 +202,9 @@ class PostItem extends StatelessWidget {
|
|||||||
final isAuthor = ua.isAuthorized && data.publisher.accountId == ua.user?.id;
|
final isAuthor = ua.isAuthorized && data.publisher.accountId == ua.user?.id;
|
||||||
|
|
||||||
// Video full view
|
// Video full view
|
||||||
if (showFullPost && data.type == 'video' && ResponsiveBreakpoints.of(context).largerThan(TABLET)) {
|
if (showFullPost &&
|
||||||
|
data.type == 'video' &&
|
||||||
|
ResponsiveBreakpoints.of(context).largerThan(TABLET)) {
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -217,7 +224,8 @@ class PostItem extends StatelessWidget {
|
|||||||
if (onDeleted != null) {}
|
if (onDeleted != null) {}
|
||||||
},
|
},
|
||||||
).padding(bottom: 8),
|
).padding(bottom: 8),
|
||||||
if (data.preload?.video != null) _PostVideoPlayer(data: data).padding(bottom: 8),
|
if (data.preload?.video != null)
|
||||||
|
_PostVideoPlayer(data: data).padding(bottom: 8),
|
||||||
_PostHeadline(data: data).padding(horizontal: 4, bottom: 8),
|
_PostHeadline(data: data).padding(horizontal: 4, bottom: 8),
|
||||||
_PostFeaturedComment(data: data),
|
_PostFeaturedComment(data: data),
|
||||||
_PostBottomAction(
|
_PostBottomAction(
|
||||||
@@ -265,7 +273,8 @@ class PostItem extends StatelessWidget {
|
|||||||
if (onDeleted != null) {}
|
if (onDeleted != null) {}
|
||||||
},
|
},
|
||||||
).padding(horizontal: 12, top: 8, bottom: 8),
|
).padding(horizontal: 12, top: 8, bottom: 8),
|
||||||
if (data.preload?.video != null) _PostVideoPlayer(data: data).padding(horizontal: 12, bottom: 8),
|
if (data.preload?.video != null)
|
||||||
|
_PostVideoPlayer(data: data).padding(horizontal: 12, bottom: 8),
|
||||||
Container(
|
Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
margin: const EdgeInsets.only(bottom: 4, left: 12, right: 12),
|
margin: const EdgeInsets.only(bottom: 4, left: 12, right: 12),
|
||||||
@@ -308,8 +317,13 @@ class PostItem extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('postArticle').tr().fontSize(13).opacity(0.75).padding(horizontal: 24, bottom: 8),
|
Text('postArticle')
|
||||||
_PostFeaturedComment(data: data, maxWidth: maxWidth).padding(horizontal: 12),
|
.tr()
|
||||||
|
.fontSize(13)
|
||||||
|
.opacity(0.75)
|
||||||
|
.padding(horizontal: 24, bottom: 8),
|
||||||
|
_PostFeaturedComment(data: data, maxWidth: maxWidth)
|
||||||
|
.padding(horizontal: 12),
|
||||||
_PostBottomAction(
|
_PostBottomAction(
|
||||||
data: data,
|
data: data,
|
||||||
showComments: showComments,
|
showComments: showComments,
|
||||||
@@ -324,7 +338,8 @@ class PostItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final displayableAttachments = data.preload?.attachments
|
final displayableAttachments = data.preload?.attachments
|
||||||
?.where((ele) => ele?.mediaType != SnMediaType.image || data.type != 'article')
|
?.where((ele) =>
|
||||||
|
ele?.mediaType != SnMediaType.image || data.type != 'article')
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final cfg = context.read<ConfigProvider>();
|
final cfg = context.read<ConfigProvider>();
|
||||||
@@ -349,9 +364,13 @@ class PostItem extends StatelessWidget {
|
|||||||
if (onDeleted != null) onDeleted!();
|
if (onDeleted != null) onDeleted!();
|
||||||
},
|
},
|
||||||
).padding(horizontal: 12, vertical: 8),
|
).padding(horizontal: 12, vertical: 8),
|
||||||
if (data.preload?.video != null) _PostVideoPlayer(data: data).padding(horizontal: 12, bottom: 8),
|
if (data.preload?.video != null)
|
||||||
if (data.type == 'question') _PostQuestionHint(data: data).padding(horizontal: 16, bottom: 8),
|
_PostVideoPlayer(data: data).padding(horizontal: 12, bottom: 8),
|
||||||
if (data.body['title'] != null || data.body['description'] != null)
|
if (data.type == 'question')
|
||||||
|
_PostQuestionHint(data: data)
|
||||||
|
.padding(horizontal: 16, bottom: 8),
|
||||||
|
if (data.body['title'] != null ||
|
||||||
|
data.body['description'] != null)
|
||||||
_PostHeadline(
|
_PostHeadline(
|
||||||
data: data,
|
data: data,
|
||||||
isEnlarge: data.type == 'article' && showFullPost,
|
isEnlarge: data.type == 'article' && showFullPost,
|
||||||
@@ -365,7 +384,8 @@ class PostItem extends StatelessWidget {
|
|||||||
if (data.repostTo != null)
|
if (data.repostTo != null)
|
||||||
_PostQuoteContent(child: data.repostTo!).padding(
|
_PostQuoteContent(child: data.repostTo!).padding(
|
||||||
horizontal: 12,
|
horizontal: 12,
|
||||||
bottom: data.preload?.attachments?.isNotEmpty ?? false ? 12 : 0,
|
bottom:
|
||||||
|
data.preload?.attachments?.isNotEmpty ?? false ? 12 : 0,
|
||||||
),
|
),
|
||||||
if (data.visibility > 0)
|
if (data.visibility > 0)
|
||||||
_PostVisibilityHint(data: data).padding(
|
_PostVisibilityHint(data: data).padding(
|
||||||
@@ -377,7 +397,9 @@ class PostItem extends StatelessWidget {
|
|||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
vertical: 4,
|
vertical: 4,
|
||||||
),
|
),
|
||||||
if (data.tags.isNotEmpty) _PostTagsList(data: data).padding(horizontal: 16, top: 4, bottom: 6),
|
if (data.tags.isNotEmpty)
|
||||||
|
_PostTagsList(data: data)
|
||||||
|
.padding(horizontal: 16, top: 4, bottom: 6),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -390,12 +412,16 @@ class PostItem extends StatelessWidget {
|
|||||||
fit: showFullPost ? BoxFit.cover : BoxFit.contain,
|
fit: showFullPost ? BoxFit.cover : BoxFit.contain,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
),
|
),
|
||||||
if (data.preload?.poll != null) PostPoll(poll: data.preload!.poll!).padding(horizontal: 12, vertical: 4),
|
if (data.preload?.poll != null)
|
||||||
if (data.body['content'] != null && (cfg.prefs.getBool(kAppExpandPostLink) ?? true))
|
PostPoll(poll: data.preload!.poll!)
|
||||||
|
.padding(horizontal: 12, vertical: 4),
|
||||||
|
if (data.body['content'] != null &&
|
||||||
|
(cfg.prefs.getBool(kAppExpandPostLink) ?? true))
|
||||||
LinkPreviewWidget(
|
LinkPreviewWidget(
|
||||||
text: data.body['content'],
|
text: data.body['content'],
|
||||||
).padding(horizontal: 4),
|
).padding(horizontal: 4),
|
||||||
_PostFeaturedComment(data: data, maxWidth: maxWidth).padding(horizontal: 12),
|
_PostFeaturedComment(data: data, maxWidth: maxWidth)
|
||||||
|
.padding(horizontal: 12),
|
||||||
Container(
|
Container(
|
||||||
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -457,7 +483,8 @@ class PostShareImageWidget extends StatelessWidget {
|
|||||||
showMenu: false,
|
showMenu: false,
|
||||||
isRelativeDate: false,
|
isRelativeDate: false,
|
||||||
).padding(horizontal: 16, bottom: 8),
|
).padding(horizontal: 16, bottom: 8),
|
||||||
if (data.type == 'question') _PostQuestionHint(data: data).padding(horizontal: 16, bottom: 8),
|
if (data.type == 'question')
|
||||||
|
_PostQuestionHint(data: data).padding(horizontal: 16, bottom: 8),
|
||||||
_PostHeadline(
|
_PostHeadline(
|
||||||
data: data,
|
data: data,
|
||||||
isEnlarge: data.type == 'article',
|
isEnlarge: data.type == 'article',
|
||||||
@@ -472,7 +499,8 @@ class PostShareImageWidget extends StatelessWidget {
|
|||||||
child: data.repostTo!,
|
child: data.repostTo!,
|
||||||
isRelativeDate: false,
|
isRelativeDate: false,
|
||||||
).padding(horizontal: 16, bottom: 8),
|
).padding(horizontal: 16, bottom: 8),
|
||||||
if (data.type != 'article' && (data.preload?.attachments?.isNotEmpty ?? false))
|
if (data.type != 'article' &&
|
||||||
|
(data.preload?.attachments?.isNotEmpty ?? false))
|
||||||
StyledWidget(AttachmentList(
|
StyledWidget(AttachmentList(
|
||||||
data: data.preload!.attachments!,
|
data: data.preload!.attachments!,
|
||||||
columned: true,
|
columned: true,
|
||||||
@@ -481,7 +509,8 @@ class PostShareImageWidget extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (data.visibility > 0) _PostVisibilityHint(data: data),
|
if (data.visibility > 0) _PostVisibilityHint(data: data),
|
||||||
if (data.body['content_truncated'] == true) _PostTruncatedHint(data: data),
|
if (data.body['content_truncated'] == true)
|
||||||
|
_PostTruncatedHint(data: data),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16),
|
).padding(horizontal: 16),
|
||||||
_PostBottomAction(
|
_PostBottomAction(
|
||||||
@@ -541,7 +570,8 @@ class PostShareImageWidget extends StatelessWidget {
|
|||||||
version: QrVersions.auto,
|
version: QrVersions.auto,
|
||||||
size: 100,
|
size: 100,
|
||||||
gapless: true,
|
gapless: true,
|
||||||
embeddedImage: AssetImage('assets/icon/icon-light-radius.png'),
|
embeddedImage:
|
||||||
|
AssetImage('assets/icon/icon-light-radius.png'),
|
||||||
embeddedImageStyle: QrEmbeddedImageStyle(
|
embeddedImageStyle: QrEmbeddedImageStyle(
|
||||||
size: Size(28, 28),
|
size: Size(28, 28),
|
||||||
),
|
),
|
||||||
@@ -572,9 +602,11 @@ class _PostQuestionHint extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(data.body['answer'] == null ? Symbols.help : Symbols.check_circle, size: 20),
|
Icon(data.body['answer'] == null ? Symbols.help : Symbols.check_circle,
|
||||||
|
size: 20),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
if (data.body['answer'] == null && data.body['reward']?.toDouble() != null)
|
if (data.body['answer'] == null &&
|
||||||
|
data.body['reward']?.toDouble() != null)
|
||||||
Text('postQuestionUnansweredWithReward'.tr(args: [
|
Text('postQuestionUnansweredWithReward'.tr(args: [
|
||||||
'${data.body['reward']}',
|
'${data.body['reward']}',
|
||||||
])).opacity(0.75)
|
])).opacity(0.75)
|
||||||
@@ -610,7 +642,9 @@ class _PostBottomAction extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final String? mostTypicalReaction = data.metric.reactionList.isNotEmpty
|
final String? mostTypicalReaction = data.metric.reactionList.isNotEmpty
|
||||||
? data.metric.reactionList.entries.reduce((a, b) => a.value > b.value ? a : b).key
|
? data.metric.reactionList.entries
|
||||||
|
.reduce((a, b) => a.value > b.value ? a : b)
|
||||||
|
.key
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
@@ -624,7 +658,8 @@ class _PostBottomAction extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if (mostTypicalReaction == null || kTemplateReactions[mostTypicalReaction] == null)
|
if (mostTypicalReaction == null ||
|
||||||
|
kTemplateReactions[mostTypicalReaction] == null)
|
||||||
Icon(Symbols.add_reaction, size: 20, color: iconColor)
|
Icon(Symbols.add_reaction, size: 20, color: iconColor)
|
||||||
else
|
else
|
||||||
Text(
|
Text(
|
||||||
@@ -636,7 +671,8 @@ class _PostBottomAction extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
if (data.totalUpvote > 0 && data.totalUpvote >= data.totalDownvote)
|
if (data.totalUpvote > 0 &&
|
||||||
|
data.totalUpvote >= data.totalDownvote)
|
||||||
Text('postReactionUpvote').plural(
|
Text('postReactionUpvote').plural(
|
||||||
data.totalUpvote,
|
data.totalUpvote,
|
||||||
)
|
)
|
||||||
@@ -655,8 +691,12 @@ class _PostBottomAction extends StatelessWidget {
|
|||||||
data: data,
|
data: data,
|
||||||
onChanged: (value, attr, delta) {
|
onChanged: (value, attr, delta) {
|
||||||
onChanged(data.copyWith(
|
onChanged(data.copyWith(
|
||||||
totalUpvote: attr == 1 ? data.totalUpvote + delta : data.totalUpvote,
|
totalUpvote: attr == 1
|
||||||
totalDownvote: attr == 2 ? data.totalDownvote + delta : data.totalDownvote,
|
? data.totalUpvote + delta
|
||||||
|
: data.totalUpvote,
|
||||||
|
totalDownvote: attr == 2
|
||||||
|
? data.totalDownvote + delta
|
||||||
|
: data.totalDownvote,
|
||||||
metric: data.metric.copyWith(reactionList: value),
|
metric: data.metric.copyWith(reactionList: value),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
@@ -904,8 +944,10 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text(
|
Text(
|
||||||
isRelativeDate
|
isRelativeDate
|
||||||
? RelativeTime(context).format(data.publishedAt ?? data.createdAt)
|
? RelativeTime(context)
|
||||||
: DateFormat('y/M/d HH:mm').format(data.publishedAt ?? data.createdAt),
|
.format(data.publishedAt ?? data.createdAt)
|
||||||
|
: DateFormat('y/M/d HH:mm')
|
||||||
|
.format(data.publishedAt ?? data.createdAt),
|
||||||
).fontSize(13),
|
).fontSize(13),
|
||||||
],
|
],
|
||||||
).opacity(0.8),
|
).opacity(0.8),
|
||||||
@@ -923,8 +965,10 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text(
|
Text(
|
||||||
isRelativeDate
|
isRelativeDate
|
||||||
? RelativeTime(context).format(data.publishedAt ?? data.createdAt)
|
? RelativeTime(context)
|
||||||
: DateFormat('y/M/d HH:mm').format(data.publishedAt ?? data.createdAt),
|
.format(data.publishedAt ?? data.createdAt)
|
||||||
|
: DateFormat('y/M/d HH:mm')
|
||||||
|
.format(data.publishedAt ?? data.createdAt),
|
||||||
).fontSize(13),
|
).fontSize(13),
|
||||||
],
|
],
|
||||||
).opacity(0.8),
|
).opacity(0.8),
|
||||||
@@ -1107,7 +1151,8 @@ class _PostContentBody extends StatelessWidget {
|
|||||||
if (data.body['content'] == null) return const SizedBox.shrink();
|
if (data.body['content'] == null) return const SizedBox.shrink();
|
||||||
final content = MarkdownTextContent(
|
final content = MarkdownTextContent(
|
||||||
isAutoWarp: data.type == 'story',
|
isAutoWarp: data.type == 'story',
|
||||||
isEnlargeSticker: true,
|
isEnlargeSticker:
|
||||||
|
RegExp(r"^:([-\w]+):$").hasMatch(data.body['content'] ?? ''),
|
||||||
textScaler: isEnlarge ? TextScaler.linear(1.1) : null,
|
textScaler: isEnlarge ? TextScaler.linear(1.1) : null,
|
||||||
content: data.body['content'],
|
content: data.body['content'],
|
||||||
attachments: data.preload?.attachments,
|
attachments: data.preload?.attachments,
|
||||||
@@ -1156,10 +1201,12 @@ class _PostQuoteContent extends StatelessWidget {
|
|||||||
onDeleted: () {},
|
onDeleted: () {},
|
||||||
).padding(bottom: 4),
|
).padding(bottom: 4),
|
||||||
_PostContentBody(data: child),
|
_PostContentBody(data: child),
|
||||||
if (child.visibility > 0) _PostVisibilityHint(data: child).padding(top: 4),
|
if (child.visibility > 0)
|
||||||
|
_PostVisibilityHint(data: child).padding(top: 4),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16),
|
).padding(horizontal: 16),
|
||||||
if (child.type != 'article' && (child.preload?.attachments?.isNotEmpty ?? false))
|
if (child.type != 'article' &&
|
||||||
|
(child.preload?.attachments?.isNotEmpty ?? false))
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(8),
|
bottomLeft: Radius.circular(8),
|
||||||
@@ -1310,7 +1357,9 @@ class _PostTruncatedHint extends StatelessWidget {
|
|||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text('postReadEstimate').tr(args: [
|
Text('postReadEstimate').tr(args: [
|
||||||
'${Duration(
|
'${Duration(
|
||||||
seconds: (data.body['content_length'] as num).toDouble() * 60 ~/ kHumanReadSpeed,
|
seconds: (data.body['content_length'] as num).toDouble() *
|
||||||
|
60 ~/
|
||||||
|
kHumanReadSpeed,
|
||||||
).inSeconds}s',
|
).inSeconds}s',
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
@@ -1349,7 +1398,8 @@ class _PostFeaturedCommentState extends State<_PostFeaturedComment> {
|
|||||||
// If this is a answered question, fetch the answer instead
|
// If this is a answered question, fetch the answer instead
|
||||||
if (widget.data.type == 'question' && widget.data.body['answer'] != null) {
|
if (widget.data.type == 'question' && widget.data.body['answer'] != null) {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
final resp = await sn.client.get('/cgi/co/posts/${widget.data.body['answer']}');
|
final resp =
|
||||||
|
await sn.client.get('/cgi/co/posts/${widget.data.body['answer']}');
|
||||||
_isAnswer = true;
|
_isAnswer = true;
|
||||||
setState(() => _featuredComment = SnPost.fromJson(resp.data));
|
setState(() => _featuredComment = SnPost.fromJson(resp.data));
|
||||||
return;
|
return;
|
||||||
@@ -1357,7 +1407,9 @@ class _PostFeaturedCommentState extends State<_PostFeaturedComment> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
final resp = await sn.client.get('/cgi/co/posts/${widget.data.id}/replies/featured', queryParameters: {
|
final resp = await sn.client.get(
|
||||||
|
'/cgi/co/posts/${widget.data.id}/replies/featured',
|
||||||
|
queryParameters: {
|
||||||
'take': 1,
|
'take': 1,
|
||||||
});
|
});
|
||||||
setState(() => _featuredComment = SnPost.fromJson(resp.data[0]));
|
setState(() => _featuredComment = SnPost.fromJson(resp.data[0]));
|
||||||
@@ -1388,7 +1440,9 @@ class _PostFeaturedCommentState extends State<_PostFeaturedComment> {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Material(
|
child: Material(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
color: _isAnswer ? Colors.green.withOpacity(0.5) : Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: _isAnswer
|
||||||
|
? Colors.green.withOpacity(0.5)
|
||||||
|
: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -1408,11 +1462,17 @@ class _PostFeaturedCommentState extends State<_PostFeaturedComment> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Gap(2),
|
const Gap(2),
|
||||||
Icon(_isAnswer ? Symbols.task_alt : Symbols.prompt_suggestion, size: 20),
|
Icon(_isAnswer ? Symbols.task_alt : Symbols.prompt_suggestion,
|
||||||
|
size: 20),
|
||||||
const Gap(10),
|
const Gap(10),
|
||||||
Text(
|
Text(
|
||||||
_isAnswer ? 'postQuestionAnswerTitle' : 'postFeaturedComment',
|
_isAnswer
|
||||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 15),
|
? 'postQuestionAnswerTitle'
|
||||||
|
: 'postFeaturedComment',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleMedium!
|
||||||
|
.copyWith(fontSize: 15),
|
||||||
).tr(),
|
).tr(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1550,7 +1610,8 @@ class _PostGetInsightPopupState extends State<_PostGetInsightPopup> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegExp cleanThinkingRegExp = RegExp(r'<think>[\s\S]*?</think>');
|
RegExp cleanThinkingRegExp = RegExp(r'<think>[\s\S]*?</think>');
|
||||||
setState(() => _response = out.replaceAll(cleanThinkingRegExp, '').trim());
|
setState(
|
||||||
|
() => _response = out.replaceAll(cleanThinkingRegExp, '').trim());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
@@ -1573,11 +1634,16 @@ class _PostGetInsightPopupState extends State<_PostGetInsightPopup> {
|
|||||||
children: [
|
children: [
|
||||||
const Icon(Symbols.book_4_spark, size: 24),
|
const Icon(Symbols.book_4_spark, size: 24),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
Text('postGetInsightTitle', style: Theme.of(context).textTheme.titleLarge).tr(),
|
Text('postGetInsightTitle',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge)
|
||||||
|
.tr(),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 20, top: 16, bottom: 12),
|
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text('postGetInsightDescription', style: Theme.of(context).textTheme.bodySmall).tr().padding(horizontal: 20),
|
Text('postGetInsightDescription',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall)
|
||||||
|
.tr()
|
||||||
|
.padding(horizontal: 20),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
if (_response == null)
|
if (_response == null)
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -1595,12 +1661,16 @@ class _PostGetInsightPopupState extends State<_PostGetInsightPopup> {
|
|||||||
leading: const Icon(Symbols.info),
|
leading: const Icon(Symbols.info),
|
||||||
title: Text('aiThinkingProcess'.tr()),
|
title: Text('aiThinkingProcess'.tr()),
|
||||||
tilePadding: const EdgeInsets.symmetric(horizontal: 20),
|
tilePadding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
collapsedBackgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh,
|
collapsedBackgroundColor:
|
||||||
|
Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
minTileHeight: 32,
|
minTileHeight: 32,
|
||||||
children: [
|
children: [
|
||||||
SelectableText(
|
SelectableText(
|
||||||
_thinkingProcess!,
|
_thinkingProcess!,
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontStyle: FontStyle.italic),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(fontStyle: FontStyle.italic),
|
||||||
).padding(horizontal: 20, vertical: 8),
|
).padding(horizontal: 20, vertical: 8),
|
||||||
],
|
],
|
||||||
).padding(vertical: 8),
|
).padding(vertical: 8),
|
||||||
@@ -1637,7 +1707,8 @@ class _PostVideoPlayer extends StatelessWidget {
|
|||||||
aspectRatio: 16 / 9,
|
aspectRatio: 16 / 9,
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: AttachmentItem(data: data.preload!.video!, heroTag: 'post-video-${data.id}'),
|
child: AttachmentItem(
|
||||||
|
data: data.preload!.video!, heroTag: 'post-video-${data.id}'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <flutter_udid/flutter_udid_plugin.h>
|
#include <flutter_udid/flutter_udid_plugin.h>
|
||||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
#include <hotkey_manager_linux/hotkey_manager_linux_plugin.h>
|
#include <hotkey_manager_linux/hotkey_manager_linux_plugin.h>
|
||||||
|
#include <local_notifier/local_notifier_plugin.h>
|
||||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin.h>
|
#include <media_kit_video/media_kit_video_plugin.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@@ -38,6 +39,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) hotkey_manager_linux_registrar =
|
g_autoptr(FlPluginRegistrar) hotkey_manager_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "HotkeyManagerLinuxPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "HotkeyManagerLinuxPlugin");
|
||||||
hotkey_manager_linux_plugin_register_with_registrar(hotkey_manager_linux_registrar);
|
hotkey_manager_linux_plugin_register_with_registrar(hotkey_manager_linux_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) local_notifier_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "LocalNotifierPlugin");
|
||||||
|
local_notifier_plugin_register_with_registrar(local_notifier_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
||||||
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
flutter_udid
|
flutter_udid
|
||||||
flutter_webrtc
|
flutter_webrtc
|
||||||
hotkey_manager_linux
|
hotkey_manager_linux
|
||||||
|
local_notifier
|
||||||
media_kit_libs_linux
|
media_kit_libs_linux
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import gal
|
|||||||
import hotkey_manager_macos
|
import hotkey_manager_macos
|
||||||
import in_app_review
|
import in_app_review
|
||||||
import livekit_client
|
import livekit_client
|
||||||
|
import local_notifier
|
||||||
import media_kit_libs_macos_video
|
import media_kit_libs_macos_video
|
||||||
import media_kit_video
|
import media_kit_video
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
@@ -53,6 +54,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
|
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
|
||||||
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
||||||
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
||||||
|
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
|
||||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
|
|||||||
32
pubspec.lock
32
pubspec.lock
@@ -357,10 +357,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dart_webrtc
|
name: dart_webrtc
|
||||||
sha256: "03df5b41b23bc185ebcf4b0ffc92d002e295bf56287fb5f9d2c321ddaf7760cc"
|
sha256: b34e90bc82f33c1023cf98661369c37bccd648c8a4cf882a875d9f5d8bbef694
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.2+hotfix.1"
|
||||||
dbus:
|
dbus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -865,10 +865,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
sha256: "9c4ca34ced1d1b780baf3776557f9edd0af18ce030969346f752e8df455faaab"
|
sha256: "6ea3a86d95b61cfe42d5715426d355b3cece6c88d0119de428d56f6c653811ce"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.10"
|
version: "0.12.11"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -1201,10 +1201,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: livekit_client
|
name: livekit_client
|
||||||
sha256: "0cfb2f48eff7a93ea8927696dc6f218aebd2fcd1fcc1b1a7b2f53ff3597fdb52"
|
sha256: "753bbf484c6b70f10f3dc1dc808dfe3755f472d80eb9682323cff07ad8e2609d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.6"
|
version: "2.4.0"
|
||||||
|
local_notifier:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: local_notifier
|
||||||
|
sha256: f6cfc933c6fbc961f4e52b5c880f68e41b2d3cd29aad557cc654fd211093a025
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1549,14 +1557,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.6"
|
version: "3.1.6"
|
||||||
platform_detect:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: platform_detect
|
|
||||||
sha256: "7394dc1d884e652785a37c3ff25c54e503c6d9fa2f35b55d5efc0a133dec122c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.5"
|
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2286,10 +2286,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webrtc_interface
|
name: webrtc_interface
|
||||||
sha256: "10fc6dc0ac16f909f5e434c18902415211d759313c87261f1e4ec5b4f6a04c26"
|
sha256: e05f00091c9c70a15bab4ccb1b6c46d9a16a6075002f02cfac3641eccb05e25d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.1+hotfix.1"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2.3.2+70
|
version: 2.3.2+71
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
@@ -123,6 +123,7 @@ dependencies:
|
|||||||
image_picker_platform_interface: ^2.10.1
|
image_picker_platform_interface: ^2.10.1
|
||||||
drift: ^2.25.1
|
drift: ^2.25.1
|
||||||
drift_flutter: ^0.2.4
|
drift_flutter: ^0.2.4
|
||||||
|
local_notifier: ^0.1.6
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <gal/gal_plugin_c_api.h>
|
#include <gal/gal_plugin_c_api.h>
|
||||||
#include <hotkey_manager_windows/hotkey_manager_windows_plugin_c_api.h>
|
#include <hotkey_manager_windows/hotkey_manager_windows_plugin_c_api.h>
|
||||||
#include <livekit_client/live_kit_plugin.h>
|
#include <livekit_client/live_kit_plugin.h>
|
||||||
|
#include <local_notifier/local_notifier_plugin.h>
|
||||||
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@@ -50,6 +51,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("HotkeyManagerWindowsPluginCApi"));
|
registry->GetRegistrarForPlugin("HotkeyManagerWindowsPluginCApi"));
|
||||||
LiveKitPluginRegisterWithRegistrar(
|
LiveKitPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("LiveKitPlugin"));
|
registry->GetRegistrarForPlugin("LiveKitPlugin"));
|
||||||
|
LocalNotifierPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("LocalNotifierPlugin"));
|
||||||
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
||||||
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
gal
|
gal
|
||||||
hotkey_manager_windows
|
hotkey_manager_windows
|
||||||
livekit_client
|
livekit_client
|
||||||
|
local_notifier
|
||||||
media_kit_libs_windows_video
|
media_kit_libs_windows_video
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
|||||||
Reference in New Issue
Block a user