Two column explore

This commit is contained in:
2025-05-24 02:52:31 +08:00
parent 4f9bf960d9
commit 1b544c2c8b
11 changed files with 265 additions and 137 deletions

View File

@ -6,6 +6,7 @@ import 'package:collection/collection.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -23,6 +24,7 @@ import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/post/publishers_modal.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:super_clipboard/super_clipboard.dart';
@RoutePage()
class PostEditScreen extends HookConsumerWidget {
@ -215,6 +217,47 @@ class PostComposeScreen extends HookConsumerWidget {
}
}
Future<void> _handlePaste() async {
final clipboard = SystemClipboard.instance;
if (clipboard == null) return;
final reader = await clipboard.read();
if (reader.canProvide(Formats.png)) {
reader.getFile(Formats.png, (file) async {
final stream = file.getStream();
final bytes = await stream.toList();
final imageBytes = bytes.expand((e) => e).toList();
// Create a temporary file to store the image
final tempDir = Directory.systemTemp;
final tempFile = File(
'${tempDir.path}/pasted_image_${DateTime.now().millisecondsSinceEpoch}.png',
);
await tempFile.writeAsBytes(imageBytes);
// Add the file to attachments
attachments.value = [
...attachments.value,
UniversalFile(
data: XFile(tempFile.path),
type: UniversalFileType.image,
),
];
});
}
}
void _handleKeyPress(RawKeyEvent event) {
if (event is! RawKeyDownEvent) return;
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
final isModifierPressed = event.isMetaPressed || event.isControlPressed;
if (isPaste && isModifierPressed) {
_handlePaste();
}
}
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
@ -291,17 +334,22 @@ class PostComposeScreen extends HookConsumerWidget {
FocusManager.instance.primaryFocus?.unfocus(),
),
const Gap(8),
TextField(
controller: contentController,
style: TextStyle(fontSize: 14),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'postPlaceholder'.tr(),
isDense: true,
RawKeyboardListener(
focusNode: FocusNode(),
onKey: _handleKeyPress,
child: TextField(
controller: contentController,
style: TextStyle(fontSize: 14),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'postPlaceholder'.tr(),
isDense: true,
),
onTapOutside:
(_) =>
FocusManager.instance.primaryFocus
?.unfocus(),
),
onTapOutside:
(_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
const Gap(8),
Column(

View File

@ -36,19 +36,25 @@ class PostDetailScreen extends HookConsumerWidget {
appBar: AppBar(title: const Text('Post')),
body: post.when(
data: (post) {
final content = Stack(
return Stack(
fit: StackFit.expand,
children: [
Column(
children: [
PostItem(
item: post!,
isOpenable: false,
backgroundColor: isWide ? Colors.transparent : null,
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Column(
children: [
PostItem(
item: post!,
isOpenable: false,
backgroundColor: isWide ? Colors.transparent : null,
),
const Divider(height: 1),
],
),
),
const Divider(height: 1),
Expanded(child: PostRepliesList(postId: id)),
Gap(MediaQuery.of(context).padding.bottom),
PostRepliesList(postId: id),
SliverGap(MediaQuery.of(context).padding.bottom + 80),
],
),
Positioned(
@ -67,30 +73,6 @@ class PostDetailScreen extends HookConsumerWidget {
),
],
);
return isWide
? Center(
child: Card(
elevation: 8,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
color: Theme.of(
context,
).colorScheme.surfaceContainerLow.withOpacity(0.8),
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: kWideScreenWidth - 160,
),
child: content,
),
),
)
: content;
},
loading: () => const Center(child: CircularProgressIndicator()),
error: (e, _) => Text('Error: $e'),