Compare commits
16 Commits
8a6bb34808
...
v3
Author | SHA1 | Date | |
---|---|---|---|
001549b190 | |||
4595865ad3 | |||
|
1834643167 | ||
|
0e816eaa3e | ||
|
7c1f24b824 | ||
c6594ea2ce
|
|||
3bec6e683e
|
|||
83e92e2eed
|
|||
|
b7d44d96ba | ||
a83b929d42
|
|||
9423affa75
|
|||
cda23db609
|
|||
61074bc5a3
|
|||
5feafa9255
|
|||
e604577c1f
|
|||
af0ddd1273
|
@@ -120,13 +120,24 @@ void main() async {
|
|||||||
windowButtonVisibility: true,
|
windowButtonVisibility: true,
|
||||||
);
|
);
|
||||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
|
final env = Platform.environment;
|
||||||
|
final isWayland = env.containsKey('WAYLAND_DISPLAY');
|
||||||
|
|
||||||
|
if (isWayland) {
|
||||||
|
try {
|
||||||
|
await windowManager.setAsFrameless();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[Wayland] setAsFrameless failed: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
await windowManager.setMinimumSize(defaultSize);
|
await windowManager.setMinimumSize(defaultSize);
|
||||||
await windowManager.show();
|
await windowManager.show();
|
||||||
await windowManager.focus();
|
await windowManager.focus();
|
||||||
final opacity = prefs.getDouble(kAppWindowOpacity) ?? 1.0;
|
final opacity = prefs.getDouble(kAppWindowOpacity) ?? 1.0;
|
||||||
await windowManager.setOpacity(opacity);
|
await windowManager.setOpacity(opacity);
|
||||||
talker.info(
|
talker.info(
|
||||||
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}",
|
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}"
|
||||||
|
"${isWayland ? " (Wayland frameless fix applied)" : ""}",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,6 @@ import 'package:island/screens/tabs.dart';
|
|||||||
import 'package:island/screens/explore.dart';
|
import 'package:island/screens/explore.dart';
|
||||||
import 'package:island/screens/discovery/article_detail.dart';
|
import 'package:island/screens/discovery/article_detail.dart';
|
||||||
import 'package:island/screens/account.dart';
|
import 'package:island/screens/account.dart';
|
||||||
import 'package:island/screens/notification.dart';
|
|
||||||
import 'package:island/screens/wallet.dart';
|
import 'package:island/screens/wallet.dart';
|
||||||
import 'package:island/screens/account/relationship.dart';
|
import 'package:island/screens/account/relationship.dart';
|
||||||
import 'package:island/screens/account/profile.dart';
|
import 'package:island/screens/account/profile.dart';
|
||||||
@@ -392,11 +391,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
name: 'notifications',
|
|
||||||
path: '/account/notifications',
|
|
||||||
builder: (context, state) => const NotificationScreen(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'wallet',
|
name: 'wallet',
|
||||||
path: '/account/wallet',
|
path: '/account/wallet',
|
||||||
|
@@ -282,7 +282,12 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed('notifications');
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder: (context) => const NotificationSheet(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
@@ -20,6 +20,7 @@ class ArticleDetailScreen extends ConsumerWidget {
|
|||||||
final articleAsync = ref.watch(articleDetailProvider(articleId));
|
final articleAsync = ref.watch(articleDetailProvider(articleId));
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
body: articleAsync.when(
|
body: articleAsync.when(
|
||||||
data:
|
data:
|
||||||
(article) => AppScaffold(
|
(article) => AppScaffold(
|
||||||
|
@@ -54,7 +54,12 @@ Widget notificationIndicatorWidget(
|
|||||||
trailing: const Icon(Symbols.chevron_right),
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 15),
|
contentPadding: EdgeInsets.only(left: 16, right: 15),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed('notifications');
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder: (context) => const NotificationSheet(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -3,7 +3,6 @@ import 'dart:math' as math;
|
|||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/account.dart';
|
import 'package:island/models/account.dart';
|
||||||
@@ -11,8 +10,8 @@ import 'package:island/pods/network.dart';
|
|||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@@ -113,8 +112,8 @@ class NotificationListNotifier extends _$NotificationListNotifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationScreen extends HookConsumerWidget {
|
class NotificationSheet extends HookConsumerWidget {
|
||||||
const NotificationScreen({super.key});
|
const NotificationSheet({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -128,19 +127,15 @@ class NotificationScreen extends HookConsumerWidget {
|
|||||||
ref.watch(notificationUnreadCountNotifierProvider.notifier).clear();
|
ref.watch(notificationUnreadCountNotifierProvider.notifier).clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return SheetScaffold(
|
||||||
appBar: AppBar(
|
titleText: 'notifications'.tr(),
|
||||||
leading: const PageBackButton(),
|
actions: [
|
||||||
title: const Text('notifications').tr(),
|
IconButton(
|
||||||
actions: [
|
onPressed: markAllRead,
|
||||||
IconButton(
|
icon: const Icon(Symbols.mark_as_unread),
|
||||||
onPressed: markAllRead,
|
),
|
||||||
icon: const Icon(Symbols.mark_as_unread),
|
],
|
||||||
),
|
child: PagingHelperView(
|
||||||
const Gap(8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: PagingHelperView(
|
|
||||||
provider: notificationListNotifierProvider,
|
provider: notificationListNotifierProvider,
|
||||||
futureRefreshable: notificationListNotifierProvider.future,
|
futureRefreshable: notificationListNotifierProvider.future,
|
||||||
notifierRefreshable: notificationListNotifierProvider.notifier,
|
notifierRefreshable: notificationListNotifierProvider.notifier,
|
||||||
|
@@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
import 'package:island/models/account.dart';
|
import 'package:island/models/account.dart';
|
||||||
|
import 'package:island/models/heatmap.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
@@ -20,6 +21,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
|
import 'package:island/widgets/activity_heatmap.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:island/services/color_extraction.dart';
|
import 'package:island/services/color_extraction.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@@ -222,6 +224,32 @@ class _PublisherBioWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PublisherHeatmapWidget extends StatelessWidget {
|
||||||
|
final AsyncValue<SnHeatmap?> heatmap;
|
||||||
|
final bool forceDense;
|
||||||
|
|
||||||
|
const _PublisherHeatmapWidget({
|
||||||
|
required this.heatmap,
|
||||||
|
this.forceDense = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return heatmap.when(
|
||||||
|
data:
|
||||||
|
(data) =>
|
||||||
|
data != null
|
||||||
|
? ActivityHeatmapWidget(
|
||||||
|
heatmap: data,
|
||||||
|
forceDense: forceDense,
|
||||||
|
).padding(horizontal: 8)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
loading: () => const SizedBox.shrink(),
|
||||||
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PublisherCategoryTabWidget extends StatelessWidget {
|
class _PublisherCategoryTabWidget extends StatelessWidget {
|
||||||
final TabController categoryTabController;
|
final TabController categoryTabController;
|
||||||
|
|
||||||
@@ -292,6 +320,13 @@ Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<SnHeatmap?> publisherHeatmap(Ref ref, String uname) async {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final resp = await apiClient.get('/sphere/publishers/$uname/heatmap');
|
||||||
|
return SnHeatmap.fromJson(resp.data);
|
||||||
|
}
|
||||||
|
|
||||||
class PublisherProfileScreen extends HookConsumerWidget {
|
class PublisherProfileScreen extends HookConsumerWidget {
|
||||||
final String name;
|
final String name;
|
||||||
const PublisherProfileScreen({super.key, required this.name});
|
const PublisherProfileScreen({super.key, required this.name});
|
||||||
@@ -301,6 +336,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
final publisher = ref.watch(publisherProvider(name));
|
final publisher = ref.watch(publisherProvider(name));
|
||||||
final badges = ref.watch(publisherBadgesProvider(name));
|
final badges = ref.watch(publisherBadgesProvider(name));
|
||||||
final subStatus = ref.watch(publisherSubscriptionStatusProvider(name));
|
final subStatus = ref.watch(publisherSubscriptionStatusProvider(name));
|
||||||
|
final heatmap = ref.watch(publisherHeatmapProvider(name));
|
||||||
final appbarColor = ref.watch(
|
final appbarColor = ref.watch(
|
||||||
publisherAppbarForcegroundColorProvider(name),
|
publisherAppbarForcegroundColorProvider(name),
|
||||||
);
|
);
|
||||||
@@ -446,6 +482,10 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
_PublisherVerificationWidget(data: data),
|
_PublisherVerificationWidget(data: data),
|
||||||
_PublisherBioWidget(data: data),
|
_PublisherBioWidget(data: data),
|
||||||
|
_PublisherHeatmapWidget(
|
||||||
|
heatmap: heatmap,
|
||||||
|
forceDense: true,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -517,6 +557,9 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: _PublisherBioWidget(data: data),
|
child: _PublisherBioWidget(data: data),
|
||||||
),
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: _PublisherHeatmapWidget(heatmap: heatmap),
|
||||||
|
),
|
||||||
SliverPostList(pubName: name, pinned: true),
|
SliverPostList(pubName: name, pinned: true),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: _PublisherCategoryTabWidget(
|
child: _PublisherCategoryTabWidget(
|
||||||
|
@@ -530,5 +530,126 @@ class _PublisherAppbarForcegroundColorProviderElement
|
|||||||
(origin as PublisherAppbarForcegroundColorProvider).pubName;
|
(origin as PublisherAppbarForcegroundColorProvider).pubName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$publisherHeatmapHash() => r'86db275ce3861a2855b5ec35fbfef85fc47b23a6';
|
||||||
|
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
@ProviderFor(publisherHeatmap)
|
||||||
|
const publisherHeatmapProvider = PublisherHeatmapFamily();
|
||||||
|
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
class PublisherHeatmapFamily extends Family<AsyncValue<SnHeatmap?>> {
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
const PublisherHeatmapFamily();
|
||||||
|
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
PublisherHeatmapProvider call(String uname) {
|
||||||
|
return PublisherHeatmapProvider(uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PublisherHeatmapProvider getProviderOverride(
|
||||||
|
covariant PublisherHeatmapProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'publisherHeatmapProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
class PublisherHeatmapProvider extends AutoDisposeFutureProvider<SnHeatmap?> {
|
||||||
|
/// See also [publisherHeatmap].
|
||||||
|
PublisherHeatmapProvider(String uname)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => publisherHeatmap(ref as PublisherHeatmapRef, uname),
|
||||||
|
from: publisherHeatmapProvider,
|
||||||
|
name: r'publisherHeatmapProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$publisherHeatmapHash,
|
||||||
|
dependencies: PublisherHeatmapFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PublisherHeatmapFamily._allTransitiveDependencies,
|
||||||
|
uname: uname,
|
||||||
|
);
|
||||||
|
|
||||||
|
PublisherHeatmapProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.uname,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String uname;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<SnHeatmap?> Function(PublisherHeatmapRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PublisherHeatmapProvider._internal(
|
||||||
|
(ref) => create(ref as PublisherHeatmapRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
uname: uname,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<SnHeatmap?> createElement() {
|
||||||
|
return _PublisherHeatmapProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PublisherHeatmapProvider && other.uname == uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, uname.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PublisherHeatmapRef on AutoDisposeFutureProviderRef<SnHeatmap?> {
|
||||||
|
/// The parameter `uname` of this provider.
|
||||||
|
String get uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PublisherHeatmapProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<SnHeatmap?>
|
||||||
|
with PublisherHeatmapRef {
|
||||||
|
_PublisherHeatmapProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uname => (origin as PublisherHeatmapProvider).uname;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
@@ -66,12 +66,12 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
if (wideScreen)
|
if (wideScreen)
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
label: 'creatorHub'.tr(),
|
label: 'creatorHub'.tr(),
|
||||||
icon: const Icon(Symbols.draw),
|
icon: const Icon(Symbols.ink_pen),
|
||||||
),
|
),
|
||||||
if (wideScreen)
|
if (wideScreen)
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
label: 'developerHub'.tr(),
|
label: 'developerHub'.tr(),
|
||||||
icon: const Icon(Symbols.code),
|
icon: const Icon(Symbols.data_object),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
extendBody: true,
|
extendBody: true,
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
body: ClipRRect(
|
body: ClipRRect(
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
topLeft: Radius.circular(16),
|
topLeft: Radius.circular(16),
|
||||||
|
@@ -11,8 +11,13 @@ import '../services/responsive.dart';
|
|||||||
/// Shows exactly 365 days (wide screen) or 90 days (non-wide screen) of data ending at the current date.
|
/// Shows exactly 365 days (wide screen) or 90 days (non-wide screen) of data ending at the current date.
|
||||||
class ActivityHeatmapWidget extends HookConsumerWidget {
|
class ActivityHeatmapWidget extends HookConsumerWidget {
|
||||||
final SnHeatmap heatmap;
|
final SnHeatmap heatmap;
|
||||||
|
final bool forceDense;
|
||||||
|
|
||||||
const ActivityHeatmapWidget({super.key, required this.heatmap});
|
const ActivityHeatmapWidget({
|
||||||
|
super.key,
|
||||||
|
required this.heatmap,
|
||||||
|
this.forceDense = false,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -21,7 +26,7 @@ class ActivityHeatmapWidget extends HookConsumerWidget {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
|
|
||||||
final isWide = isWideScreen(context);
|
final isWide = isWideScreen(context);
|
||||||
final days = isWide ? 365 : 90;
|
final days = (isWide && !forceDense) ? 365 : 90;
|
||||||
|
|
||||||
// Start from exactly the selected days ago
|
// Start from exactly the selected days ago
|
||||||
final startDate = now.subtract(Duration(days: days));
|
final startDate = now.subtract(Duration(days: days));
|
||||||
|
@@ -314,28 +314,22 @@ class AppScaffold extends HookConsumerWidget {
|
|||||||
|
|
||||||
final noBackground = isNoBackground ?? isWideScreen(context);
|
final noBackground = isNoBackground ?? isWideScreen(context);
|
||||||
|
|
||||||
final content = Column(
|
final builtWidget = Focus(
|
||||||
children: [
|
|
||||||
IgnorePointer(
|
|
||||||
child: SizedBox(height: appBar != null ? appBarHeight + safeTop : 0),
|
|
||||||
),
|
|
||||||
if (body != null) Expanded(child: body!),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Focus(
|
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
extendBody: extendBody ?? true,
|
extendBody: extendBody ?? true,
|
||||||
extendBodyBehindAppBar: true,
|
extendBodyBehindAppBar: true,
|
||||||
backgroundColor:
|
backgroundColor: Colors.transparent,
|
||||||
noBackground
|
body: Column(
|
||||||
? Colors.transparent
|
children: [
|
||||||
: Theme.of(context).scaffoldBackgroundColor,
|
IgnorePointer(
|
||||||
body:
|
child: SizedBox(
|
||||||
noBackground
|
height: appBar != null ? appBarHeight + safeTop : 0,
|
||||||
? content
|
),
|
||||||
: AppBackground(isRoot: true, child: content),
|
),
|
||||||
|
if (body != null) Expanded(child: body!),
|
||||||
|
],
|
||||||
|
),
|
||||||
appBar: appBar,
|
appBar: appBar,
|
||||||
bottomNavigationBar: bottomNavigationBar,
|
bottomNavigationBar: bottomNavigationBar,
|
||||||
bottomSheet: bottomSheet,
|
bottomSheet: bottomSheet,
|
||||||
@@ -348,6 +342,10 @@ class AppScaffold extends HookConsumerWidget {
|
|||||||
onEndDrawerChanged: onEndDrawerChanged,
|
onEndDrawerChanged: onEndDrawerChanged,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return noBackground
|
||||||
|
? builtWidget
|
||||||
|
: AppBackground(isRoot: true, child: builtWidget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,10 +374,10 @@ class PageBackButton extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isDesktop =
|
final hasPageAction =
|
||||||
!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows);
|
!kIsWeb && Platform.isMacOS;
|
||||||
|
|
||||||
if (isDesktop && isWideScreen(context)) return const SizedBox.shrink();
|
if (hasPageAction && isWideScreen(context)) return const SizedBox.shrink();
|
||||||
|
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
@@ -73,10 +73,8 @@ class ChatInput extends HookConsumerWidget {
|
|||||||
final chatSubscribe = ref.watch(chatSubscribeNotifierProvider(chatRoom.id));
|
final chatSubscribe = ref.watch(chatSubscribeNotifierProvider(chatRoom.id));
|
||||||
|
|
||||||
void send() {
|
void send() {
|
||||||
|
inputFocusNode.requestFocus();
|
||||||
onSend.call();
|
onSend.call();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
inputFocusNode.requestFocus();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertNewLine() {
|
void insertNewLine() {
|
||||||
@@ -539,6 +537,10 @@ class ChatInput extends HookConsumerWidget {
|
|||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) =>
|
(_) =>
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
textInputAction:
|
||||||
|
settings.enterToSend
|
||||||
|
? TextInputAction.send
|
||||||
|
: null,
|
||||||
onSubmitted:
|
onSubmitted:
|
||||||
settings.enterToSend ? (_) => send() : null,
|
settings.enterToSend ? (_) => send() : null,
|
||||||
);
|
);
|
||||||
@@ -550,11 +552,13 @@ class ChatInput extends HookConsumerWidget {
|
|||||||
final triggerIndex =
|
final triggerIndex =
|
||||||
atIndex > colonIndex ? atIndex : colonIndex;
|
atIndex > colonIndex ? atIndex : colonIndex;
|
||||||
if (triggerIndex == -1) return [];
|
if (triggerIndex == -1) return [];
|
||||||
|
final chopped = pattern.substring(triggerIndex);
|
||||||
|
if (chopped.contains(' ')) return [];
|
||||||
final service = ref.read(autocompleteServiceProvider);
|
final service = ref.read(autocompleteServiceProvider);
|
||||||
try {
|
try {
|
||||||
return await service.getSuggestions(
|
return await service.getSuggestions(
|
||||||
chatRoom.id,
|
chatRoom.id,
|
||||||
pattern,
|
chopped,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return [];
|
||||||
@@ -645,7 +649,7 @@ class ChatInput extends HookConsumerWidget {
|
|||||||
direction: VerticalDirection.up,
|
direction: VerticalDirection.up,
|
||||||
hideOnEmpty: true,
|
hideOnEmpty: true,
|
||||||
hideOnLoading: true,
|
hideOnLoading: true,
|
||||||
debounceDuration: const Duration(milliseconds: 500),
|
debounceDuration: const Duration(milliseconds: 1000),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
|
@@ -14,7 +14,6 @@ import 'package:island/pods/chat/messages_notifier.dart';
|
|||||||
import 'package:island/pods/translate.dart';
|
import 'package:island/pods/translate.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/widgets/account/account_pfc.dart';
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
|
||||||
import 'package:island/widgets/chat/message_content.dart';
|
import 'package:island/widgets/chat/message_content.dart';
|
||||||
import 'package:island/widgets/chat/message_indicators.dart';
|
import 'package:island/widgets/chat/message_indicators.dart';
|
||||||
import 'package:island/widgets/chat/message_sender_info.dart';
|
import 'package:island/widgets/chat/message_sender_info.dart';
|
||||||
@@ -666,17 +665,11 @@ class MessageItemDisplayBubble extends HookConsumerWidget {
|
|||||||
? Theme.of(context).colorScheme.primaryContainer.withOpacity(0.5)
|
? Theme.of(context).colorScheme.primaryContainer.withOpacity(0.5)
|
||||||
: Theme.of(context).colorScheme.surfaceContainer;
|
: Theme.of(context).colorScheme.surfaceContainer;
|
||||||
|
|
||||||
final hasBackground =
|
|
||||||
ref.watch(backgroundImageFileProvider).valueOrNull != null;
|
|
||||||
|
|
||||||
final remoteMessage = message.toRemoteMessage();
|
final remoteMessage = message.toRemoteMessage();
|
||||||
final sender = remoteMessage.sender;
|
final sender = remoteMessage.sender;
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
color:
|
color: Colors.transparent,
|
||||||
hasBackground
|
|
||||||
? Colors.transparent
|
|
||||||
: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@@ -23,12 +23,12 @@ class PostComposeDialog extends HookConsumerWidget {
|
|||||||
this.isBottomSheet = false,
|
this.isBottomSheet = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
static Future<SnPost?> show(
|
static Future<bool?> show(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
SnPost? originalPost,
|
SnPost? originalPost,
|
||||||
PostComposeInitialState? initialState,
|
PostComposeInitialState? initialState,
|
||||||
}) {
|
}) {
|
||||||
return showDialog<SnPost>(
|
return showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder:
|
||||||
|
@@ -149,9 +149,11 @@ class ComposeFormFields extends HookConsumerWidget {
|
|||||||
final triggerIndex =
|
final triggerIndex =
|
||||||
atIndex > colonIndex ? atIndex : colonIndex;
|
atIndex > colonIndex ? atIndex : colonIndex;
|
||||||
if (triggerIndex == -1) return [];
|
if (triggerIndex == -1) return [];
|
||||||
|
final chopped = pattern.substring(triggerIndex);
|
||||||
|
if (chopped.contains(' ')) return [];
|
||||||
final service = ref.read(autocompleteServiceProvider);
|
final service = ref.read(autocompleteServiceProvider);
|
||||||
try {
|
try {
|
||||||
return await service.getGeneralSuggestions(pattern);
|
return await service.getGeneralSuggestions(chopped);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -235,7 +237,7 @@ class ComposeFormFields extends HookConsumerWidget {
|
|||||||
direction: VerticalDirection.down,
|
direction: VerticalDirection.down,
|
||||||
hideOnEmpty: true,
|
hideOnEmpty: true,
|
||||||
hideOnLoading: true,
|
hideOnLoading: true,
|
||||||
debounceDuration: const Duration(milliseconds: 500),
|
debounceDuration: const Duration(milliseconds: 1000),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -23,6 +23,7 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
bool? pinned,
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
|
bool? includeReplies,
|
||||||
}) {
|
}) {
|
||||||
return fetch(cursor: null);
|
return fetch(cursor: null);
|
||||||
}
|
}
|
||||||
@@ -42,6 +43,7 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
if (categories != null) 'categories': categories,
|
if (categories != null) 'categories': categories,
|
||||||
if (shuffle) 'shuffle': true,
|
if (shuffle) 'shuffle': true,
|
||||||
if (pinned != null) 'pinned': pinned,
|
if (pinned != null) 'pinned': pinned,
|
||||||
|
if (includeReplies != null) 'includeReplies': includeReplies,
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
|
@@ -6,7 +6,7 @@ part of 'post_list.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$postListNotifierHash() => r'3c0a8154ded4bcd8f5456f7a4ea2e542f57efa85';
|
String _$postListNotifierHash() => r'fc139ad4df0deb67bcbb949560319f2f7fbfb503';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -38,6 +38,7 @@ abstract class _$PostListNotifier
|
|||||||
late final List<String>? tags;
|
late final List<String>? tags;
|
||||||
late final bool? pinned;
|
late final bool? pinned;
|
||||||
late final bool shuffle;
|
late final bool shuffle;
|
||||||
|
late final bool? includeReplies;
|
||||||
|
|
||||||
FutureOr<CursorPagingData<SnPost>> build({
|
FutureOr<CursorPagingData<SnPost>> build({
|
||||||
String? pubName,
|
String? pubName,
|
||||||
@@ -47,6 +48,7 @@ abstract class _$PostListNotifier
|
|||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
bool? pinned,
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
|
bool? includeReplies,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +71,7 @@ class PostListNotifierFamily
|
|||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
bool? pinned,
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
|
bool? includeReplies,
|
||||||
}) {
|
}) {
|
||||||
return PostListNotifierProvider(
|
return PostListNotifierProvider(
|
||||||
pubName: pubName,
|
pubName: pubName,
|
||||||
@@ -78,6 +81,7 @@ class PostListNotifierFamily
|
|||||||
tags: tags,
|
tags: tags,
|
||||||
pinned: pinned,
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
|
includeReplies: includeReplies,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +97,7 @@ class PostListNotifierFamily
|
|||||||
tags: provider.tags,
|
tags: provider.tags,
|
||||||
pinned: provider.pinned,
|
pinned: provider.pinned,
|
||||||
shuffle: provider.shuffle,
|
shuffle: provider.shuffle,
|
||||||
|
includeReplies: provider.includeReplies,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +132,7 @@ class PostListNotifierProvider
|
|||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
bool? pinned,
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
|
bool? includeReplies,
|
||||||
}) : this._internal(
|
}) : this._internal(
|
||||||
() =>
|
() =>
|
||||||
PostListNotifier()
|
PostListNotifier()
|
||||||
@@ -136,7 +142,8 @@ class PostListNotifierProvider
|
|||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags
|
..tags = tags
|
||||||
..pinned = pinned
|
..pinned = pinned
|
||||||
..shuffle = shuffle,
|
..shuffle = shuffle
|
||||||
|
..includeReplies = includeReplies,
|
||||||
from: postListNotifierProvider,
|
from: postListNotifierProvider,
|
||||||
name: r'postListNotifierProvider',
|
name: r'postListNotifierProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
@@ -153,6 +160,7 @@ class PostListNotifierProvider
|
|||||||
tags: tags,
|
tags: tags,
|
||||||
pinned: pinned,
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
|
includeReplies: includeReplies,
|
||||||
);
|
);
|
||||||
|
|
||||||
PostListNotifierProvider._internal(
|
PostListNotifierProvider._internal(
|
||||||
@@ -169,6 +177,7 @@ class PostListNotifierProvider
|
|||||||
required this.tags,
|
required this.tags,
|
||||||
required this.pinned,
|
required this.pinned,
|
||||||
required this.shuffle,
|
required this.shuffle,
|
||||||
|
required this.includeReplies,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
final String? pubName;
|
final String? pubName;
|
||||||
@@ -178,6 +187,7 @@ class PostListNotifierProvider
|
|||||||
final List<String>? tags;
|
final List<String>? tags;
|
||||||
final bool? pinned;
|
final bool? pinned;
|
||||||
final bool shuffle;
|
final bool shuffle;
|
||||||
|
final bool? includeReplies;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
||||||
@@ -191,6 +201,7 @@ class PostListNotifierProvider
|
|||||||
tags: tags,
|
tags: tags,
|
||||||
pinned: pinned,
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
|
includeReplies: includeReplies,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +218,8 @@ class PostListNotifierProvider
|
|||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags
|
..tags = tags
|
||||||
..pinned = pinned
|
..pinned = pinned
|
||||||
..shuffle = shuffle,
|
..shuffle = shuffle
|
||||||
|
..includeReplies = includeReplies,
|
||||||
from: from,
|
from: from,
|
||||||
name: null,
|
name: null,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
@@ -220,6 +232,7 @@ class PostListNotifierProvider
|
|||||||
tags: tags,
|
tags: tags,
|
||||||
pinned: pinned,
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
|
includeReplies: includeReplies,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -242,7 +255,8 @@ class PostListNotifierProvider
|
|||||||
other.categories == categories &&
|
other.categories == categories &&
|
||||||
other.tags == tags &&
|
other.tags == tags &&
|
||||||
other.pinned == pinned &&
|
other.pinned == pinned &&
|
||||||
other.shuffle == shuffle;
|
other.shuffle == shuffle &&
|
||||||
|
other.includeReplies == includeReplies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -255,6 +269,7 @@ class PostListNotifierProvider
|
|||||||
hash = _SystemHash.combine(hash, tags.hashCode);
|
hash = _SystemHash.combine(hash, tags.hashCode);
|
||||||
hash = _SystemHash.combine(hash, pinned.hashCode);
|
hash = _SystemHash.combine(hash, pinned.hashCode);
|
||||||
hash = _SystemHash.combine(hash, shuffle.hashCode);
|
hash = _SystemHash.combine(hash, shuffle.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, includeReplies.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
@@ -284,6 +299,9 @@ mixin PostListNotifierRef
|
|||||||
|
|
||||||
/// The parameter `shuffle` of this provider.
|
/// The parameter `shuffle` of this provider.
|
||||||
bool get shuffle;
|
bool get shuffle;
|
||||||
|
|
||||||
|
/// The parameter `includeReplies` of this provider.
|
||||||
|
bool? get includeReplies;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostListNotifierProviderElement
|
class _PostListNotifierProviderElement
|
||||||
@@ -310,6 +328,9 @@ class _PostListNotifierProviderElement
|
|||||||
bool? get pinned => (origin as PostListNotifierProvider).pinned;
|
bool? get pinned => (origin as PostListNotifierProvider).pinned;
|
||||||
@override
|
@override
|
||||||
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
|
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
|
||||||
|
@override
|
||||||
|
bool? get includeReplies =>
|
||||||
|
(origin as PostListNotifierProvider).includeReplies;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
|
@@ -68,21 +68,24 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const kInputChipHeight = 54.0;
|
||||||
|
|
||||||
return publishers.when(
|
return publishers.when(
|
||||||
data:
|
data:
|
||||||
(data) => Material(
|
(data) => Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(28),
|
||||||
child: Padding(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
|
constraints: BoxConstraints(minHeight: kInputChipHeight),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId: currentPublisher.value?.picture?.id,
|
fileId: currentPublisher.value?.picture?.id,
|
||||||
radius: 16,
|
radius: (kInputChipHeight * 0.5) - 6,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
@@ -106,11 +109,13 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
isCollapsed: true,
|
isCollapsed: true,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 12,
|
horizontal: 12,
|
||||||
vertical: 9,
|
vertical: 14,
|
||||||
),
|
),
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
),
|
),
|
||||||
style: TextStyle(fontSize: 14),
|
style: TextStyle(fontSize: 14),
|
||||||
maxLines: null,
|
minLines: 1,
|
||||||
|
maxLines: 5,
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
@@ -130,6 +135,10 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Symbols.launch, size: 20),
|
icon: const Icon(Symbols.launch, size: 20),
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: kInputChipHeight - 6,
|
||||||
|
minHeight: kInputChipHeight - 6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon:
|
icon:
|
||||||
@@ -143,6 +152,10 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
onPressed: submitting.value ? null : performAction,
|
onPressed: submitting.value ? null : performAction,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: kInputChipHeight - 6,
|
||||||
|
minHeight: kInputChipHeight - 6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
@@ -19,35 +20,37 @@ class PostRepliesSheet extends HookConsumerWidget {
|
|||||||
|
|
||||||
return SheetScaffold(
|
return SheetScaffold(
|
||||||
titleText: 'repliesCount'.plural(post.repliesCount),
|
titleText: 'repliesCount'.plural(post.repliesCount),
|
||||||
child: Column(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
// Replies list
|
CustomScrollView(
|
||||||
Expanded(
|
slivers: [
|
||||||
child: CustomScrollView(
|
PostRepliesList(
|
||||||
slivers: [
|
postId: post.id.toString(),
|
||||||
PostRepliesList(
|
onOpen: () {
|
||||||
postId: post.id.toString(),
|
Navigator.pop(context);
|
||||||
onOpen: () {
|
},
|
||||||
Navigator.pop(context);
|
),
|
||||||
},
|
SliverGap(80),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
// Quick reply section
|
|
||||||
if (user.value != null)
|
if (user.value != null)
|
||||||
PostQuickReply(
|
Positioned(
|
||||||
parent: post,
|
bottom: 0,
|
||||||
onPosted: () {
|
left: 0,
|
||||||
ref.invalidate(postRepliesNotifierProvider(post.id));
|
right: 0,
|
||||||
},
|
child: PostQuickReply(
|
||||||
onLaunch: () {
|
parent: post,
|
||||||
Navigator.of(context).pop();
|
onPosted: () {
|
||||||
},
|
ref.invalidate(postRepliesNotifierProvider(post.id));
|
||||||
).padding(
|
},
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
onLaunch: () {
|
||||||
top: 8,
|
Navigator.of(context).pop();
|
||||||
horizontal: 16,
|
},
|
||||||
|
).padding(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 16,
|
||||||
|
top: 8,
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 3.3.0+135
|
version: 3.3.0+136
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
|
Reference in New Issue
Block a user