mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: merge release/0.6.1
This commit is contained in:
parent
7586a0ed48
commit
e73b310076
@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||
LIB_NAME = "dart_ffi"
|
||||
APPFLOWY_VERSION = "0.6.0"
|
||||
APPFLOWY_VERSION = "0.6.1"
|
||||
FLUTTER_DESKTOP_FEATURES = "dart"
|
||||
PRODUCT_NAME = "AppFlowy"
|
||||
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
||||
|
@ -4,6 +4,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/home/space/mobile_space_header.dart';
|
||||
import 'package:appflowy/mobile/presentation/home/space/mobile_space_menu.dart';
|
||||
import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
|
||||
import 'package:appflowy/mobile/presentation/presentation.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_bloc.dart';
|
||||
@ -22,6 +23,18 @@ class MobileSpace extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MobileSpaceState extends State<MobileSpace> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
createNewPageNotifier.addListener(_createNewPage);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
createNewPageNotifier.removeListener(_createNewPage);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<SpaceBloc, SpaceState>(
|
||||
@ -81,6 +94,14 @@ class _MobileSpaceState extends State<MobileSpace> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _createNewPage() {
|
||||
context.read<SpaceBloc>().add(
|
||||
SpaceEvent.createPage(
|
||||
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Pages extends StatelessWidget {
|
||||
|
@ -1,18 +1,15 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/application/mobile_router.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/util/theme_extension.dart';
|
||||
import 'package:appflowy/workspace/application/workspace/workspace_service.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
final PropertyValueNotifier<ViewLayoutPB?> createNewPageNotifier =
|
||||
PropertyValueNotifier(null);
|
||||
|
||||
const _homeLabel = 'home';
|
||||
const _addLabel = 'add';
|
||||
const _notificationLabel = 'notification';
|
||||
@ -93,7 +90,7 @@ class MobileBottomNavigationBar extends StatelessWidget {
|
||||
void _onTap(BuildContext context, int bottomBarIndex) {
|
||||
if (_items[bottomBarIndex].label == _addLabel) {
|
||||
// show an add dialog
|
||||
_showCreatePageBottomSheet(context);
|
||||
createNewPageNotifier.value = ViewLayoutPB.Document;
|
||||
return;
|
||||
}
|
||||
// When navigating to a new branch, it's recommended to use the goBranch
|
||||
@ -108,40 +105,4 @@ class MobileBottomNavigationBar extends StatelessWidget {
|
||||
initialLocation: bottomBarIndex == navigationShell.currentIndex,
|
||||
);
|
||||
}
|
||||
|
||||
void _showCreatePageBottomSheet(BuildContext context) {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
showHeader: true,
|
||||
title: LocaleKeys.sideBar_addAPage.tr(),
|
||||
showDragHandle: true,
|
||||
showCloseButton: true,
|
||||
useRootNavigator: true,
|
||||
builder: (sheetContext) {
|
||||
return AddNewPageWidgetBottomSheet(
|
||||
view: ViewPB(),
|
||||
onAction: (layout) async {
|
||||
Navigator.of(sheetContext).pop();
|
||||
final currentWorkspaceId =
|
||||
await FolderEventReadCurrentWorkspace().send();
|
||||
await currentWorkspaceId.fold((s) async {
|
||||
final workspaceService = WorkspaceService(workspaceId: s.id);
|
||||
final result = await workspaceService.createView(
|
||||
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
viewSection: ViewSectionPB.Private,
|
||||
layout: layout,
|
||||
);
|
||||
result.fold((s) {
|
||||
context.pushView(s);
|
||||
}, (e) {
|
||||
Log.error('Failed to create new page: $e');
|
||||
});
|
||||
}, (e) {
|
||||
Log.error('Failed to read current workspace: $e');
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +73,7 @@ class _AppFlowyMobileToolbarState extends State<AppFlowyMobileToolbar> {
|
||||
ValueListenableBuilder(
|
||||
valueListenable: isKeyboardShow,
|
||||
builder: (context, isKeyboardShow, __) {
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 110),
|
||||
return SizedBox(
|
||||
// only adding padding when the keyboard is triggered by editor
|
||||
height: isKeyboardShow && widget.editorState.selection != null
|
||||
? widget.toolbarHeight
|
||||
@ -383,37 +382,26 @@ class _MobileToolbarState extends State<_MobileToolbar>
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: cachedKeyboardHeight,
|
||||
builder: (_, height, ___) {
|
||||
var paddingHeight = height;
|
||||
if (Platform.isAndroid) {
|
||||
// use the viewInsets to get the keyboard height on Android
|
||||
paddingHeight = MediaQuery.of(context).viewInsets.bottom;
|
||||
// if the padding height is 0 and the keyboard height is not 0,
|
||||
// use the keyboard height
|
||||
if (paddingHeight == 0 && height != 0) {
|
||||
paddingHeight = height + MediaQuery.of(context).viewPadding.bottom;
|
||||
}
|
||||
}
|
||||
debugPrint('Keyboard height: $paddingHeight');
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(microseconds: 110),
|
||||
height: paddingHeight,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: showMenuNotifier,
|
||||
builder: (_, showingMenu, __) {
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(microseconds: 110),
|
||||
height: height,
|
||||
child: (showingMenu && selectedMenuIndex != null)
|
||||
? widget.toolbarItems[selectedMenuIndex!].menuBuilder?.call(
|
||||
context,
|
||||
widget.editorState,
|
||||
this,
|
||||
) ??
|
||||
const SizedBox.shrink()
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
),
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: showMenuNotifier,
|
||||
builder: (_, showingMenu, __) {
|
||||
var paddingHeight = height;
|
||||
if (Platform.isAndroid) {
|
||||
paddingHeight =
|
||||
height + MediaQuery.of(context).viewPadding.bottom;
|
||||
}
|
||||
return SizedBox(
|
||||
height: paddingHeight,
|
||||
child: (showingMenu && selectedMenuIndex != null)
|
||||
? widget.toolbarItems[selectedMenuIndex!].menuBuilder?.call(
|
||||
context,
|
||||
widget.editorState,
|
||||
this,
|
||||
) ??
|
||||
const SizedBox.shrink()
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -19,6 +19,7 @@ import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
@ -257,6 +258,10 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
);
|
||||
},
|
||||
reset: (userProfile, workspaceId) async {
|
||||
if (workspaceId == _workspaceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
_reset(userProfile, workspaceId);
|
||||
|
||||
add(
|
||||
@ -321,6 +326,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
required String icon,
|
||||
required String iconColor,
|
||||
required SpacePermission permission,
|
||||
String? viewId,
|
||||
}) async {
|
||||
final section = switch (permission) {
|
||||
SpacePermission.publicToAll => ViewSectionPB.Public,
|
||||
@ -331,6 +337,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
name: name,
|
||||
viewSection: section,
|
||||
setAsCurrent: false,
|
||||
viewId: viewId,
|
||||
);
|
||||
return await result.fold((space) async {
|
||||
Log.info('Space created: $space');
|
||||
@ -476,56 +483,82 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
if (members.items.length == 1 || isOwner) {
|
||||
// create a new public space and a new private space
|
||||
// move all the views in the workspace to the new public/private space
|
||||
final publicViews =
|
||||
await _workspaceService.getPublicViews().getOrThrow();
|
||||
// only migrate the public space if there are any public views
|
||||
if (publicViews.isNotEmpty) {
|
||||
final publicSpace = await _createSpace(
|
||||
name: 'Shared',
|
||||
icon: builtInSpaceIcons.first,
|
||||
iconColor: builtInSpaceColors.first,
|
||||
permission: SpacePermission.publicToAll,
|
||||
);
|
||||
|
||||
if (publicSpace != null) {
|
||||
for (final view in publicViews.reversed) {
|
||||
if (view.isSpace) {
|
||||
continue;
|
||||
}
|
||||
await ViewBackendService.moveViewV2(
|
||||
viewId: view.id,
|
||||
newParentId: publicSpace.id,
|
||||
prevViewId: view.parentViewId,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// create a new private space
|
||||
final privateViews =
|
||||
await _workspaceService.getPrivateViews().getOrThrow();
|
||||
// only migrate the private space if there are any private views
|
||||
if (privateViews.isNotEmpty) {
|
||||
final privateSpace = await _createSpace(
|
||||
name: 'Private',
|
||||
icon: builtInSpaceIcons.last,
|
||||
iconColor: builtInSpaceColors.last,
|
||||
permission: SpacePermission.private,
|
||||
var publicViews = await _workspaceService.getPublicViews().getOrThrow();
|
||||
final containsPublicSpace = publicViews.any(
|
||||
(e) => e.isSpace && e.spacePermission == SpacePermission.publicToAll,
|
||||
);
|
||||
if (privateSpace != null) {
|
||||
for (final view in privateViews.reversed) {
|
||||
publicViews = publicViews.where((e) => !e.isSpace).toList();
|
||||
// if there is already a public space, don't migrate the public space
|
||||
// only migrate the public space if there are any public views
|
||||
if (publicViews.isEmpty || containsPublicSpace) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final viewId = fixedUuid(user.id.toInt(), UuidType.publicSpace);
|
||||
final publicSpace = await _createSpace(
|
||||
name: 'Shared',
|
||||
icon: builtInSpaceIcons.first,
|
||||
iconColor: builtInSpaceColors.first,
|
||||
permission: SpacePermission.publicToAll,
|
||||
viewId: viewId,
|
||||
);
|
||||
|
||||
Log.info('migrating: created a new public space: ${publicSpace?.id}');
|
||||
|
||||
if (publicSpace != null) {
|
||||
for (final view in publicViews.reversed) {
|
||||
if (view.isSpace) {
|
||||
continue;
|
||||
}
|
||||
await ViewBackendService.moveViewV2(
|
||||
viewId: view.id,
|
||||
newParentId: privateSpace.id,
|
||||
prevViewId: view.parentViewId,
|
||||
newParentId: publicSpace.id,
|
||||
prevViewId: null,
|
||||
);
|
||||
Log.info(
|
||||
'migrating: migrate ${view.name}(${view.id}) to public space(${publicSpace.id})',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a new private space
|
||||
final viewId = fixedUuid(user.id.toInt(), UuidType.privateSpace);
|
||||
var privateViews = await _workspaceService.getPrivateViews().getOrThrow();
|
||||
// if there is already a private space, don't migrate the private space
|
||||
final containsPrivateSpace = privateViews.any(
|
||||
(e) => e.isSpace && e.spacePermission == SpacePermission.private,
|
||||
);
|
||||
privateViews = privateViews.where((e) => !e.isSpace).toList();
|
||||
if (privateViews.isEmpty || containsPrivateSpace) {
|
||||
return true;
|
||||
}
|
||||
// only migrate the private space if there are any private views
|
||||
final privateSpace = await _createSpace(
|
||||
name: 'Private',
|
||||
icon: builtInSpaceIcons.last,
|
||||
iconColor: builtInSpaceColors.last,
|
||||
permission: SpacePermission.private,
|
||||
viewId: viewId,
|
||||
);
|
||||
Log.info('migrating: created a new private space: ${privateSpace?.id}');
|
||||
|
||||
if (privateSpace != null) {
|
||||
for (final view in privateViews.reversed) {
|
||||
if (view.isSpace) {
|
||||
continue;
|
||||
}
|
||||
await ViewBackendService.moveViewV2(
|
||||
viewId: view.id,
|
||||
newParentId: privateSpace.id,
|
||||
prevViewId: null,
|
||||
);
|
||||
Log.info(
|
||||
'migrating: migrate ${view.name}(${view.id}) to private space(${privateSpace.id})',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
Log.error('migrate space error: $e');
|
||||
@ -538,14 +571,16 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
required List<ViewPB> publicViews,
|
||||
required List<ViewPB> privateViews,
|
||||
}) async {
|
||||
final publicSpaces =
|
||||
spaces.where((e) => e.spacePermission == SpacePermission.publicToAll);
|
||||
final publicSpaces = spaces.where(
|
||||
(e) => e.spacePermission == SpacePermission.publicToAll,
|
||||
);
|
||||
if (publicSpaces.isEmpty && publicViews.isNotEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final privateSpaces =
|
||||
spaces.where((e) => e.spacePermission == SpacePermission.private);
|
||||
final privateSpaces = spaces.where(
|
||||
(e) => e.spacePermission == SpacePermission.private,
|
||||
);
|
||||
if (privateSpaces.isEmpty && privateViews.isNotEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class ViewBackendService {
|
||||
/// If the index is null, the view will be added to the end of the list.
|
||||
int? index,
|
||||
ViewSectionPB? section,
|
||||
final String? viewId,
|
||||
}) {
|
||||
final payload = CreateViewPayloadPB.create()
|
||||
..parentViewId = parentViewId
|
||||
@ -63,6 +64,10 @@ class ViewBackendService {
|
||||
payload.section = section;
|
||||
}
|
||||
|
||||
if (viewId != null) {
|
||||
payload.viewId = viewId;
|
||||
}
|
||||
|
||||
return FolderEventCreateView(payload).send();
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ class WorkspaceService {
|
||||
int? index,
|
||||
ViewLayoutPB? layout,
|
||||
bool? setAsCurrent,
|
||||
String? viewId,
|
||||
}) {
|
||||
final payload = CreateViewPayloadPB.create()
|
||||
..parentViewId = workspaceId
|
||||
@ -37,6 +38,10 @@ class WorkspaceService {
|
||||
payload.setAsCurrent = setAsCurrent;
|
||||
}
|
||||
|
||||
if (viewId != null) {
|
||||
payload.viewId = viewId;
|
||||
}
|
||||
|
||||
return FolderEventCreateView(payload).send();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,19 @@
|
||||
import 'package:uuid/data.dart';
|
||||
import 'package:uuid/rng.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
const _uuid = Uuid();
|
||||
|
||||
String uuid() {
|
||||
return const Uuid().v4();
|
||||
return _uuid.v4();
|
||||
}
|
||||
|
||||
String fixedUuid(int seed, UuidType type) {
|
||||
return _uuid.v4(config: V4Options(null, MathRNG(seed: seed + type.index)));
|
||||
}
|
||||
|
||||
enum UuidType {
|
||||
// 0.6.0
|
||||
publicSpace,
|
||||
privateSpace,
|
||||
}
|
||||
|
@ -2174,10 +2174,10 @@ packages:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
name: uuid
|
||||
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
|
||||
sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.3"
|
||||
version: "4.4.0"
|
||||
value_layout_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 0.6.0
|
||||
version: 0.6.1
|
||||
|
||||
environment:
|
||||
flutter: ">=3.22.0"
|
||||
@ -199,7 +199,7 @@ dependency_overrides:
|
||||
ref: e44458d
|
||||
path: sheet
|
||||
|
||||
uuid: ^4.1.0
|
||||
uuid: ^4.4.0
|
||||
|
||||
flutter_cache_manager:
|
||||
git:
|
||||
|
@ -21,6 +21,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
|
@ -45,6 +45,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
@ -76,6 +77,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
@ -102,6 +104,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
|
@ -65,6 +65,7 @@ impl DocumentEventTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(core.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
|
@ -42,6 +42,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
let view = EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
|
@ -230,6 +230,7 @@ impl EventIntegrationTest {
|
||||
set_as_current: false,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(self.clone())
|
||||
.event(FolderEvent::CreateView)
|
||||
@ -293,6 +294,7 @@ impl ViewTest {
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
|
||||
let view = EventBuilder::new(sdk.clone())
|
||||
|
@ -252,6 +252,7 @@ pub async fn create_view(
|
||||
set_as_current: true,
|
||||
index: None,
|
||||
section: None,
|
||||
view_id: None,
|
||||
};
|
||||
EventBuilder::new(sdk.clone())
|
||||
.event(CreateView)
|
||||
|
@ -258,6 +258,9 @@ pub struct CreateViewPayloadPB {
|
||||
// The view in private section will only be shown in the user's private view list.
|
||||
#[pb(index = 10, one_of)]
|
||||
pub section: Option<ViewSectionPB>,
|
||||
|
||||
#[pb(index = 11, one_of)]
|
||||
pub view_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone, Default)]
|
||||
@ -313,7 +316,8 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
|
||||
fn try_into(self) -> Result<CreateViewParams, Self::Error> {
|
||||
let name = ViewName::parse(self.name)?.0;
|
||||
let parent_view_id = ViewIdentify::parse(self.parent_view_id)?.0;
|
||||
let view_id = gen_view_id().to_string();
|
||||
// if view_id is not provided, generate a new view_id
|
||||
let view_id = self.view_id.unwrap_or_else(|| gen_view_id().to_string());
|
||||
|
||||
Ok(CreateViewParams {
|
||||
parent_view_id,
|
||||
|
@ -59,8 +59,6 @@ AppDir:
|
||||
- libwayland-cursor0:amd64
|
||||
- libwayland-client0:amd64
|
||||
- libwayland-egl1:amd64
|
||||
- libmpv-dev:amd64
|
||||
- mpv:amd64
|
||||
files:
|
||||
include: []
|
||||
exclude:
|
||||
|
Loading…
Reference in New Issue
Block a user