Skip to content

Commit

Permalink
フォルダとファイルを移動できるように
Browse files Browse the repository at this point in the history
  • Loading branch information
poppingmoon committed Oct 23, 2023
1 parent c5c8a06 commit 0cbefc8
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 11 deletions.
20 changes: 19 additions & 1 deletion lib/router/app_router.gr.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions lib/state_notifier/drive_page/drive_files_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/model/pagination_state.dart';
import 'package:miria/providers.dart';
import 'package:misskey_dart/misskey_dart.dart';

class DriveFilesNotifier extends AutoDisposeFamilyNotifier<
Expand Down Expand Up @@ -110,4 +111,33 @@ class DriveFilesNotifier extends AutoDisposeFamilyNotifier<
items: state.map((file) => file.id == fileId ? response : file).toList(),
);
}

Future<void> move({
required String fileId,
required String? folderId,
}) async {
if (folderId == _folderId) {
return;
}
// folderIdがnullのときキーが削除されるのを回避
final response = await _misskey.apiService.post<Map<String, dynamic>>(
"drive/files/update",
{
"fileId": fileId,
"folderId": folderId,
},
excludeRemoveNullPredicate: (key, _) => key == "folderId",
);
final file = DriveFile.fromJson(response);
state = state.copyWith(
items: state.where((file) => file.id != fileId).toList(),
);
ref
.read(driveFilesNotifierProvider((_misskey, folderId)).notifier)
.add(file);
}

void add(DriveFile file) {
state = state.copyWith(items: [file, ...state]);
}
}
30 changes: 30 additions & 0 deletions lib/state_notifier/drive_page/drive_folders_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/model/pagination_state.dart';
import 'package:miria/providers.dart';
import 'package:misskey_dart/misskey_dart.dart';

class DriveFoldersNotifier extends AutoDisposeFamilyNotifier<
Expand Down Expand Up @@ -85,4 +86,33 @@ class DriveFoldersNotifier extends AutoDisposeFamilyNotifier<
.toList(),
);
}

Future<void> move({
required String folderId,
required String? parentId,
}) async {
if (parentId == _folderId) {
return;
}
// parentIdがnullのときキーが削除されるのを回避
final response = await _misskey.apiService.post<Map<String, dynamic>>(
"drive/folders/update",
{
"folderId": folderId,
"parentId": parentId,
},
excludeRemoveNullPredicate: (key, _) => key == "parentId",
);
final folder = DriveFolder.fromJson(response);
state = state.copyWith(
items: state.where((file) => file.id != folderId).toList(),
);
ref
.read(driveFoldersNotifierProvider((_misskey, parentId)).notifier)
.add(folder);
}

void add(DriveFolder folder) {
state = state.copyWith(items: [folder, ...state]);
}
}
27 changes: 27 additions & 0 deletions lib/view/drive_page/drive_file_modal_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:miria/providers.dart';
import 'package:miria/router/app_router.dart';
import 'package:miria/view/common/error_dialog_handler.dart';
import 'package:miria/view/dialogs/simple_confirm_dialog.dart';
import 'package:miria/view/drive_page/drive_folder_select_dialog.dart';
import 'package:miria/view/note_create_page/file_settings_dialog.dart';
import 'package:misskey_dart/misskey_dart.dart';

Expand Down Expand Up @@ -97,6 +98,27 @@ class DriveFileModalSheet extends ConsumerWidget {
Navigator.of(context).pop();
}

Future<void> move(WidgetRef ref) async {
final context = ref.context;
final misskey = ref.read(misskeyProvider(account));
final result = await showDialog<(DriveFolder?,)>(
context: context,
builder: (context) => DriveFolderSelectDialog(account: account),
);
if (result == null) return;
await ref
.read(driveFilesNotifierProvider((misskey, file.folderId)).notifier)
.move(
fileId: file.id,
folderId: result.$1?.id,
);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("移動しました")),
);
Navigator.of(context).pop();
}

Future<void> delete(WidgetRef ref) async {
final context = ref.context;
final misskey = ref.read(misskeyProvider(account));
Expand Down Expand Up @@ -163,6 +185,11 @@ class DriveFileModalSheet extends ConsumerWidget {
title: const Text("ダウンロード"),
onTap: () => download(ref).expectFailure(context),
),
ListTile(
leading: const Icon(Icons.drive_file_move),
title: const Text("移動"),
onTap: () => move(ref).expectFailure(context),
),
ListTile(
leading: const Icon(Icons.delete),
title: const Text("削除"),
Expand Down
27 changes: 27 additions & 0 deletions lib/view/drive_page/drive_folder_modal_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:miria/providers.dart';
import 'package:miria/view/common/error_dialog_handler.dart';
import 'package:miria/view/common/text_form_field_dialog.dart';
import 'package:miria/view/dialogs/simple_confirm_dialog.dart';
import 'package:miria/view/drive_page/drive_folder_select_dialog.dart';
import 'package:misskey_dart/misskey_dart.dart';

class DriveFolderModalSheet extends ConsumerWidget {
Expand Down Expand Up @@ -39,6 +40,27 @@ class DriveFolderModalSheet extends ConsumerWidget {
}
}

Future<void> move(WidgetRef ref) async {
final context = ref.context;
final misskey = ref.read(misskeyProvider(account));
final result = await showDialog<(DriveFolder?,)>(
context: context,
builder: (context) => DriveFolderSelectDialog(account: account),
);
if (result == null) return;
await ref
.read(driveFoldersNotifierProvider((misskey, folder.parentId)).notifier)
.move(
folderId: folder.id,
parentId: result.$1?.id,
);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("移動しました")),
);
Navigator.of(context).pop();
}

Future<void> delete(WidgetRef ref) async {
final context = ref.context;
final misskey = ref.read(misskeyProvider(account));
Expand Down Expand Up @@ -72,6 +94,11 @@ class DriveFolderModalSheet extends ConsumerWidget {
title: const Text("名前を変更"),
onTap: () => changeName(ref).expectFailure(context),
),
ListTile(
leading: const Icon(Icons.drive_file_move),
title: const Text("移動"),
onTap: () => move(ref).expectFailure(context),
),
ListTile(
leading: const Icon(Icons.delete),
title: const Text("削除"),
Expand Down
39 changes: 39 additions & 0 deletions lib/view/drive_page/drive_folder_select_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/model/account.dart';
import 'package:miria/providers.dart';
import 'package:miria/state_notifier/drive_page/breadcrumbs_notifier.dart';
import 'package:miria/view/drive_page/drive_page.dart';

class DriveFolderSelectDialog extends StatelessWidget {
const DriveFolderSelectDialog({
super.key,
required this.account,
});

final Account account;

@override
Widget build(BuildContext context) {
return ProviderScope(
overrides: [
breadcrumbsNotifierProvider.overrideWith(BreadcrumbsNotifier.new),
],
child: Dialog(
child: DrivePage(
account: account,
title: const Text("フォルダを選択"),
floatingActionButtonBuilder: (context, folder) {
return FloatingActionButton.extended(
onPressed: () {
Navigator.of(context).pop((folder,));
},
label: const Text("選択"),
icon: const Icon(Icons.check),
);
},
),
),
);
}
}
33 changes: 23 additions & 10 deletions lib/view/drive_page/drive_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,21 @@ import 'package:miria/view/drive_page/breadcrumbs.dart';
import 'package:miria/view/drive_page/drive_create_modal_sheet.dart';
import 'package:miria/view/drive_page/drive_file_grid_item.dart';
import 'package:miria/view/drive_page/drive_folder_grid_item.dart';
import 'package:misskey_dart/misskey_dart.dart';

@RoutePage()
class DrivePage extends ConsumerWidget {
const DrivePage({super.key, required this.account});
const DrivePage({
super.key,
required this.account,
this.title,
this.floatingActionButtonBuilder,
});

final Account account;
final Widget? title;
final Widget Function(BuildContext context, DriveFolder? currentFolder)?
floatingActionButtonBuilder;

static const itemMaxCrossAxisExtent = 400.0;

Expand Down Expand Up @@ -171,16 +180,20 @@ class DrivePage extends ConsumerWidget {
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => showModalBottomSheet<void>(
context: context,
builder: (context) => DriveCreateModalSheet(
account: account,
folder: currentFolder,
floatingActionButton: floatingActionButtonBuilder?.call(
context,
currentFolder,
) ??
FloatingActionButton(
onPressed: () => showModalBottomSheet<void>(
context: context,
builder: (context) => DriveCreateModalSheet(
account: account,
folder: currentFolder,
),
),
child: const Icon(Icons.add),
),
),
child: const Icon(Icons.add),
),
),
);
}
Expand Down

0 comments on commit 0cbefc8

Please sign in to comment.