Compare commits

...

17 Commits

Author SHA1 Message Date
LittleSheep
7c1f24b824 🔀 Merge pull request #183 from Texas0295/v3
[FIX] linux: correct Wayland window buffer mismatch by setAsFreameless()
2025-10-15 00:47:58 +08:00
c6594ea2ce 🚀 Launch 3.3.0+136 2025-10-15 00:46:34 +08:00
3bec6e683e 🐛 Fix chat input not enter to send 2025-10-15 00:42:26 +08:00
83e92e2eed Show heatmap on pub profile 2025-10-15 00:27:32 +08:00
Texas0295
b7d44d96ba [FIX] linux: correct Wayland window buffer mismatch by setAsFreameless()
Wayland (Hyprland, Sway, etc.) compositors misreport window buffer geometry
when using transparent + hidden titlebar settings.

This causes Flutter to render outside the actual visible region
and the debug banner to be cropped offscreen.

Calling windowManager.setAsFrameless() once after window creation
forces compositor to reconfigure the surface and align buffer size
with the visible client area.

No effect on X11, Windows, or macOS.

Signed-off-by: Texas0295 <kimura@texas0295.top>
2025-10-15 00:06:03 +08:00
a83b929d42 ♻️ Convert the notification to sheet 2025-10-14 23:44:07 +08:00
9423affa75 🐛 Fix bugs 2025-10-14 23:01:40 +08:00
cda23db609 🐛 Make the background image not responsive for virtual keyboard to provide better visual experience on iOS 26 2025-10-14 22:53:59 +08:00
61074bc5a3 🐛 Fix compose dialog 2025-10-14 22:53:38 +08:00
5feafa9255 💄 Optimize quick reply input again... 2025-10-14 22:48:34 +08:00
e604577c1f 💄 Optimize quick reply input 2025-10-14 22:27:51 +08:00
af0ddd1273 💄 Optimize and bug fixes in auto complete 2025-10-14 22:26:06 +08:00
8a6bb34808 🔨 Fix android build 2025-10-14 01:39:59 +08:00
4ef8445c77 ⬆️ Upgrade the dependcenies 2025-10-14 01:38:16 +08:00
ec39ad6ca3 💄 Optimizations 2025-10-14 01:37:54 +08:00
eabb3154f1 💄 Optimize card colors 2025-10-14 01:16:02 +08:00
910bf20eef 🐛 Fix mobile haven't enter to submit 2025-10-13 01:48:30 +08:00
31 changed files with 539 additions and 406 deletions

View File

@@ -25,8 +25,13 @@ android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() }
defaultConfig {
applicationId = "dev.solsynth.solian"
// You can update the following values to match your application needs.
@@ -71,16 +76,3 @@ flutter {
source = "../.."
}
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
jvmToolchain(21)
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}

View File

@@ -44,83 +44,83 @@ PODS:
- Flutter
- file_saver (0.0.1):
- Flutter
- Firebase/CoreOnly (12.2.0):
- FirebaseCore (~> 12.2.0)
- Firebase/Crashlytics (12.2.0):
- Firebase/CoreOnly (12.4.0):
- FirebaseCore (~> 12.4.0)
- Firebase/Crashlytics (12.4.0):
- Firebase/CoreOnly
- FirebaseCrashlytics (~> 12.2.0)
- Firebase/Messaging (12.2.0):
- FirebaseCrashlytics (~> 12.4.0)
- Firebase/Messaging (12.4.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 12.2.0)
- firebase_analytics (12.0.2):
- FirebaseMessaging (~> 12.4.0)
- firebase_analytics (12.0.3):
- firebase_core
- FirebaseAnalytics (= 12.2.0)
- FirebaseAnalytics (= 12.4.0)
- Flutter
- firebase_core (4.1.1):
- Firebase/CoreOnly (= 12.2.0)
- firebase_core (4.2.0):
- Firebase/CoreOnly (= 12.4.0)
- Flutter
- firebase_crashlytics (5.0.2):
- Firebase/Crashlytics (= 12.2.0)
- firebase_crashlytics (5.0.3):
- Firebase/Crashlytics (= 12.4.0)
- firebase_core
- Flutter
- firebase_messaging (16.0.2):
- Firebase/Messaging (= 12.2.0)
- firebase_messaging (16.0.3):
- Firebase/Messaging (= 12.4.0)
- firebase_core
- Flutter
- FirebaseAnalytics (12.2.0):
- FirebaseAnalytics/Default (= 12.2.0)
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseAnalytics (12.4.0):
- FirebaseAnalytics/Default (= 12.4.0)
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- FirebaseAnalytics/Default (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- GoogleAppMeasurement/Default (= 12.2.0)
- FirebaseAnalytics/Default (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleAppMeasurement/Default (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- FirebaseCore (12.2.0):
- FirebaseCoreInternal (~> 12.2.0)
- FirebaseCore (12.4.0):
- FirebaseCoreInternal (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- FirebaseCoreExtension (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseCoreInternal (12.2.0):
- FirebaseCoreExtension (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseCoreInternal (12.4.0):
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- FirebaseCrashlytics (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseRemoteConfigInterop (~> 12.2.0)
- FirebaseSessions (~> 12.2.0)
- FirebaseCrashlytics (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- FirebaseRemoteConfigInterop (~> 12.4.0)
- FirebaseSessions (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/Environment (~> 8.1)
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- FirebaseInstallations (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (12.4.0):
- FirebaseCore (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- PromisesObjC (~> 2.4)
- FirebaseMessaging (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseMessaging (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Reachability (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- nanopb (~> 3.30910.0)
- FirebaseRemoteConfigInterop (12.2.0)
- FirebaseSessions (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseCoreExtension (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseRemoteConfigInterop (12.4.0)
- FirebaseSessions (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseCoreExtension (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
@@ -157,27 +157,28 @@ PODS:
- gal (1.0.0):
- Flutter
- FlutterMacOS
- GoogleAdsOnDeviceConversion (2.3.0):
- GoogleAdsOnDeviceConversion (3.1.0):
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/Core (12.2.0):
- GoogleAppMeasurement/Core (12.4.0):
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/Default (12.2.0):
- GoogleAdsOnDeviceConversion (= 2.3.0)
- GoogleAppMeasurement/Core (= 12.2.0)
- GoogleAppMeasurement/IdentitySupport (= 12.2.0)
- GoogleAppMeasurement/Default (12.4.0):
- GoogleAdsOnDeviceConversion (~> 3.1.0)
- GoogleAppMeasurement/Core (= 12.4.0)
- GoogleAppMeasurement/IdentitySupport (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/IdentitySupport (12.2.0):
- GoogleAppMeasurement/Core (= 12.2.0)
- GoogleAppMeasurement/IdentitySupport (12.4.0):
- GoogleAppMeasurement/Core (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
@@ -486,20 +487,20 @@ SPEC CHECKSUMS:
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
firebase_analytics: 8c78ce6224e0623152379d6cc7ef3d9098477b7e
firebase_core: dfc4bd142bee4bc53a5d482397ca322c2dd3165d
firebase_crashlytics: e55dcf895eed0dd87c447dd5aff8db7f1bb8bbdb
firebase_messaging: 38c66c1184695b0c87abe51d40fc590718abed1a
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
firebase_analytics: 1d024068b1d4707d5ba7a42a12976ddf3316d835
firebase_core: 744984dbbed8b3036abf34f0b98d80f130a7e464
firebase_crashlytics: f3a9a4338ab99b67042f64e9e22e1bf349cb44ed
firebase_messaging: 82c70650c426a0a14873e1acdb9ec2b443c4e8b4
FirebaseAnalytics: 0fc2b20091f0ddd21bf73397cf8f0eb5346dc24f
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
FirebaseCrashlytics: a6ece278a837c7e88de2d9b5da0a3542f2342395
FirebaseInstallations: ae9f4902cb5bf1d0c5eaa31ec1f4e5495a0714e2
FirebaseMessaging: d33971b7bb252745ea6cd31ab190d1a1df4b8ed5
FirebaseRemoteConfigInterop: 1e31ec72b89c9924367c59bfb5ec9ab60d1d6766
FirebaseSessions: ba7c7a7ca8696a8d540eb3fe3800fbe98c79786d
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
@@ -512,8 +513,8 @@ SPEC CHECKSUMS:
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
flutter_webrtc: c3e21fc0dcd9d8eb246ae4d5256fcbeb2f5ecd22
gal: baecd024ebfd13c441269ca7404792a7152fde89
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a

View File

@@ -120,13 +120,25 @@ void main() async {
windowButtonVisibility: true,
);
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.setAsFrameless();
await windowManager.setMinimumSize(defaultSize);
await windowManager.show();
await windowManager.focus();
final opacity = prefs.getDouble(kAppWindowOpacity) ?? 1.0;
await windowManager.setOpacity(opacity);
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)" : ""}",
);
});
}

View File

@@ -114,9 +114,9 @@ final apiClientProvider = Provider<Dio>((ref) {
dio: dio,
retries: 3,
retryDelays: const [
Duration(seconds: 1),
Duration(seconds: 2),
Duration(seconds: 3),
Duration(milliseconds: 300),
Duration(milliseconds: 500),
Duration(milliseconds: 1000),
],
retryEvaluator: (err, _) => err.requestOptions.method == 'GET',
),

View File

@@ -88,6 +88,7 @@ ThemeData createAppTheme(Brightness brightness, AppSettings settings) {
color: colorScheme.surfaceContainer.withOpacity(
settings.cardTransparency,
),
elevation: settings.cardTransparency <= 1 ? 0 : null,
),
pageTransitionsTheme: PageTransitionsTheme(
builders: {

View File

@@ -282,7 +282,11 @@ class AccountScreen extends HookConsumerWidget {
],
),
onTap: () {
context.pushNamed('notifications');
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => const NotificationScreen(),
);
},
),
ListTile(

View File

@@ -20,6 +20,7 @@ class ArticleDetailScreen extends ConsumerWidget {
final articleAsync = ref.watch(articleDetailProvider(articleId));
return AppScaffold(
isNoBackground: false,
body: articleAsync.when(
data:
(article) => AppScaffold(

View File

@@ -54,7 +54,11 @@ Widget notificationIndicatorWidget(
trailing: const Icon(Symbols.chevron_right),
contentPadding: EdgeInsets.only(left: 16, right: 15),
onTap: () {
GoRouter.of(context).pushNamed('notifications');
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => const NotificationScreen(),
);
},
),
);
@@ -330,7 +334,7 @@ class ExploreScreen extends HookConsumerWidget {
),
PostFeaturedList(),
PostComposeCard(
onSubmit: (post) {
onSubmit: () {
activitiesNotifier.forceRefresh();
},
),

View File

@@ -3,7 +3,6 @@ import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.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/route.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/sheet.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:relative_time/relative_time.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -128,19 +127,15 @@ class NotificationScreen extends HookConsumerWidget {
ref.watch(notificationUnreadCountNotifierProvider.notifier).clear();
}
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
title: const Text('notifications').tr(),
return SheetScaffold(
titleText: 'notifications'.tr(),
actions: [
IconButton(
onPressed: markAllRead,
icon: const Icon(Symbols.mark_as_unread),
),
const Gap(8),
],
),
body: PagingHelperView(
child: PagingHelperView(
provider: notificationListNotifierProvider,
futureRefreshable: notificationListNotifierProvider.future,
notifierRefreshable: notificationListNotifierProvider.notifier,

View File

@@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/models/publisher.dart';
import 'package:island/models/account.dart';
import 'package:island/models/heatmap.dart';
import 'package:island/pods/config.dart';
import 'package:island/pods/network.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/markdown.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:island/services/color_extraction.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 {
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 {
final String name;
const PublisherProfileScreen({super.key, required this.name});
@@ -301,6 +336,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
final publisher = ref.watch(publisherProvider(name));
final badges = ref.watch(publisherBadgesProvider(name));
final subStatus = ref.watch(publisherSubscriptionStatusProvider(name));
final heatmap = ref.watch(publisherHeatmapProvider(name));
final appbarColor = ref.watch(
publisherAppbarForcegroundColorProvider(name),
);
@@ -446,6 +482,10 @@ class PublisherProfileScreen extends HookConsumerWidget {
),
_PublisherVerificationWidget(data: data),
_PublisherBioWidget(data: data),
_PublisherHeatmapWidget(
heatmap: heatmap,
forceDense: true,
),
],
),
),
@@ -517,6 +557,9 @@ class PublisherProfileScreen extends HookConsumerWidget {
SliverToBoxAdapter(
child: _PublisherBioWidget(data: data),
),
SliverToBoxAdapter(
child: _PublisherHeatmapWidget(heatmap: heatmap),
),
SliverPostList(pubName: name, pinned: true),
SliverToBoxAdapter(
child: _PublisherCategoryTabWidget(

View File

@@ -530,5 +530,126 @@ class _PublisherAppbarForcegroundColorProviderElement
(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: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View File

@@ -66,12 +66,12 @@ class TabsScreen extends HookConsumerWidget {
if (wideScreen)
NavigationDestination(
label: 'creatorHub'.tr(),
icon: const Icon(Symbols.draw),
icon: const Icon(Symbols.ink_pen),
),
if (wideScreen)
NavigationDestination(
label: 'developerHub'.tr(),
icon: const Icon(Symbols.code),
icon: const Icon(Symbols.data_object),
),
];
@@ -126,6 +126,7 @@ class TabsScreen extends HookConsumerWidget {
return Scaffold(
backgroundColor: Colors.transparent,
extendBody: true,
resizeToAvoidBottomInset: false,
body: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),

View File

@@ -99,7 +99,7 @@ class EventDetailsWidget extends StatelessWidget {
],
),
if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true))
Text('eventCalandarEmpty').tr(),
Text('eventCalendarEmpty').tr(),
],
).padding(vertical: 24, horizontal: 24);
}

View File

@@ -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.
class ActivityHeatmapWidget extends HookConsumerWidget {
final SnHeatmap heatmap;
final bool forceDense;
const ActivityHeatmapWidget({super.key, required this.heatmap});
const ActivityHeatmapWidget({
super.key,
required this.heatmap,
this.forceDense = false,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -21,7 +26,7 @@ class ActivityHeatmapWidget extends HookConsumerWidget {
final now = DateTime.now();
final isWide = isWideScreen(context);
final days = isWide ? 365 : 90;
final days = (isWide && !forceDense) ? 365 : 90;
// Start from exactly the selected days ago
final startDate = now.subtract(Duration(days: days));

View File

@@ -314,28 +314,22 @@ class AppScaffold extends HookConsumerWidget {
final noBackground = isNoBackground ?? isWideScreen(context);
final content = Column(
children: [
IgnorePointer(
child: SizedBox(height: appBar != null ? appBarHeight + safeTop : 0),
),
if (body != null) Expanded(child: body!),
],
);
return Focus(
final builtWidget = Focus(
focusNode: focusNode,
child: Scaffold(
extendBody: extendBody ?? true,
extendBodyBehindAppBar: true,
backgroundColor:
noBackground
? Colors.transparent
: Theme.of(context).scaffoldBackgroundColor,
body:
noBackground
? content
: AppBackground(isRoot: true, child: content),
backgroundColor: Colors.transparent,
body: Column(
children: [
IgnorePointer(
child: SizedBox(
height: appBar != null ? appBarHeight + safeTop : 0,
),
),
if (body != null) Expanded(child: body!),
],
),
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
bottomSheet: bottomSheet,
@@ -348,6 +342,10 @@ class AppScaffold extends HookConsumerWidget {
onEndDrawerChanged: onEndDrawerChanged,
),
);
return noBackground
? builtWidget
: AppBackground(isRoot: true, child: builtWidget);
}
}

View File

@@ -73,10 +73,8 @@ class ChatInput extends HookConsumerWidget {
final chatSubscribe = ref.watch(chatSubscribeNotifierProvider(chatRoom.id));
void send() {
onSend.call();
WidgetsBinding.instance.addPostFrameCallback((_) {
inputFocusNode.requestFocus();
});
onSend.call();
}
void insertNewLine() {
@@ -120,6 +118,8 @@ class ChatInput extends HookConsumerWidget {
}
}
final settings = ref.watch(appSettingsNotifierProvider);
inputFocusNode.onKeyEvent = (node, event) {
if (event is! KeyDownEvent) return KeyEventResult.ignored;
@@ -133,7 +133,7 @@ class ChatInput extends HookConsumerWidget {
return KeyEventResult.handled;
}
final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend;
final enterToSend = settings.enterToSend;
final isEnter = event.logicalKey == LogicalKeyboardKey.enter;
if (isEnter) {
@@ -467,24 +467,28 @@ class ChatInput extends HookConsumerWidget {
),
UploadMenu(
items: [
MenuItemData(
UploadMenuItemData(
Symbols.add_a_photo,
'addPhoto',
() => onPickFile(true),
),
MenuItemData(
UploadMenuItemData(
Symbols.videocam,
'addVideo',
() => onPickFile(false),
),
MenuItemData(Symbols.mic, 'addAudio', onPickAudio),
MenuItemData(
UploadMenuItemData(
Symbols.mic,
'addAudio',
onPickAudio,
),
UploadMenuItemData(
Symbols.file_upload,
'uploadFile',
onPickGeneralFile,
),
if (onLinkAttachment != null)
MenuItemData(
UploadMenuItemData(
Symbols.attach_file,
'linkAttachment',
onLinkAttachment!,
@@ -528,11 +532,17 @@ class ChatInput extends HookConsumerWidget {
? '${messageController.text.length}/4096'
: null,
),
maxLines: 3,
maxLines: 5,
minLines: 1,
onTapOutside:
(_) =>
FocusManager.instance.primaryFocus?.unfocus(),
textInputAction:
settings.enterToSend
? TextInputAction.send
: null,
onSubmitted:
settings.enterToSend ? (_) => send() : null,
);
},
suggestionsCallback: (pattern) async {
@@ -542,11 +552,13 @@ class ChatInput extends HookConsumerWidget {
final triggerIndex =
atIndex > colonIndex ? atIndex : colonIndex;
if (triggerIndex == -1) return [];
final chopped = pattern.substring(triggerIndex);
if (chopped.contains(' ')) return [];
final service = ref.read(autocompleteServiceProvider);
try {
return await service.getSuggestions(
chatRoom.id,
pattern,
chopped,
);
} catch (e) {
return [];
@@ -637,7 +649,7 @@ class ChatInput extends HookConsumerWidget {
direction: VerticalDirection.up,
hideOnEmpty: true,
hideOnLoading: true,
debounceDuration: const Duration(milliseconds: 500),
debounceDuration: const Duration(milliseconds: 1000),
),
),
IconButton(

View File

@@ -161,6 +161,7 @@ class MessageItem extends HookConsumerWidget {
clipBehavior: Clip.none,
children: [
SwipeTo(
swipeSensitivity: 15,
rightSwipeWidget: Transform.flip(
flipX: true,
child: Icon(Symbols.menu_open),
@@ -477,6 +478,8 @@ class _MessageActionSheetState extends State<MessageActionSheet> {
Navigator.pop(context);
},
),
Gap(MediaQuery.of(context).padding.bottom),
],
),
),

View File

@@ -34,9 +34,9 @@ class PostComposeCard extends HookConsumerWidget {
final SnPost? originalPost;
final PostComposeInitialState? initialState;
final VoidCallback? onCancel;
final Function(SnPost)? onSubmit;
final Function()? onSubmit;
final Function(ComposeState)? onStateChanged;
final bool isInDialog;
final bool isDialog;
const PostComposeCard({
super.key,
@@ -45,7 +45,7 @@ class PostComposeCard extends HookConsumerWidget {
this.onCancel,
this.onSubmit,
this.onStateChanged,
this.isInDialog = false,
this.isDialog = false,
});
@override
@@ -164,20 +164,19 @@ class PostComposeCard extends HookConsumerWidget {
// Reset the form for new composition
ComposeStateUtils.resetForm(state);
// Call the widget's onSubmit callback to trigger activity list refresh
// Note: onSubmit still receives the post from the return value
onSubmit?.call();
},
);
}
final maxHeight = math.min(
640.0,
MediaQuery.of(context).size.height * (isInDialog ? 0.8 : 0.72),
MediaQuery.of(context).size.height * (isDialog ? 0.8 : 0.72),
);
return Card(
margin: EdgeInsets.zero,
color: Theme.of(context).colorScheme.surfaceContainer,
color: isDialog ? Theme.of(context).colorScheme.surfaceContainer : null,
child: Container(
constraints: BoxConstraints(maxHeight: maxHeight),
child: Column(
@@ -311,7 +310,7 @@ class PostComposeCard extends HookConsumerWidget {
onTap: () {
if (state.currentPublisher.value == null) {
// No publisher loaded, guide user to create one
if (isInDialog) {
if (isDialog) {
Navigator.of(context).pop();
}
context.pushNamed('creatorNew').then((value) {
@@ -348,7 +347,7 @@ class PostComposeCard extends HookConsumerWidget {
onPublisherTap: () {
if (state.currentPublisher.value == null) {
// No publisher loaded, guide user to create one
if (isInDialog) {
if (isDialog) {
Navigator.of(context).pop();
}
context.pushNamed('creatorNew').then((

View File

@@ -23,12 +23,12 @@ class PostComposeDialog extends HookConsumerWidget {
this.isBottomSheet = false,
});
static Future<SnPost?> show(
static Future<bool?> show(
BuildContext context, {
SnPost? originalPost,
PostComposeInitialState? initialState,
}) {
return showDialog<SnPost>(
return showDialog<bool>(
context: context,
useRootNavigator: true,
builder:
@@ -74,8 +74,8 @@ class PostComposeDialog extends HookConsumerWidget {
originalPost: originalPost,
initialState: restoredInitialState.value ?? initialState,
onCancel: () => Navigator.of(context).pop(),
onSubmit: (post) => Navigator.of(context).pop(post),
isInDialog: true,
onSubmit: () => Navigator.of(context).pop(true),
isDialog: true,
),
),
);

View File

@@ -149,9 +149,11 @@ class ComposeFormFields extends HookConsumerWidget {
final triggerIndex =
atIndex > colonIndex ? atIndex : colonIndex;
if (triggerIndex == -1) return [];
final chopped = pattern.substring(triggerIndex);
if (chopped.contains(' ')) return [];
final service = ref.read(autocompleteServiceProvider);
try {
return await service.getGeneralSuggestions(pattern);
return await service.getGeneralSuggestions(chopped);
} catch (e) {
return [];
}
@@ -235,7 +237,7 @@ class ComposeFormFields extends HookConsumerWidget {
direction: VerticalDirection.down,
hideOnEmpty: true,
hideOnLoading: true,
debounceDuration: const Duration(milliseconds: 500),
debounceDuration: const Duration(milliseconds: 1000),
),
],
),

View File

@@ -16,7 +16,6 @@ import 'package:island/widgets/post/compose_shared.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:textfield_tags/textfield_tags.dart';
part 'compose_settings_sheet.g.dart';
@@ -37,98 +36,6 @@ Future<List<SnPostCategory>> postCategories(Ref ref) async {
return uniqueCategories.values.toList();
}
/// A reusable widget for tag input fields with chip display
class ChipTagInputField extends StatelessWidget {
final InputFieldValues inputFieldValues;
final String labelText;
final String hintText;
const ChipTagInputField({
super.key,
required this.inputFieldValues,
required this.labelText,
required this.hintText,
});
@override
Widget build(BuildContext context) {
return TextField(
controller: inputFieldValues.textEditingController,
focusNode: inputFieldValues.focusNode,
decoration: InputDecoration(
label: Text(labelText).tr(),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.all(16),
hintText: inputFieldValues.tags.isNotEmpty ? '' : hintText.tr(),
errorText: inputFieldValues.error,
prefixIconConstraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.8,
),
prefixIcon:
inputFieldValues.tags.isNotEmpty
? SingleChildScrollView(
controller: inputFieldValues.tagScrollController,
scrollDirection: Axis.vertical,
child: Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 8),
child: Wrap(
runSpacing: 4.0,
spacing: 4.0,
children:
inputFieldValues.tags.map<Widget>((dynamic tag) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
color: Theme.of(context).colorScheme.primary,
),
margin: const EdgeInsets.only(left: 5),
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 5.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
InkWell(
child: Text(
'#$tag',
style: TextStyle(
color:
Theme.of(
context,
).colorScheme.onPrimary,
),
),
),
const Gap(4),
InkWell(
child: const Icon(
Icons.cancel,
size: 14.0,
color: Color.fromARGB(255, 233, 233, 233),
),
onTap: () {
inputFieldValues.onTagRemoved(tag);
},
),
],
),
);
}).toList(),
),
),
)
: null,
),
onChanged: inputFieldValues.onTagChanged,
onSubmitted: inputFieldValues.onTagSubmitted,
);
}
}
class ComposeSettingsSheet extends HookConsumerWidget {
final ComposeState state;

View File

@@ -82,10 +82,10 @@ class ComposeToolbar extends HookConsumerWidget {
}
final uploadMenuItems = [
MenuItemData(Symbols.add_a_photo, 'addPhoto', pickPhotoMedia),
MenuItemData(Symbols.videocam, 'addVideo', pickVideoMedia),
MenuItemData(Symbols.mic, 'addAudio', addAudio),
MenuItemData(Symbols.file_upload, 'uploadFile', pickGeneralFile),
UploadMenuItemData(Symbols.add_a_photo, 'addPhoto', pickPhotoMedia),
UploadMenuItemData(Symbols.videocam, 'addVideo', pickVideoMedia),
UploadMenuItemData(Symbols.mic, 'addAudio', addAudio),
UploadMenuItemData(Symbols.file_upload, 'uploadFile', pickGeneralFile),
];
final colorScheme = Theme.of(context).colorScheme;

View File

@@ -334,7 +334,7 @@ class PostActionableItem extends HookConsumerWidget {
);
},
child: Material(
color: Theme.of(context).colorScheme.surfaceContainerLow,
color: Theme.of(context).cardTheme.color,
borderRadius:
borderRadius != null
? BorderRadius.all(Radius.circular(borderRadius!))

View File

@@ -23,6 +23,7 @@ class PostListNotifier extends _$PostListNotifier
List<String>? tags,
bool? pinned,
bool shuffle = false,
bool? includeReplies,
}) {
return fetch(cursor: null);
}
@@ -42,6 +43,7 @@ class PostListNotifier extends _$PostListNotifier
if (categories != null) 'categories': categories,
if (shuffle) 'shuffle': true,
if (pinned != null) 'pinned': pinned,
if (includeReplies != null) 'includeReplies': includeReplies,
};
final response = await client.get(

View File

@@ -6,7 +6,7 @@ part of 'post_list.dart';
// RiverpodGenerator
// **************************************************************************
String _$postListNotifierHash() => r'3c0a8154ded4bcd8f5456f7a4ea2e542f57efa85';
String _$postListNotifierHash() => r'fc139ad4df0deb67bcbb949560319f2f7fbfb503';
/// Copied from Dart SDK
class _SystemHash {
@@ -38,6 +38,7 @@ abstract class _$PostListNotifier
late final List<String>? tags;
late final bool? pinned;
late final bool shuffle;
late final bool? includeReplies;
FutureOr<CursorPagingData<SnPost>> build({
String? pubName,
@@ -47,6 +48,7 @@ abstract class _$PostListNotifier
List<String>? tags,
bool? pinned,
bool shuffle = false,
bool? includeReplies,
});
}
@@ -69,6 +71,7 @@ class PostListNotifierFamily
List<String>? tags,
bool? pinned,
bool shuffle = false,
bool? includeReplies,
}) {
return PostListNotifierProvider(
pubName: pubName,
@@ -78,6 +81,7 @@ class PostListNotifierFamily
tags: tags,
pinned: pinned,
shuffle: shuffle,
includeReplies: includeReplies,
);
}
@@ -93,6 +97,7 @@ class PostListNotifierFamily
tags: provider.tags,
pinned: provider.pinned,
shuffle: provider.shuffle,
includeReplies: provider.includeReplies,
);
}
@@ -127,6 +132,7 @@ class PostListNotifierProvider
List<String>? tags,
bool? pinned,
bool shuffle = false,
bool? includeReplies,
}) : this._internal(
() =>
PostListNotifier()
@@ -136,7 +142,8 @@ class PostListNotifierProvider
..categories = categories
..tags = tags
..pinned = pinned
..shuffle = shuffle,
..shuffle = shuffle
..includeReplies = includeReplies,
from: postListNotifierProvider,
name: r'postListNotifierProvider',
debugGetCreateSourceHash:
@@ -153,6 +160,7 @@ class PostListNotifierProvider
tags: tags,
pinned: pinned,
shuffle: shuffle,
includeReplies: includeReplies,
);
PostListNotifierProvider._internal(
@@ -169,6 +177,7 @@ class PostListNotifierProvider
required this.tags,
required this.pinned,
required this.shuffle,
required this.includeReplies,
}) : super.internal();
final String? pubName;
@@ -178,6 +187,7 @@ class PostListNotifierProvider
final List<String>? tags;
final bool? pinned;
final bool shuffle;
final bool? includeReplies;
@override
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
@@ -191,6 +201,7 @@ class PostListNotifierProvider
tags: tags,
pinned: pinned,
shuffle: shuffle,
includeReplies: includeReplies,
);
}
@@ -207,7 +218,8 @@ class PostListNotifierProvider
..categories = categories
..tags = tags
..pinned = pinned
..shuffle = shuffle,
..shuffle = shuffle
..includeReplies = includeReplies,
from: from,
name: null,
dependencies: null,
@@ -220,6 +232,7 @@ class PostListNotifierProvider
tags: tags,
pinned: pinned,
shuffle: shuffle,
includeReplies: includeReplies,
),
);
}
@@ -242,7 +255,8 @@ class PostListNotifierProvider
other.categories == categories &&
other.tags == tags &&
other.pinned == pinned &&
other.shuffle == shuffle;
other.shuffle == shuffle &&
other.includeReplies == includeReplies;
}
@override
@@ -255,6 +269,7 @@ class PostListNotifierProvider
hash = _SystemHash.combine(hash, tags.hashCode);
hash = _SystemHash.combine(hash, pinned.hashCode);
hash = _SystemHash.combine(hash, shuffle.hashCode);
hash = _SystemHash.combine(hash, includeReplies.hashCode);
return _SystemHash.finish(hash);
}
@@ -284,6 +299,9 @@ mixin PostListNotifierRef
/// The parameter `shuffle` of this provider.
bool get shuffle;
/// The parameter `includeReplies` of this provider.
bool? get includeReplies;
}
class _PostListNotifierProviderElement
@@ -310,6 +328,9 @@ class _PostListNotifierProviderElement
bool? get pinned => (origin as PostListNotifierProvider).pinned;
@override
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
@override
bool? get includeReplies =>
(origin as PostListNotifierProvider).includeReplies;
}
// ignore_for_file: type=lint

View File

@@ -68,21 +68,24 @@ class PostQuickReply extends HookConsumerWidget {
}
}
const kInputChipHeight = 54.0;
return publishers.when(
data:
(data) => Material(
elevation: 2,
color: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(20),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
borderRadius: BorderRadius.circular(28),
child: Container(
constraints: BoxConstraints(minHeight: kInputChipHeight),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
child: ProfilePictureWidget(
fileId: currentPublisher.value?.picture?.id,
radius: 16,
radius: (kInputChipHeight * 0.5) - 6,
),
onTap: () {
showModalBottomSheet(
@@ -106,11 +109,13 @@ class PostQuickReply extends HookConsumerWidget {
isCollapsed: true,
contentPadding: EdgeInsets.symmetric(
horizontal: 12,
vertical: 9,
vertical: 14,
),
visualDensity: VisualDensity.compact,
),
style: TextStyle(fontSize: 14),
maxLines: null,
minLines: 1,
maxLines: 5,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
@@ -130,6 +135,10 @@ class PostQuickReply extends HookConsumerWidget {
},
icon: const Icon(Symbols.launch, size: 20),
visualDensity: VisualDensity.compact,
constraints: BoxConstraints(
maxHeight: kInputChipHeight - 6,
minHeight: kInputChipHeight - 6,
),
),
IconButton(
icon:
@@ -143,6 +152,10 @@ class PostQuickReply extends HookConsumerWidget {
color: Theme.of(context).colorScheme.primary,
onPressed: submitting.value ? null : performAction,
visualDensity: VisualDensity.compact,
constraints: BoxConstraints(
maxHeight: kInputChipHeight - 6,
minHeight: kInputChipHeight - 6,
),
),
],
),

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/pods/userinfo.dart';
@@ -19,11 +20,9 @@ class PostRepliesSheet extends HookConsumerWidget {
return SheetScaffold(
titleText: 'repliesCount'.plural(post.repliesCount),
child: Column(
child: Stack(
children: [
// Replies list
Expanded(
child: CustomScrollView(
CustomScrollView(
slivers: [
PostRepliesList(
postId: post.id.toString(),
@@ -31,12 +30,15 @@ class PostRepliesSheet extends HookConsumerWidget {
Navigator.pop(context);
},
),
SliverGap(80),
],
),
),
// Quick reply section
if (user.value != null)
PostQuickReply(
Positioned(
bottom: 0,
left: 0,
right: 0,
child: PostQuickReply(
parent: post,
onPosted: () {
ref.invalidate(postRepliesNotifierProvider(post.id));
@@ -49,6 +51,7 @@ class PostRepliesSheet extends HookConsumerWidget {
top: 8,
horizontal: 16,
),
),
],
),
);

View File

@@ -2,16 +2,16 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
class MenuItemData {
class UploadMenuItemData {
final IconData icon;
final String textKey;
final VoidCallback onPressed;
const MenuItemData(this.icon, this.textKey, this.onPressed);
const UploadMenuItemData(this.icon, this.textKey, this.onPressed);
}
class UploadMenu extends StatelessWidget {
final List<MenuItemData> items;
final List<UploadMenuItemData> items;
final bool isCompact;
final Color? iconColor;
@@ -51,6 +51,7 @@ class UploadMenu extends StatelessWidget {
onPressed: item.onPressed,
leadingIcon: Icon(item.icon),
style: ButtonStyle(
visualDensity: VisualDensity.compact,
padding: WidgetStatePropertyAll(
EdgeInsets.only(left: 12, right: 16, top: 20, bottom: 20),
),

View File

@@ -13,85 +13,85 @@ PODS:
- FlutterMacOS
- file_selector_macos (0.0.1):
- FlutterMacOS
- Firebase/CoreOnly (12.2.0):
- FirebaseCore (~> 12.2.0)
- Firebase/Crashlytics (12.2.0):
- Firebase/CoreOnly (12.4.0):
- FirebaseCore (~> 12.4.0)
- Firebase/Crashlytics (12.4.0):
- Firebase/CoreOnly
- FirebaseCrashlytics (~> 12.2.0)
- Firebase/Messaging (12.2.0):
- FirebaseCrashlytics (~> 12.4.0)
- Firebase/Messaging (12.4.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 12.2.0)
- firebase_analytics (12.0.2):
- FirebaseMessaging (~> 12.4.0)
- firebase_analytics (12.0.3):
- firebase_core
- FirebaseAnalytics (= 12.2.0)
- FirebaseAnalytics (= 12.4.0)
- FlutterMacOS
- firebase_core (4.1.1):
- Firebase/CoreOnly (~> 12.2.0)
- firebase_core (4.2.0):
- Firebase/CoreOnly (~> 12.4.0)
- FlutterMacOS
- firebase_crashlytics (5.0.2):
- Firebase/CoreOnly (~> 12.2.0)
- Firebase/Crashlytics (~> 12.2.0)
- firebase_crashlytics (5.0.3):
- Firebase/CoreOnly (~> 12.4.0)
- Firebase/Crashlytics (~> 12.4.0)
- firebase_core
- FlutterMacOS
- firebase_messaging (16.0.2):
- Firebase/CoreOnly (~> 12.2.0)
- Firebase/Messaging (~> 12.2.0)
- firebase_messaging (16.0.3):
- Firebase/CoreOnly (~> 12.4.0)
- Firebase/Messaging (~> 12.4.0)
- firebase_core
- FlutterMacOS
- FirebaseAnalytics (12.2.0):
- FirebaseAnalytics/Default (= 12.2.0)
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseAnalytics (12.4.0):
- FirebaseAnalytics/Default (= 12.4.0)
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- FirebaseAnalytics/Default (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- GoogleAppMeasurement/Default (= 12.2.0)
- FirebaseAnalytics/Default (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleAppMeasurement/Default (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- FirebaseCore (12.2.0):
- FirebaseCoreInternal (~> 12.2.0)
- FirebaseCore (12.4.0):
- FirebaseCoreInternal (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- FirebaseCoreExtension (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseCoreInternal (12.2.0):
- FirebaseCoreExtension (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseCoreInternal (12.4.0):
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- FirebaseCrashlytics (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseRemoteConfigInterop (~> 12.2.0)
- FirebaseSessions (~> 12.2.0)
- FirebaseCrashlytics (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- FirebaseRemoteConfigInterop (~> 12.4.0)
- FirebaseSessions (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/Environment (~> 8.1)
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- FirebaseInstallations (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (12.4.0):
- FirebaseCore (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- PromisesObjC (~> 2.4)
- FirebaseMessaging (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseMessaging (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Reachability (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- nanopb (~> 3.30910.0)
- FirebaseRemoteConfigInterop (12.2.0)
- FirebaseSessions (12.2.0):
- FirebaseCore (~> 12.2.0)
- FirebaseCoreExtension (~> 12.2.0)
- FirebaseInstallations (~> 12.2.0)
- FirebaseRemoteConfigInterop (12.4.0)
- FirebaseSessions (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseCoreExtension (~> 12.4.0)
- FirebaseInstallations (~> 12.4.0)
- GoogleDataTransport (~> 10.1)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
@@ -118,23 +118,23 @@ PODS:
- gal (1.0.0):
- Flutter
- FlutterMacOS
- GoogleAppMeasurement/Core (12.2.0):
- GoogleAppMeasurement/Core (12.4.0):
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/Default (12.2.0):
- GoogleAdsOnDeviceConversion (= 2.3.0)
- GoogleAppMeasurement/Core (= 12.2.0)
- GoogleAppMeasurement/IdentitySupport (= 12.2.0)
- GoogleAppMeasurement/Default (12.4.0):
- GoogleAdsOnDeviceConversion (~> 3.1.0)
- GoogleAppMeasurement/Core (= 12.4.0)
- GoogleAppMeasurement/IdentitySupport (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/IdentitySupport (12.2.0):
- GoogleAppMeasurement/Core (= 12.2.0)
- GoogleAppMeasurement/IdentitySupport (12.4.0):
- GoogleAppMeasurement/Core (= 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/MethodSwizzler (~> 8.1)
- GoogleUtilities/Network (~> 8.1)
@@ -416,20 +416,20 @@ SPEC CHECKSUMS:
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
firebase_analytics: 26346c2ccb9ba410c2f33d5d34c62e6369cbbf29
firebase_core: 54fd706197e1779d510b297548eee74d3b39577c
firebase_crashlytics: 3694b4aca0849f6919244d7bbbb40615f989f46b
firebase_messaging: 658f1a6906d80faec2fb20e3aadb81af6b09e441
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
firebase_analytics: d876586269c1d8d2b3dcac085bc2d97c62abc9df
firebase_core: d81d1a44df95699ce074ae63d8cb43e9df21e142
firebase_crashlytics: 723622cc39a9fa7320585424f5864c5699893ce1
firebase_messaging: 31f412ae5a54e02d1c46d467969f7ad92c4b81ec
FirebaseAnalytics: 0fc2b20091f0ddd21bf73397cf8f0eb5346dc24f
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
FirebaseCrashlytics: a6ece278a837c7e88de2d9b5da0a3542f2342395
FirebaseInstallations: ae9f4902cb5bf1d0c5eaa31ec1f4e5495a0714e2
FirebaseMessaging: d33971b7bb252745ea6cd31ab190d1a1df4b8ed5
FirebaseRemoteConfigInterop: 1e31ec72b89c9924367c59bfb5ec9ab60d1d6766
FirebaseSessions: ba7c7a7ca8696a8d540eb3fe3800fbe98c79786d
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_local_notifications: 4bf37a31afde695b56091b4ae3e4d9c7a7e6cda0
flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284
@@ -439,7 +439,7 @@ SPEC CHECKSUMS:
flutter_webrtc: 718eae22a371cd94e5d56aa4f301443ebc5bb737
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
gal: baecd024ebfd13c441269ca7404792a7152fde89
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba

View File

@@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "23d16f00a2da8ffa997c782453c73867b0609bd90435195671a54de38a3566df"
sha256: f871a7d1b686bea1f13722aa51ab31554d05c81f47054d6de48cc8c45153508b
url: "https://pub.dev"
source: hosted
version: "1.3.62"
version: "1.3.63"
analyzer:
dependency: transitive
description:
@@ -629,90 +629,90 @@ packages:
dependency: "direct main"
description:
name: firebase_analytics
sha256: fce78440ab7b95563054039aac5e342088efed9dc009ac6f81d5cac07155d509
sha256: "3cfc4089e61e810ffb531af63cfde2c8cfd36f12dc14fdba359e623992311015"
url: "https://pub.dev"
source: hosted
version: "12.0.2"
version: "12.0.3"
firebase_analytics_platform_interface:
dependency: transitive
description:
name: firebase_analytics_platform_interface
sha256: "75bdcd2d2635c4cdcd7ec13727527751ddf2f9933e5bf1264a2387920246f3c5"
sha256: "775fc18d9b00a014362510a33f76f1f34deb30f69a64edcb41a7dfd0ebd9cf98"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
version: "5.0.3"
firebase_analytics_web:
dependency: transitive
description:
name: firebase_analytics_web
sha256: ed5767695b131cdd425ee6d49934dca80689d9df40609c0d0aa8907ee6f0f785
sha256: "6eafa8fef5fdca6c922ac3e353c9a093c12344a3ba996e65fd40f8db0a00d26f"
url: "https://pub.dev"
source: hosted
version: "0.6.0+2"
version: "0.6.0+3"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "4dd96f05015c0dcceaa47711394c32971aee70169625d5e2477e7676c01ce0ee"
sha256: "132e1c311bc41e7d387b575df0aacdf24efbf4930365eb61042be5bde3978f03"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
version: "4.2.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: "5873a370f0d232918e23a5a6137dbe4c2c47cf017301f4ea02d9d636e52f60f0"
sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64
url: "https://pub.dev"
source: hosted
version: "6.0.1"
version: "6.0.2"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: "61a51037312dac781f713308903bb7a1762a7f92f7bc286a3a0947fb2a713b82"
sha256: ecde2def458292404a4fcd3731ee4992fd631a0ec359d2d67c33baa8da5ec8ae
url: "https://pub.dev"
source: hosted
version: "3.1.1"
version: "3.2.0"
firebase_crashlytics:
dependency: "direct main"
description:
name: firebase_crashlytics
sha256: a636096df0d2a4bc72397bfc669a4fffc8896016a58de1a6f45a49d9ba064f94
sha256: "2f53d0d3c0875105b166f09bdf026026bb74f26930c6ffcd5d65b311ca5a9f58"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
version: "5.0.3"
firebase_crashlytics_platform_interface:
dependency: transitive
description:
name: firebase_crashlytics_platform_interface
sha256: "1ccad077a6fc7bace97d8eace263f42e66dc23a23a839de864a4f10ac4a7c264"
sha256: de5c857525fc9576cd3fc30fc72422bc2371179ecae110246c0135ae896c6de3
url: "https://pub.dev"
source: hosted
version: "3.8.13"
version: "3.8.14"
firebase_messaging:
dependency: "direct main"
description:
name: firebase_messaging
sha256: ba12ad0b600e0c939fbb9391e1cd3320a5b5dad5284276b9182fc21eb1e72c2b
sha256: "5021279acd1cb5ccaceaa388e616e82cc4a2e4d862f02637df0e8ab766e6900a"
url: "https://pub.dev"
source: hosted
version: "16.0.2"
version: "16.0.3"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
sha256: b4bade67bfc09fcc56eb012b3fc72b59ca9e2259a34cdfb81b368169770ff536
sha256: f3a16c51f02055ace2a7c16ccb341c1f1b36b67c13270a48bcef68c1d970bbe8
url: "https://pub.dev"
source: hosted
version: "4.7.2"
version: "4.7.3"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
sha256: "8ae4a00d178993feb79603cad324b53696375cbb78805e8eb603fe331866629d"
sha256: "3eb9a1382caeb95b370f21e36d4a460496af777c9c2ef5df9b90d4803982c069"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
version: "4.0.3"
fixnum:
dependency: transitive
description:
@@ -770,10 +770,10 @@ packages:
dependency: "direct main"
description:
name: flutter_card_swiper
sha256: "1eacbfab31b572223042e03409726553aec431abe48af48c8d591d376d070d3d"
sha256: "9fbe75c913c0a01f34f9f98068ad198e396695fcf8abfa433cc53652fceb5617"
url: "https://pub.dev"
source: hosted
version: "7.0.2"
version: "7.1.0"
flutter_colorpicker:
dependency: "direct main"
description:
@@ -1992,10 +1992,11 @@ packages:
receive_sharing_intent:
dependency: "direct main"
description:
name: receive_sharing_intent
sha256: ec76056e4d258ad708e76d85591d933678625318e411564dcb9059048ca3a593
url: "https://pub.dev"
source: hosted
path: "."
ref: master
resolved-ref: "2cea396843cd3ab1b5ec4334be4233864637874e"
url: "https://github.com/KasemJaffer/receive_sharing_intent"
source: git
version: "1.8.1"
record:
dependency: "direct main"
@@ -2430,10 +2431,10 @@ packages:
dependency: transitive
description:
name: sqlite3
sha256: "809bc27297bd0633ef360a7e27e056e93a2ef598079616db97b0c93e275f6d31"
sha256: f18fd9a72d7a1ad2920db61368f2a69368f1cc9b56b8233e9d83b47b0a8435aa
url: "https://pub.dev"
source: hosted
version: "2.9.2"
version: "2.9.3"
sqlite3_flutter_libs:
dependency: transitive
description:
@@ -2674,15 +2675,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.6"
textfield_tags:
dependency: "direct main"
description:
path: "."
ref: "fixes/allow-controller-re-registration"
resolved-ref: "7574e79649e34df1c3cc0c49b2f0cc2b92de6a7b"
url: "https://github.com/lionelmennig/textfield_tags.git"
source: git
version: "3.0.1"
timezone:
dependency: "direct main"
description:

View File

@@ -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: 3.3.0+135
version: 3.3.0+136
environment:
sdk: ^3.7.2
@@ -78,9 +78,9 @@ dependencies:
image_picker_android: ^0.8.13+4
super_context_menu: ^0.9.1
modal_bottom_sheet: ^3.0.0
firebase_messaging: ^16.0.2
firebase_messaging: ^16.0.3
flutter_udid: ^4.0.0
firebase_core: ^4.1.1
firebase_core: ^4.2.0
web_socket_channel: ^3.0.3
material_symbols_icons: ^4.2874.0
drift: ^2.28.2
@@ -121,12 +121,12 @@ dependencies:
flutter_secure_storage: ^9.2.4
flutter_math_fork: ^0.7.4
share_plus: ^12.0.0
receive_sharing_intent: ^1.8.1
top_snackbar_flutter: ^3.3.0
textfield_tags:
# https://github.com/KasemJaffer/receive_sharing_intent/pull/333
receive_sharing_intent:
git:
url: https://github.com/lionelmennig/textfield_tags.git
ref: fixes/allow-controller-re-registration
url: https://github.com/KasemJaffer/receive_sharing_intent
ref: master
top_snackbar_flutter: ^3.3.0
mime: ^2.0.0
html2md: ^1.3.2
flutter_typeahead: ^5.2.0
@@ -134,11 +134,11 @@ dependencies:
flutter_app_update: ^3.2.2
archive: ^4.0.7
process_run: ^1.2.4
firebase_crashlytics: ^5.0.2
firebase_analytics: ^12.0.2
firebase_crashlytics: ^5.0.3
firebase_analytics: ^12.0.3
material_color_utilities: ^0.11.1
screenshot: ^3.0.0
flutter_card_swiper: ^7.0.2
flutter_card_swiper: ^7.1.0
file_saver: ^0.3.1
tray_manager: ^0.5.1
flutter_webrtc: ^1.2.0