🐛 Dozen of hot fixes
This commit is contained in:
@ -7,6 +7,7 @@ import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker_android/image_picker_android.dart';
|
||||
@ -158,6 +159,28 @@ class IslandApp extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
||||
|
||||
Future<void> handleInitialLink() async {
|
||||
final String? link = await channel.invokeMethod('initialLink');
|
||||
if (link != null) {
|
||||
final router = ref.read(routerProvider);
|
||||
router.go(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||
handleInitialLink();
|
||||
}
|
||||
|
||||
channel.setMethodCallHandler((call) async {
|
||||
if (call.method == 'newLink') {
|
||||
final String link = call.arguments;
|
||||
final router = ref.read(routerProvider);
|
||||
router.go(link);
|
||||
}
|
||||
});
|
||||
|
||||
// When the app is opened from a terminated state.
|
||||
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
||||
if (message != null) {
|
||||
|
@ -79,33 +79,37 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
return EventCalanderScreen(name: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/creators',
|
||||
builder: (context, state) => const CreatorHubScreen(),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => CreatorHubShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':name/posts',
|
||||
path: '/creators',
|
||||
builder: (context, state) => const CreatorHubScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/creators/:name/posts',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return CreatorPostListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers',
|
||||
path: '/creators/:name/stickers',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return StickersScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers/new',
|
||||
path: '/creators/:name/stickers/new',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return NewStickerPacksScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers/:packId/edit',
|
||||
path: '/creators/:name/stickers/:packId/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final packId = state.pathParameters['packId']!;
|
||||
@ -113,7 +117,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers/:packId',
|
||||
path: '/creators/:name/stickers/:packId',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final packId = state.pathParameters['packId']!;
|
||||
@ -121,14 +125,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers/:packId/new',
|
||||
path: '/creators/:name/stickers/:packId/new',
|
||||
builder: (context, state) {
|
||||
final packId = state.pathParameters['packId']!;
|
||||
return NewStickersScreen(packId: packId);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/stickers/:packId/:id/edit',
|
||||
path: '/creators/:name/stickers/:packId/:id/edit',
|
||||
builder: (context, state) {
|
||||
final packId = state.pathParameters['packId']!;
|
||||
final id = state.pathParameters['id']!;
|
||||
@ -136,11 +140,11 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: 'new',
|
||||
path: '/creators/new',
|
||||
builder: (context, state) => const NewPublisherScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name/edit',
|
||||
path: '/creators/:name/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return EditPublisherScreen(name: name);
|
||||
@ -173,56 +177,64 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
},
|
||||
routes: [
|
||||
// Explore tab
|
||||
GoRoute(
|
||||
path: '/',
|
||||
builder: (context, state) => const ExploreScreen(),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => ExploreShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'posts/:id',
|
||||
path: '/',
|
||||
builder: (context, state) => const ExploreScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/posts/:id',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return PostDetailScreen(id: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: 'publishers/:name',
|
||||
path: '/publishers/:name',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return PublisherProfileScreen(name: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: 'discovery/realms',
|
||||
path: '/discovery/realms',
|
||||
builder: (context, state) => const DiscoveryRealmsScreen(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Chat tab
|
||||
GoRoute(
|
||||
path: '/chat',
|
||||
builder: (context, state) => const ChatListScreen(),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => ChatShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'new',
|
||||
path: '/chat',
|
||||
builder: (context, state) => const ChatListScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/chat/new',
|
||||
builder: (context, state) => const NewChatScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: ':id',
|
||||
path: '/chat/:id',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return ChatRoomScreen(id: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':id/edit',
|
||||
path: '/chat/:id/edit',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return EditChatScreen(id: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: ':id/detail',
|
||||
path: '/chat/:id/detail',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return ChatDetailScreen(id: id);
|
||||
@ -258,39 +270,43 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
),
|
||||
|
||||
// Account tab
|
||||
GoRoute(
|
||||
path: '/account',
|
||||
builder: (context, state) => const AccountScreen(),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => AccountShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'notifications',
|
||||
path: '/account',
|
||||
builder: (context, state) => const AccountScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/account/notifications',
|
||||
builder: (context, state) => const NotificationScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'wallet',
|
||||
path: '/account/wallet',
|
||||
builder: (context, state) => const WalletScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'relationships',
|
||||
path: '/account/relationships',
|
||||
builder: (context, state) => const RelationshipScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: ':name',
|
||||
path: '/account/:name',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return AccountProfileScreen(name: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: 'me/update',
|
||||
path: '/account/me/update',
|
||||
builder: (context, state) => const UpdateProfileScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'me/leveling',
|
||||
path: '/account/me/leveling',
|
||||
builder: (context, state) => const LevelingScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'settings',
|
||||
path: '/account/settings',
|
||||
builder: (context, state) => const AccountSettingsScreen(),
|
||||
),
|
||||
],
|
||||
|
@ -143,7 +143,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
progress: user.value!.profile.levelingProgress,
|
||||
),
|
||||
onTap: () {
|
||||
context.push('/account/leveling');
|
||||
context.push('/account/me/leveling');
|
||||
},
|
||||
).padding(horizontal: 12),
|
||||
Row(
|
||||
@ -210,7 +210,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('wallet').tr(),
|
||||
onTap: () {
|
||||
context.push('/wallet');
|
||||
context.push('/account/wallet');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
|
@ -53,17 +53,21 @@ Future<List<SnAccountBadge>> accountBadges(Ref ref, String uname) async {
|
||||
|
||||
@riverpod
|
||||
Future<Color?> accountAppbarForcegroundColor(Ref ref, String uname) async {
|
||||
final account = await ref.watch(accountProvider(uname).future);
|
||||
if (account.profile.background == null) return null;
|
||||
final palette = await PaletteGenerator.fromImageProvider(
|
||||
CloudImageWidget.provider(
|
||||
fileId: account.profile.background!.id,
|
||||
serverUrl: ref.watch(serverUrlProvider),
|
||||
),
|
||||
);
|
||||
final dominantColor = palette.dominantColor?.color;
|
||||
if (dominantColor == null) return null;
|
||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||
try {
|
||||
final account = await ref.watch(accountProvider(uname).future);
|
||||
if (account.profile.background == null) return null;
|
||||
final palette = await PaletteGenerator.fromImageProvider(
|
||||
CloudImageWidget.provider(
|
||||
fileId: account.profile.background!.id,
|
||||
serverUrl: ref.watch(serverUrlProvider),
|
||||
),
|
||||
);
|
||||
final dominantColor = palette.dominantColor?.color;
|
||||
if (dominantColor == null) return null;
|
||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
|
@ -4,19 +4,18 @@ import 'dart:math' as math;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/websocket.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/route.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/markdown.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
part 'notification.g.dart';
|
||||
|
||||
@ -180,36 +179,17 @@ class NotificationScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
if (notification.meta['link'] is String) {
|
||||
final href = notification.meta['link'];
|
||||
final uri = Uri.tryParse(href);
|
||||
if (uri == null) {
|
||||
showSnackBar(
|
||||
'brokenLink'.tr(args: []),
|
||||
action: SnackBarAction(
|
||||
label: 'copyToClipboard'.tr(),
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: href));
|
||||
clearSnackBar(context);
|
||||
},
|
||||
),
|
||||
if (notification.meta['action_uri'] != null) {
|
||||
var uri = notification.meta['action_uri'] as String;
|
||||
if (uri.startsWith('/')) {
|
||||
// In-app routes
|
||||
rootNavigatorKey.currentContext?.push(
|
||||
notification.meta['action_uri'],
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
// External URLs
|
||||
launchUrlString(uri);
|
||||
}
|
||||
if (uri.scheme == 'solian') {
|
||||
context.push(
|
||||
['', uri.host, ...uri.pathSegments].join('/'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
showConfirmAlert(
|
||||
'openLinkConfirmDescription'.tr(args: [href]),
|
||||
'openLinkConfirm'.tr(),
|
||||
).then((value) {
|
||||
if (value) {
|
||||
launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
Reference in New Issue
Block a user