Compare commits

..

3 Commits

Author SHA1 Message Date
cbd1eaf1af 🐛 Fix some link preview compatibility issue 2025-01-25 01:40:54 +08:00
ac41cbd99f Toggleable preview link 2025-01-25 01:36:11 +08:00
9f9c90abc4 🐛 Fix call room meaningless safe area 2025-01-23 19:22:55 +08:00
8 changed files with 159 additions and 144 deletions

View File

@ -196,6 +196,10 @@
"settingsFeatures": "Features", "settingsFeatures": "Features",
"settingsNotifyWithHaptic": "Haptic when Notified", "settingsNotifyWithHaptic": "Haptic when Notified",
"settingsNotifyWithHapticDescription": "Vibrate lightly when a new notification appears in the foreground.", "settingsNotifyWithHapticDescription": "Vibrate lightly when a new notification appears in the foreground.",
"settingsExpandPostLink": "Expand Post Link",
"settingsExpandPostLinkDescription": "Expand the post link in the post list.",
"settingsExpandChatLink": "Expand Chat Link",
"settingsExpandChatLinkDescription": "Expand the chat link in the chat list.",
"settingsNetwork": "Network", "settingsNetwork": "Network",
"settingsNetworkServer": "HyperNet Server", "settingsNetworkServer": "HyperNet Server",
"settingsNetworkServerDescription": "Set the HyperNet server address, choose ours or build your own.", "settingsNetworkServerDescription": "Set the HyperNet server address, choose ours or build your own.",

View File

@ -194,6 +194,10 @@
"settingsFeatures": "功能", "settingsFeatures": "功能",
"settingsNotifyWithHaptic": "新通知时振动", "settingsNotifyWithHaptic": "新通知时振动",
"settingsNotifyWithHapticDescription": "在应用在前台时收到新通知出现时出发轻量的振动。", "settingsNotifyWithHapticDescription": "在应用在前台时收到新通知出现时出发轻量的振动。",
"settingsExpandPostLink": "展开帖子链接",
"settingsExpandPostLinkDescription": "在帖子列表中展开显示帖子中的链接。",
"settingsExpandChatLink": "展开聊天链接",
"settingsExpandChatLinkDescription": "在聊天信息中展开显示内容中的链接。",
"settingsNetwork": "网络", "settingsNetwork": "网络",
"settingsNetworkServer": "HyperNet 服务器", "settingsNetworkServer": "HyperNet 服务器",
"settingsNetworkServerDescription": "设置 HyperNet 服务器地址,选择我们提供的,或者自己搭建。", "settingsNetworkServerDescription": "设置 HyperNet 服务器地址,选择我们提供的,或者自己搭建。",

View File

@ -15,6 +15,8 @@ const kAppBackgroundStoreKey = 'app_has_background';
const kAppColorSchemeStoreKey = 'app_color_scheme'; const kAppColorSchemeStoreKey = 'app_color_scheme';
const kAppDrawerPreferCollapse = 'app_drawer_prefer_collapse'; const kAppDrawerPreferCollapse = 'app_drawer_prefer_collapse';
const kAppNotifyWithHaptic = 'app_notify_with_haptic'; const kAppNotifyWithHaptic = 'app_notify_with_haptic';
const kAppExpandPostLink = 'app_expand_post_link';
const kAppExpandChatLink = 'app_expand_chat_link';
const Map<String, FilterQuality> kImageQualityLevel = { const Map<String, FilterQuality> kImageQualityLevel = {
'settingsImageQualityLowest': FilterQuality.none, 'settingsImageQualityLowest': FilterQuality.none,

View File

@ -14,6 +14,7 @@ import 'package:surface/widgets/navigation/app_scaffold.dart';
class CallRoomScreen extends StatefulWidget { class CallRoomScreen extends StatefulWidget {
final String scope; final String scope;
final String alias; final String alias;
const CallRoomScreen({super.key, required this.scope, required this.alias}); const CallRoomScreen({super.key, required this.scope, required this.alias});
@override @override
@ -36,8 +37,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
return Stack( return Stack(
children: [ children: [
Container( Container(
color: color: Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
child: call.focusTrack != null child: call.focusTrack != null
? InteractiveParticipantWidget( ? InteractiveParticipantWidget(
isFixedAvatar: false, isFixedAvatar: false,
@ -72,8 +72,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
color: Theme.of(context).cardColor, color: Theme.of(context).cardColor,
participant: track, participant: track,
onTap: () { onTap: () {
if (track.participant.sid != if (track.participant.sid != call.focusTrack?.participant.sid) {
call.focusTrack?.participant.sid) {
call.setFocusTrack(track); call.setFocusTrack(track);
} }
}, },
@ -115,14 +114,10 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)), borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InteractiveParticipantWidget( child: InteractiveParticipantWidget(
color: Theme.of(context) color: Theme.of(context).colorScheme.surfaceContainerHigh.withOpacity(0.75),
.colorScheme
.surfaceContainerHigh
.withOpacity(0.75),
participant: track, participant: track,
onTap: () { onTap: () {
if (track.participant.sid != if (track.participant.sid != call.focusTrack?.participant.sid) {
call.focusTrack?.participant.sid) {
call.setFocusTrack(track); call.setFocusTrack(track);
} }
}, },
@ -160,24 +155,17 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
text: TextSpan(children: [ text: TextSpan(children: [
TextSpan( TextSpan(
text: 'call'.tr(), text: 'call'.tr(),
style: Theme.of(context) style: Theme.of(context).textTheme.titleLarge!.copyWith(color: Colors.white),
.textTheme
.titleLarge!
.copyWith(color: Colors.white),
), ),
const TextSpan(text: '\n'), const TextSpan(text: '\n'),
TextSpan( TextSpan(
text: call.lastDuration.toString(), text: call.lastDuration.toString(),
style: Theme.of(context) style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.white),
.textTheme
.bodySmall!
.copyWith(color: Colors.white),
), ),
]), ]),
), ),
), ),
body: SafeArea( body: GestureDetector(
child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
child: Column( child: Column(
children: [ children: [
@ -191,8 +179,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
Builder(builder: (context) { Builder(builder: (context) {
final call = context.read<ChatCallProvider>(); final call = context.read<ChatCallProvider>();
final connectionQuality = final connectionQuality =
call.room.localParticipant?.connectionQuality ?? call.room.localParticipant?.connectionQuality ?? livekit.ConnectionQuality.unknown;
livekit.ConnectionQuality.unknown;
return Expanded( return Expanded(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -214,35 +201,24 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
children: [ children: [
Text( Text(
{ {
livekit.ConnectionState.disconnected: livekit.ConnectionState.disconnected: 'callStatusDisconnected'.tr(),
'callStatusDisconnected'.tr(), livekit.ConnectionState.connected: 'callStatusConnected'.tr(),
livekit.ConnectionState.connected: livekit.ConnectionState.connecting: 'callStatusConnecting'.tr(),
'callStatusConnected'.tr(), livekit.ConnectionState.reconnecting: 'callStatusReconnecting'.tr(),
livekit.ConnectionState.connecting:
'callStatusConnecting'.tr(),
livekit.ConnectionState.reconnecting:
'callStatusReconnecting'.tr(),
}[call.room.connectionState]!, }[call.room.connectionState]!,
), ),
const Gap(6), const Gap(6),
if (connectionQuality != if (connectionQuality != livekit.ConnectionQuality.unknown)
livekit.ConnectionQuality.unknown)
Icon( Icon(
{ {
livekit.ConnectionQuality.excellent: livekit.ConnectionQuality.excellent: Icons.signal_cellular_alt,
Icons.signal_cellular_alt, livekit.ConnectionQuality.good: Icons.signal_cellular_alt_2_bar,
livekit.ConnectionQuality.good: livekit.ConnectionQuality.poor: Icons.signal_cellular_alt_1_bar,
Icons.signal_cellular_alt_2_bar,
livekit.ConnectionQuality.poor:
Icons.signal_cellular_alt_1_bar,
}[connectionQuality], }[connectionQuality],
color: { color: {
livekit.ConnectionQuality.excellent: livekit.ConnectionQuality.excellent: Colors.green,
Colors.green, livekit.ConnectionQuality.good: Colors.orange,
livekit.ConnectionQuality.good: livekit.ConnectionQuality.poor: Colors.red,
Colors.orange,
livekit.ConnectionQuality.poor:
Colors.red,
}[connectionQuality], }[connectionQuality],
size: 16, size: 16,
) )
@ -264,9 +240,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
Row( Row(
children: [ children: [
IconButton( IconButton(
icon: _layoutMode == 0 icon: _layoutMode == 0 ? const Icon(Icons.view_list) : const Icon(Icons.grid_view),
? const Icon(Icons.view_list)
: const Icon(Icons.grid_view),
onPressed: () { onPressed: () {
_switchLayout(); _switchLayout();
}, },
@ -278,8 +252,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
), ),
Expanded( Expanded(
child: Material( child: Material(
color: color: Theme.of(context).colorScheme.surfaceContainerLow,
Theme.of(context).colorScheme.surfaceContainerLow,
child: Builder( child: Builder(
builder: (context) { builder: (context) {
switch (_layoutMode) { switch (_layoutMode) {
@ -304,7 +277,6 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
), ),
onTap: () {}, onTap: () {},
), ),
),
); );
}); });
} }

View File

@ -276,6 +276,30 @@ class _SettingsScreenState extends State<SettingsScreen> {
}); });
}, },
), ),
CheckboxListTile(
secondary: const Icon(Symbols.link),
title: Text('settingsExpandPostLink').tr(),
subtitle: Text('settingsExpandPostLinkDescription').tr(),
contentPadding: const EdgeInsets.only(left: 24, right: 17),
value: _prefs.getBool(kAppExpandPostLink) ?? true,
onChanged: (value) {
setState(() {
_prefs.setBool(kAppExpandPostLink, value ?? false);
});
},
),
CheckboxListTile(
secondary: const Icon(Symbols.chat),
title: Text('settingsExpandChatLink').tr(),
subtitle: Text('settingsExpandChatLinkDescription').tr(),
contentPadding: const EdgeInsets.only(left: 24, right: 17),
value: _prefs.getBool(kAppExpandChatLink) ?? true,
onChanged: (value) {
setState(() {
_prefs.setBool(kAppExpandChatLink, value ?? false);
});
},
),
], ],
), ),
Column( Column(

View File

@ -8,6 +8,7 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:popover/popover.dart'; import 'package:popover/popover.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/config.dart';
import 'package:surface/providers/user_directory.dart'; import 'package:surface/providers/user_directory.dart';
import 'package:surface/providers/userinfo.dart'; import 'package:surface/providers/userinfo.dart';
import 'package:surface/types/chat.dart'; import 'package:surface/types/chat.dart';
@ -53,6 +54,8 @@ class ChatMessage extends StatelessWidget {
final dateFormatter = DateFormat('MM/dd HH:mm'); final dateFormatter = DateFormat('MM/dd HH:mm');
final cfg = context.read<ConfigProvider>();
return SwipeTo( return SwipeTo(
key: Key('chat-message-${data.id}'), key: Key('chat-message-${data.id}'),
iconOnLeftSwipe: Symbols.reply, iconOnLeftSwipe: Symbols.reply,
@ -192,7 +195,10 @@ class ChatMessage extends StatelessWidget {
], ],
).opacity(isPending ? 0.5 : 1), ).opacity(isPending ? 0.5 : 1),
), ),
if (data.body['text'] != null && data.type == 'messages.new' && (data.body['text']?.isNotEmpty ?? false)) if (data.body['text'] != null &&
data.type == 'messages.new' &&
(data.body['text']?.isNotEmpty ?? false) &&
(cfg.prefs.getBool(kAppExpandChatLink) ?? true))
LinkPreviewWidget(text: data.body['text']!), LinkPreviewWidget(text: data.body['text']!),
if (data.preload?.attachments?.isNotEmpty ?? false) if (data.preload?.attachments?.isNotEmpty ?? false)
AttachmentList( AttachmentList(

View File

@ -81,8 +81,9 @@ class _LinkPreviewEntry extends StatelessWidget {
child: AspectRatio( child: AspectRatio(
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: AutoResizeUniversalImage( child: AutoResizeUniversalImage(
meta.image!, meta.image!.startsWith('//') ? 'https:${meta.image}' : meta.image!,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
), ),

View File

@ -203,6 +203,8 @@ class PostItem extends StatelessWidget {
?.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>();
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
@ -261,7 +263,7 @@ 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.body['content'] != null) 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),