Compare commits
12 Commits
3585941ccb
...
2.4.2+86
Author | SHA1 | Date | |
---|---|---|---|
69d5e95565 | |||
3e3442fc89 | |||
8181010b0b | |||
269caf7555 | |||
ae0809ad35 | |||
4005f03cf8 | |||
4bd8ec54f1 | |||
51a387851f | |||
8ed847d870 | |||
dfe13de220 | |||
b02a54c1e9 | |||
55a7e7d900 |
@ -941,5 +941,12 @@
|
||||
"settingsResetMemorizedWindowSize": "Reset Window Size",
|
||||
"settingsResetMemorizedWindowSizeDescription": "Reset the memorized window size, and set it to the default size.",
|
||||
"chatDirect": "Direct Messages",
|
||||
"back": "返回"
|
||||
"back": "Back",
|
||||
"badgeProgramDeveloper": "Developer Program Member",
|
||||
"badgeProgramStellar": "A Stellar",
|
||||
"badgeProgramModerator": "Community Moderator",
|
||||
"postEditedHint": "edited",
|
||||
"splashScreenServer": "Server",
|
||||
"splashScreenServerName": "Potato",
|
||||
"splashScreenCaption": "Trying to establishing connection with HyperNet™"
|
||||
}
|
||||
|
@ -938,5 +938,12 @@
|
||||
"settingsResetMemorizedWindowSize": "重置窗口大小",
|
||||
"settingsResetMemorizedWindowSizeDescription": "重置记忆的窗口大小,以重新设置为默认大小。",
|
||||
"chatDirect": "私信",
|
||||
"back": "返回"
|
||||
"back": "返回",
|
||||
"badgeProgramDeveloper": "开发者计划成员",
|
||||
"badgeProgramStellar": "一颗恒星",
|
||||
"badgeProgramModerator": "社区管理员",
|
||||
"postEditedHint": "已编辑",
|
||||
"splashScreenServer": "服务器",
|
||||
"splashScreenServerName": "土豆",
|
||||
"splashScreenCaption": "正在尝试与 HyperNet™ 取得太阳链连接"
|
||||
}
|
||||
|
@ -189,6 +189,11 @@ PODS:
|
||||
- Flutter
|
||||
- flutter_webrtc
|
||||
- WebRTC-SDK (= 125.6422.06)
|
||||
- livekit_noise_filter (0.0.1):
|
||||
- Flutter
|
||||
- flutter_webrtc
|
||||
- LiveKitKrispNoiseFilter (= 0.0.7)
|
||||
- LiveKitKrispNoiseFilter (0.0.7)
|
||||
- media_kit_libs_ios_video (1.0.4):
|
||||
- Flutter
|
||||
- media_kit_video (0.0.1):
|
||||
@ -283,6 +288,7 @@ DEPENDENCIES:
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- Kingfisher (~> 8.0)
|
||||
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||
- livekit_noise_filter (from `.symlinks/plugins/livekit_noise_filter/ios`)
|
||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
@ -315,6 +321,7 @@ SPEC REPOS:
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- Kingfisher
|
||||
- LiveKitKrispNoiseFilter
|
||||
- nanopb
|
||||
- OrderedSet
|
||||
- PromisesObjC
|
||||
@ -369,6 +376,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
livekit_client:
|
||||
:path: ".symlinks/plugins/livekit_client/ios"
|
||||
livekit_noise_filter:
|
||||
:path: ".symlinks/plugins/livekit_noise_filter/ios"
|
||||
media_kit_libs_ios_video:
|
||||
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
||||
media_kit_video:
|
||||
@ -438,6 +447,8 @@ SPEC CHECKSUMS:
|
||||
in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457
|
||||
Kingfisher: 323e5c4ec7983aaace12af655a7b51a7f88a599d
|
||||
livekit_client: 08755cabfa4da4ed455642f460cfbb39bc518070
|
||||
livekit_noise_filter: a26aeb1c1eae6db0a023fd2f6ea3ff108c3ecbb0
|
||||
LiveKitKrispNoiseFilter: efe418ceca28163ace0ff222bd2cc02384645d84
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
|
@ -241,7 +241,7 @@ class PostWriteController extends ChangeNotifier {
|
||||
contentController.text = post.body['content'] ?? '';
|
||||
aliasController.text = post.alias ?? '';
|
||||
rewardController.text = post.body['reward']?.toString() ?? '';
|
||||
videoAttachment = post.preload?.video;
|
||||
videoAttachment = SnAttachment.fromJson(post.body['video']);
|
||||
publishedAt = post.publishedAt;
|
||||
publishedUntil = post.publishedUntil;
|
||||
visibleUsers = List.from(post.visibleUsersList ?? [], growable: true);
|
||||
@ -252,17 +252,21 @@ class PostWriteController extends ChangeNotifier {
|
||||
categories =
|
||||
List.from(post.categories.map((ele) => ele.alias), growable: true);
|
||||
attachments.addAll(
|
||||
post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
|
||||
poll = post.preload?.poll;
|
||||
post.body['attachments']
|
||||
.where(SnAttachment.fromJson)
|
||||
?.map(PostWriteMedia) ??
|
||||
[],
|
||||
);
|
||||
poll = post.poll;
|
||||
|
||||
editingDraft = post.isDraft;
|
||||
|
||||
if (post.preload?.thumbnail != null &&
|
||||
(post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
|
||||
thumbnail = PostWriteMedia(post.preload!.thumbnail);
|
||||
if (post.body['thumbnail'] != null) {
|
||||
thumbnail =
|
||||
PostWriteMedia(SnAttachment.fromJson(post.body['thumbnail']));
|
||||
}
|
||||
if (post.preload?.realm != null) {
|
||||
realm = post.preload!.realm!;
|
||||
if (post.realm != null) {
|
||||
realm = post.realm!;
|
||||
}
|
||||
|
||||
editingPost = post;
|
||||
|
359
lib/main.dart
359
lib/main.dart
@ -15,6 +15,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@ -49,6 +50,7 @@ import 'package:surface/router.dart';
|
||||
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
import 'package:surface/widgets/menu_bar.dart';
|
||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||
import 'package:surface/widgets/version_label.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
import 'package:version/version.dart';
|
||||
@ -57,6 +59,7 @@ import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:image_picker_android/image_picker_android.dart';
|
||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||
import 'package:local_notifier/local_notifier.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void appBackgroundDispatcher() {
|
||||
@ -257,6 +260,7 @@ class _AppSplashScreen extends StatefulWidget {
|
||||
|
||||
class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
bool _isBusy = false;
|
||||
double _initPercentage = 0;
|
||||
String _phaseText = 'appInitStarting';
|
||||
|
||||
void _tryRequestRating() async {
|
||||
@ -331,20 +335,24 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
// The Network initialization must be done after the HomeWidget initialization
|
||||
// The Network initialization will save the server url to the HomeWidget
|
||||
// The Network initialization will also save initialize the Config, so it not need to be initialized again
|
||||
_initPercentage = 0.1;
|
||||
_setPhaseText('network');
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
await sn.initializeUserAgent();
|
||||
await sn.setConfigWithNative();
|
||||
if (!mounted) return;
|
||||
_initPercentage = 0.2;
|
||||
_setPhaseText('userdata');
|
||||
final ua = context.read<UserProvider>();
|
||||
await ua.initialize();
|
||||
if (!mounted) return;
|
||||
_initPercentage = 0.3;
|
||||
_setPhaseText('websocket');
|
||||
final ws = context.read<WebSocketProvider>();
|
||||
await ws.tryConnect();
|
||||
try {
|
||||
if (!mounted) return;
|
||||
_initPercentage = 0.9;
|
||||
_setPhaseText('keyPair');
|
||||
final kp = context.read<KeyPairProvider>();
|
||||
kp.reloadActive();
|
||||
@ -357,24 +365,25 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
notify.listen();
|
||||
try {
|
||||
notify.registerPushNotifications();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('stickers');
|
||||
final sticker = context.read<SnStickerProvider>();
|
||||
await sticker.listSticker();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('userDirectory');
|
||||
final ud = context.read<UserDirectoryProvider>();
|
||||
await ud.loadAccountCache();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('realm');
|
||||
final rm = context.read<SnRealmProvider>();
|
||||
await rm.refreshAvailableRealms();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('chat');
|
||||
final ct = context.read<ChatChannelProvider>();
|
||||
await ct.refreshAvailableChannels();
|
||||
_initPercentage = 1;
|
||||
_setPhaseText('done');
|
||||
} catch (_) {}
|
||||
if (!mounted) return;
|
||||
_setPhaseText('stickers');
|
||||
final sticker = context.read<SnStickerProvider>();
|
||||
await sticker.listSticker();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('userDirectory');
|
||||
final ud = context.read<UserDirectoryProvider>();
|
||||
await ud.loadAccountCache();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('realm');
|
||||
final rm = context.read<SnRealmProvider>();
|
||||
await rm.refreshAvailableRealms();
|
||||
if (!mounted) return;
|
||||
_setPhaseText('chat');
|
||||
final ct = context.read<ChatChannelProvider>();
|
||||
await ct.refreshAvailableChannels();
|
||||
_setPhaseText('done');
|
||||
_playIntro();
|
||||
}
|
||||
} catch (err) {
|
||||
@ -396,8 +405,22 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
final cfg = context.read<ConfigProvider>();
|
||||
if (!cfg.soundEffects) return;
|
||||
|
||||
final date = DateTime.now();
|
||||
final player = AudioPlayer(playerId: 'launch-done-player');
|
||||
await player.play(AssetSource('audio/sfx/launch-done.mp3'), volume: 0.8);
|
||||
await player.play(
|
||||
(cfg.aprilFoolFeatures && date.month == 4 && date.day == 1)
|
||||
? AssetSource('audio/sfx/launch-intro.mp3')
|
||||
: AssetSource('audio/sfx/launch-done.mp3'),
|
||||
volume: 0.8,
|
||||
ctx: AudioContext(
|
||||
android: AudioContextAndroid(
|
||||
contentType: AndroidContentType.sonification,
|
||||
usageType: AndroidUsageType.notificationEvent,
|
||||
),
|
||||
iOS: AudioContextIOS(category: AVAudioSessionCategory.ambient),
|
||||
),
|
||||
mode: PlayerMode.lowLatency,
|
||||
);
|
||||
player.onPlayerComplete.listen((_) {
|
||||
player.dispose();
|
||||
});
|
||||
@ -456,15 +479,22 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
AppLifecycleListener(onExitRequested: _onExitRequested);
|
||||
}
|
||||
|
||||
_trayInitialization();
|
||||
_hotkeyInitialization();
|
||||
_notifyInitialization();
|
||||
_initialize().then((_) {
|
||||
_postInitialization();
|
||||
_tryRequestRating();
|
||||
_checkForUpdate();
|
||||
setState(() => _isBusy = false);
|
||||
});
|
||||
try {
|
||||
_trayInitialization();
|
||||
_hotkeyInitialization();
|
||||
_notifyInitialization();
|
||||
_initialize().then((_) {
|
||||
_postInitialization();
|
||||
_tryRequestRating();
|
||||
_checkForUpdate();
|
||||
setState(() => _isBusy = false);
|
||||
}).catchError((err) {
|
||||
logging.error('[Bootstrap] Unable to initialize app', err);
|
||||
setState(() => _isBusy = false);
|
||||
});
|
||||
} catch (err) {
|
||||
logging.error('[Bootstrap] Unable to initialize (pre-stage) app', err);
|
||||
}
|
||||
}
|
||||
|
||||
Future<AppExitResponse> _onExitRequested() async {
|
||||
@ -555,46 +585,10 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
});
|
||||
return SizeChangedLayoutNotifier(
|
||||
child: _isBusy
|
||||
? Material(
|
||||
key: Key('app-splash-screen-$_isBusy'),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/icon/kanban-1st.jpg'),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.1,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
backgroundBlendMode: BlendMode.darken,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 240),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icon/icon.png',
|
||||
width: 64,
|
||||
height: 64,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
Text('Solar Network').bold(),
|
||||
AppVersionLabel(),
|
||||
Gap(8),
|
||||
Text(_phaseText, textAlign: TextAlign.center),
|
||||
Gap(16),
|
||||
const LinearProgressIndicator(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
? _AppLoadingScreen(
|
||||
isBusy: _isBusy,
|
||||
initPercentage: _initPercentage,
|
||||
phaseText: _phaseText,
|
||||
)
|
||||
: widget.child,
|
||||
);
|
||||
@ -604,3 +598,234 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AppLoadingScreen extends StatelessWidget {
|
||||
const _AppLoadingScreen({
|
||||
required this.isBusy,
|
||||
required this.initPercentage,
|
||||
required this.phaseText,
|
||||
});
|
||||
|
||||
final bool isBusy;
|
||||
final double initPercentage;
|
||||
final String phaseText;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (ResponsiveScaffold.getIsExpand(context)) {
|
||||
return Material(
|
||||
key: Key('app-splash-screen-$isBusy'),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/icon/kanban-1st.jpg'),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.1,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
backgroundBlendMode: BlendMode.darken,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TweenAnimationBuilder<double>(
|
||||
tween: Tween(begin: 0, end: initPercentage),
|
||||
duration: Duration(milliseconds: 300),
|
||||
builder: (context, value, _) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${(value * 100).toStringAsFixed(0)}%')
|
||||
.padding(left: 32, bottom: 4),
|
||||
LinearProgressIndicator(
|
||||
value: value,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(0),
|
||||
),
|
||||
stopIndicatorColor: Colors.transparent,
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
const Gap(24),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TweenAnimationBuilder<double>(
|
||||
tween: Tween(begin: 0, end: initPercentage),
|
||||
duration: Duration(milliseconds: 300),
|
||||
builder: (context, value, _) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text('${(value * 100).toStringAsFixed(0)}%')
|
||||
.padding(right: 32, bottom: 4),
|
||||
Transform.flip(
|
||||
flipX: true,
|
||||
child: LinearProgressIndicator(
|
||||
value: value,
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(0),
|
||||
),
|
||||
stopIndicatorColor: Colors.transparent,
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
const Gap(24),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 240, minWidth: 160),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).colorScheme.surface.withOpacity(0.85),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 3,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'splashScreenServer',
|
||||
style: GoogleFonts.notoSerifHk(height: 1, fontSize: 11),
|
||||
textAlign: TextAlign.center,
|
||||
).tr().opacity(0.85),
|
||||
Text(
|
||||
'splashScreenServerName',
|
||||
style: GoogleFonts.notoSerifHk(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
).tr().opacity(0.85),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: '#',
|
||||
style: GoogleFonts.notoSerifHk(),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '0',
|
||||
style: GoogleFonts.notoSerifHk(
|
||||
fontSize: 80,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
).padding(vertical: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: MediaQuery.of(context).size.height * 0.2,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
phaseText,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
AnimateWidgetExtensions(Text(
|
||||
'splashScreenCaption',
|
||||
textAlign: TextAlign.center,
|
||||
).tr())
|
||||
.animate(onPlay: (e) => e.repeat())
|
||||
.fadeIn(duration: 500.ms, curve: Curves.easeOut)
|
||||
.then()
|
||||
.fadeOut(
|
||||
duration: 500.ms,
|
||||
delay: 1000.ms,
|
||||
curve: Curves.easeIn,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 8,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icon/icon.png',
|
||||
width: 40,
|
||||
height: 40,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
).padding(all: 4),
|
||||
const Gap(4),
|
||||
Text('Solar Network').bold(),
|
||||
Expanded(child: const SizedBox()),
|
||||
AppVersionLabel(),
|
||||
const Gap(12),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Material(
|
||||
key: Key('app-splash-screen-$isBusy'),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/icon/kanban-1st.jpg'),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.1,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
backgroundBlendMode: BlendMode.darken,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 240),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icon/icon.png',
|
||||
width: 64,
|
||||
height: 64,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
Text('Solar Network').bold(),
|
||||
AppVersionLabel(),
|
||||
Gap(8),
|
||||
Text(phaseText, textAlign: TextAlign.center),
|
||||
Gap(16),
|
||||
TweenAnimationBuilder<double>(
|
||||
tween: Tween(begin: 0, end: initPercentage),
|
||||
duration: Duration(milliseconds: 300),
|
||||
builder: (context, value, _) =>
|
||||
LinearProgressIndicator(value: value),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,14 @@ class NotificationProvider extends ChangeNotifier {
|
||||
_notifySoundPlayer.play(
|
||||
AssetSource('audio/notify/metal-pipe.mp3'),
|
||||
volume: 0.6,
|
||||
ctx: AudioContext(
|
||||
android: AudioContextAndroid(
|
||||
contentType: AndroidContentType.sonification,
|
||||
usageType: AndroidUsageType.notificationEvent,
|
||||
),
|
||||
iOS: AudioContextIOS(category: AVAudioSessionCategory.ambient),
|
||||
),
|
||||
mode: PlayerMode.lowLatency,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,144 +1,31 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:surface/providers/sn_attachment.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/sn_realm.dart';
|
||||
import 'package:surface/providers/user_directory.dart';
|
||||
import 'package:surface/types/poll.dart';
|
||||
import 'package:surface/types/post.dart';
|
||||
import 'package:surface/types/realm.dart';
|
||||
|
||||
class SnPostContentProvider {
|
||||
late final SnNetworkProvider _sn;
|
||||
late final UserDirectoryProvider _ud;
|
||||
late final SnAttachmentProvider _attach;
|
||||
late final SnRealmProvider _realm;
|
||||
|
||||
SnPostContentProvider(BuildContext context) {
|
||||
_sn = context.read<SnNetworkProvider>();
|
||||
_ud = context.read<UserDirectoryProvider>();
|
||||
_attach = context.read<SnAttachmentProvider>();
|
||||
_realm = context.read<SnRealmProvider>();
|
||||
}
|
||||
|
||||
Future<SnPoll> _fetchPoll(int id) async {
|
||||
final resp = await _sn.client.get('/cgi/co/polls/$id');
|
||||
return SnPoll.fromJson(resp.data);
|
||||
}
|
||||
|
||||
Future<List<SnPost>> _preloadRelatedDataInBatch(List<SnPost> out) async {
|
||||
Set<String> rids = {};
|
||||
Set<int> uids = {};
|
||||
for (var i = 0; i < out.length; i++) {
|
||||
rids.addAll(out[i].body['attachments']?.cast<String>() ?? []);
|
||||
if (out[i].body['thumbnail'] != null) {
|
||||
rids.add(out[i].body['thumbnail']);
|
||||
}
|
||||
if (out[i].body['video'] != null) {
|
||||
rids.add(out[i].body['video']);
|
||||
}
|
||||
if (out[i].repostTo != null) {
|
||||
out[i] = out[i].copyWith(
|
||||
repostTo: await _preloadRelatedDataSingle(out[i].repostTo!),
|
||||
);
|
||||
}
|
||||
if (out[i].publisher.type == 0) {
|
||||
uids.add(out[i].publisher.accountId);
|
||||
}
|
||||
}
|
||||
|
||||
final attachments = await _attach.getMultiple(rids.toList());
|
||||
for (var i = 0; i < out.length; i++) {
|
||||
SnPoll? poll;
|
||||
SnRealm? realm;
|
||||
if (out[i].pollId != null) {
|
||||
poll = await _fetchPoll(out[i].pollId!);
|
||||
}
|
||||
if (out[i].realmId != null) {
|
||||
realm = await _realm.getRealm(out[i].realmId!);
|
||||
}
|
||||
|
||||
out[i] = out[i].copyWith(
|
||||
preload: SnPostPreload(
|
||||
thumbnail: attachments
|
||||
.where((ele) => ele?.rid == out[i].body['thumbnail'])
|
||||
.firstOrNull,
|
||||
attachments: attachments
|
||||
.where((ele) =>
|
||||
out[i].body['attachments']?.contains(ele?.rid) ?? false)
|
||||
.toList(),
|
||||
video: attachments
|
||||
.where((ele) => ele?.rid == out[i].body['video'])
|
||||
.firstOrNull,
|
||||
poll: poll,
|
||||
realm: realm,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
uids.addAll(
|
||||
attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
||||
await _ud.listAccount(uids);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Future<SnPost> _preloadRelatedDataSingle(SnPost out) async {
|
||||
Set<String> rids = {};
|
||||
Set<int> uids = {};
|
||||
rids.addAll(out.body['attachments']?.cast<String>() ?? []);
|
||||
if (out.body['thumbnail'] != null) {
|
||||
rids.add(out.body['thumbnail']);
|
||||
}
|
||||
if (out.body['video'] != null) {
|
||||
rids.add(out.body['video']);
|
||||
}
|
||||
if (out.repostTo != null) {
|
||||
out = out.copyWith(
|
||||
repostTo: await _preloadRelatedDataSingle(out.repostTo!),
|
||||
);
|
||||
}
|
||||
if (out.publisher.type == 0) {
|
||||
uids.add(out.publisher.accountId);
|
||||
}
|
||||
|
||||
final attachments = await _attach.getMultiple(rids.toList());
|
||||
|
||||
SnPoll? poll;
|
||||
SnRealm? realm;
|
||||
if (out.pollId != null) {
|
||||
poll = await _fetchPoll(out.pollId!);
|
||||
}
|
||||
if (out.realmId != null) {
|
||||
realm = await _realm.getRealm(out.realmId!);
|
||||
}
|
||||
|
||||
out = out.copyWith(
|
||||
preload: SnPostPreload(
|
||||
thumbnail: attachments
|
||||
.where((ele) => ele?.rid == out.body['thumbnail'])
|
||||
.firstOrNull,
|
||||
attachments: attachments
|
||||
.where(
|
||||
(ele) => out.body['attachments']?.contains(ele?.rid) ?? false)
|
||||
.toList(),
|
||||
video: attachments
|
||||
.where((ele) => ele?.rid == out.body['video'])
|
||||
.firstOrNull,
|
||||
poll: poll,
|
||||
realm: realm,
|
||||
),
|
||||
);
|
||||
|
||||
uids.addAll(
|
||||
attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
||||
await _ud.listAccount(uids);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Future<List<SnPost>> listRecommendations() async {
|
||||
final resp = await _sn.client.get('/cgi/co/recommendations');
|
||||
final resp = await _sn.client.get(
|
||||
'/cgi/co/recommendations',
|
||||
options: Options(headers: {
|
||||
'X-API-Version': '2',
|
||||
}),
|
||||
);
|
||||
final out = _preloadRelatedDataInBatch(
|
||||
List.from(resp.data.map((ele) => SnPost.fromJson(ele))),
|
||||
);
|
||||
@ -202,6 +89,9 @@ class SnPostContentProvider {
|
||||
if (realm != null) 'realm': realm,
|
||||
if (channel != null) 'channel': channel,
|
||||
},
|
||||
options: Options(headers: {
|
||||
'X-API-Version': '2',
|
||||
}),
|
||||
);
|
||||
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
||||
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
||||
@ -215,11 +105,16 @@ class SnPostContentProvider {
|
||||
int take = 10,
|
||||
int offset = 0,
|
||||
}) async {
|
||||
final resp = await _sn.client
|
||||
.get('/cgi/co/posts/$parentId/replies', queryParameters: {
|
||||
'take': take,
|
||||
'offset': offset,
|
||||
});
|
||||
final resp = await _sn.client.get(
|
||||
'/cgi/co/posts/$parentId/replies',
|
||||
queryParameters: {
|
||||
'take': take,
|
||||
'offset': offset,
|
||||
},
|
||||
options: Options(headers: {
|
||||
'X-API-Version': '2',
|
||||
}),
|
||||
);
|
||||
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
||||
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
||||
);
|
||||
@ -234,13 +129,20 @@ class SnPostContentProvider {
|
||||
Iterable<String>? tags,
|
||||
Iterable<String>? categories,
|
||||
}) async {
|
||||
final resp = await _sn.client.get('/cgi/co/posts/search', queryParameters: {
|
||||
'take': take,
|
||||
'offset': offset,
|
||||
'probe': searchTerm,
|
||||
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
||||
if (categories?.isNotEmpty ?? false) 'categories': categories!.join(','),
|
||||
});
|
||||
final resp = await _sn.client.get(
|
||||
'/cgi/co/posts/search',
|
||||
queryParameters: {
|
||||
'take': take,
|
||||
'offset': offset,
|
||||
'probe': searchTerm,
|
||||
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
||||
if (categories?.isNotEmpty ?? false)
|
||||
'categories': categories!.join(','),
|
||||
},
|
||||
options: Options(headers: {
|
||||
'X-API-Version': '2',
|
||||
}),
|
||||
);
|
||||
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
||||
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
||||
);
|
||||
@ -249,7 +151,12 @@ class SnPostContentProvider {
|
||||
}
|
||||
|
||||
Future<SnPost> getPost(dynamic id) async {
|
||||
final resp = await _sn.client.get('/cgi/co/posts/$id');
|
||||
final resp = await _sn.client.get(
|
||||
'/cgi/co/posts/$id',
|
||||
options: Options(headers: {
|
||||
'X-API-Version': '2',
|
||||
}),
|
||||
);
|
||||
final out = _preloadRelatedDataSingle(
|
||||
SnPost.fromJson(resp.data),
|
||||
);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:surface/screens/abuse_report.dart';
|
||||
@ -54,16 +53,6 @@ import 'package:surface/types/post.dart';
|
||||
import 'package:surface/widgets/about.dart';
|
||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||
|
||||
Widget _fadeThroughTransition(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation, Widget child) {
|
||||
return FadeThroughTransition(
|
||||
animation: animation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
fillColor: Colors.transparent,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
final _appRoutes = [
|
||||
GoRoute(
|
||||
path: '/',
|
||||
@ -305,10 +294,7 @@ final _appRoutes = [
|
||||
GoRoute(
|
||||
path: '/realm',
|
||||
name: 'realm',
|
||||
pageBuilder: (context, state) => CustomTransitionPage(
|
||||
transitionsBuilder: _fadeThroughTransition,
|
||||
child: const RealmScreen(),
|
||||
),
|
||||
builder: (context, state) => const RealmScreen(),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/:alias/community',
|
||||
|
@ -110,7 +110,7 @@ class AccountScreen extends StatelessWidget {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: AutoAppBarLeading(),
|
||||
title: Text("screenAccount").tr(),
|
||||
|
@ -59,7 +59,7 @@ class _ActionEventScreenState extends State<ActionEventScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountActionEvent').tr(),
|
||||
|
@ -91,7 +91,7 @@ class _AccountAuthTicketState extends State<AccountAuthTicket> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountAuthTickets').tr(),
|
||||
|
@ -70,7 +70,7 @@ class _AccountBadgesScreenState extends State<AccountBadgesScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: Text('screenAccountBadges').tr(),
|
||||
),
|
||||
|
@ -69,7 +69,7 @@ class _AccountContactMethodState extends State<AccountContactMethod> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountContactMethods').tr(),
|
||||
|
@ -62,7 +62,7 @@ class _FactorSettingsScreenState extends State<FactorSettingsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: PageBackButton(),
|
||||
title: Text('screenFactorSettings').tr(),
|
||||
|
@ -37,7 +37,7 @@ class _KeyPairScreenState extends State<KeyPairScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: Text('screenKeyPairs').tr(),
|
||||
),
|
||||
|
@ -75,7 +75,7 @@ class _AccountNotifyPrefsScreenState extends State<AccountNotifyPrefsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountSettingsNotify').tr(),
|
||||
|
@ -70,7 +70,7 @@ class _AccountSecurityPrefsScreenState
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountSettingsSecurity').tr(),
|
||||
|
@ -244,7 +244,7 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('screenAccountProfileEdit').tr()),
|
||||
@ -263,7 +263,7 @@ class _ProfileEditScreenState extends State<ProfileEditScreen> {
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
aspectRatio: 16 / 7,
|
||||
child: Container(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -61,6 +61,21 @@ final Map<String, (String, IconData, Color)> kBadgesMeta = {
|
||||
Symbols.thumb_up,
|
||||
Colors.lightGreen,
|
||||
),
|
||||
'programs.developers': (
|
||||
'badgeProgramDeveloper',
|
||||
Symbols.code,
|
||||
Colors.blue,
|
||||
),
|
||||
'programs.stellar': (
|
||||
'badgeProgramStellar',
|
||||
Symbols.family_star,
|
||||
Colors.orange,
|
||||
),
|
||||
'programs.moderator': (
|
||||
'badgeProgramModerator',
|
||||
Symbols.sword_rose,
|
||||
Colors.blue,
|
||||
),
|
||||
};
|
||||
|
||||
class UserScreen extends StatefulWidget {
|
||||
|
@ -70,7 +70,7 @@ class _AccountProgramScreenState extends State<AccountProgramScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: Text('accountProgram').tr(),
|
||||
),
|
||||
|
@ -196,7 +196,7 @@ class _AccountPublisherEditScreenState
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: PageBackButton(),
|
||||
title: Text('screenAccountPublisherEdit').tr()),
|
||||
@ -214,7 +214,7 @@ class _AccountPublisherEditScreenState
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
aspectRatio: 16 / 7,
|
||||
child: Container(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -26,7 +26,7 @@ class _AccountPublisherNewScreenState extends State<AccountPublisherNewScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('screenAccountPublisherNew').tr(),
|
||||
|
@ -82,7 +82,7 @@ class _PublisherScreenState extends State<PublisherScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('screenAccountPublishers').tr(),
|
||||
|
@ -55,7 +55,7 @@ class _PunishmentsScreenState extends State<PunishmentsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: Text('accountPunishments').tr(),
|
||||
leading: PageBackButton(),
|
||||
|
@ -37,7 +37,7 @@ class AccountSettingsScreen extends StatelessWidget {
|
||||
final ua = context.watch<UserProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: PageBackButton(),
|
||||
title: Text('screenAccountSettings').tr(),
|
||||
|
@ -8,7 +8,6 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/user_directory.dart';
|
||||
import 'package:surface/types/attachment.dart';
|
||||
import 'package:surface/widgets/attachment/attachment_zoom.dart';
|
||||
import 'package:surface/widgets/attachment/attachment_item.dart';
|
||||
@ -53,7 +52,6 @@ class _AlbumScreenState extends State<AlbumScreen> {
|
||||
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
final ud = context.read<UserDirectoryProvider>();
|
||||
final resp = await sn.client.get('/cgi/uc/attachments', queryParameters: {
|
||||
'take': 10,
|
||||
'offset': _attachments.length,
|
||||
@ -64,8 +62,6 @@ class _AlbumScreenState extends State<AlbumScreen> {
|
||||
_attachments.addAll(attachments);
|
||||
_heroTags.addAll(_attachments.map((_) => uuid.v4()));
|
||||
|
||||
await ud.listAccount(attachments.map((e) => e.accountId).toSet());
|
||||
|
||||
_totalCount = resp.data['count'] as int?;
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
|
@ -223,7 +223,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
}
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: AutoAppBarLeading(),
|
||||
title: Text('screenChat').tr(),
|
||||
@ -389,7 +389,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
children: [
|
||||
if (_focusedRealm!.banner != null)
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
aspectRatio: 16 / 7,
|
||||
child: AutoResizeUniversalImage(
|
||||
sn.getAttachmentUrl(
|
||||
_focusedRealm!.banner!,
|
||||
|
@ -124,7 +124,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
||||
listenable: call,
|
||||
builder: (context, _) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -220,7 +220,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
||||
final isOwned = ua.isAuthorized && _channel?.accountId == ua.user?.id;
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: _channel != null ? Text(_channel!.name) : Text('loading').tr(),
|
||||
),
|
||||
|
@ -141,7 +141,7 @@ class _ChatManageScreenState extends State<ChatManageScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: widget.editingChannelAlias != null
|
||||
? Text('screenChatManage').tr()
|
||||
|
@ -304,7 +304,7 @@ class _ChatRoomScreenState extends State<ChatRoomScreen> {
|
||||
final ud = context.read<UserDirectoryProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
_channel?.type == 1
|
||||
|
@ -157,7 +157,7 @@ class _ExploreScreenState extends State<ExploreScreen>
|
||||
Widget build(BuildContext context) {
|
||||
final cfg = context.watch<ConfigProvider>();
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
floatingActionButtonLocation: ExpandableFab.location,
|
||||
floatingActionButton: ExpandableFab(
|
||||
key: _fabKey,
|
||||
|
@ -11,13 +11,11 @@ import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/notification.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/types/notification.dart';
|
||||
import 'package:surface/types/post.dart';
|
||||
import 'package:surface/widgets/app_bar_leading.dart';
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
import 'package:surface/widgets/loading_indicator.dart';
|
||||
import 'package:surface/widgets/markdown_content.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 '../providers/userinfo.dart';
|
||||
@ -219,34 +217,24 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
||||
'interactive.subscription',
|
||||
].contains(nty.topic) &&
|
||||
nty.metadata['related_post'] != null)
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(8)),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(
|
||||
EdgeInsets.zero,
|
||||
),
|
||||
child: PostItem(
|
||||
data: SnPost.fromJson(
|
||||
nty.metadata['related_post']!),
|
||||
showComments: false,
|
||||
showReactions: false,
|
||||
showMenu: false,
|
||||
).padding(vertical: 4),
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
onTap: () {
|
||||
child: Text('postReadMore').tr(),
|
||||
onPressed: () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'postDetail',
|
||||
pathParameters: {
|
||||
'slug': nty
|
||||
.metadata['related_post']!['id']
|
||||
.toString()
|
||||
'slug': nty.metadata['related_post']['id']
|
||||
.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
).padding(top: 8),
|
||||
),
|
||||
const Gap(8),
|
||||
Row(
|
||||
children: [
|
||||
|
@ -66,7 +66,7 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
||||
final double maxWidth = _data?.type == 'video' ? double.infinity : 640;
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
onPressed: () {
|
||||
|
@ -79,6 +79,7 @@ class _PostShuffleScreenState extends State<PostShuffleScreen> {
|
||||
key: ValueKey(ele),
|
||||
data: ele,
|
||||
maxWidth: 640,
|
||||
useReplace: true,
|
||||
onChanged: (ele) {
|
||||
_posts[idx] = ele;
|
||||
setState(() {});
|
||||
|
@ -286,7 +286,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen>
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
body: NestedScrollView(
|
||||
controller: _scrollController,
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
|
@ -45,7 +45,7 @@ class _WalletScreenState extends State<WalletScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(
|
||||
leading: PageBackButton(), title: Text('screenAccountWallet').tr()),
|
||||
body: Column(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:surface/types/account.dart';
|
||||
|
||||
part 'attachment.freezed.dart';
|
||||
|
||||
@ -39,6 +40,7 @@ abstract class SnAttachment with _$SnAttachment {
|
||||
required int? refId,
|
||||
required SnAttachmentPool? pool,
|
||||
required int? poolId,
|
||||
required SnAccount? account,
|
||||
required int accountId,
|
||||
int? thumbnailId,
|
||||
SnAttachment? thumbnail,
|
||||
@ -49,7 +51,8 @@ abstract class SnAttachment with _$SnAttachment {
|
||||
@Default({}) Map<String, dynamic> metadata,
|
||||
}) = _SnAttachment;
|
||||
|
||||
factory SnAttachment.fromJson(Map<String, Object?> json) => _$SnAttachmentFromJson(json);
|
||||
factory SnAttachment.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentFromJson(json);
|
||||
|
||||
Map<String, dynamic> get data => {
|
||||
...metadata,
|
||||
@ -85,7 +88,8 @@ abstract class SnAttachmentFragment with _$SnAttachmentFragment {
|
||||
@Default([]) List<String> fileChunksMissing,
|
||||
}) = _SnAttachmentFragment;
|
||||
|
||||
factory SnAttachmentFragment.fromJson(Map<String, Object?> json) => _$SnAttachmentFragmentFromJson(json);
|
||||
factory SnAttachmentFragment.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentFragmentFromJson(json);
|
||||
|
||||
SnMediaType get mediaType => switch (mimetype.split('/').firstOrNull) {
|
||||
'image' => SnMediaType.image,
|
||||
@ -109,7 +113,8 @@ abstract class SnAttachmentPool with _$SnAttachmentPool {
|
||||
required int? accountId,
|
||||
}) = _SnAttachmentPool;
|
||||
|
||||
factory SnAttachmentPool.fromJson(Map<String, Object?> json) => _$SnAttachmentPoolFromJson(json);
|
||||
factory SnAttachmentPool.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentPoolFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -122,7 +127,8 @@ abstract class SnAttachmentDestination with _$SnAttachmentDestination {
|
||||
required bool isBoost,
|
||||
}) = _SnAttachmentDestination;
|
||||
|
||||
factory SnAttachmentDestination.fromJson(Map<String, Object?> json) => _$SnAttachmentDestinationFromJson(json);
|
||||
factory SnAttachmentDestination.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentDestinationFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -139,7 +145,8 @@ abstract class SnAttachmentBoost with _$SnAttachmentBoost {
|
||||
required int account,
|
||||
}) = _SnAttachmentBoost;
|
||||
|
||||
factory SnAttachmentBoost.fromJson(Map<String, Object?> json) => _$SnAttachmentBoostFromJson(json);
|
||||
factory SnAttachmentBoost.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentBoostFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -158,7 +165,8 @@ abstract class SnSticker with _$SnSticker {
|
||||
required int accountId,
|
||||
}) = _SnSticker;
|
||||
|
||||
factory SnSticker.fromJson(Map<String, Object?> json) => _$SnStickerFromJson(json);
|
||||
factory SnSticker.fromJson(Map<String, Object?> json) =>
|
||||
_$SnStickerFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -175,7 +183,8 @@ abstract class SnStickerPack with _$SnStickerPack {
|
||||
required int accountId,
|
||||
}) = _SnStickerPack;
|
||||
|
||||
factory SnStickerPack.fromJson(Map<String, Object?> json) => _$SnStickerPackFromJson(json);
|
||||
factory SnStickerPack.fromJson(Map<String, Object?> json) =>
|
||||
_$SnStickerPackFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -186,5 +195,6 @@ abstract class SnAttachmentBilling with _$SnAttachmentBilling {
|
||||
required double includedRatio,
|
||||
}) = _SnAttachmentBilling;
|
||||
|
||||
factory SnAttachmentBilling.fromJson(Map<String, Object?> json) => _$SnAttachmentBillingFromJson(json);
|
||||
factory SnAttachmentBilling.fromJson(Map<String, Object?> json) =>
|
||||
_$SnAttachmentBillingFromJson(json);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ mixin _$SnAttachment {
|
||||
int? get refId;
|
||||
SnAttachmentPool? get pool;
|
||||
int? get poolId;
|
||||
SnAccount? get account;
|
||||
int get accountId;
|
||||
int? get thumbnailId;
|
||||
SnAttachment? get thumbnail;
|
||||
@ -98,6 +99,7 @@ mixin _$SnAttachment {
|
||||
(identical(other.refId, refId) || other.refId == refId) &&
|
||||
(identical(other.pool, pool) || other.pool == pool) &&
|
||||
(identical(other.poolId, poolId) || other.poolId == poolId) &&
|
||||
(identical(other.account, account) || other.account == account) &&
|
||||
(identical(other.accountId, accountId) ||
|
||||
other.accountId == accountId) &&
|
||||
(identical(other.thumbnailId, thumbnailId) ||
|
||||
@ -140,6 +142,7 @@ mixin _$SnAttachment {
|
||||
refId,
|
||||
pool,
|
||||
poolId,
|
||||
account,
|
||||
accountId,
|
||||
thumbnailId,
|
||||
thumbnail,
|
||||
@ -152,7 +155,7 @@ mixin _$SnAttachment {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAttachment(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, rid: $rid, uuid: $uuid, size: $size, name: $name, alt: $alt, mimetype: $mimetype, hash: $hash, destination: $destination, refCount: $refCount, contentRating: $contentRating, qualityRating: $qualityRating, cleanedAt: $cleanedAt, isAnalyzed: $isAnalyzed, isSelfRef: $isSelfRef, isIndexable: $isIndexable, ref: $ref, refId: $refId, pool: $pool, poolId: $poolId, accountId: $accountId, thumbnailId: $thumbnailId, thumbnail: $thumbnail, compressedId: $compressedId, compressed: $compressed, boosts: $boosts, usermeta: $usermeta, metadata: $metadata)';
|
||||
return 'SnAttachment(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, rid: $rid, uuid: $uuid, size: $size, name: $name, alt: $alt, mimetype: $mimetype, hash: $hash, destination: $destination, refCount: $refCount, contentRating: $contentRating, qualityRating: $qualityRating, cleanedAt: $cleanedAt, isAnalyzed: $isAnalyzed, isSelfRef: $isSelfRef, isIndexable: $isIndexable, ref: $ref, refId: $refId, pool: $pool, poolId: $poolId, account: $account, accountId: $accountId, thumbnailId: $thumbnailId, thumbnail: $thumbnail, compressedId: $compressedId, compressed: $compressed, boosts: $boosts, usermeta: $usermeta, metadata: $metadata)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,6 +189,7 @@ abstract mixin class $SnAttachmentCopyWith<$Res> {
|
||||
int? refId,
|
||||
SnAttachmentPool? pool,
|
||||
int? poolId,
|
||||
SnAccount? account,
|
||||
int accountId,
|
||||
int? thumbnailId,
|
||||
SnAttachment? thumbnail,
|
||||
@ -197,6 +201,7 @@ abstract mixin class $SnAttachmentCopyWith<$Res> {
|
||||
|
||||
$SnAttachmentCopyWith<$Res>? get ref;
|
||||
$SnAttachmentPoolCopyWith<$Res>? get pool;
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
$SnAttachmentCopyWith<$Res>? get thumbnail;
|
||||
$SnAttachmentCopyWith<$Res>? get compressed;
|
||||
}
|
||||
@ -236,6 +241,7 @@ class _$SnAttachmentCopyWithImpl<$Res> implements $SnAttachmentCopyWith<$Res> {
|
||||
Object? refId = freezed,
|
||||
Object? pool = freezed,
|
||||
Object? poolId = freezed,
|
||||
Object? account = freezed,
|
||||
Object? accountId = null,
|
||||
Object? thumbnailId = freezed,
|
||||
Object? thumbnail = freezed,
|
||||
@ -338,6 +344,10 @@ class _$SnAttachmentCopyWithImpl<$Res> implements $SnAttachmentCopyWith<$Res> {
|
||||
? _self.poolId
|
||||
: poolId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
account: freezed == account
|
||||
? _self.account
|
||||
: account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
accountId: null == accountId
|
||||
? _self.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
@ -401,6 +411,20 @@ class _$SnAttachmentCopyWithImpl<$Res> implements $SnAttachmentCopyWith<$Res> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnAttachment
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnAttachment
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@ -457,6 +481,7 @@ class _SnAttachment extends SnAttachment {
|
||||
required this.refId,
|
||||
required this.pool,
|
||||
required this.poolId,
|
||||
required this.account,
|
||||
required this.accountId,
|
||||
this.thumbnailId,
|
||||
this.thumbnail,
|
||||
@ -521,6 +546,8 @@ class _SnAttachment extends SnAttachment {
|
||||
@override
|
||||
final int? poolId;
|
||||
@override
|
||||
final SnAccount? account;
|
||||
@override
|
||||
final int accountId;
|
||||
@override
|
||||
final int? thumbnailId;
|
||||
@ -612,6 +639,7 @@ class _SnAttachment extends SnAttachment {
|
||||
(identical(other.refId, refId) || other.refId == refId) &&
|
||||
(identical(other.pool, pool) || other.pool == pool) &&
|
||||
(identical(other.poolId, poolId) || other.poolId == poolId) &&
|
||||
(identical(other.account, account) || other.account == account) &&
|
||||
(identical(other.accountId, accountId) ||
|
||||
other.accountId == accountId) &&
|
||||
(identical(other.thumbnailId, thumbnailId) ||
|
||||
@ -654,6 +682,7 @@ class _SnAttachment extends SnAttachment {
|
||||
refId,
|
||||
pool,
|
||||
poolId,
|
||||
account,
|
||||
accountId,
|
||||
thumbnailId,
|
||||
thumbnail,
|
||||
@ -666,7 +695,7 @@ class _SnAttachment extends SnAttachment {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAttachment(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, rid: $rid, uuid: $uuid, size: $size, name: $name, alt: $alt, mimetype: $mimetype, hash: $hash, destination: $destination, refCount: $refCount, contentRating: $contentRating, qualityRating: $qualityRating, cleanedAt: $cleanedAt, isAnalyzed: $isAnalyzed, isSelfRef: $isSelfRef, isIndexable: $isIndexable, ref: $ref, refId: $refId, pool: $pool, poolId: $poolId, accountId: $accountId, thumbnailId: $thumbnailId, thumbnail: $thumbnail, compressedId: $compressedId, compressed: $compressed, boosts: $boosts, usermeta: $usermeta, metadata: $metadata)';
|
||||
return 'SnAttachment(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, rid: $rid, uuid: $uuid, size: $size, name: $name, alt: $alt, mimetype: $mimetype, hash: $hash, destination: $destination, refCount: $refCount, contentRating: $contentRating, qualityRating: $qualityRating, cleanedAt: $cleanedAt, isAnalyzed: $isAnalyzed, isSelfRef: $isSelfRef, isIndexable: $isIndexable, ref: $ref, refId: $refId, pool: $pool, poolId: $poolId, account: $account, accountId: $accountId, thumbnailId: $thumbnailId, thumbnail: $thumbnail, compressedId: $compressedId, compressed: $compressed, boosts: $boosts, usermeta: $usermeta, metadata: $metadata)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -702,6 +731,7 @@ abstract mixin class _$SnAttachmentCopyWith<$Res>
|
||||
int? refId,
|
||||
SnAttachmentPool? pool,
|
||||
int? poolId,
|
||||
SnAccount? account,
|
||||
int accountId,
|
||||
int? thumbnailId,
|
||||
SnAttachment? thumbnail,
|
||||
@ -716,6 +746,8 @@ abstract mixin class _$SnAttachmentCopyWith<$Res>
|
||||
@override
|
||||
$SnAttachmentPoolCopyWith<$Res>? get pool;
|
||||
@override
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
@override
|
||||
$SnAttachmentCopyWith<$Res>? get thumbnail;
|
||||
@override
|
||||
$SnAttachmentCopyWith<$Res>? get compressed;
|
||||
@ -757,6 +789,7 @@ class __$SnAttachmentCopyWithImpl<$Res>
|
||||
Object? refId = freezed,
|
||||
Object? pool = freezed,
|
||||
Object? poolId = freezed,
|
||||
Object? account = freezed,
|
||||
Object? accountId = null,
|
||||
Object? thumbnailId = freezed,
|
||||
Object? thumbnail = freezed,
|
||||
@ -859,6 +892,10 @@ class __$SnAttachmentCopyWithImpl<$Res>
|
||||
? _self.poolId
|
||||
: poolId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
account: freezed == account
|
||||
? _self.account
|
||||
: account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
accountId: null == accountId
|
||||
? _self.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
@ -922,6 +959,20 @@ class __$SnAttachmentCopyWithImpl<$Res>
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnAttachment
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnAttachment
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
|
@ -39,6 +39,9 @@ _SnAttachment _$SnAttachmentFromJson(Map<String, dynamic> json) =>
|
||||
? null
|
||||
: SnAttachmentPool.fromJson(json['pool'] as Map<String, dynamic>),
|
||||
poolId: (json['pool_id'] as num?)?.toInt(),
|
||||
account: json['account'] == null
|
||||
? null
|
||||
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
accountId: (json['account_id'] as num).toInt(),
|
||||
thumbnailId: (json['thumbnail_id'] as num?)?.toInt(),
|
||||
thumbnail: json['thumbnail'] == null
|
||||
@ -82,6 +85,7 @@ Map<String, dynamic> _$SnAttachmentToJson(_SnAttachment instance) =>
|
||||
'ref_id': instance.refId,
|
||||
'pool': instance.pool?.toJson(),
|
||||
'pool_id': instance.poolId,
|
||||
'account': instance.account?.toJson(),
|
||||
'account_id': instance.accountId,
|
||||
'thumbnail_id': instance.thumbnailId,
|
||||
'thumbnail': instance.thumbnail?.toJson(),
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:surface/types/account.dart';
|
||||
import 'package:surface/types/attachment.dart';
|
||||
import 'package:surface/types/poll.dart';
|
||||
import 'package:surface/types/realm.dart';
|
||||
@ -26,6 +27,7 @@ abstract class SnPost with _$SnPost {
|
||||
required int? replyId,
|
||||
required int? repostId,
|
||||
required int? realmId,
|
||||
required SnRealm? realm,
|
||||
required SnPost? replyTo,
|
||||
required SnPost? repostTo,
|
||||
required List<int>? visibleUsersList,
|
||||
@ -43,9 +45,9 @@ abstract class SnPost with _$SnPost {
|
||||
@Default(0) int totalAggregatedViews,
|
||||
required int publisherId,
|
||||
required int? pollId,
|
||||
required SnPoll? poll,
|
||||
required SnPublisher publisher,
|
||||
required SnMetric metric,
|
||||
SnPostPreload? preload,
|
||||
}) = _SnPost;
|
||||
|
||||
factory SnPost.fromJson(Map<String, Object?> json) => _$SnPostFromJson(json);
|
||||
@ -146,6 +148,7 @@ abstract class SnPublisher with _$SnPublisher {
|
||||
required int totalDownvote,
|
||||
required int? realmId,
|
||||
required int accountId,
|
||||
required SnAccount? account,
|
||||
}) = _SnPublisher;
|
||||
|
||||
factory SnPublisher.fromJson(Map<String, Object?> json) =>
|
||||
|
@ -30,6 +30,7 @@ mixin _$SnPost {
|
||||
int? get replyId;
|
||||
int? get repostId;
|
||||
int? get realmId;
|
||||
SnRealm? get realm;
|
||||
SnPost? get replyTo;
|
||||
SnPost? get repostTo;
|
||||
List<int>? get visibleUsersList;
|
||||
@ -47,9 +48,9 @@ mixin _$SnPost {
|
||||
int get totalAggregatedViews;
|
||||
int get publisherId;
|
||||
int? get pollId;
|
||||
SnPoll? get poll;
|
||||
SnPublisher get publisher;
|
||||
SnMetric get metric;
|
||||
SnPostPreload? get preload;
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@ -88,6 +89,7 @@ mixin _$SnPost {
|
||||
(identical(other.repostId, repostId) ||
|
||||
other.repostId == repostId) &&
|
||||
(identical(other.realmId, realmId) || other.realmId == realmId) &&
|
||||
(identical(other.realm, realm) || other.realm == realm) &&
|
||||
(identical(other.replyTo, replyTo) || other.replyTo == replyTo) &&
|
||||
(identical(other.repostTo, repostTo) ||
|
||||
other.repostTo == repostTo) &&
|
||||
@ -119,10 +121,10 @@ mixin _$SnPost {
|
||||
(identical(other.publisherId, publisherId) ||
|
||||
other.publisherId == publisherId) &&
|
||||
(identical(other.pollId, pollId) || other.pollId == pollId) &&
|
||||
(identical(other.poll, poll) || other.poll == poll) &&
|
||||
(identical(other.publisher, publisher) ||
|
||||
other.publisher == publisher) &&
|
||||
(identical(other.metric, metric) || other.metric == metric) &&
|
||||
(identical(other.preload, preload) || other.preload == preload));
|
||||
(identical(other.metric, metric) || other.metric == metric));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -144,6 +146,7 @@ mixin _$SnPost {
|
||||
replyId,
|
||||
repostId,
|
||||
realmId,
|
||||
realm,
|
||||
replyTo,
|
||||
repostTo,
|
||||
const DeepCollectionEquality().hash(visibleUsersList),
|
||||
@ -161,14 +164,14 @@ mixin _$SnPost {
|
||||
totalAggregatedViews,
|
||||
publisherId,
|
||||
pollId,
|
||||
poll,
|
||||
publisher,
|
||||
metric,
|
||||
preload
|
||||
metric
|
||||
]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, body: $body, language: $language, alias: $alias, aliasPrefix: $aliasPrefix, tags: $tags, categories: $categories, replies: $replies, replyId: $replyId, repostId: $repostId, realmId: $realmId, replyTo: $replyTo, repostTo: $repostTo, visibleUsersList: $visibleUsersList, invisibleUsersList: $invisibleUsersList, visibility: $visibility, editedAt: $editedAt, pinnedAt: $pinnedAt, lockedAt: $lockedAt, isDraft: $isDraft, publishedAt: $publishedAt, publishedUntil: $publishedUntil, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, totalViews: $totalViews, totalAggregatedViews: $totalAggregatedViews, publisherId: $publisherId, pollId: $pollId, publisher: $publisher, metric: $metric, preload: $preload)';
|
||||
return 'SnPost(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, body: $body, language: $language, alias: $alias, aliasPrefix: $aliasPrefix, tags: $tags, categories: $categories, replies: $replies, replyId: $replyId, repostId: $repostId, realmId: $realmId, realm: $realm, replyTo: $replyTo, repostTo: $repostTo, visibleUsersList: $visibleUsersList, invisibleUsersList: $invisibleUsersList, visibility: $visibility, editedAt: $editedAt, pinnedAt: $pinnedAt, lockedAt: $lockedAt, isDraft: $isDraft, publishedAt: $publishedAt, publishedUntil: $publishedUntil, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, totalViews: $totalViews, totalAggregatedViews: $totalAggregatedViews, publisherId: $publisherId, pollId: $pollId, poll: $poll, publisher: $publisher, metric: $metric)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,6 +196,7 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
||||
int? replyId,
|
||||
int? repostId,
|
||||
int? realmId,
|
||||
SnRealm? realm,
|
||||
SnPost? replyTo,
|
||||
SnPost? repostTo,
|
||||
List<int>? visibleUsersList,
|
||||
@ -210,15 +214,16 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
||||
int totalAggregatedViews,
|
||||
int publisherId,
|
||||
int? pollId,
|
||||
SnPoll? poll,
|
||||
SnPublisher publisher,
|
||||
SnMetric metric,
|
||||
SnPostPreload? preload});
|
||||
SnMetric metric});
|
||||
|
||||
$SnRealmCopyWith<$Res>? get realm;
|
||||
$SnPostCopyWith<$Res>? get replyTo;
|
||||
$SnPostCopyWith<$Res>? get repostTo;
|
||||
$SnPollCopyWith<$Res>? get poll;
|
||||
$SnPublisherCopyWith<$Res> get publisher;
|
||||
$SnMetricCopyWith<$Res> get metric;
|
||||
$SnPostPreloadCopyWith<$Res>? get preload;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -248,6 +253,7 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
Object? replyId = freezed,
|
||||
Object? repostId = freezed,
|
||||
Object? realmId = freezed,
|
||||
Object? realm = freezed,
|
||||
Object? replyTo = freezed,
|
||||
Object? repostTo = freezed,
|
||||
Object? visibleUsersList = freezed,
|
||||
@ -265,9 +271,9 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
Object? totalAggregatedViews = null,
|
||||
Object? publisherId = null,
|
||||
Object? pollId = freezed,
|
||||
Object? poll = freezed,
|
||||
Object? publisher = null,
|
||||
Object? metric = null,
|
||||
Object? preload = freezed,
|
||||
}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id
|
||||
@ -330,6 +336,10 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
? _self.realmId
|
||||
: realmId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
realm: freezed == realm
|
||||
? _self.realm
|
||||
: realm // ignore: cast_nullable_to_non_nullable
|
||||
as SnRealm?,
|
||||
replyTo: freezed == replyTo
|
||||
? _self.replyTo
|
||||
: replyTo // ignore: cast_nullable_to_non_nullable
|
||||
@ -398,6 +408,10 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
? _self.pollId
|
||||
: pollId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
poll: freezed == poll
|
||||
? _self.poll
|
||||
: poll // ignore: cast_nullable_to_non_nullable
|
||||
as SnPoll?,
|
||||
publisher: null == publisher
|
||||
? _self.publisher
|
||||
: publisher // ignore: cast_nullable_to_non_nullable
|
||||
@ -406,13 +420,23 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
? _self.metric
|
||||
: metric // ignore: cast_nullable_to_non_nullable
|
||||
as SnMetric,
|
||||
preload: freezed == preload
|
||||
? _self.preload
|
||||
: preload // ignore: cast_nullable_to_non_nullable
|
||||
as SnPostPreload?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnRealmCopyWith<$Res>? get realm {
|
||||
if (_self.realm == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||
return _then(_self.copyWith(realm: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@ -441,6 +465,20 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPollCopyWith<$Res>? get poll {
|
||||
if (_self.poll == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPollCopyWith<$Res>(_self.poll!, (value) {
|
||||
return _then(_self.copyWith(poll: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@ -460,20 +498,6 @@ class _$SnPostCopyWithImpl<$Res> implements $SnPostCopyWith<$Res> {
|
||||
return _then(_self.copyWith(metric: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostPreloadCopyWith<$Res>? get preload {
|
||||
if (_self.preload == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPostPreloadCopyWith<$Res>(_self.preload!, (value) {
|
||||
return _then(_self.copyWith(preload: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -495,6 +519,7 @@ class _SnPost extends SnPost {
|
||||
required this.replyId,
|
||||
required this.repostId,
|
||||
required this.realmId,
|
||||
required this.realm,
|
||||
required this.replyTo,
|
||||
required this.repostTo,
|
||||
required final List<int>? visibleUsersList,
|
||||
@ -512,9 +537,9 @@ class _SnPost extends SnPost {
|
||||
this.totalAggregatedViews = 0,
|
||||
required this.publisherId,
|
||||
required this.pollId,
|
||||
required this.poll,
|
||||
required this.publisher,
|
||||
required this.metric,
|
||||
this.preload})
|
||||
required this.metric})
|
||||
: _body = body,
|
||||
_tags = tags,
|
||||
_categories = categories,
|
||||
@ -583,6 +608,8 @@ class _SnPost extends SnPost {
|
||||
@override
|
||||
final int? realmId;
|
||||
@override
|
||||
final SnRealm? realm;
|
||||
@override
|
||||
final SnPost? replyTo;
|
||||
@override
|
||||
final SnPost? repostTo;
|
||||
@ -637,11 +664,11 @@ class _SnPost extends SnPost {
|
||||
@override
|
||||
final int? pollId;
|
||||
@override
|
||||
final SnPoll? poll;
|
||||
@override
|
||||
final SnPublisher publisher;
|
||||
@override
|
||||
final SnMetric metric;
|
||||
@override
|
||||
final SnPostPreload? preload;
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@ -685,6 +712,7 @@ class _SnPost extends SnPost {
|
||||
(identical(other.repostId, repostId) ||
|
||||
other.repostId == repostId) &&
|
||||
(identical(other.realmId, realmId) || other.realmId == realmId) &&
|
||||
(identical(other.realm, realm) || other.realm == realm) &&
|
||||
(identical(other.replyTo, replyTo) || other.replyTo == replyTo) &&
|
||||
(identical(other.repostTo, repostTo) ||
|
||||
other.repostTo == repostTo) &&
|
||||
@ -716,10 +744,10 @@ class _SnPost extends SnPost {
|
||||
(identical(other.publisherId, publisherId) ||
|
||||
other.publisherId == publisherId) &&
|
||||
(identical(other.pollId, pollId) || other.pollId == pollId) &&
|
||||
(identical(other.poll, poll) || other.poll == poll) &&
|
||||
(identical(other.publisher, publisher) ||
|
||||
other.publisher == publisher) &&
|
||||
(identical(other.metric, metric) || other.metric == metric) &&
|
||||
(identical(other.preload, preload) || other.preload == preload));
|
||||
(identical(other.metric, metric) || other.metric == metric));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -741,6 +769,7 @@ class _SnPost extends SnPost {
|
||||
replyId,
|
||||
repostId,
|
||||
realmId,
|
||||
realm,
|
||||
replyTo,
|
||||
repostTo,
|
||||
const DeepCollectionEquality().hash(_visibleUsersList),
|
||||
@ -758,14 +787,14 @@ class _SnPost extends SnPost {
|
||||
totalAggregatedViews,
|
||||
publisherId,
|
||||
pollId,
|
||||
poll,
|
||||
publisher,
|
||||
metric,
|
||||
preload
|
||||
metric
|
||||
]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, body: $body, language: $language, alias: $alias, aliasPrefix: $aliasPrefix, tags: $tags, categories: $categories, replies: $replies, replyId: $replyId, repostId: $repostId, realmId: $realmId, replyTo: $replyTo, repostTo: $repostTo, visibleUsersList: $visibleUsersList, invisibleUsersList: $invisibleUsersList, visibility: $visibility, editedAt: $editedAt, pinnedAt: $pinnedAt, lockedAt: $lockedAt, isDraft: $isDraft, publishedAt: $publishedAt, publishedUntil: $publishedUntil, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, totalViews: $totalViews, totalAggregatedViews: $totalAggregatedViews, publisherId: $publisherId, pollId: $pollId, publisher: $publisher, metric: $metric, preload: $preload)';
|
||||
return 'SnPost(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, body: $body, language: $language, alias: $alias, aliasPrefix: $aliasPrefix, tags: $tags, categories: $categories, replies: $replies, replyId: $replyId, repostId: $repostId, realmId: $realmId, realm: $realm, replyTo: $replyTo, repostTo: $repostTo, visibleUsersList: $visibleUsersList, invisibleUsersList: $invisibleUsersList, visibility: $visibility, editedAt: $editedAt, pinnedAt: $pinnedAt, lockedAt: $lockedAt, isDraft: $isDraft, publishedAt: $publishedAt, publishedUntil: $publishedUntil, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, totalViews: $totalViews, totalAggregatedViews: $totalAggregatedViews, publisherId: $publisherId, pollId: $pollId, poll: $poll, publisher: $publisher, metric: $metric)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,6 +820,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
||||
int? replyId,
|
||||
int? repostId,
|
||||
int? realmId,
|
||||
SnRealm? realm,
|
||||
SnPost? replyTo,
|
||||
SnPost? repostTo,
|
||||
List<int>? visibleUsersList,
|
||||
@ -808,20 +838,22 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
||||
int totalAggregatedViews,
|
||||
int publisherId,
|
||||
int? pollId,
|
||||
SnPoll? poll,
|
||||
SnPublisher publisher,
|
||||
SnMetric metric,
|
||||
SnPostPreload? preload});
|
||||
SnMetric metric});
|
||||
|
||||
@override
|
||||
$SnRealmCopyWith<$Res>? get realm;
|
||||
@override
|
||||
$SnPostCopyWith<$Res>? get replyTo;
|
||||
@override
|
||||
$SnPostCopyWith<$Res>? get repostTo;
|
||||
@override
|
||||
$SnPollCopyWith<$Res>? get poll;
|
||||
@override
|
||||
$SnPublisherCopyWith<$Res> get publisher;
|
||||
@override
|
||||
$SnMetricCopyWith<$Res> get metric;
|
||||
@override
|
||||
$SnPostPreloadCopyWith<$Res>? get preload;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -851,6 +883,7 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
Object? replyId = freezed,
|
||||
Object? repostId = freezed,
|
||||
Object? realmId = freezed,
|
||||
Object? realm = freezed,
|
||||
Object? replyTo = freezed,
|
||||
Object? repostTo = freezed,
|
||||
Object? visibleUsersList = freezed,
|
||||
@ -868,9 +901,9 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
Object? totalAggregatedViews = null,
|
||||
Object? publisherId = null,
|
||||
Object? pollId = freezed,
|
||||
Object? poll = freezed,
|
||||
Object? publisher = null,
|
||||
Object? metric = null,
|
||||
Object? preload = freezed,
|
||||
}) {
|
||||
return _then(_SnPost(
|
||||
id: null == id
|
||||
@ -933,6 +966,10 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
? _self.realmId
|
||||
: realmId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
realm: freezed == realm
|
||||
? _self.realm
|
||||
: realm // ignore: cast_nullable_to_non_nullable
|
||||
as SnRealm?,
|
||||
replyTo: freezed == replyTo
|
||||
? _self.replyTo
|
||||
: replyTo // ignore: cast_nullable_to_non_nullable
|
||||
@ -1001,6 +1038,10 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
? _self.pollId
|
||||
: pollId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
poll: freezed == poll
|
||||
? _self.poll
|
||||
: poll // ignore: cast_nullable_to_non_nullable
|
||||
as SnPoll?,
|
||||
publisher: null == publisher
|
||||
? _self.publisher
|
||||
: publisher // ignore: cast_nullable_to_non_nullable
|
||||
@ -1009,13 +1050,23 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
? _self.metric
|
||||
: metric // ignore: cast_nullable_to_non_nullable
|
||||
as SnMetric,
|
||||
preload: freezed == preload
|
||||
? _self.preload
|
||||
: preload // ignore: cast_nullable_to_non_nullable
|
||||
as SnPostPreload?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnRealmCopyWith<$Res>? get realm {
|
||||
if (_self.realm == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||
return _then(_self.copyWith(realm: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@ -1044,6 +1095,20 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPollCopyWith<$Res>? get poll {
|
||||
if (_self.poll == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPollCopyWith<$Res>(_self.poll!, (value) {
|
||||
return _then(_self.copyWith(poll: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@ -1063,20 +1128,6 @@ class __$SnPostCopyWithImpl<$Res> implements _$SnPostCopyWith<$Res> {
|
||||
return _then(_self.copyWith(metric: value));
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostPreloadCopyWith<$Res>? get preload {
|
||||
if (_self.preload == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPostPreloadCopyWith<$Res>(_self.preload!, (value) {
|
||||
return _then(_self.copyWith(preload: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -2465,6 +2516,7 @@ mixin _$SnPublisher {
|
||||
int get totalDownvote;
|
||||
int? get realmId;
|
||||
int get accountId;
|
||||
SnAccount? get account;
|
||||
|
||||
/// Create a copy of SnPublisher
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@ -2501,7 +2553,8 @@ mixin _$SnPublisher {
|
||||
other.totalDownvote == totalDownvote) &&
|
||||
(identical(other.realmId, realmId) || other.realmId == realmId) &&
|
||||
(identical(other.accountId, accountId) ||
|
||||
other.accountId == accountId));
|
||||
other.accountId == accountId) &&
|
||||
(identical(other.account, account) || other.account == account));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -2521,11 +2574,12 @@ mixin _$SnPublisher {
|
||||
totalUpvote,
|
||||
totalDownvote,
|
||||
realmId,
|
||||
accountId);
|
||||
accountId,
|
||||
account);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPublisher(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, name: $name, nick: $nick, description: $description, avatar: $avatar, banner: $banner, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, realmId: $realmId, accountId: $accountId)';
|
||||
return 'SnPublisher(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, name: $name, nick: $nick, description: $description, avatar: $avatar, banner: $banner, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, realmId: $realmId, accountId: $accountId, account: $account)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2549,7 +2603,10 @@ abstract mixin class $SnPublisherCopyWith<$Res> {
|
||||
int totalUpvote,
|
||||
int totalDownvote,
|
||||
int? realmId,
|
||||
int accountId});
|
||||
int accountId,
|
||||
SnAccount? account});
|
||||
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -2578,6 +2635,7 @@ class _$SnPublisherCopyWithImpl<$Res> implements $SnPublisherCopyWith<$Res> {
|
||||
Object? totalDownvote = null,
|
||||
Object? realmId = freezed,
|
||||
Object? accountId = null,
|
||||
Object? account = freezed,
|
||||
}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id
|
||||
@ -2636,8 +2694,26 @@ class _$SnPublisherCopyWithImpl<$Res> implements $SnPublisherCopyWith<$Res> {
|
||||
? _self.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
account: freezed == account
|
||||
? _self.account
|
||||
: account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPublisher
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -2657,7 +2733,8 @@ class _SnPublisher implements SnPublisher {
|
||||
required this.totalUpvote,
|
||||
required this.totalDownvote,
|
||||
required this.realmId,
|
||||
required this.accountId});
|
||||
required this.accountId,
|
||||
required this.account});
|
||||
factory _SnPublisher.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPublisherFromJson(json);
|
||||
|
||||
@ -2689,6 +2766,8 @@ class _SnPublisher implements SnPublisher {
|
||||
final int? realmId;
|
||||
@override
|
||||
final int accountId;
|
||||
@override
|
||||
final SnAccount? account;
|
||||
|
||||
/// Create a copy of SnPublisher
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@ -2730,7 +2809,8 @@ class _SnPublisher implements SnPublisher {
|
||||
other.totalDownvote == totalDownvote) &&
|
||||
(identical(other.realmId, realmId) || other.realmId == realmId) &&
|
||||
(identical(other.accountId, accountId) ||
|
||||
other.accountId == accountId));
|
||||
other.accountId == accountId) &&
|
||||
(identical(other.account, account) || other.account == account));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@ -2750,11 +2830,12 @@ class _SnPublisher implements SnPublisher {
|
||||
totalUpvote,
|
||||
totalDownvote,
|
||||
realmId,
|
||||
accountId);
|
||||
accountId,
|
||||
account);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPublisher(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, name: $name, nick: $nick, description: $description, avatar: $avatar, banner: $banner, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, realmId: $realmId, accountId: $accountId)';
|
||||
return 'SnPublisher(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, type: $type, name: $name, nick: $nick, description: $description, avatar: $avatar, banner: $banner, totalUpvote: $totalUpvote, totalDownvote: $totalDownvote, realmId: $realmId, accountId: $accountId, account: $account)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2780,7 +2861,11 @@ abstract mixin class _$SnPublisherCopyWith<$Res>
|
||||
int totalUpvote,
|
||||
int totalDownvote,
|
||||
int? realmId,
|
||||
int accountId});
|
||||
int accountId,
|
||||
SnAccount? account});
|
||||
|
||||
@override
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -2809,6 +2894,7 @@ class __$SnPublisherCopyWithImpl<$Res> implements _$SnPublisherCopyWith<$Res> {
|
||||
Object? totalDownvote = null,
|
||||
Object? realmId = freezed,
|
||||
Object? accountId = null,
|
||||
Object? account = freezed,
|
||||
}) {
|
||||
return _then(_SnPublisher(
|
||||
id: null == id
|
||||
@ -2867,8 +2953,26 @@ class __$SnPublisherCopyWithImpl<$Res> implements _$SnPublisherCopyWith<$Res> {
|
||||
? _self.accountId
|
||||
: accountId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
account: freezed == account
|
||||
? _self.account
|
||||
: account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPublisher
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
@ -32,6 +32,9 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
replyId: (json['reply_id'] as num?)?.toInt(),
|
||||
repostId: (json['repost_id'] as num?)?.toInt(),
|
||||
realmId: (json['realm_id'] as num?)?.toInt(),
|
||||
realm: json['realm'] == null
|
||||
? null
|
||||
: SnRealm.fromJson(json['realm'] as Map<String, dynamic>),
|
||||
replyTo: json['reply_to'] == null
|
||||
? null
|
||||
: SnPost.fromJson(json['reply_to'] as Map<String, dynamic>),
|
||||
@ -68,12 +71,12 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
(json['total_aggregated_views'] as num?)?.toInt() ?? 0,
|
||||
publisherId: (json['publisher_id'] as num).toInt(),
|
||||
pollId: (json['poll_id'] as num?)?.toInt(),
|
||||
poll: json['poll'] == null
|
||||
? null
|
||||
: SnPoll.fromJson(json['poll'] as Map<String, dynamic>),
|
||||
publisher:
|
||||
SnPublisher.fromJson(json['publisher'] as Map<String, dynamic>),
|
||||
metric: SnMetric.fromJson(json['metric'] as Map<String, dynamic>),
|
||||
preload: json['preload'] == null
|
||||
? null
|
||||
: SnPostPreload.fromJson(json['preload'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
@ -92,6 +95,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'reply_id': instance.replyId,
|
||||
'repost_id': instance.repostId,
|
||||
'realm_id': instance.realmId,
|
||||
'realm': instance.realm?.toJson(),
|
||||
'reply_to': instance.replyTo?.toJson(),
|
||||
'repost_to': instance.repostTo?.toJson(),
|
||||
'visible_users_list': instance.visibleUsersList,
|
||||
@ -109,9 +113,9 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'total_aggregated_views': instance.totalAggregatedViews,
|
||||
'publisher_id': instance.publisherId,
|
||||
'poll_id': instance.pollId,
|
||||
'poll': instance.poll?.toJson(),
|
||||
'publisher': instance.publisher.toJson(),
|
||||
'metric': instance.metric.toJson(),
|
||||
'preload': instance.preload?.toJson(),
|
||||
};
|
||||
|
||||
_SnPostTag _$SnPostTagFromJson(Map<String, dynamic> json) => _SnPostTag(
|
||||
@ -241,6 +245,9 @@ _SnPublisher _$SnPublisherFromJson(Map<String, dynamic> json) => _SnPublisher(
|
||||
totalDownvote: (json['total_downvote'] as num).toInt(),
|
||||
realmId: (json['realm_id'] as num?)?.toInt(),
|
||||
accountId: (json['account_id'] as num).toInt(),
|
||||
account: json['account'] == null
|
||||
? null
|
||||
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPublisherToJson(_SnPublisher instance) =>
|
||||
@ -259,6 +266,7 @@ Map<String, dynamic> _$SnPublisherToJson(_SnPublisher instance) =>
|
||||
'total_downvote': instance.totalDownvote,
|
||||
'realm_id': instance.realmId,
|
||||
'account_id': instance.accountId,
|
||||
'account': instance.account?.toJson(),
|
||||
};
|
||||
|
||||
_SnSubscription _$SnSubscriptionFromJson(Map<String, dynamic> json) =>
|
||||
|
@ -17,4 +17,5 @@ const Map<String, ReactInfo> kTemplateReactions = {
|
||||
'party': ReactInfo(icon: '🎉', attitude: 1),
|
||||
'joy': ReactInfo(icon: '🤣', attitude: 1),
|
||||
'pray': ReactInfo(icon: '🙏', attitude: 1),
|
||||
'heart': ReactInfo(icon: '❤️', attitude: 1),
|
||||
};
|
||||
|
@ -16,7 +16,6 @@ import 'package:photo_view/photo_view_gallery.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/user_directory.dart';
|
||||
import 'package:surface/types/attachment.dart';
|
||||
import 'package:surface/widgets/account/account_image.dart';
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
@ -418,8 +417,7 @@ class _AttachmentZoomDetailPopup extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ud = context.read<UserDirectoryProvider>();
|
||||
final account = ud.getFromCache(data.accountId);
|
||||
final account = data.account!;
|
||||
|
||||
const tableGap = TableRow(
|
||||
children: [
|
||||
@ -461,12 +459,12 @@ class _AttachmentZoomDetailPopup extends StatelessWidget {
|
||||
children: [
|
||||
if (data.accountId > 0)
|
||||
AccountImage(
|
||||
content: account?.avatar,
|
||||
content: account.avatar,
|
||||
radius: 8,
|
||||
),
|
||||
const Gap(8),
|
||||
Text(data.accountId > 0
|
||||
? account?.nick ?? 'unknown'.tr()
|
||||
? account.nick
|
||||
: 'unknown'.tr()),
|
||||
const Gap(8),
|
||||
Text('#${data.accountId}',
|
||||
|
@ -26,11 +26,13 @@ class _LinkPreviewWidgetState extends State<LinkPreviewWidget> {
|
||||
|
||||
Future<void> _getLinkMeta() async {
|
||||
final linkRegex = RegExp(r'https?:\/\/[^\s/$.?#].[^\s]*');
|
||||
final links = linkRegex.allMatches(widget.text).map((e) => e.group(0)).toSet();
|
||||
final links =
|
||||
linkRegex.allMatches(widget.text).map((e) => e.group(0)).toSet();
|
||||
|
||||
final lp = context.read<SnLinkPreviewProvider>();
|
||||
|
||||
final List<Future<SnLinkMeta?>> futures = links.where((e) => e != null).map((e) => lp.getLinkMeta(e!)).toList();
|
||||
final List<Future<SnLinkMeta?>> futures =
|
||||
links.where((e) => e != null).map((e) => lp.getLinkMeta(e!)).toList();
|
||||
final results = await Future.wait(futures);
|
||||
|
||||
_links.addAll(results.where((e) => e != null).map((e) => e!).toList());
|
||||
@ -66,7 +68,9 @@ class _LinkPreviewEntry extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE) ? double.infinity : 480,
|
||||
maxWidth: ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE)
|
||||
? double.infinity
|
||||
: 480,
|
||||
),
|
||||
child: GestureDetector(
|
||||
child: Card(
|
||||
@ -74,16 +78,25 @@ class _LinkPreviewEntry extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (meta.image != null)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 4),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: AutoResizeUniversalImage(
|
||||
meta.image!.startsWith('//') ? 'https:${meta.image}' : meta.image!,
|
||||
fit: BoxFit.contain,
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
topRight: Radius.circular(8),
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 4),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(8)),
|
||||
child: AutoResizeUniversalImage(
|
||||
meta.image!.startsWith('//')
|
||||
? 'https:${meta.image}'
|
||||
: meta.image!,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -98,7 +111,8 @@ class _LinkPreviewEntry extends StatelessWidget {
|
||||
width: 36,
|
||||
height: 36,
|
||||
child: meta.icon!.endsWith('.svg')
|
||||
? SvgPicture.network(meta.icon!, width: 36, height: 36)
|
||||
? SvgPicture.network(meta.icon!,
|
||||
width: 36, height: 36)
|
||||
: UniversalImage(
|
||||
meta.icon!,
|
||||
noErrorWidget: true,
|
||||
|
@ -87,6 +87,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
onTap: () {
|
||||
GoRouter.of(context).pushNamed(ele.screen);
|
||||
nav.setIndex(idx);
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
);
|
||||
})
|
||||
|
@ -282,7 +282,7 @@ class ResponsiveScaffoldLanding extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
if (ResponsiveScaffold.getIsExpand(context) || child == null) {
|
||||
return AppScaffold(
|
||||
noBackground: true,
|
||||
noBackground: ResponsiveScaffold.getIsExpand(context),
|
||||
appBar: AppBar(),
|
||||
body: const SizedBox.shrink(),
|
||||
);
|
||||
|
@ -179,57 +179,54 @@ class _PostCommentListPopupState extends State<PostCommentListPopup> {
|
||||
final ua = context.watch<UserProvider>();
|
||||
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.85,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Symbols.comment, size: 24),
|
||||
const Gap(16),
|
||||
Text('postCommentsDetailed')
|
||||
.plural(widget.commentCount)
|
||||
.textStyle(Theme.of(context).textTheme.titleLarge!),
|
||||
],
|
||||
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
if (ua.isAuthorized)
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
height: 240,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.symmetric(
|
||||
horizontal: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1 / devicePixelRatio,
|
||||
),
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Symbols.comment, size: 24),
|
||||
const Gap(16),
|
||||
Text('postCommentsDetailed')
|
||||
.plural(widget.commentCount)
|
||||
.textStyle(Theme.of(context).textTheme.titleLarge!),
|
||||
],
|
||||
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||
Expanded(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
if (ua.isAuthorized)
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
height: 240,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.symmetric(
|
||||
horizontal: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1 / devicePixelRatio,
|
||||
),
|
||||
),
|
||||
child: PostMiniEditor(
|
||||
postReplyId: widget.post.id,
|
||||
onPost: () {
|
||||
_childListKey.currentState!.refresh();
|
||||
},
|
||||
onExpand: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
child: PostMiniEditor(
|
||||
postReplyId: widget.post.id,
|
||||
onPost: () {
|
||||
_childListKey.currentState!.refresh();
|
||||
},
|
||||
onExpand: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
PostCommentSliverList(
|
||||
parentPost: widget.post,
|
||||
key: _childListKey,
|
||||
),
|
||||
],
|
||||
),
|
||||
PostCommentSliverList(
|
||||
parentPost: widget.post,
|
||||
key: _childListKey,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -274,8 +274,10 @@ class _PostItemState extends State<PostItem> {
|
||||
final isParentAuthor = ua.isAuthorized &&
|
||||
widget.data.replyTo?.publisher.accountId == ua.user?.id;
|
||||
|
||||
final displayableAttachments = widget.data.preload?.attachments
|
||||
?.where((ele) =>
|
||||
final displayableAttachments = widget.data.body['attachments']
|
||||
?.map((e) => SnAttachment.fromJson(e))
|
||||
.cast<SnAttachment>()
|
||||
.where((ele) =>
|
||||
ele?.mediaType != SnMediaType.image ||
|
||||
widget.data.type != 'article')
|
||||
.toList();
|
||||
@ -284,7 +286,7 @@ class _PostItemState extends State<PostItem> {
|
||||
|
||||
var attachmentSize = math.min(
|
||||
MediaQuery.of(context).size.width, widget.maxWidth ?? double.infinity);
|
||||
if ((widget.data.preload?.attachments?.length ?? 0) > 1) {
|
||||
if ((widget.data.body['attachments']?.length ?? 0) > 1) {
|
||||
attachmentSize -= 80;
|
||||
}
|
||||
|
||||
@ -341,7 +343,7 @@ class _PostItemState extends State<PostItem> {
|
||||
],
|
||||
),
|
||||
const Gap(8),
|
||||
if (widget.data.preload?.thumbnail != null)
|
||||
if (widget.data.body['thumbnail'] != null)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
decoration: BoxDecoration(
|
||||
@ -361,14 +363,14 @@ class _PostItemState extends State<PostItem> {
|
||||
),
|
||||
child: AutoResizeUniversalImage(
|
||||
sn.getAttachmentUrl(
|
||||
widget.data.preload!.thumbnail!.rid,
|
||||
widget.data.body['thumbnail']['rid'],
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.data.preload?.video != null)
|
||||
if (widget.data.body['video'] != null)
|
||||
_PostVideoPlayer(data: widget.data).padding(bottom: 8),
|
||||
if (widget.data.type == 'question')
|
||||
_PostQuestionHint(data: widget.data).padding(bottom: 8),
|
||||
@ -455,10 +457,10 @@ class _PostItemState extends State<PostItem> {
|
||||
if (widget.data.repostTo != null)
|
||||
_PostQuoteContent(child: widget.data.repostTo!).padding(
|
||||
top: 4,
|
||||
bottom: widget.data.preload?.attachments?.isNotEmpty ??
|
||||
false
|
||||
? 12
|
||||
: 0,
|
||||
bottom:
|
||||
widget.data.body['attachments'].isNotEmpty ?? false
|
||||
? 12
|
||||
: 0,
|
||||
),
|
||||
],
|
||||
).padding(
|
||||
@ -479,11 +481,11 @@ class _PostItemState extends State<PostItem> {
|
||||
fit: widget.showFullPost ? BoxFit.cover : BoxFit.contain,
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
),
|
||||
if (widget.data.preload?.poll != null)
|
||||
if (widget.data.poll != null)
|
||||
StyledWidget(Container(
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: widget.maxWidth ?? double.infinity),
|
||||
child: PostPoll(poll: widget.data.preload!.poll!),
|
||||
child: PostPoll(poll: widget.data.poll!),
|
||||
))
|
||||
.padding(
|
||||
left: 12,
|
||||
@ -585,7 +587,7 @@ class _PostItemState extends State<PostItem> {
|
||||
),
|
||||
],
|
||||
).padding(bottom: widget.showCompactAvatar ? 4 : 0),
|
||||
if (widget.data.preload?.thumbnail != null)
|
||||
if (widget.data.body['thumbnail'] != null)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
decoration: BoxDecoration(
|
||||
@ -605,14 +607,14 @@ class _PostItemState extends State<PostItem> {
|
||||
),
|
||||
child: AutoResizeUniversalImage(
|
||||
sn.getAttachmentUrl(
|
||||
widget.data.preload!.thumbnail!.rid,
|
||||
widget.data.body['thumbnail']['rid'],
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.data.preload?.video != null)
|
||||
if (widget.data.body['video'] != null)
|
||||
_PostVideoPlayer(data: widget.data)
|
||||
.padding(bottom: 8),
|
||||
if (widget.data.type == 'question')
|
||||
@ -712,7 +714,7 @@ class _PostItemState extends State<PostItem> {
|
||||
_isTranslated ||
|
||||
_isTranslating) &&
|
||||
(widget.data.repostTo != null ||
|
||||
(widget.data.preload?.attachments
|
||||
(widget.data.body['attachments']
|
||||
?.isNotEmpty ??
|
||||
false))
|
||||
? 8
|
||||
@ -722,7 +724,7 @@ class _PostItemState extends State<PostItem> {
|
||||
_PostQuoteContent(child: widget.data.repostTo!)
|
||||
.padding(
|
||||
bottom:
|
||||
(widget.data.preload?.attachments?.isNotEmpty ??
|
||||
(widget.data.body['attachments']?.isNotEmpty ??
|
||||
false)
|
||||
? 8
|
||||
: 0,
|
||||
@ -746,8 +748,8 @@ class _PostItemState extends State<PostItem> {
|
||||
padding:
|
||||
EdgeInsets.only(left: widget.showAvatar ? 60 : 12, right: 12),
|
||||
),
|
||||
if (widget.data.preload?.poll != null)
|
||||
PostPoll(poll: widget.data.preload!.poll!).padding(
|
||||
if (widget.data.poll != null)
|
||||
PostPoll(poll: widget.data.poll!).padding(
|
||||
left: widget.showAvatar ? 60 : 12,
|
||||
right: 12,
|
||||
top: 12,
|
||||
@ -808,7 +810,7 @@ class PostShareImageWidget extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (data.preload?.thumbnail != null)
|
||||
if (data.body['thumbnail'] != null)
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: ClipRRect(
|
||||
@ -817,7 +819,7 @@ class PostShareImageWidget extends StatelessWidget {
|
||||
topRight: Radius.circular(8),
|
||||
),
|
||||
child: AutoResizeUniversalImage(
|
||||
sn.getAttachmentUrl(data.preload!.thumbnail!.rid),
|
||||
sn.getAttachmentUrl(data.body['thumbnail']['rid']),
|
||||
fit: BoxFit.cover,
|
||||
filterQuality: FilterQuality.high,
|
||||
),
|
||||
@ -855,9 +857,13 @@ class PostShareImageWidget extends StatelessWidget {
|
||||
isRelativeDate: false,
|
||||
).padding(horizontal: 16, bottom: 8),
|
||||
if (data.type != 'article' &&
|
||||
(data.preload?.attachments?.isNotEmpty ?? false))
|
||||
(data.body['attachments']?.isNotEmpty ?? false))
|
||||
StyledWidget(AttachmentList(
|
||||
data: data.preload!.attachments!,
|
||||
data: data.body['attachments']
|
||||
?.map((e) => SnAttachment.fromJson(e))
|
||||
.cast<SnAttachment>()
|
||||
.toList() ??
|
||||
[],
|
||||
columned: true,
|
||||
fit: BoxFit.contain,
|
||||
filterQuality: FilterQuality.high,
|
||||
@ -1146,31 +1152,9 @@ class _PostHeadline extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isEnlarge) {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (data.preload?.thumbnail != null)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: AutoResizeUniversalImage(
|
||||
sn.getAttachmentUrl(data.preload!.thumbnail!.rid),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (data.body['title'] != null || (title?.isNotEmpty ?? false))
|
||||
Text(
|
||||
title ?? data.body['title'],
|
||||
@ -1255,7 +1239,7 @@ class _PostAvatar extends StatelessWidget {
|
||||
: null;
|
||||
|
||||
return GestureDetector(
|
||||
child: data.preload?.realm == null
|
||||
child: data.realm == null
|
||||
? AccountImage(
|
||||
filterQuality: filterQuality,
|
||||
content: data.publisher.avatar,
|
||||
@ -1271,7 +1255,7 @@ class _PostAvatar extends StatelessWidget {
|
||||
)
|
||||
: AccountImage(
|
||||
filterQuality: filterQuality,
|
||||
content: data.preload!.realm!.avatar,
|
||||
content: data.realm!.avatar,
|
||||
radius: isCompact ? 12 : 20,
|
||||
borderRadius: isCompact ? 4 : 8,
|
||||
badgeOffset: Offset(-6, -4),
|
||||
@ -1568,6 +1552,7 @@ class _PostContentHeader extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
if (isCompact) {
|
||||
return Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
@ -1575,7 +1560,6 @@ class _PostContentHeader extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
).bold(),
|
||||
),
|
||||
const Gap(4),
|
||||
Flexible(
|
||||
child: Text(
|
||||
isRelativeDate
|
||||
@ -1587,6 +1571,10 @@ class _PostContentHeader extends StatelessWidget {
|
||||
overflow: TextOverflow.fade,
|
||||
).fontSize(13).opacity(0.8),
|
||||
),
|
||||
if (data.editedAt != null)
|
||||
Flexible(
|
||||
child: Text('postEditedHint').tr().fontSize(13).opacity(0.8),
|
||||
)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
@ -1596,20 +1584,20 @@ class _PostContentHeader extends StatelessWidget {
|
||||
Row(
|
||||
children: [
|
||||
Text(data.publisher.nick).bold(),
|
||||
if (data.preload?.realm != null)
|
||||
if (data.realm != null)
|
||||
const Icon(Symbols.arrow_right, size: 16)
|
||||
.padding(horizontal: 2)
|
||||
.opacity(0.5),
|
||||
if (data.preload?.realm != null) Text(data.preload!.realm!.name),
|
||||
if (data.realm != null) Text(data.realm!.name),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
'@${data.publisher.name}',
|
||||
maxLines: 1,
|
||||
).fontSize(13),
|
||||
const Gap(4),
|
||||
Text(
|
||||
isRelativeDate
|
||||
? RelativeTime(context)
|
||||
@ -1619,6 +1607,8 @@ class _PostContentHeader extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.fade,
|
||||
).fontSize(13),
|
||||
if (data.editedAt != null)
|
||||
Text('postEditedHint').tr().fontSize(13),
|
||||
],
|
||||
).opacity(0.8),
|
||||
],
|
||||
@ -1648,7 +1638,11 @@ class _PostContentBody extends StatelessWidget {
|
||||
RegExp(r"^:([-\w]+):$").hasMatch(data.body['content'] ?? ''),
|
||||
textScaler: isEnlarge ? TextScaler.linear(1.1) : null,
|
||||
content: text,
|
||||
attachments: data.preload?.attachments,
|
||||
attachments: data.body['attachments']
|
||||
?.map((e) => SnAttachment.fromJson(e))
|
||||
.cast<SnAttachment>()
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
|
||||
if (isSelectable) {
|
||||
@ -1706,14 +1700,14 @@ class _PostQuoteContent extends StatelessWidget {
|
||||
],
|
||||
).padding(horizontal: 16),
|
||||
if (child.type != 'article' &&
|
||||
(child.preload?.attachments?.isNotEmpty ?? false))
|
||||
(child.body['attachments']?.isNotEmpty ?? false))
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
child: AttachmentList(
|
||||
data: child.preload!.attachments!,
|
||||
data: child.body['attachments']!,
|
||||
maxHeight: 360,
|
||||
minWidth: 640,
|
||||
fit: BoxFit.contain,
|
||||
@ -2062,8 +2056,6 @@ class _PostFeaturedCommentState extends State<_PostFeaturedComment> {
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => PostCommentListPopup(
|
||||
post: widget.data,
|
||||
commentCount: widget.data.metric.replyCount,
|
||||
@ -2352,7 +2344,7 @@ class _PostVideoPlayer extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
child: AttachmentItem(
|
||||
data: data.preload!.video!,
|
||||
data: data.body['video'],
|
||||
heroTag: 'post-video-${data.id}',
|
||||
),
|
||||
),
|
||||
|
@ -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
|
||||
# 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.
|
||||
version: 2.4.2+85
|
||||
version: 2.4.2+86
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.4
|
||||
|
Reference in New Issue
Block a user