♻️ Optimized large screen display post effect
✨ Push notification
This commit is contained in:
@ -12,6 +12,7 @@ import 'package:responsive_framework/responsive_framework.dart';
|
||||
import 'package:surface/firebase_options.dart';
|
||||
import 'package:surface/providers/channel.dart';
|
||||
import 'package:surface/providers/navigation.dart';
|
||||
import 'package:surface/providers/notification.dart';
|
||||
import 'package:surface/providers/sn_attachment.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/theme.dart';
|
||||
@ -73,6 +74,7 @@ class SolianApp extends StatelessWidget {
|
||||
Provider(create: (ctx) => SnAttachmentProvider(ctx)),
|
||||
Provider(create: (ctx) => UserDirectoryProvider(ctx)),
|
||||
ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)),
|
||||
ChangeNotifierProvider(create: (ctx) => NotificationProvider(ctx)),
|
||||
ChangeNotifierProvider(create: (ctx) => WebSocketProvider(ctx)),
|
||||
ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)),
|
||||
],
|
||||
|
58
lib/providers/notification.dart
Normal file
58
lib/providers/notification.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_udid/flutter_udid.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/userinfo.dart';
|
||||
import 'package:surface/providers/websocket.dart';
|
||||
|
||||
class NotificationProvider extends ChangeNotifier {
|
||||
late final SnNetworkProvider _sn;
|
||||
late final UserProvider _ua;
|
||||
late final WebSocketProvider _ws;
|
||||
|
||||
NotificationProvider(BuildContext context) {
|
||||
_sn = context.read<SnNetworkProvider>();
|
||||
_ua = context.read<UserProvider>();
|
||||
_ws = context.read<WebSocketProvider>();
|
||||
}
|
||||
|
||||
Future<void> registerPushNotifications() async {
|
||||
if (kIsWeb) return;
|
||||
if (!_ua.isAuthorized) return;
|
||||
|
||||
late final String? token;
|
||||
late final String provider;
|
||||
var deviceUuid = await FlutterUdid.consistentUdid;
|
||||
|
||||
if (deviceUuid.isEmpty) {
|
||||
log("Unable to active push notifications, couldn't get device uuid");
|
||||
return;
|
||||
} else {
|
||||
log('Device UUID is $deviceUuid');
|
||||
log('Registering device push notifications...');
|
||||
}
|
||||
|
||||
if (Platform.isIOS || Platform.isMacOS) {
|
||||
provider = 'apple';
|
||||
token = await FirebaseMessaging.instance.getAPNSToken();
|
||||
} else {
|
||||
provider = 'firebase';
|
||||
token = await FirebaseMessaging.instance.getToken();
|
||||
}
|
||||
log('Device Push Token is $token');
|
||||
|
||||
await _sn.client.post(
|
||||
'/cgi/id/notifications/subscribe',
|
||||
data: {
|
||||
'provider': provider,
|
||||
'device_token': token,
|
||||
'device_id': deviceUuid,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import 'package:gap/gap.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_attachment.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/types/post.dart';
|
||||
@ -174,10 +173,7 @@ class _ExploreScreenState extends State<ExploreScreen> {
|
||||
onFetchData: _fetchPosts,
|
||||
itemBuilder: (context, idx) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 640),
|
||||
child: PostItem(data: _posts[idx]),
|
||||
).center(),
|
||||
child: PostItem(data: _posts[idx], maxWidth: 640),
|
||||
onTap: () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'postDetail',
|
||||
|
@ -30,7 +30,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
final nav = context.watch<NavigationProvider>();
|
||||
|
||||
final backgroundColor = ResponsiveBreakpoints.of(context).largerThan(MOBILE)
|
||||
? Theme.of(context).colorScheme.surface
|
||||
? Colors.transparent
|
||||
: null;
|
||||
|
||||
return ListenableBuilder(
|
||||
@ -57,7 +57,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
).padding(
|
||||
horizontal: 32,
|
||||
top: MediaQuery.of(context).padding.top > 16 ? 8 : 16,
|
||||
bottom: 16,
|
||||
bottom: 8,
|
||||
),
|
||||
...destinations.where((ele) => ele.isPinned).map((ele) {
|
||||
return NavigationDrawerDestination(
|
||||
|
@ -95,12 +95,10 @@ class PostCommentSliverListState extends State<PostCommentSliverList> {
|
||||
onFetchData: _fetchPosts,
|
||||
itemBuilder: (context, idx) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: widget.maxWidth ?? double.infinity,
|
||||
),
|
||||
child: PostItem(data: _posts[idx]),
|
||||
).center(),
|
||||
child: PostItem(
|
||||
data: _posts[idx],
|
||||
maxWidth: widget.maxWidth,
|
||||
),
|
||||
onTap: () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'postDetail',
|
||||
|
@ -18,12 +18,14 @@ class PostItem extends StatelessWidget {
|
||||
final SnPost data;
|
||||
final bool showReactions;
|
||||
final bool showComments;
|
||||
final double? maxWidth;
|
||||
final Function(SnPost data)? onChanged;
|
||||
const PostItem({
|
||||
super.key,
|
||||
required this.data,
|
||||
this.showReactions = true,
|
||||
this.showComments = true,
|
||||
this.maxWidth,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@ -34,14 +36,23 @@ class PostItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_PostContentHeader(data: data).padding(horizontal: 12, vertical: 8),
|
||||
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
||||
if (data.repostTo != null)
|
||||
_PostQuoteContent(child: data.repostTo!).padding(
|
||||
horizontal: 12,
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
||||
child: Column(
|
||||
children: [
|
||||
_PostContentHeader(data: data)
|
||||
.padding(horizontal: 12, vertical: 8),
|
||||
_PostContentBody(data: data.body)
|
||||
.padding(horizontal: 16, bottom: 6),
|
||||
if (data.repostTo != null)
|
||||
_PostQuoteContent(child: data.repostTo!).padding(
|
||||
horizontal: 12,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (data.preload?.attachments?.isNotEmpty ?? true)
|
||||
AttachmentList(
|
||||
data: data.preload!.attachments!,
|
||||
@ -49,12 +60,19 @@ class PostItem extends StatelessWidget {
|
||||
maxHeight: 520,
|
||||
listPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
),
|
||||
_PostBottomAction(
|
||||
data: data,
|
||||
showComments: showComments,
|
||||
showReactions: showReactions,
|
||||
onChanged: _onChanged,
|
||||
).padding(left: 12, right: 18),
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
||||
child: Column(
|
||||
children: [
|
||||
_PostBottomAction(
|
||||
data: data,
|
||||
showComments: showComments,
|
||||
showReactions: showReactions,
|
||||
onChanged: _onChanged,
|
||||
).padding(left: 12, right: 18),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user