Add file from ID

🐛 Fix explore unauthorized render error on large screen
This commit is contained in:
2025-07-28 02:01:36 +08:00
parent 5ecd39b6a9
commit d8cd33e79a
6 changed files with 157 additions and 26 deletions

View File

@@ -147,6 +147,10 @@
"addVideo": "Add video", "addVideo": "Add video",
"addPhoto": "Add photo", "addPhoto": "Add photo",
"addFile": "Add file", "addFile": "Add file",
"addAttachmentById": "Add Attachment by ID",
"enterFileId": "Enter File ID",
"fileIdCannotBeEmpty": "File ID cannot be empty",
"failedToFetchFile": "Failed to fetch file: {}",
"createDirectMessage": "Send new DM", "createDirectMessage": "Send new DM",
"gotoDirectMessage": "Go to DM", "gotoDirectMessage": "Go to DM",
"react": "React", "react": "React",

View File

@@ -123,6 +123,10 @@
"addVideo": "添加视频", "addVideo": "添加视频",
"addPhoto": "添加照片", "addPhoto": "添加照片",
"addFile": "添加文件", "addFile": "添加文件",
"addAttachmentById": "通过 ID 添加附件",
"enterFileId": "输入文件 ID",
"fileIdCannotBeEmpty": "文件 ID 不能为空",
"failedToFetchFile": "获取文件失败: {}",
"createDirectMessage": "创建新私人消息", "createDirectMessage": "创建新私人消息",
"gotoDirectMessage": "前往私信", "gotoDirectMessage": "前往私信",
"react": "反应", "react": "反应",

View File

@@ -123,6 +123,10 @@
"addVideo": "新增影片", "addVideo": "新增影片",
"addPhoto": "新增照片", "addPhoto": "新增照片",
"addFile": "新增檔案", "addFile": "新增檔案",
"addAttachmentById": "透過 ID 新增附件",
"enterFileId": "輸入檔案 ID",
"fileIdCannotBeEmpty": "檔案 ID 不能為空",
"failedToFetchFile": "無法取得檔案: {}",
"createDirectMessage": "建立新私人訊息", "createDirectMessage": "建立新私人訊息",
"gotoDirectMessage": "Go to DM", "gotoDirectMessage": "Go to DM",
"react": "反應", "react": "反應",

View File

@@ -84,6 +84,8 @@ class ExploreScreen extends HookConsumerWidget {
selectedDay.value = day; selectedDay.value = day;
} }
final user = ref.watch(userInfoProvider);
return AppScaffold( return AppScaffold(
noBackground: false, noBackground: false,
appBar: AppBar( appBar: AppBar(
@@ -198,36 +200,60 @@ class ExploreScreen extends HookConsumerWidget {
children: [ children: [
Flexible(flex: 3, child: bodyView), Flexible(flex: 3, child: bodyView),
const VerticalDivider(width: 1), const VerticalDivider(width: 1),
Flexible( if (user.value != null)
flex: 2, Flexible(
child: SingleChildScrollView( flex: 2,
child: Column( child: SingleChildScrollView(
children: [ child: Column(
CheckInWidget(), children: [
Card( CheckInWidget(),
margin: EdgeInsets.only(left: 16, right: 16, top: 8), Card(
child: Column( margin: EdgeInsets.only(
children: [ left: 16,
// Use the reusable EventCalendarWidget right: 16,
EventCalendarWidget( top: 8,
events: events, ),
initialDate: now, child: Column(
showEventDetails: true, children: [
onMonthChanged: onMonthChanged, // Use the reusable EventCalendarWidget
onDaySelected: onDaySelected, EventCalendarWidget(
), events: events,
], initialDate: now,
showEventDetails: true,
onMonthChanged: onMonthChanged,
onDaySelected: onDaySelected,
),
],
),
), ),
), FortuneGraphWidget(
FortuneGraphWidget( events: events,
events: events, constrainWidth: true,
constrainWidth: true, onPointSelected: onDaySelected,
onPointSelected: onDaySelected, ),
],
),
),
)
else
Flexible(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Welcome to\nthe Solar Network',
style: Theme.of(context).textTheme.titleLarge,
).bold(),
const Gap(2),
Text(
'Login to explore more!',
style: Theme.of(context).textTheme.bodyLarge,
), ),
], ],
), ).padding(horizontal: 36, vertical: 16),
), ),
),
], ],
); );
} }

View File

@@ -469,6 +469,11 @@ class PostComposeScreen extends HookConsumerWidget {
icon: const Icon(Symbols.videocam), icon: const Icon(Symbols.videocam),
color: colorScheme.primary, color: colorScheme.primary,
), ),
IconButton(
onPressed: () => ComposeLogic.addAttachmentById(ref, state, context),
icon: const Icon(Symbols.attach_file),
color: colorScheme.primary,
),
], ],
).padding( ).padding(
bottom: MediaQuery.of(context).padding.bottom + 16, bottom: MediaQuery.of(context).padding.bottom + 16,

View File

@@ -392,6 +392,94 @@ class ComposeLogic {
]; ];
} }
static Future<void> addAttachmentById(
WidgetRef ref,
ComposeState state,
BuildContext context,
) async {
final TextEditingController idController = TextEditingController();
String? errorMessage;
await showDialog(
context: context,
builder: (BuildContext dialogContext) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text('addAttachmentById'.tr()),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: idController,
decoration: InputDecoration(
hintText: 'enterFileId'.tr(),
errorText: errorMessage,
),
),
],
),
actions: <Widget>[
TextButton(
child: Text('cancel'.tr()),
onPressed: () {
Navigator.of(dialogContext).pop();
},
),
TextButton(
child: Text('add'.tr()),
onPressed: () async {
final fileId = idController.text.trim();
if (fileId.isEmpty) {
setState(() {
errorMessage = 'fileIdCannotBeEmpty'.tr();
});
return;
}
try {
final client = ref.read(apiClientProvider);
final response = await client.get(
'/drive/files/$fileId/info',
);
final SnCloudFile cloudFile = SnCloudFile.fromJson(
response.data,
);
state.attachments.value = [
...state.attachments.value,
UniversalFile(
data: cloudFile,
type: switch (cloudFile.mimeType
?.split('/')
.firstOrNull) {
'image' => UniversalFileType.image,
'video' => UniversalFileType.video,
'audio' => UniversalFileType.audio,
_ => UniversalFileType.file,
},
),
];
if (context.mounted) {
Navigator.of(dialogContext).pop();
}
} catch (e) {
setState(() {
errorMessage = 'failedToFetchFile'.tr(
args: [e.toString()],
);
});
}
},
),
],
);
},
);
},
);
}
static Future<void> uploadAttachment( static Future<void> uploadAttachment(
WidgetRef ref, WidgetRef ref,
ComposeState state, ComposeState state,