Merge branch 'AppFlowy-IO:main' into main

This commit is contained in:
Stefan Weiberg 2024-08-27 16:51:24 +02:00 committed by GitHub
commit 2c871d543f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
315 changed files with 8524 additions and 2205 deletions

View File

@ -12,7 +12,7 @@ import 'util.dart';
extension AppFlowyAuthTest on WidgetTester {
Future<void> tapGoogleLoginInButton() async {
await tapButton(
find.byKey(const Key('signInWithGoogleButton')),
find.byKey(signInWithGoogleButtonKey),
);
}
@ -36,7 +36,7 @@ extension AppFlowyAuthTest on WidgetTester {
}
void expectToSeeGoogleLoginButton() {
expect(find.byKey(const Key('signInWithGoogleButton')), findsOneWidget);
expect(find.byKey(signInWithGoogleButtonKey), findsOneWidget);
}
void assertSwitchValue(Finder finder, bool value) {

View File

@ -372,6 +372,7 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AppFlowy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -383,6 +384,8 @@
STRIP_STYLE = "non-global";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
@ -511,6 +514,7 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AppFlowy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -522,6 +526,8 @@
STRIP_STYLE = "non-global";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -545,6 +551,7 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AppFlowy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -556,6 +563,8 @@
STRIP_STYLE = "non-global";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;

View File

@ -1,75 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>AppFlowy requires access to the camera.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>AppFlowy requires access to the photo library.</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true />
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
</array>
<key>FLTEnableImpeller</key>
<false />
<key>CFBundleName</key>
<string>AppFlowy</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>appflowy-flutter</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true />
<key>UIApplicationSupportsIndirectInputEvents</key>
<true />
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false />
<key>NSAppTransportSecurity</key>
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
</array>
<key>CFBundleName</key>
<string>AppFlowy</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>CFBundleURLName</key>
<string></string>
<key>CFBundleURLSchemes</key>
<array>
<string>appflowy-flutter</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>FLTEnableImpeller</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</plist>
<key>NSCameraUsageDescription</key>
<string>AppFlowy requires access to the camera.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>AppFlowy requires access to the photo library.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
</plist>

View File

@ -65,7 +65,7 @@ class _MobileBottomSheetRenameWidgetState
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
textColor: Colors.white,
fontColor: Colors.white,
fillColor: Theme.of(context).primaryColor,
onPressed: () {
widget.onRename(controller.text);

View File

@ -64,6 +64,10 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
case MobileViewItemBottomSheetBodyAction.duplicate:
Navigator.pop(context);
context.read<ViewBloc>().add(const ViewEvent.duplicate());
showToastNotification(
context,
message: LocaleKeys.button_duplicateSuccessfully.tr(),
);
break;
case MobileViewItemBottomSheetBodyAction.share:
// unimplemented
@ -79,6 +83,12 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
context
.read<FavoriteBloc>()
.add(FavoriteEvent.toggle(widget.view));
showToastNotification(
context,
message: !widget.view.isFavorite
? LocaleKeys.button_favoriteSuccessfully.tr()
: LocaleKeys.button_unfavoriteSuccessfully.tr(),
);
break;
case MobileViewItemBottomSheetBodyAction.removeFromRecent:
_removeFromRecent(context);

View File

@ -177,7 +177,13 @@ class _HomePageState extends State<_HomePage> {
getIt<CachedRecentService>().reset();
mCurrentWorkspace.value = state.currentWorkspace;
_showResultDialog(context, state);
Debounce.debounce(
'workspace_action_result',
const Duration(milliseconds: 150),
() {
_showResultDialog(context, state);
},
);
},
builder: (context, state) {
if (state.currentWorkspace == null) {

View File

@ -47,15 +47,6 @@ class MobileHomePageHeader extends StatelessWidget {
: _MobileUser(userProfile: userProfile),
),
const HomePageSettingsPopupMenu(),
// GestureDetector(
// onTap: () => context.push(
// MobileHomeSettingPage.routeName,
// ),
// child: const Padding(
// padding: EdgeInsets.all(8.0),
// child: FlowySvg(FlowySvgs.m_notification_settings_s),
// ),
// ),
const HSpace(8.0),
],
),

View File

@ -3,9 +3,11 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/presentation.dart';
import 'package:appflowy/mobile/presentation/setting/workspace/invite_members_screen.dart';
import 'package:appflowy/shared/popup_menu/appflowy_popup_menu.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart'
hide PopupMenuButton, PopupMenuDivider, PopupMenuItem, PopupMenuEntry;
import 'package:go_router/go_router.dart';
enum _MobileSettingsPopupMenuItem {
@ -28,9 +30,9 @@ class HomePageSettingsPopupMenu extends StatelessWidget {
Radius.circular(12.0),
),
),
// todo: replace it with shadows
shadowColor: const Color(0x68000000),
elevation: 10,
color: Theme.of(context).colorScheme.surface,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: FlowySvg(

View File

@ -36,6 +36,7 @@ class EmptySpacePlaceholder extends StatelessWidget {
lineHeight: 1.3,
color: Theme.of(context).hintColor,
),
const VSpace(kBottomNavigationBarHeight + 36.0),
],
),
);

View File

@ -1,12 +1,14 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/presentation.dart';
import 'package:appflowy/shared/popup_menu/appflowy_popup_menu.dart';
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart'
hide PopupMenuButton, PopupMenuDivider, PopupMenuItem, PopupMenuEntry;
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';

View File

@ -16,13 +16,10 @@ class AppFlowyCloudPage extends StatelessWidget {
appBar: FlowyAppBar(
titleText: LocaleKeys.settings_menu_cloudSettings.tr(),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: SettingCloud(
restartAppFlowy: () async {
await runAppFlowy();
},
),
body: SettingCloud(
restartAppFlowy: () async {
await runAppFlowy();
},
),
);
}

View File

@ -33,7 +33,9 @@ class UserSessionSettingGroup extends StatelessWidget {
);
},
builder: (context, state) {
return const ThirdPartySignInButtons();
return const ThirdPartySignInButtons(
expanded: true,
);
},
),
),

View File

@ -34,6 +34,7 @@ class InviteMembersScreen extends StatelessWidget {
titleText: LocaleKeys.settings_appearance_members_label.tr(),
),
body: const _InviteMemberPage(),
resizeToAvoidBottomInset: false,
);
}
}
@ -193,6 +194,9 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
final actionType = actionResult.actionType;
final result = actionResult.result;
// get keyboard height
final keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
// only show the result dialog when the action is WorkspaceMemberActionType.add
if (actionType == WorkspaceMemberActionType.add) {
result.fold(
@ -201,6 +205,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
context,
message:
LocaleKeys.settings_appearance_members_addMemberSuccess.tr(),
bottomPadding: keyboardHeight,
);
},
(f) {
@ -216,6 +221,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
showToastNotification(
context,
type: ToastificationType.error,
bottomPadding: keyboardHeight,
message: message,
);
},
@ -227,6 +233,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
context,
message:
LocaleKeys.settings_appearance_members_inviteMemberSuccess.tr(),
bottomPadding: keyboardHeight,
);
},
(f) {
@ -244,6 +251,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
context,
type: ToastificationType.error,
message: message,
bottomPadding: keyboardHeight,
);
},
);
@ -255,6 +263,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
message: LocaleKeys
.settings_appearance_members_removeFromWorkspaceSuccess
.tr(),
bottomPadding: keyboardHeight,
);
},
(f) {
@ -264,6 +273,7 @@ class _InviteMemberPageState extends State<_InviteMemberPage> {
message: LocaleKeys
.settings_appearance_members_removeFromWorkspaceFailed
.tr(),
bottomPadding: keyboardHeight,
);
},
);

View File

@ -89,6 +89,15 @@ class CellController<T, D> {
fieldId: _cellContext.fieldId,
);
_rowCache.addListener(
rowId: rowId,
onRowChanged: (context, reason) {
if (reason == const ChangedReason.didFetchRow()) {
_onRowMetaChanged?.call();
}
},
);
// 1. Listen on user edit event and load the new cell data if needed.
// For example:
// user input: 12

View File

@ -44,7 +44,8 @@ class RowCache {
for (final fieldInfo in fieldInfos) {
_cellMemCache.removeCellWithFieldId(fieldInfo.id);
}
_changedNotifier.receive(const ChangedReason.fieldDidChange());
_changedNotifier?.receive(const ChangedReason.fieldDidChange());
});
}
@ -53,7 +54,7 @@ class RowCache {
final CellMemCache _cellMemCache;
final RowLifeCycle _rowLifeCycle;
final RowFieldsDelegate _fieldDelegate;
final RowChangesetNotifier _changedNotifier;
RowChangesetNotifier? _changedNotifier;
/// Returns a unmodifiable list of RowInfo
UnmodifiableListView<RowInfo> get rowInfos {
@ -67,7 +68,8 @@ class RowCache {
}
CellMemCache get cellCache => _cellMemCache;
ChangedReason get changeReason => _changedNotifier.reason;
ChangedReason get changeReason =>
_changedNotifier?.reason ?? const InitialListState();
RowInfo? getRow(RowId rowId) {
return _rowList.get(rowId);
@ -78,18 +80,19 @@ class RowCache {
final rowInfo = buildGridRow(row);
_rowList.add(rowInfo);
}
_changedNotifier.receive(const ChangedReason.setInitialRows());
_changedNotifier?.receive(const ChangedReason.setInitialRows());
}
void setRowMeta(RowMetaPB rowMeta) {
final rowInfo = buildGridRow(rowMeta);
_rowList.add(rowInfo);
_changedNotifier.receive(const ChangedReason.didFetchRow());
_changedNotifier?.receive(const ChangedReason.didFetchRow());
}
void dispose() {
_rowLifeCycle.onRowDisposed();
_changedNotifier.dispose();
_changedNotifier?.dispose();
_changedNotifier = null;
_cellMemCache.dispose();
}
@ -106,7 +109,7 @@ class RowCache {
void reorderAllRows(List<String> rowIds) {
_rowList.reorderWithRowIds(rowIds);
_changedNotifier.receive(const ChangedReason.reorderRows());
_changedNotifier?.receive(const ChangedReason.reorderRows());
}
void reorderSingleRow(ReorderSingleRowPB reorderRow) {
@ -117,7 +120,7 @@ class RowCache {
reorderRow.oldIndex,
reorderRow.newIndex,
);
_changedNotifier.receive(
_changedNotifier?.receive(
ChangedReason.reorderSingleRow(
reorderRow,
rowInfo,
@ -130,7 +133,7 @@ class RowCache {
for (final rowId in deletedRowIds) {
final deletedRow = _rowList.remove(rowId);
if (deletedRow != null) {
_changedNotifier.receive(ChangedReason.delete(deletedRow));
_changedNotifier?.receive(ChangedReason.delete(deletedRow));
}
}
}
@ -140,7 +143,7 @@ class RowCache {
final insertedIndex =
_rowList.insert(insertedRow.index, buildGridRow(insertedRow.rowMeta));
if (insertedIndex != null) {
_changedNotifier.receive(ChangedReason.insert(insertedIndex));
_changedNotifier?.receive(ChangedReason.insert(insertedIndex));
}
}
}
@ -165,7 +168,7 @@ class RowCache {
_rowList.updateRows(updatedList, (rowId) => buildGridRow(rowId));
if (updatedIndexs.isNotEmpty) {
_changedNotifier.receive(ChangedReason.update(updatedIndexs));
_changedNotifier?.receive(ChangedReason.update(updatedIndexs));
}
}
@ -173,7 +176,7 @@ class RowCache {
for (final rowId in invisibleRows) {
final deletedRow = _rowList.remove(rowId);
if (deletedRow != null) {
_changedNotifier.receive(ChangedReason.delete(deletedRow));
_changedNotifier?.receive(ChangedReason.delete(deletedRow));
}
}
}
@ -183,14 +186,16 @@ class RowCache {
final insertedIndex =
_rowList.insert(insertedRow.index, buildGridRow(insertedRow.rowMeta));
if (insertedIndex != null) {
_changedNotifier.receive(ChangedReason.insert(insertedIndex));
_changedNotifier?.receive(ChangedReason.insert(insertedIndex));
}
}
}
void onRowsChanged(void Function(ChangedReason) onRowChanged) {
_changedNotifier.addListener(() {
onRowChanged(_changedNotifier.reason);
_changedNotifier?.addListener(() {
if (_changedNotifier != null) {
onRowChanged(_changedNotifier!.reason);
}
});
}
@ -203,17 +208,19 @@ class RowCache {
final rowInfo = _rowList.get(rowId);
if (rowInfo != null) {
final cellDataMap = _makeCells(rowInfo.rowMeta);
onRowChanged(cellDataMap, _changedNotifier.reason);
if (_changedNotifier != null) {
onRowChanged(cellDataMap, _changedNotifier!.reason);
}
}
}
}
_changedNotifier.addListener(listenerHandler);
_changedNotifier?.addListener(listenerHandler);
return listenerHandler;
}
void removeRowListener(VoidCallback callback) {
_changedNotifier.removeListener(callback);
_changedNotifier?.removeListener(callback);
}
List<CellContext> loadCells(RowMetaPB rowMeta) {
@ -242,7 +249,7 @@ class RowCache {
rowId: rowMetaPB.id,
);
_changedNotifier.receive(ChangedReason.update(updatedIndexs));
_changedNotifier?.receive(ChangedReason.update(updatedIndexs));
}
},
(err) => Log.error(err),

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/row/row_service.dart';
import 'package:appflowy/plugins/database/domain/row_listener.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:flutter/material.dart';
import '../cell/cell_cache.dart';
@ -18,21 +20,11 @@ class RowController {
}) : _rowMeta = rowMeta,
_rowCache = rowCache,
_rowBackendSvc = RowBackendService(viewId: viewId),
_rowListener = RowListener(rowMeta.id) {
_rowBackendSvc.initRow(rowMeta.id);
_rowListener.start(
onMetaChanged: (newRowMeta) {
if (_isDisposed) {
return;
}
_rowMeta = newRowMeta;
_rowCache.setRowMeta(newRowMeta);
},
);
}
_rowListener = RowListener(rowMeta.id);
RowMetaPB _rowMeta;
final String? groupId;
VoidCallback? _onRowMetaChanged;
final String viewId;
final List<VoidCallback> _onRowChangedListeners = [];
final RowCache _rowCache;
@ -40,14 +32,52 @@ class RowController {
final RowBackendService _rowBackendSvc;
bool _isDisposed = false;
CellMemCache get cellCache => _rowCache.cellCache;
String get rowId => rowMeta.id;
RowMetaPB get rowMeta => _rowMeta;
CellMemCache get cellCache => _rowCache.cellCache;
List<CellContext> loadCells() => _rowCache.loadCells(rowMeta);
void addListener({OnRowChanged? onRowChanged}) {
Future<void> initialize() async {
await _rowBackendSvc.initRow(rowMeta.id);
unawaited(
_rowBackendSvc.getRowMeta(rowId).then(
(result) {
if (_isDisposed) {
return;
}
result.fold(
(rowMeta) {
_rowMeta = rowMeta;
_rowCache.setRowMeta(rowMeta);
_onRowMetaChanged?.call();
},
(error) => debugPrint(error.toString()),
);
},
),
);
_rowListener.start(
onRowFetched: (DidFetchRowPB row) {
_rowCache.setRowMeta(row.meta);
},
onMetaChanged: (newRowMeta) {
if (_isDisposed) {
return;
}
_rowMeta = newRowMeta;
_rowCache.setRowMeta(newRowMeta);
_onRowMetaChanged?.call();
},
);
}
void addListener({
OnRowChanged? onRowChanged,
VoidCallback? onMetaChanged,
}) {
final fn = _rowCache.addListener(
rowId: rowMeta.id,
onRowChanged: (context, reasons) {
@ -60,6 +90,7 @@ class RowController {
// Add the listener to the list so that we can remove it later.
_onRowChangedListeners.add(fn);
_onRowMetaChanged = onMetaChanged;
}
Future<void> dispose() async {

View File

@ -2,9 +2,7 @@ import 'dart:async';
import 'dart:collection';
import 'package:appflowy/plugins/database/application/row/row_service.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import '../defines.dart';
import '../field/field_controller.dart';
@ -93,17 +91,6 @@ class DatabaseViewCache {
(reorderRow) => _rowCache.reorderSingleRow(reorderRow),
(err) => Log.error(err),
),
onReloadRows: () {
final payload = DatabaseViewIdPB(value: viewId);
DatabaseEventGetAllRows(payload).send().then((result) {
result.fold(
(rows) {
_rowCache.setInitialRows(rows.items);
},
(err) => Log.error(err),
);
});
},
);
_rowCache.onRowsChanged(

View File

@ -32,7 +32,6 @@ class DatabaseViewListener {
required ReorderAllRowsCallback onReorderAllRows,
required SingleRowCallback onReorderSingleRow,
required RowsVisibilityCallback onRowsVisibilityChanged,
required void Function() onReloadRows,
}) {
// Stop any existing listener
_listener?.stop();
@ -47,7 +46,6 @@ class DatabaseViewListener {
onReorderAllRows,
onReorderSingleRow,
onRowsVisibilityChanged,
onReloadRows,
),
);
}
@ -59,7 +57,6 @@ class DatabaseViewListener {
ReorderAllRowsCallback onReorderAllRows,
SingleRowCallback onReorderSingleRow,
RowsVisibilityCallback onRowsVisibilityChanged,
void Function() onReloadRows,
) {
switch (ty) {
case DatabaseNotification.DidUpdateViewRowsVisibility:
@ -94,9 +91,6 @@ class DatabaseViewListener {
(error) => onReorderSingleRow(FlowyResult.failure(error)),
);
break;
case DatabaseNotification.ReloadRows:
onReloadRows();
break;
default:
break;
}

View File

@ -653,7 +653,7 @@ class _BoardCardState extends State<_BoardCard> {
onTap: (context) => _openCard(
context: context,
databaseController: databaseController,
rowMeta: context.read<CardBloc>().state.rowMeta,
rowMeta: context.read<CardBloc>().rowController.rowMeta,
),
onShiftTap: (_) {
Focus.of(context).requestFocus();

View File

@ -26,6 +26,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
_dispatch();
_startListening();
_init();
rowController.initialize();
}
final FieldController fieldController;

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/row/row_service.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/calculations/calculations_row.dart';
@ -305,22 +307,26 @@ class _GridRowsState extends State<_GridRows> {
buildWhen: (previous, current) => previous.fields != current.fields,
builder: (context, state) {
return Flexible(
child: _WrapScrollView(
scrollController: widget.scrollController,
contentWidth: GridLayout.headerWidth(state.fields),
child: BlocConsumer<GridBloc, GridState>(
listenWhen: (previous, current) =>
previous.rowCount != current.rowCount,
listener: (context, state) => _evaluateFloatingCalculations(),
builder: (context, state) {
return ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(
scrollbars: false,
),
child: _renderList(context, state),
);
},
),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints layoutConstraits) {
return _WrapScrollView(
scrollController: widget.scrollController,
contentWidth: GridLayout.headerWidth(state.fields),
child: BlocConsumer<GridBloc, GridState>(
listenWhen: (previous, current) =>
previous.rowCount != current.rowCount,
listener: (context, state) => _evaluateFloatingCalculations(),
builder: (context, state) {
return ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(
scrollbars: false,
),
child: _renderList(context, state, layoutConstraits),
);
},
),
);
},
),
);
},
@ -330,19 +336,19 @@ class _GridRowsState extends State<_GridRows> {
Widget _renderList(
BuildContext context,
GridState state,
BoxConstraints layoutConstraints,
) {
// 1. GridRowBottomBar
// 2. GridCalculationsRow
// 3. Footer Padding
final itemCount = state.rowInfos.length + 3;
return Stack(
children: [
Positioned.fill(
child: ReorderableListView.builder(
/// This is a workaround related to
/// https://github.com/flutter/flutter/issues/25652
cacheExtent: 5000,
cacheExtent: max(layoutConstraints.maxHeight * 2, 500),
scrollController: widget.scrollController.verticalController,
physics: const ClampingScrollPhysics(),
buildDefaultDragHandles: false,
@ -421,7 +427,7 @@ class _GridRowsState extends State<_GridRows> {
);
final child = GridRow(
key: ValueKey(rowMeta.id),
key: ValueKey(rowId),
fieldController: databaseController.fieldController,
rowId: rowId,
viewId: viewId,

View File

@ -57,7 +57,7 @@ class _DatabaseViewSettingContent extends StatelessWidget {
builder: (context, state) {
return Padding(
padding: EdgeInsets.symmetric(
horizontal: GridSize.horizontalHeaderPadding + 40,
horizontal: GridSize.horizontalHeaderPadding,
),
child: DecoratedBox(
decoration: BoxDecoration(

View File

@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/mobile/presentation/database/card/card.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
import 'package:appflowy/plugins/database/application/row/row_cache.dart';
import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/row/action.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
@ -73,13 +74,18 @@ class _RowCardState extends State<RowCard> {
@override
void initState() {
super.initState();
final rowController = RowController(
viewId: widget.viewId,
rowMeta: widget.rowMeta,
rowCache: widget.rowCache,
);
_cardBloc = CardBloc(
fieldController: widget.fieldController,
viewId: widget.viewId,
groupFieldId: widget.groupingFieldId,
isEditing: widget.isEditing,
rowMeta: widget.rowMeta,
rowCache: widget.rowCache,
rowController: rowController,
)..add(const CardEvent.initial());
}
@ -143,7 +149,7 @@ class _RowCardState extends State<RowCard> {
popupBuilder: (_) {
return RowActionMenu.board(
viewId: _cardBloc.viewId,
rowId: _cardBloc.rowId,
rowId: _cardBloc.rowController.rowId,
groupId: widget.groupId,
);
},

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/application/row/row_service.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:flutter/foundation.dart';
@ -7,7 +8,6 @@ import 'package:flutter/foundation.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
import 'package:appflowy/plugins/database/application/row/row_cache.dart';
import 'package:appflowy/plugins/database/domain/row_listener.dart';
import 'package:appflowy/plugins/database/widgets/setting/field_visibility_extension.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -19,42 +19,35 @@ class CardBloc extends Bloc<CardEvent, CardState> {
required this.fieldController,
required this.groupFieldId,
required this.viewId,
required RowMetaPB rowMeta,
required RowCache rowCache,
required bool isEditing,
}) : rowId = rowMeta.id,
_rowListener = RowListener(rowMeta.id),
_rowCache = rowCache,
super(
required this.rowController,
}) : super(
CardState.initial(
rowMeta,
_makeCells(
fieldController,
groupFieldId,
rowCache.loadCells(rowMeta),
rowController,
),
isEditing,
rowController.rowMeta,
),
) {
_dispatch();
}
final FieldController fieldController;
final String rowId;
final String? groupFieldId;
final RowCache _rowCache;
final String viewId;
final RowListener _rowListener;
final RowController rowController;
VoidCallback? _rowCallback;
@override
Future<void> close() async {
if (_rowCallback != null) {
_rowCache.removeRowListener(_rowCallback!);
_rowCallback = null;
}
await _rowListener.stop();
await rowController.dispose();
return super.close();
}
@ -85,20 +78,17 @@ class CardBloc extends Bloc<CardEvent, CardState> {
}
Future<void> _startListening() async {
_rowCallback = _rowCache.addListener(
rowId: rowId,
rowController.addListener(
onRowChanged: (cellMap, reason) {
if (!isClosed) {
final cells = _makeCells(fieldController, groupFieldId, cellMap);
final cells =
_makeCells(fieldController, groupFieldId, rowController);
add(CardEvent.didReceiveCells(cells, reason));
}
},
);
_rowListener.start(
onMetaChanged: (rowMeta) {
onMetaChanged: () {
if (!isClosed) {
add(CardEvent.didUpdateRowMeta(rowMeta));
add(CardEvent.didUpdateRowMeta(rowController.rowMeta));
}
},
);
@ -108,16 +98,18 @@ class CardBloc extends Bloc<CardEvent, CardState> {
List<CellMeta> _makeCells(
FieldController fieldController,
String? groupFieldId,
List<CellContext> cellContexts,
RowController rowController,
) {
// Only show the non-hidden cells and cells that aren't of the grouping field
cellContexts.removeWhere((cellContext) {
final cellContext = rowController.loadCells();
cellContext.removeWhere((cellContext) {
final fieldInfo = fieldController.getField(cellContext.fieldId);
return fieldInfo == null ||
!(fieldInfo.visibility?.isVisibleState() ?? false) ||
(groupFieldId != null && cellContext.fieldId == groupFieldId);
});
return cellContexts
return cellContext
.map(
(cellCtx) => CellMeta(
fieldId: cellCtx.fieldId,
@ -157,19 +149,19 @@ class CellMeta with _$CellMeta {
class CardState with _$CardState {
const factory CardState({
required List<CellMeta> cells,
required RowMetaPB rowMeta,
required bool isEditing,
required RowMetaPB rowMeta,
ChangedReason? changeReason,
}) = _RowCardState;
factory CardState.initial(
RowMetaPB rowMeta,
List<CellMeta> cells,
bool isEditing,
RowMetaPB rowMeta,
) =>
CardState(
cells: cells,
rowMeta: rowMeta,
isEditing: isEditing,
rowMeta: rowMeta,
);
}

View File

@ -8,6 +8,7 @@ import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -202,8 +203,14 @@ class _URLAccessoryIconContainer extends StatelessWidget {
),
borderRadius: Corners.s6Border,
),
child: Center(
child: child,
child: FlowyHover(
style: HoverStyle(
backgroundColor: AFThemeExtension.of(context).background,
hoverColor: AFThemeExtension.of(context).lightGreyHover,
),
child: Center(
child: child,
),
),
);
}

View File

@ -372,7 +372,7 @@ class _NewTaskItemState extends State<NewTaskItem> {
? Theme.of(context).disabledColor
: Theme.of(context).colorScheme.primaryContainer,
fontColor: Theme.of(context).colorScheme.onPrimary,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
onPressed: _textEditingController.text.isEmpty
? null
: () {

View File

@ -499,11 +499,12 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
}
void _customizeBlockComponentBackgroundColorDecorator() {
if (!context.mounted) {
return;
}
blockComponentBackgroundColorDecorator = (Node node, String colorString) =>
buildEditorCustomizedColor(context, node, colorString);
blockComponentBackgroundColorDecorator = (Node node, String colorString) {
if (context.mounted) {
return buildEditorCustomizedColor(context, node, colorString);
}
return null;
};
}
void _initEditorL10n() => AppFlowyEditorL10n.current = EditorI18n();

File diff suppressed because it is too large Load Diff

View File

@ -121,6 +121,8 @@ extension ProviderTypePBExtension on ProviderTypePB {
return ProviderTypePB.Google;
case 'discord':
return ProviderTypePB.Discord;
case 'apple':
return ProviderTypePB.Apple;
default:
throw UnimplementedError();
}

View File

@ -1,16 +1,16 @@
import 'package:flutter/foundation.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
show UserProfilePB;
import 'package:appflowy_result/appflowy_result.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -208,6 +208,8 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
}
SignInState _stateFromCode(FlowyError error) {
Log.error('SignInState _stateFromCode: ${error.msg}');
switch (error.code) {
case ErrorCode.EmailFormatInvalid:
return state.copyWith(

View File

@ -1,11 +1,12 @@
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/user/presentation/router.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flutter/material.dart';
import 'package:toastification/toastification.dart';
void handleOpenWorkspaceError(BuildContext context, FlowyError error) {
Log.error(error);
@ -15,24 +16,24 @@ void handleOpenWorkspaceError(BuildContext context, FlowyError error) {
getIt<AuthRouter>().pushWorkspaceErrorScreen(context, userFolder, error);
break;
case ErrorCode.InvalidEncryptSecret:
showSnapBar(
case ErrorCode.HttpError:
showToastNotification(
context,
error.msg,
message: error.msg,
type: ToastificationType.error,
);
break;
case ErrorCode.HttpError:
showSnapBar(
context,
error.msg,
);
default:
showSnapBar(
showToastNotification(
context,
error.msg,
onClosed: () {
getIt<AuthService>().signOut();
runAppFlowy();
},
message: error.msg,
type: ToastificationType.error,
callbacks: ToastificationCallbacks(
onDismissed: (_) {
getIt<AuthService>().signOut();
runAppFlowy();
},
),
);
}
}

View File

@ -1,5 +1,3 @@
import 'package:flutter/material.dart';
import 'package:appflowy/core/frameless_window.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
@ -10,6 +8,7 @@ import 'package:appflowy/user/presentation/widgets/widgets.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class DesktopSignInScreen extends StatelessWidget {
@ -45,14 +44,14 @@ class DesktopSignInScreen extends StatelessWidget {
if (isAuthEnabled) ...[
const _OrDivider(),
const VSpace(10),
const VSpace(20),
const ThirdPartySignInButtons(),
],
const VSpace(20),
// anonymous sign in
const SignInAnonymousButtonV2(),
const VSpace(10),
const VSpace(16),
// sign in agreement
const SignInAgreement(),

View File

@ -1,4 +1,4 @@
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
@ -8,6 +8,7 @@ import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
@ -23,26 +24,26 @@ class MobileSignInScreen extends StatelessWidget {
return BlocBuilder<SignInBloc, SignInState>(
builder: (context, state) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 40),
padding: const EdgeInsets.symmetric(vertical: 38, horizontal: 40),
child: Column(
children: [
const Spacer(flex: 4),
_buildLogo(),
const VSpace(spacing * 2),
_buildWelcomeText(),
const VSpace(spacing),
_buildAppNameText(colorScheme),
const VSpace(spacing * 2),
const SignInWithMagicLinkButtons(),
const VSpace(spacing),
if (isAuthEnabled) _buildThirdPartySignInButtons(colorScheme),
const VSpace(spacing),
const SignInAnonymousButtonV2(),
const VSpace(spacing),
const VSpace(spacing * 1.5),
const SignInAgreement(),
const VSpace(spacing),
_buildSettingsButton(context),
if (!isAuthEnabled) const Spacer(flex: 2),
const Spacer(flex: 2),
const Spacer(),
Expanded(child: _buildSettingsButton(context)),
],
),
),
@ -51,19 +52,10 @@ class MobileSignInScreen extends StatelessWidget {
);
}
Widget _buildWelcomeText() {
return FlowyText(
LocaleKeys.welcomeTo.tr(),
textAlign: TextAlign.center,
fontSize: 32,
fontWeight: FontWeight.w700,
);
}
Widget _buildLogo() {
return const FlowySvg(
FlowySvgs.flowy_logo_xl,
size: Size.square(64),
size: Size.square(56),
blendMode: null,
);
}
@ -72,7 +64,7 @@ class MobileSignInScreen extends StatelessWidget {
return FlowyText(
LocaleKeys.appName.tr(),
textAlign: TextAlign.center,
fontSize: 32,
fontSize: 28,
color: const Color(0xFF00BCF0),
fontWeight: FontWeight.w700,
);
@ -89,6 +81,7 @@ class MobileSignInScreen extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 8),
child: FlowyText(
LocaleKeys.signIn_or.tr(),
fontSize: 12,
color: colorScheme.onSecondary,
),
),
@ -96,23 +89,45 @@ class MobileSignInScreen extends StatelessWidget {
],
),
const VSpace(16),
const ThirdPartySignInButtons(),
// expand third-party sign in buttons on Android by default.
// on iOS, the github and discord buttons are collapsed by default.
ThirdPartySignInButtons(
expanded: Platform.isAndroid,
),
],
);
}
Widget _buildSettingsButton(BuildContext context) {
return FlowyButton(
text: FlowyText(
LocaleKeys.signIn_settings.tr(),
textAlign: TextAlign.center,
fontSize: 12.0,
fontWeight: FontWeight.w500,
decoration: TextDecoration.underline,
),
onTap: () {
context.push(MobileLaunchSettingsPage.routeName);
},
return Row(
mainAxisSize: MainAxisSize.min,
children: [
FlowyButton(
useIntrinsicWidth: true,
text: FlowyText(
LocaleKeys.signIn_settings.tr(),
textAlign: TextAlign.center,
fontSize: 12.0,
// fontWeight: FontWeight.w500,
color: Colors.grey,
decoration: TextDecoration.underline,
),
onTap: () {
context.push(MobileLaunchSettingsPage.routeName);
},
),
const HSpace(24),
SignInAnonymousButtonV2(
child: FlowyText(
LocaleKeys.signIn_anonymous.tr(),
textAlign: TextAlign.center,
fontSize: 12.0,
// fontWeight: FontWeight.w500,
color: Colors.grey,
decoration: TextDecoration.underline,
),
),
],
);
}
}

View File

@ -1,5 +1,3 @@
import 'package:flutter/material.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/router.dart';
@ -7,6 +5,7 @@ import 'package:appflowy/user/presentation/screens/sign_in_screen/desktop_sign_i
import 'package:appflowy/user/presentation/screens/sign_in_screen/mobile_loading_screen.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/mobile_sign_in_screen.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../helpers/helpers.dart';
@ -21,16 +20,7 @@ class SignInScreen extends StatelessWidget {
return BlocProvider(
create: (context) => getIt<SignInBloc>(),
child: BlocConsumer<SignInBloc, SignInState>(
listener: (context, state) {
final successOrFail = state.successOrFail;
if (successOrFail != null) {
handleUserProfileResult(
successOrFail,
context,
getIt<AuthRouter>(),
);
}
},
listener: _showSignInError,
builder: (context, state) {
final isLoading = context.read<SignInBloc>().state.isSubmitting;
if (PlatformExtension.isMobile) {
@ -43,4 +33,15 @@ class SignInScreen extends StatelessWidget {
),
);
}
void _showSignInError(BuildContext context, SignInState state) {
final successOrFail = state.successOrFail;
if (successOrFail != null) {
handleUserProfileResult(
successOrFail,
context,
getIt<AuthRouter>(),
);
}
}
}

View File

@ -34,11 +34,19 @@ class _SignInWithMagicLinkButtonsState
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 48.0,
height: PlatformExtension.isMobile ? 38.0 : 48.0,
child: FlowyTextField(
autoFocus: false,
controller: controller,
borderRadius: BorderRadius.circular(4.0),
hintText: LocaleKeys.signIn_pleaseInputYourEmail.tr(),
hintStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: 14.0,
color: Theme.of(context).hintColor,
),
textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: 14.0,
),
keyboardType: TextInputType.emailAddress,
onSubmitted: (_) => _sendMagicLink(context, controller.text),
),
@ -88,14 +96,14 @@ class _ConfirmButton extends StatelessWidget {
if (PlatformExtension.isMobile) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 56),
minimumSize: const Size(double.infinity, 32),
maximumSize: const Size(double.infinity, 38),
),
onPressed: onTap,
child: FlowyText(
name,
fontSize: 14,
color: Theme.of(context).colorScheme.onPrimary,
fontWeight: FontWeight.w500,
),
);
} else {
@ -108,6 +116,7 @@ class _ConfirmButton extends StatelessWidget {
text: FlowyText.medium(
name,
textAlign: TextAlign.center,
color: Theme.of(context).colorScheme.onPrimary,
),
radius: Corners.s6Border,
),

View File

@ -21,7 +21,11 @@ class SignInAgreement extends StatelessWidget {
),
TextSpan(
text: '${LocaleKeys.web_termOfUse.tr()} ',
style: const TextStyle(color: Colors.blue, fontSize: 12),
style: const TextStyle(
color: Colors.grey,
fontSize: 12,
decoration: TextDecoration.underline,
),
mouseCursor: SystemMouseCursors.click,
recognizer: TapGestureRecognizer()
..onTap = () => afLaunchUrlString('https://appflowy.io/terms'),
@ -32,7 +36,11 @@ class SignInAgreement extends StatelessWidget {
),
TextSpan(
text: LocaleKeys.web_privacyPolicy.tr(),
style: const TextStyle(color: Colors.blue, fontSize: 12),
style: const TextStyle(
color: Colors.grey,
fontSize: 12,
decoration: TextDecoration.underline,
),
mouseCursor: SystemMouseCursors.click,
recognizer: TapGestureRecognizer()
..onTap = () => afLaunchUrlString('https://appflowy.io/privacy'),

View File

@ -89,8 +89,11 @@ class SignInAnonymousButton extends StatelessWidget {
class SignInAnonymousButtonV2 extends StatelessWidget {
const SignInAnonymousButtonV2({
super.key,
this.child,
});
final Widget? child;
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInBloc, SignInState>(
@ -126,11 +129,12 @@ class SignInAnonymousButtonV2 extends StatelessWidget {
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: onTap,
child: FlowyText(
text,
color: Colors.blue,
fontSize: 12,
),
child: child ??
FlowyText(
text,
color: Colors.blue,
fontSize: 12,
),
),
);
},

View File

@ -20,7 +20,7 @@ class MobileSignInOrLogoutButton extends StatelessWidget {
return GestureDetector(
onTap: onPressed,
child: Container(
height: 48,
height: 38,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(4),
@ -54,7 +54,7 @@ class MobileSignInOrLogoutButton extends StatelessWidget {
FlowyText(
labelText,
fontSize: 14.0,
fontWeight: FontWeight.w500,
fontWeight: FontWeight.w400,
),
],
),

View File

@ -0,0 +1,137 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/base/gesture.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
enum ThirdPartySignInButtonType {
apple,
google,
github,
discord,
anonymous;
FlowySvgData get icon {
switch (this) {
case ThirdPartySignInButtonType.apple:
return FlowySvgs.m_apple_icon_xl;
case ThirdPartySignInButtonType.google:
return FlowySvgs.m_google_icon_xl;
case ThirdPartySignInButtonType.github:
return FlowySvgs.m_github_icon_xl;
case ThirdPartySignInButtonType.discord:
return FlowySvgs.m_discord_icon_xl;
case ThirdPartySignInButtonType.anonymous:
return FlowySvgs.m_discord_icon_xl;
}
}
String get labelText {
switch (this) {
case ThirdPartySignInButtonType.apple:
return LocaleKeys.signIn_signInWithApple.tr();
case ThirdPartySignInButtonType.google:
return LocaleKeys.signIn_signInWithGoogle.tr();
case ThirdPartySignInButtonType.github:
return LocaleKeys.signIn_signInWithGithub.tr();
case ThirdPartySignInButtonType.discord:
return LocaleKeys.signIn_signInWithDiscord.tr();
case ThirdPartySignInButtonType.anonymous:
return 'Anonymous session';
}
}
// https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple
Color backgroundColor(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
switch (this) {
case ThirdPartySignInButtonType.apple:
return isDarkMode ? Colors.white : Colors.black;
case ThirdPartySignInButtonType.google:
case ThirdPartySignInButtonType.github:
case ThirdPartySignInButtonType.discord:
case ThirdPartySignInButtonType.anonymous:
return isDarkMode ? Colors.black : Colors.grey.shade100;
}
}
Color textColor(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
switch (this) {
case ThirdPartySignInButtonType.apple:
return isDarkMode ? Colors.black : Colors.white;
case ThirdPartySignInButtonType.google:
case ThirdPartySignInButtonType.github:
case ThirdPartySignInButtonType.discord:
case ThirdPartySignInButtonType.anonymous:
return isDarkMode ? Colors.white : Colors.black;
}
}
BlendMode? get blendMode {
switch (this) {
case ThirdPartySignInButtonType.apple:
case ThirdPartySignInButtonType.github:
return BlendMode.srcIn;
default:
return null;
}
}
}
class MobileThirdPartySignInButton extends StatelessWidget {
const MobileThirdPartySignInButton({
super.key,
this.height = 38,
this.fontSize = 14.0,
required this.onPressed,
required this.type,
});
final VoidCallback onPressed;
final double height;
final double fontSize;
final ThirdPartySignInButtonType type;
@override
Widget build(BuildContext context) {
final style = Theme.of(context);
return AnimatedGestureDetector(
scaleFactor: 1.0,
onTapUp: onPressed,
child: Container(
height: height,
decoration: BoxDecoration(
color: type.backgroundColor(context),
borderRadius: const BorderRadius.all(
Radius.circular(4),
),
border: Border.all(
color: style.colorScheme.outline,
width: 0.5,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (type != ThirdPartySignInButtonType.anonymous)
FlowySvg(
type.icon,
size: Size.square(fontSize),
blendMode: type.blendMode,
color: type.textColor(context),
),
const HSpace(8.0),
FlowyText(
type.labelText,
fontSize: fontSize,
color: type.textColor(context),
),
],
),
),
);
}
}

View File

@ -1,126 +1,167 @@
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/user/application/sign_in_bloc.dart';
import 'package:appflowy/user/presentation/presentation.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ThirdPartySignInButtons extends StatelessWidget {
import 'third_party_sign_in_button.dart';
@visibleForTesting
const Key signInWithGoogleButtonKey = Key('signInWithGoogleButton');
class ThirdPartySignInButtons extends StatefulWidget {
/// Used in DesktopSignInScreen, MobileSignInScreen and SettingThirdPartyLogin
const ThirdPartySignInButtons({super.key});
@override
Widget build(BuildContext context) {
// Get themeMode from AppearanceSettingsCubit
// When user changes themeMode, it changes the state in AppearanceSettingsCubit, but the themeMode for the MaterialApp won't change, it only got updated(get value from AppearanceSettingsCubit) when user open the app again. Thus, we should get themeMode from AppearanceSettingsCubit rather than MediaQuery.
final themeModeFromCubit =
context.watch<AppearanceSettingsCubit>().state.themeMode;
final isDarkMode = themeModeFromCubit == ThemeMode.system
? MediaQuery.of(context).platformBrightness == Brightness.dark
: themeModeFromCubit == ThemeMode.dark;
return BlocBuilder<SignInBloc, SignInState>(
builder: (context, state) {
final (googleText, githubText, discordText) = switch (state.loginType) {
LoginType.signIn => (
LocaleKeys.signIn_signInWithGoogle.tr(),
LocaleKeys.signIn_signInWithGithub.tr(),
LocaleKeys.signIn_signInWithDiscord.tr()
),
LoginType.signUp => (
LocaleKeys.signIn_signUpWithGoogle.tr(),
LocaleKeys.signIn_signUpWithGithub.tr(),
LocaleKeys.signIn_signUpWithDiscord.tr()
),
};
return Column(
children: [
_ThirdPartySignInButton(
key: const Key('signInWithGoogleButton'),
icon: FlowySvgs.google_mark_xl,
labelText: googleText,
onPressed: () {
_signInWithGoogle(context);
},
),
const VSpace(8),
_ThirdPartySignInButton(
icon: isDarkMode
? FlowySvgs.github_mark_white_xl
: FlowySvgs.github_mark_black_xl,
labelText: githubText,
onPressed: () {
_signInWithGithub(context);
},
),
const VSpace(8),
_ThirdPartySignInButton(
icon: isDarkMode
? FlowySvgs.discord_mark_white_xl
: FlowySvgs.discord_mark_blurple_xl,
labelText: discordText,
onPressed: () {
_signInWithDiscord(context);
},
),
],
);
},
);
}
}
class _ThirdPartySignInButton extends StatelessWidget {
/// Build button based on current Platform(mobile or desktop).
const _ThirdPartySignInButton({
const ThirdPartySignInButtons({
super.key,
required this.icon,
required this.labelText,
required this.onPressed,
this.expanded = false,
});
final FlowySvgData icon;
final String labelText;
final bool expanded;
final VoidCallback onPressed;
@override
State<ThirdPartySignInButtons> createState() =>
_ThirdPartySignInButtonsState();
}
class _ThirdPartySignInButtonsState extends State<ThirdPartySignInButtons> {
bool expanded = false;
@override
void initState() {
super.initState();
expanded = widget.expanded;
}
@override
Widget build(BuildContext context) {
if (PlatformExtension.isMobile) {
return MobileSignInOrLogoutButton(
icon: icon,
labelText: labelText,
onPressed: onPressed,
if (PlatformExtension.isDesktopOrWeb) {
const padding = 16.0;
return Column(
children: [
_DesktopSignInButton(
key: signInWithGoogleButtonKey,
type: ThirdPartySignInButtonType.google,
onPressed: () {
_signInWithGoogle(context);
},
),
const VSpace(padding),
_DesktopSignInButton(
type: ThirdPartySignInButtonType.github,
onPressed: () {
_signInWithGithub(context);
},
),
const VSpace(padding),
_DesktopSignInButton(
type: ThirdPartySignInButtonType.discord,
onPressed: () {
_signInWithDiscord(context);
},
),
],
);
} else {
return _DesktopSignInButton(
icon: icon,
labelText: labelText,
onPressed: onPressed,
const padding = 8.0;
return BlocBuilder<SignInBloc, SignInState>(
builder: (context, state) {
return Column(
children: [
if (Platform.isIOS) ...[
MobileThirdPartySignInButton(
type: ThirdPartySignInButtonType.apple,
onPressed: () {
_signInWithApple(context);
},
),
const VSpace(padding),
],
MobileThirdPartySignInButton(
type: ThirdPartySignInButtonType.google,
onPressed: () {
_signInWithGoogle(context);
},
),
if (expanded) ...[
const VSpace(padding),
MobileThirdPartySignInButton(
type: ThirdPartySignInButtonType.github,
onPressed: () {
_signInWithGithub(context);
},
),
const VSpace(padding),
MobileThirdPartySignInButton(
type: ThirdPartySignInButtonType.discord,
onPressed: () {
_signInWithDiscord(context);
},
),
],
if (!expanded) ...[
const VSpace(padding * 2),
GestureDetector(
onTap: () {
setState(() {
expanded = !expanded;
});
},
child: FlowyText(
LocaleKeys.signIn_continueAnotherWay.tr(),
color: Theme.of(context).colorScheme.onSurface,
decoration: TextDecoration.underline,
fontSize: 14,
),
),
],
],
);
},
);
}
}
void _signInWithApple(BuildContext context) {
context.read<SignInBloc>().add(
const SignInEvent.signedInWithOAuth('apple'),
);
}
void _signInWithGoogle(BuildContext context) {
context.read<SignInBloc>().add(
const SignInEvent.signedInWithOAuth('google'),
);
}
void _signInWithGithub(BuildContext context) {
context
.read<SignInBloc>()
.add(const SignInEvent.signedInWithOAuth('github'));
}
void _signInWithDiscord(BuildContext context) {
context
.read<SignInBloc>()
.add(const SignInEvent.signedInWithOAuth('discord'));
}
}
class _DesktopSignInButton extends StatelessWidget {
const _DesktopSignInButton({
required this.icon,
required this.labelText,
super.key,
required this.type,
required this.onPressed,
});
final FlowySvgData icon;
final String labelText;
final ThirdPartySignInButtonType type;
final VoidCallback onPressed;
@override
@ -139,8 +180,8 @@ class _DesktopSignInButton extends StatelessWidget {
// Some icons are not square, so we just use a fixed width here.
width: 24,
child: FlowySvg(
icon,
blendMode: null,
type.icon,
blendMode: type.blendMode,
),
),
),
@ -148,7 +189,7 @@ class _DesktopSignInButton extends StatelessWidget {
padding: const EdgeInsets.only(left: 8),
alignment: Alignment.centerLeft,
child: FlowyText(
labelText,
type.labelText,
fontSize: 14,
),
),
@ -177,19 +218,3 @@ class _DesktopSignInButton extends StatelessWidget {
);
}
}
void _signInWithGoogle(BuildContext context) {
context.read<SignInBloc>().add(
const SignInEvent.signedInWithOAuth('google'),
);
}
void _signInWithGithub(BuildContext context) {
context.read<SignInBloc>().add(const SignInEvent.signedInWithOAuth('github'));
}
void _signInWithDiscord(BuildContext context) {
context
.read<SignInBloc>()
.add(const SignInEvent.signedInWithOAuth('discord'));
}

View File

@ -1,7 +1,7 @@
export 'magic_link_sign_in_buttons.dart';
export 'sign_in_anonymous_button.dart';
export 'sign_in_or_logout_button.dart';
export 'third_party_sign_in_button.dart';
// export 'switch_sign_in_sign_up_button.dart';
export 'third_party_sign_in_buttons.dart';
export 'sign_in_agreement.dart';

View File

@ -559,7 +559,10 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
return true;
}
final viewId = fixedUuid(user.id.toInt(), UuidType.publicSpace);
final viewId = fixedUuid(
user.id.toInt() + (_workspaceId?.hashCode ?? 0),
UuidType.publicSpace,
);
final publicSpace = await _createSpace(
name: 'Shared',
icon: builtInSpaceIcons.first,

View File

@ -3,6 +3,7 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart';
@ -31,7 +32,6 @@ class SidebarSpace extends StatelessWidget {
@override
Widget build(BuildContext context) {
// const sectionPadding = 16.0;
return ValueListenableBuilder(
valueListenable: getIt<MenuSharedState>().notifier,
builder: (context, value, child) {
@ -89,6 +89,8 @@ class _SpaceState extends State<_Space> {
@override
Widget build(BuildContext context) {
final currentWorkspace =
context.watch<UserWorkspaceBloc>().state.currentWorkspace;
return BlocBuilder<SpaceBloc, SpaceState>(
builder: (context, state) {
if (state.spaces.isEmpty) {
@ -115,7 +117,12 @@ class _SpaceState extends State<_Space> {
onEnter: (_) => isHovered.value = true,
onExit: (_) => isHovered.value = false,
child: SpacePages(
key: ValueKey(currentSpace.id),
key: ValueKey(
Object.hashAll([
currentWorkspace?.workspaceId ?? '',
currentSpace.id,
]),
),
isExpandedNotifier: isExpandedNotifier,
space: currentSpace,
isHovered: isHovered,

View File

@ -107,7 +107,6 @@ class SingleSettingAction extends StatelessWidget {
radius: Corners.s8Border,
hoverColor: hoverColor(context),
fontColor: fontColor(context),
textColor: fontColor(context),
fontHoverColor: fontHoverColor(context),
borderColor: borderColor(context),
fontSize: 12,

View File

@ -447,7 +447,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
LocaleKeys.button_confirm.tr(),
constraints: const BoxConstraints.tightFor(height: 42),
mainAxisAlignment: MainAxisAlignment.center,
textColor: Theme.of(context).colorScheme.onPrimary,
fontColor: Theme.of(context).colorScheme.onPrimary,
fillColor: Theme.of(context).primaryColor,
onPressed: () {
if (isStartDay) {

View File

@ -303,14 +303,18 @@ void showToastNotification(
required String message,
String? description,
ToastificationType type = ToastificationType.success,
ToastificationCallbacks? callbacks,
double bottomPadding = 100,
}) {
if (PlatformExtension.isMobile) {
toastification.showCustom(
alignment: Alignment.bottomCenter,
autoCloseDuration: const Duration(milliseconds: 3000),
callbacks: callbacks ?? const ToastificationCallbacks(),
builder: (_, __) => _MToast(
message: message,
type: type,
bottomPadding: bottomPadding,
),
);
return;
@ -346,10 +350,12 @@ class _MToast extends StatelessWidget {
const _MToast({
required this.message,
this.type = ToastificationType.success,
this.bottomPadding = 100,
});
final String message;
final ToastificationType type;
final double bottomPadding;
@override
Widget build(BuildContext context) {
@ -362,7 +368,7 @@ class _MToast extends StatelessWidget {
);
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.only(bottom: 100, left: 16, right: 16),
padding: EdgeInsets.only(bottom: bottomPadding, left: 16, right: 16),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 13.0),
decoration: BoxDecoration(

View File

@ -297,7 +297,6 @@ class FlowyTextButton extends StatelessWidget {
this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
this.hoverColor,
this.fillColor,
this.textColor,
this.heading,
this.radius,
this.mainAxisAlignment = MainAxisAlignment.start,
@ -353,7 +352,6 @@ class FlowyTextButton extends StatelessWidget {
final Widget? heading;
final Color? hoverColor;
final Color? fillColor;
final Color? textColor;
final BorderRadius? radius;
final MainAxisAlignment mainAxisAlignment;
final String? tooltip;
@ -376,9 +374,10 @@ class FlowyTextButton extends StatelessWidget {
children.add(FlowyText(
text,
overflow: overflow,
color: textColor,
color: fontColor ?? Theme.of(context).colorScheme.onPrimary,
textAlign: TextAlign.center,
lineHeight: lineHeight,
fontSize: fontSize,
));
Widget child = Row(

View File

@ -38,6 +38,7 @@ class FlowyTextField extends StatefulWidget {
final bool isDense;
final bool readOnly;
final Color? enableBorderColor;
final BorderRadius? borderRadius;
const FlowyTextField({
super.key,
@ -74,6 +75,7 @@ class FlowyTextField extends StatefulWidget {
this.isDense = true,
this.readOnly = false,
this.enableBorderColor,
this.borderRadius,
});
@override
@ -180,7 +182,7 @@ class FlowyTextFieldState extends State<FlowyTextField> {
(widget.maxLines == null || widget.maxLines! > 1) ? 12 : 0,
),
enabledBorder: OutlineInputBorder(
borderRadius: Corners.s8Border,
borderRadius: widget.borderRadius ?? Corners.s8Border,
borderSide: BorderSide(
color: widget.enableBorderColor ??
Theme.of(context).colorScheme.outline,
@ -202,7 +204,7 @@ class FlowyTextFieldState extends State<FlowyTextField> {
suffixText: widget.showCounter ? _suffixText() : "",
counterText: "",
focusedBorder: OutlineInputBorder(
borderRadius: Corners.s8Border,
borderRadius: widget.borderRadius ?? Corners.s8Border,
borderSide: BorderSide(
color: widget.readOnly
? widget.enableBorderColor ??
@ -214,13 +216,13 @@ class FlowyTextFieldState extends State<FlowyTextField> {
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
),
borderRadius: Corners.s8Border,
borderRadius: widget.borderRadius ?? Corners.s8Border,
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
),
borderRadius: Corners.s8Border,
borderRadius: widget.borderRadius ?? Corners.s8Border,
),
prefixIcon: widget.prefixIcon,
suffixIcon: widget.suffixIcon,

View File

@ -51,11 +51,9 @@ class RoundedTextButton extends StatelessWidget {
radius: borderRadius ?? Corners.s6Border,
fontColor: textColor ?? Theme.of(context).colorScheme.onPrimary,
fillColor: fillColor ?? Theme.of(context).colorScheme.primary,
textColor: textColor,
hoverColor:
hoverColor ?? Theme.of(context).colorScheme.primaryContainer,
padding: padding,
),
),
);

View File

@ -53,8 +53,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "8e17d14"
resolved-ref: "8e17d1447eea0b57ff92e31dbe88796ce759fb37"
ref: a64a516
resolved-ref: a64a5165e79bd2424e594b793843a7158e7d4fb4
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git
version: "3.2.0"

View File

@ -190,7 +190,7 @@ dependency_overrides:
appflowy_editor:
git:
url: https://github.com/AppFlowy-IO/appflowy-editor.git
ref: "8e17d14"
ref: "a64a516"
appflowy_editor_plugins:
git:

View File

@ -172,7 +172,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bincode",
@ -192,7 +192,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bytes",
@ -291,6 +291,17 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "async-lock"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
"event-listener",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-stream"
version = "0.3.5"
@ -826,7 +837,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"again",
"anyhow",
@ -877,7 +888,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -890,7 +901,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"futures-channel",
"futures-util",
@ -964,7 +975,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -989,7 +1000,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"async-trait",
@ -1018,7 +1029,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -1038,7 +1049,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"bytes",
@ -1057,7 +1068,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -1100,7 +1111,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"async-stream",
@ -1138,7 +1149,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bincode",
@ -1163,7 +1174,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"async-trait",
@ -1180,7 +1191,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"collab",
@ -1209,6 +1220,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "console"
version = "0.14.1"
@ -1426,7 +1446,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa 1.0.6",
"phf 0.8.0",
"phf 0.11.2",
"smallvec",
]
@ -1551,7 +1571,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -1864,6 +1884,27 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "event-listener"
version = "5.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
dependencies = [
"event-listener",
"pin-project-lite",
]
[[package]]
name = "faccess"
version = "0.2.4"
@ -3076,7 +3117,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"futures-util",
@ -3093,7 +3134,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -3525,7 +3566,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bytes",
@ -4615,6 +4656,12 @@ dependencies = [
"system-deps 6.1.1",
]
[[package]]
name = "parking"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -6122,7 +6169,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -8400,12 +8447,14 @@ dependencies = [
[[package]]
name = "yrs"
version = "0.19.2"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8ca5126331b9a5ef5bb10f3f1c3d01b05f298d348c66f8fb15497d83ee73176"
checksum = "a8fc56b25e3aaf4b81a73f2a9a68ceae1e02d9005552e24058cfb9f96db73f33"
dependencies = [
"arc-swap",
"atomic_refcell",
"async-lock",
"async-trait",
"dashmap 6.0.1",
"fastrand",
"serde",
"serde_json",

View File

@ -53,7 +53,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ae3833ea91c238a66ca7bda63763d1d654740fb4" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5badffc97b17984d5f25a178c0c5a477338039c4" }
[dependencies]
serde_json.workspace = true
@ -116,13 +116,13 @@ custom-protocol = ["tauri/custom-protocol"]
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
# Working directory: frontend
# To update the commit ID, run:

View File

@ -68,7 +68,7 @@ const createServer = async (req: Request) => {
logger.info(`Request URL: ${hostname}${reqUrl.pathname}`);
if (['/after-payment', '/login'].includes(reqUrl.pathname)) {
if (['/after-payment', '/login', '/as-template'].includes(reqUrl.pathname)) {
timer();
const htmlData = fs.readFileSync(indexPath, 'utf8');
const $ = load(htmlData);

View File

@ -73,6 +73,7 @@
"react-datepicker": "^4.23.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.13",
"react-hook-form": "^7.52.2",
"react-hot-toast": "^2.4.1",
"react-i18next": "^14.1.0",
"react-katex": "^3.0.1",
@ -137,6 +138,7 @@
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.13",
"axios-mock-adapter": "^2.0.0",
"babel-jest": "^29.6.2",
"chalk": "^4.1.2",
"cheerio": "1.0.0-rc.12",

View File

@ -152,6 +152,9 @@ dependencies:
react-error-boundary:
specifier: ^4.0.13
version: 4.0.13(react@18.2.0)
react-hook-form:
specifier: ^7.52.2
version: 7.52.2(react@18.2.0)
react-hot-toast:
specifier: ^2.4.1
version: 2.4.1(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0)
@ -340,6 +343,9 @@ devDependencies:
autoprefixer:
specifier: ^10.4.13
version: 10.4.13(postcss@8.4.21)
axios-mock-adapter:
specifier: ^2.0.0
version: 2.0.0(axios@1.7.2)
babel-jest:
specifier: ^29.6.2
version: 29.6.2(@babel/core@7.24.3)
@ -4945,6 +4951,16 @@ packages:
/aws4@1.12.0:
resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==}
/axios-mock-adapter@2.0.0(axios@1.7.2):
resolution: {integrity: sha512-D/K0J5Zm6KvaMTnsWrBQZWLzKN9GxUFZEa0mx2qeEHXDeTugCoplWehy8y36dj5vuSjhe1u/Dol8cZ8lzzmDew==}
peerDependencies:
axios: '>= 0.17.0'
dependencies:
axios: 1.7.2
fast-deep-equal: 3.1.3
is-buffer: 2.0.5
dev: true
/axios@1.7.2:
resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==}
dependencies:
@ -4953,7 +4969,6 @@ packages:
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
dev: false
/b4a@1.6.6:
resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==}
@ -6709,7 +6724,6 @@ packages:
peerDependenciesMeta:
debug:
optional: true
dev: false
/for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@ -7289,6 +7303,11 @@ packages:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
dev: false
/is-buffer@2.0.5:
resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
engines: {node: '>=4'}
dev: true
/is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
@ -9258,7 +9277,6 @@ packages:
/proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: false
/psl@1.9.0:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
@ -9512,6 +9530,15 @@ packages:
/react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
/react-hook-form@7.52.2(react@18.2.0):
resolution: {integrity: sha512-pqfPEbERnxxiNMPd0bzmt1tuaPcVccywFDpyk2uV5xCIBphHV5T8SVnX9/o3kplPE1zzKt77+YIoq+EMwJp56A==}
engines: {node: '>=18.0.0'}
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
dependencies:
react: 18.2.0
dev: false
/react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==}
engines: {node: '>=10'}

View File

@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bincode",
@ -183,7 +183,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bytes",
@ -301,6 +301,17 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "async-lock"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
"event-listener",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-stream"
version = "0.3.5"
@ -800,7 +811,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"again",
"anyhow",
@ -851,7 +862,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -864,7 +875,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"futures-channel",
"futures-util",
@ -947,7 +958,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -972,7 +983,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"async-trait",
@ -1001,7 +1012,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -1021,7 +1032,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"bytes",
@ -1040,7 +1051,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"arc-swap",
@ -1083,7 +1094,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"async-stream",
@ -1121,7 +1132,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bincode",
@ -1146,7 +1157,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"async-trait",
@ -1163,7 +1174,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=97163517303bb0ed468992a4511aac6eb8775a4d#97163517303bb0ed468992a4511aac6eb8775a4d"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=49cf2206d7494bb3006402b807e7f171905213e3#49cf2206d7494bb3006402b807e7f171905213e3"
dependencies = [
"anyhow",
"collab",
@ -1192,6 +1203,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "console"
version = "0.14.1"
@ -1416,7 +1436,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa 1.0.10",
"phf 0.8.0",
"phf 0.11.2",
"smallvec",
]
@ -1541,7 +1561,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -1894,6 +1914,27 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
[[package]]
name = "event-listener"
version = "5.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
dependencies = [
"event-listener",
"pin-project-lite",
]
[[package]]
name = "faccess"
version = "0.2.4"
@ -3143,7 +3184,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"futures-util",
@ -3160,7 +3201,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -3597,7 +3638,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"bytes",
@ -4677,6 +4718,12 @@ dependencies = [
"system-deps 6.2.2",
]
[[package]]
name = "parking"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -6186,7 +6233,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ae3833ea91c238a66ca7bda63763d1d654740fb4#ae3833ea91c238a66ca7bda63763d1d654740fb4"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5badffc97b17984d5f25a178c0c5a477338039c4#5badffc97b17984d5f25a178c0c5a477338039c4"
dependencies = [
"anyhow",
"app-error",
@ -8658,12 +8705,14 @@ dependencies = [
[[package]]
name = "yrs"
version = "0.19.2"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8ca5126331b9a5ef5bb10f3f1c3d01b05f298d348c66f8fb15497d83ee73176"
checksum = "a8fc56b25e3aaf4b81a73f2a9a68ceae1e02d9005552e24058cfb9f96db73f33"
dependencies = [
"arc-swap",
"atomic_refcell",
"async-lock",
"async-trait",
"dashmap 6.0.1",
"fastrand",
"serde",
"serde_json",

View File

@ -52,7 +52,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ae3833ea91c238a66ca7bda63763d1d654740fb4" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5badffc97b17984d5f25a178c0c5a477338039c4" }
[dependencies]
serde_json.workspace = true
@ -116,13 +116,13 @@ custom-protocol = ["tauri/custom-protocol"]
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "97163517303bb0ed468992a4511aac6eb8775a4d" }
collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "49cf2206d7494bb3006402b807e7f171905213e3" }
# Working directory: frontend
# To update the commit ID, run:

View File

@ -34,6 +34,7 @@ export enum BlockType {
TableBlock = 'table',
TableCell = 'table/cell',
LinkPreview = 'link_preview',
FileBlock = 'file',
}
export enum InlineBlockType {
@ -85,6 +86,18 @@ export interface LinkPreviewBlockData extends BlockData {
url?: string;
}
export enum FieldURLType {
Upload = 2,
Link = 1,
}
export interface FileBlockData extends BlockData {
name: string;
uploaded_at: number;
url: string;
url_type: FieldURLType;
}
export enum ImageType {
Local = 0,
Internal = 1,
@ -271,151 +284,151 @@ export enum YjsDatabaseKey {
export interface YDoc extends Y.Doc {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getMap(key: YjsEditorKey.data_section): YSharedRoot | any;
getMap (key: YjsEditorKey.data_section): YSharedRoot | any;
}
export interface YDatabaseRow extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): RowId;
get (key: YjsDatabaseKey.id): RowId;
get(key: YjsDatabaseKey.height): string;
get (key: YjsDatabaseKey.height): string;
get(key: YjsDatabaseKey.visibility): boolean;
get (key: YjsDatabaseKey.visibility): boolean;
get(key: YjsDatabaseKey.created_at): CreatedAt;
get (key: YjsDatabaseKey.created_at): CreatedAt;
get(key: YjsDatabaseKey.last_modified): LastModified;
get (key: YjsDatabaseKey.last_modified): LastModified;
get(key: YjsDatabaseKey.cells): YDatabaseCells;
get (key: YjsDatabaseKey.cells): YDatabaseCells;
}
export interface YDatabaseCells extends Y.Map<unknown> {
get(key: FieldId): YDatabaseCell;
get (key: FieldId): YDatabaseCell;
}
export type EndTimestamp = string;
export type ReminderId = string;
export interface YDatabaseCell extends Y.Map<unknown> {
get(key: YjsDatabaseKey.created_at): CreatedAt;
get (key: YjsDatabaseKey.created_at): CreatedAt;
get(key: YjsDatabaseKey.last_modified): LastModified;
get (key: YjsDatabaseKey.last_modified): LastModified;
get(key: YjsDatabaseKey.field_type): string;
get (key: YjsDatabaseKey.field_type): string;
get(key: YjsDatabaseKey.data): object | string | boolean | number;
get (key: YjsDatabaseKey.data): object | string | boolean | number;
get(key: YjsDatabaseKey.end_timestamp): EndTimestamp;
get (key: YjsDatabaseKey.end_timestamp): EndTimestamp;
get(key: YjsDatabaseKey.include_time): boolean;
get (key: YjsDatabaseKey.include_time): boolean;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.is_range): boolean;
get (key: YjsDatabaseKey.is_range): boolean;
get(key: YjsDatabaseKey.reminder_id): ReminderId;
get (key: YjsDatabaseKey.reminder_id): ReminderId;
}
export interface YSharedRoot extends Y.Map<unknown> {
get(key: YjsEditorKey.document): YDocument;
get (key: YjsEditorKey.document): YDocument;
get(key: YjsEditorKey.folder): YFolder;
get (key: YjsEditorKey.folder): YFolder;
get(key: YjsEditorKey.database): YDatabase;
get (key: YjsEditorKey.database): YDatabase;
get(key: YjsEditorKey.database_row): YDatabaseRow;
get (key: YjsEditorKey.database_row): YDatabaseRow;
}
export interface YFolder extends Y.Map<unknown> {
get(key: YjsFolderKey.views): YViews;
get (key: YjsFolderKey.views): YViews;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.meta): YFolderMeta;
get (key: YjsFolderKey.meta): YFolderMeta;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.relation): YFolderRelation;
get (key: YjsFolderKey.relation): YFolderRelation;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.section): YFolderSection;
get (key: YjsFolderKey.section): YFolderSection;
}
export interface YViews extends Y.Map<unknown> {
get(key: ViewId): YView;
get (key: ViewId): YView;
}
export interface YView extends Y.Map<unknown> {
get(key: YjsFolderKey.id): ViewId;
get (key: YjsFolderKey.id): ViewId;
get(key: YjsFolderKey.bid): string;
get (key: YjsFolderKey.bid): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.name): string;
get (key: YjsFolderKey.name): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.icon | YjsFolderKey.extra): string;
get (key: YjsFolderKey.icon | YjsFolderKey.extra): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsFolderKey.layout): string;
get (key: YjsFolderKey.layout): string;
}
export interface YFolderRelation extends Y.Map<unknown> {
get(key: ViewId): Y.Array<ViewId>;
get (key: ViewId): Y.Array<ViewId>;
}
export interface YFolderMeta extends Y.Map<unknown> {
get(key: YjsFolderKey.current_view | YjsFolderKey.current_workspace): string;
get (key: YjsFolderKey.current_view | YjsFolderKey.current_workspace): string;
}
export interface YFolderSection extends Y.Map<unknown> {
get(key: YjsFolderKey.favorite | YjsFolderKey.private | YjsFolderKey.recent | YjsFolderKey.trash): YFolderSectionItem;
get (key: YjsFolderKey.favorite | YjsFolderKey.private | YjsFolderKey.recent | YjsFolderKey.trash): YFolderSectionItem;
}
export interface YFolderSectionItem extends Y.Map<unknown> {
get(key: string): Y.Array<unknown>;
get (key: string): Y.Array<unknown>;
}
export interface YDocument extends Y.Map<unknown> {
get(key: YjsEditorKey.blocks | YjsEditorKey.page_id | YjsEditorKey.meta): YBlocks | YMeta | string;
get (key: YjsEditorKey.blocks | YjsEditorKey.page_id | YjsEditorKey.meta): YBlocks | YMeta | string;
}
export interface YBlocks extends Y.Map<unknown> {
get(key: BlockId): YBlock;
get (key: BlockId): YBlock;
}
export interface YBlock extends Y.Map<unknown> {
get(key: YjsEditorKey.block_id | YjsEditorKey.block_parent): BlockId;
get (key: YjsEditorKey.block_id | YjsEditorKey.block_parent): BlockId;
get(key: YjsEditorKey.block_type): BlockType;
get (key: YjsEditorKey.block_type): BlockType;
get(key: YjsEditorKey.block_data): string;
get (key: YjsEditorKey.block_data): string;
get(key: YjsEditorKey.block_children): ChildrenId;
get (key: YjsEditorKey.block_children): ChildrenId;
get(key: YjsEditorKey.block_external_id): ExternalId;
get (key: YjsEditorKey.block_external_id): ExternalId;
}
export interface YMeta extends Y.Map<unknown> {
get(key: YjsEditorKey.children_map | YjsEditorKey.text_map): YChildrenMap | YTextMap;
get (key: YjsEditorKey.children_map | YjsEditorKey.text_map): YChildrenMap | YTextMap;
}
export interface YChildrenMap extends Y.Map<unknown> {
get(key: ChildrenId): Y.Array<BlockId>;
get (key: ChildrenId): Y.Array<BlockId>;
}
export interface YTextMap extends Y.Map<unknown> {
get(key: ExternalId): Y.Text;
get (key: ExternalId): Y.Text;
}
export interface YDatabase extends Y.Map<unknown> {
get(key: YjsDatabaseKey.views): YDatabaseViews;
get (key: YjsDatabaseKey.views): YDatabaseViews;
get(key: YjsDatabaseKey.metas): YDatabaseMetas;
get (key: YjsDatabaseKey.metas): YDatabaseMetas;
get(key: YjsDatabaseKey.fields): YDatabaseFields;
get (key: YjsDatabaseKey.fields): YDatabaseFields;
get(key: YjsDatabaseKey.id): string;
get (key: YjsDatabaseKey.id): string;
}
export interface YDatabaseViews extends Y.Map<YDatabaseView> {
get(key: ViewId): YDatabaseView;
get (key: ViewId): YDatabaseView;
}
export type DatabaseId = string;
@ -431,32 +444,32 @@ export enum DatabaseViewLayout {
}
export interface YDatabaseView extends Y.Map<unknown> {
get(key: YjsDatabaseKey.database_id): DatabaseId;
get (key: YjsDatabaseKey.database_id): DatabaseId;
get(key: YjsDatabaseKey.name): string;
get (key: YjsDatabaseKey.name): string;
get(key: YjsDatabaseKey.created_at): CreatedAt;
get (key: YjsDatabaseKey.created_at): CreatedAt;
get(key: YjsDatabaseKey.modified_at): ModifiedAt;
get (key: YjsDatabaseKey.modified_at): ModifiedAt;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.layout): string;
get (key: YjsDatabaseKey.layout): string;
get(key: YjsDatabaseKey.layout_settings): YDatabaseLayoutSettings;
get (key: YjsDatabaseKey.layout_settings): YDatabaseLayoutSettings;
get(key: YjsDatabaseKey.filters): YDatabaseFilters;
get (key: YjsDatabaseKey.filters): YDatabaseFilters;
get(key: YjsDatabaseKey.groups): YDatabaseGroups;
get (key: YjsDatabaseKey.groups): YDatabaseGroups;
get(key: YjsDatabaseKey.sorts): YDatabaseSorts;
get (key: YjsDatabaseKey.sorts): YDatabaseSorts;
get(key: YjsDatabaseKey.field_settings): YDatabaseFieldSettings;
get (key: YjsDatabaseKey.field_settings): YDatabaseFieldSettings;
get(key: YjsDatabaseKey.field_orders): YDatabaseFieldOrders;
get (key: YjsDatabaseKey.field_orders): YDatabaseFieldOrders;
get(key: YjsDatabaseKey.row_orders): YDatabaseRowOrders;
get (key: YjsDatabaseKey.row_orders): YDatabaseRowOrders;
get(key: YjsDatabaseKey.calculations): YDatabaseCalculations;
get (key: YjsDatabaseKey.calculations): YDatabaseCalculations;
}
export type YDatabaseFieldOrders = Y.Array<unknown>; // [ { id: FieldId } ]
@ -477,128 +490,128 @@ export type GroupId = string;
export interface YDatabaseLayoutSettings extends Y.Map<unknown> {
// DatabaseViewLayout.Board
get(key: '1'): YDatabaseBoardLayoutSetting;
get (key: '1'): YDatabaseBoardLayoutSetting;
// DatabaseViewLayout.Calendar
get(key: '2'): YDatabaseCalendarLayoutSetting;
get (key: '2'): YDatabaseCalendarLayoutSetting;
}
export interface YDatabaseBoardLayoutSetting extends Y.Map<unknown> {
get(key: YjsDatabaseKey.hide_ungrouped_column | YjsDatabaseKey.collapse_hidden_groups): boolean;
get (key: YjsDatabaseKey.hide_ungrouped_column | YjsDatabaseKey.collapse_hidden_groups): boolean;
}
export interface YDatabaseCalendarLayoutSetting extends Y.Map<unknown> {
get(key: YjsDatabaseKey.first_day_of_week | YjsDatabaseKey.field_id | YjsDatabaseKey.layout_ty): string;
get (key: YjsDatabaseKey.first_day_of_week | YjsDatabaseKey.field_id | YjsDatabaseKey.layout_ty): string;
get(key: YjsDatabaseKey.show_week_numbers | YjsDatabaseKey.show_weekends): boolean;
get (key: YjsDatabaseKey.show_week_numbers | YjsDatabaseKey.show_weekends): boolean;
}
export interface YDatabaseGroup extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): GroupId;
get (key: YjsDatabaseKey.id): GroupId;
get(key: YjsDatabaseKey.field_id): FieldId;
get (key: YjsDatabaseKey.field_id): FieldId;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.content): string;
get (key: YjsDatabaseKey.content): string;
get(key: YjsDatabaseKey.groups): YDatabaseGroupColumns;
get (key: YjsDatabaseKey.groups): YDatabaseGroupColumns;
}
export type YDatabaseGroupColumns = Y.Array<YDatabaseGroupColumn>;
export interface YDatabaseGroupColumn extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): string;
get (key: YjsDatabaseKey.id): string;
get(key: YjsDatabaseKey.visible): boolean;
get (key: YjsDatabaseKey.visible): boolean;
}
export interface YDatabaseRowOrder extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): SortId;
get (key: YjsDatabaseKey.id): SortId;
get(key: YjsDatabaseKey.height): number;
get (key: YjsDatabaseKey.height): number;
}
export interface YDatabaseSort extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): SortId;
get (key: YjsDatabaseKey.id): SortId;
get(key: YjsDatabaseKey.field_id): FieldId;
get (key: YjsDatabaseKey.field_id): FieldId;
get(key: YjsDatabaseKey.condition): string;
get (key: YjsDatabaseKey.condition): string;
}
export type FilterId = string;
export interface YDatabaseFilter extends Y.Map<unknown> {
get(key: YjsDatabaseKey.id): FilterId;
get (key: YjsDatabaseKey.id): FilterId;
get(key: YjsDatabaseKey.field_id): FieldId;
get (key: YjsDatabaseKey.field_id): FieldId;
get(key: YjsDatabaseKey.type | YjsDatabaseKey.condition | YjsDatabaseKey.content | YjsDatabaseKey.filter_type): string;
get (key: YjsDatabaseKey.type | YjsDatabaseKey.condition | YjsDatabaseKey.content | YjsDatabaseKey.filter_type): string;
}
export interface YDatabaseCalculation extends Y.Map<unknown> {
get(key: YjsDatabaseKey.field_id): FieldId;
get (key: YjsDatabaseKey.field_id): FieldId;
get(key: YjsDatabaseKey.id | YjsDatabaseKey.type | YjsDatabaseKey.calculation_value): string;
get (key: YjsDatabaseKey.id | YjsDatabaseKey.type | YjsDatabaseKey.calculation_value): string;
}
export interface YDatabaseFieldSettings extends Y.Map<unknown> {
get(key: FieldId): YDatabaseFieldSetting;
get (key: FieldId): YDatabaseFieldSetting;
}
export interface YDatabaseFieldSetting extends Y.Map<unknown> {
get(key: YjsDatabaseKey.visibility): string;
get (key: YjsDatabaseKey.visibility): string;
get(key: YjsDatabaseKey.wrap): boolean;
get (key: YjsDatabaseKey.wrap): boolean;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.width): string;
get (key: YjsDatabaseKey.width): string;
}
export interface YDatabaseMetas extends Y.Map<unknown> {
get(key: YjsDatabaseKey.iid): string;
get (key: YjsDatabaseKey.iid): string;
}
export interface YDatabaseFields extends Y.Map<YDatabaseField> {
get(key: FieldId): YDatabaseField;
get (key: FieldId): YDatabaseField;
}
export interface YDatabaseField extends Y.Map<unknown> {
get(key: YjsDatabaseKey.name): string;
get (key: YjsDatabaseKey.name): string;
get(key: YjsDatabaseKey.id): FieldId;
get (key: YjsDatabaseKey.id): FieldId;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.type): string;
get (key: YjsDatabaseKey.type): string;
get(key: YjsDatabaseKey.type_option): YDatabaseFieldTypeOption;
get (key: YjsDatabaseKey.type_option): YDatabaseFieldTypeOption;
get(key: YjsDatabaseKey.is_primary): boolean;
get (key: YjsDatabaseKey.is_primary): boolean;
get(key: YjsDatabaseKey.last_modified): LastModified;
get (key: YjsDatabaseKey.last_modified): LastModified;
}
export interface YDatabaseFieldTypeOption extends Y.Map<unknown> {
// key is the field type
get(key: string): YMapFieldTypeOption;
get (key: string): YMapFieldTypeOption;
}
export interface YMapFieldTypeOption extends Y.Map<unknown> {
get(key: YjsDatabaseKey.content): string;
get (key: YjsDatabaseKey.content): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.data): string;
get (key: YjsDatabaseKey.data): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.time_format): string;
get (key: YjsDatabaseKey.time_format): string;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.date_format): string;
get (key: YjsDatabaseKey.date_format): string;
get(key: YjsDatabaseKey.database_id): DatabaseId;
get (key: YjsDatabaseKey.database_id): DatabaseId;
// eslint-disable-next-line @typescript-eslint/unified-signatures
get(key: YjsDatabaseKey.format): string;
get (key: YjsDatabaseKey.format): string;
}
export enum CollabType {

View File

@ -1,7 +1,7 @@
import { GetViewRowsMap, LoadView, LoadViewMeta } from '@/application/collab.type';
import { db } from '@/application/db';
import { ViewMeta } from '@/application/db/tables/view_metas';
import { AFConfigContext } from '@/components/app/AppConfig';
import { AFConfigContext } from '@/components/app/app.hooks';
import { useLiveQuery } from 'dexie-react-hooks';
import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
@ -9,6 +9,7 @@ import { useNavigate } from 'react-router-dom';
export interface PublishContextType {
namespace: string;
publishName: string;
isTemplateThumb?: boolean;
viewMeta?: ViewMeta;
toView: (viewId: string) => Promise<void>;
loadViewMeta: LoadViewMeta;
@ -23,10 +24,12 @@ export const PublishProvider = ({
children,
namespace,
publishName,
isTemplateThumb,
}: {
children: React.ReactNode;
namespace: string;
publishName: string;
isTemplateThumb?: boolean;
}) => {
const viewMeta = useLiveQuery(async () => {
const name = `${namespace}_${publishName}`;
@ -87,7 +90,7 @@ export const PublishProvider = ({
return Promise.reject(e);
}
},
[navigate, service]
[navigate, service],
);
const loadViewMeta = useCallback(
@ -124,7 +127,7 @@ export const PublishProvider = ({
return Promise.reject(e);
}
},
[service]
[service],
);
const getViewRowsMap = useCallback(
@ -148,7 +151,7 @@ export const PublishProvider = ({
return Promise.reject(e);
}
},
[service]
[service],
);
const loadView = useCallback(
@ -173,7 +176,7 @@ export const PublishProvider = ({
return Promise.reject(e);
}
},
[service]
[service],
);
useEffect(() => {
@ -195,6 +198,7 @@ export const PublishProvider = ({
toView,
namespace,
publishName,
isTemplateThumb,
}}
>
{children}
@ -202,6 +206,6 @@ export const PublishProvider = ({
);
};
export function usePublishContext() {
export function usePublishContext () {
return useContext(PublishContext);
}

View File

@ -15,7 +15,7 @@ import { Fetcher, StrategyType } from '@/application/services/js-services/cache/
// import { IndexeddbPersistence } from 'y-indexeddb';
import * as Y from 'yjs';
export function collabTypeToDBType(type: CollabType) {
export function collabTypeToDBType (type: CollabType) {
switch (type) {
case CollabType.Folder:
return 'folder';
@ -44,7 +44,7 @@ const collabSharedRootKeyMap = {
[CollabType.Empty]: YjsEditorKey.empty,
};
export function hasCollabCache(doc: YDoc) {
export function hasCollabCache (doc: YDoc) {
const data = doc.getMap(YjsEditorKey.data_section) as YSharedRoot;
return Object.values(collabSharedRootKeyMap).some((key) => {
@ -52,7 +52,7 @@ export function hasCollabCache(doc: YDoc) {
});
}
export async function hasViewMetaCache(name: string) {
export async function hasViewMetaCache (name: string) {
const data = await db.view_metas.get(name);
return !!data;
@ -64,7 +64,7 @@ export async function getPublishViewMeta<
child_views: PublishViewInfo[];
ancestor_views: PublishViewInfo[];
}
>(
> (
fetcher: Fetcher<T>,
{
namespace,
@ -73,7 +73,7 @@ export async function getPublishViewMeta<
namespace: string;
publishName: string;
},
strategy: StrategyType = StrategyType.CACHE_AND_NETWORK
strategy: StrategyType = StrategyType.CACHE_AND_NETWORK,
) {
const name = `${namespace}_${publishName}`;
const exist = await hasViewMetaCache(name);
@ -124,7 +124,7 @@ export async function getPublishView<
ancestor_views: PublishViewInfo[];
};
}
>(
> (
fetcher: Fetcher<T>,
{
namespace,
@ -133,7 +133,7 @@ export async function getPublishView<
namespace: string;
publishName: string;
},
strategy: StrategyType = StrategyType.CACHE_AND_NETWORK
strategy: StrategyType = StrategyType.CACHE_AND_NETWORK,
) {
const name = `${namespace}_${publishName}`;
const doc = await openCollabDB(name);
@ -197,7 +197,7 @@ export async function revalidatePublishViewMeta<
child_views: PublishViewInfo[];
ancestor_views: PublishViewInfo[];
}
>(name: string, fetcher: Fetcher<T>) {
> (name: string, fetcher: Fetcher<T>) {
const { view, child_views, ancestor_views } = await fetcher();
const dbView = await db.view_metas.get(name);
@ -211,7 +211,7 @@ export async function revalidatePublishViewMeta<
visible_view_ids: dbView?.visible_view_ids ?? [],
database_relations: dbView?.database_relations ?? {},
},
name
name,
);
return db.view_metas.get(name);
@ -225,7 +225,7 @@ export async function revalidatePublishView<
relations?: Record<DatabaseId, ViewId>;
meta: PublishViewMetaData;
}
>(name: string, fetcher: Fetcher<T>, collab: YDoc, rowMapDoc: Y.Doc) {
> (name: string, fetcher: Fetcher<T>, collab: YDoc, rowMapDoc: Y.Doc) {
const { data, meta, rows, visibleViewIds = [], relations = {} } = await fetcher();
await db.view_metas.put(
@ -237,7 +237,7 @@ export async function revalidatePublishView<
visible_view_ids: visibleViewIds,
database_relations: relations,
},
name
name,
);
if (rows) {
@ -260,16 +260,14 @@ export async function revalidatePublishView<
}
}
console.log('====', data);
applyYDoc(collab, data);
}
export async function deleteViewMeta(name: string) {
export async function deleteViewMeta (name: string) {
await db.view_metas.delete(name);
}
export async function deleteView(name: string) {
export async function deleteView (name: string) {
console.log('deleteView', name);
await deleteViewMeta(name);
await closeCollabDB(name);

View File

@ -4,6 +4,13 @@ import { initGrantService, refreshToken } from '@/application/services/js-servic
import { blobToBytes } from '@/application/services/js-services/http/utils';
import { AFCloudConfig } from '@/application/services/services.type';
import { getTokenParsed, invalidToken } from '@/application/session/token';
import {
Template,
TemplateCategory,
TemplateCategoryFormValues,
TemplateCreator, TemplateCreatorFormValues, TemplateSummary,
UploadTemplatePayload,
} from '@/application/template.type';
import { FolderView, User, Workspace } from '@/application/types';
import axios, { AxiosInstance } from 'axios';
import dayjs from 'dayjs';
@ -12,13 +19,16 @@ export * from './gotrue';
let axiosInstance: AxiosInstance | null = null;
export function initAPIService(config: AFCloudConfig) {
export function initAPIService (config: AFCloudConfig) {
if (axiosInstance) {
return;
}
axiosInstance = axios.create({
baseURL: config.baseURL,
headers: {
'Content-Type': 'application/json',
},
});
initGrantService(config.gotrueURL);
@ -27,10 +37,6 @@ export function initAPIService(config: AFCloudConfig) {
async (config) => {
const token = getTokenParsed();
Object.assign(config.headers, {
'Content-Type': 'application/json',
});
if (!token) {
return config;
}
@ -56,7 +62,7 @@ export function initAPIService(config: AFCloudConfig) {
},
(error) => {
return Promise.reject(error);
}
},
);
axiosInstance.interceptors.response.use(async (response) => {
@ -83,7 +89,7 @@ export function initAPIService(config: AFCloudConfig) {
});
}
export async function signInWithUrl(url: string) {
export async function signInWithUrl (url: string) {
const hash = new URL(url).hash;
if (!hash) {
@ -100,7 +106,7 @@ export async function signInWithUrl(url: string) {
await refreshToken(refresh_token);
}
export async function verifyToken(accessToken: string) {
export async function verifyToken (accessToken: string) {
const url = `/api/user/verify/${accessToken}`;
const response = await axiosInstance?.get<{
code: number;
@ -119,7 +125,7 @@ export async function verifyToken(accessToken: string) {
return Promise.reject(data);
}
export async function getCurrentUser(): Promise<User> {
export async function getCurrentUser (): Promise<User> {
const url = '/api/user/profile';
const response = await axiosInstance?.get<{
code: number;
@ -155,14 +161,14 @@ export async function getCurrentUser(): Promise<User> {
return Promise.reject(data);
}
export async function getPublishViewMeta(namespace: string, publishName: string) {
export async function getPublishViewMeta (namespace: string, publishName: string) {
const url = `/api/workspace/published/${namespace}/${publishName}`;
const response = await axiosInstance?.get(url);
return response?.data;
}
export async function getPublishViewBlob(namespace: string, publishName: string) {
export async function getPublishViewBlob (namespace: string, publishName: string) {
const url = `/api/workspace/published/${namespace}/${publishName}/blob`;
const response = await axiosInstance?.get(url, {
responseType: 'blob',
@ -171,7 +177,7 @@ export async function getPublishViewBlob(namespace: string, publishName: string)
return blobToBytes(response?.data);
}
export async function getPublishView(publishNamespace: string, publishName: string) {
export async function getPublishView (publishNamespace: string, publishName: string) {
const meta = await getPublishViewMeta(publishNamespace, publishName);
const blob = await getPublishViewBlob(publishNamespace, publishName);
@ -207,7 +213,7 @@ export async function getPublishView(publishNamespace: string, publishName: stri
}
}
export async function getPublishInfoWithViewId(viewId: string) {
export async function getPublishInfoWithViewId (viewId: string) {
const url = `/api/workspace/published-info/${viewId}`;
const response = await axiosInstance?.get<{
code: number;
@ -227,7 +233,7 @@ export async function getPublishInfoWithViewId(viewId: string) {
return Promise.reject(data);
}
export async function getPublishViewComments(viewId: string): Promise<GlobalComment[]> {
export async function getPublishViewComments (viewId: string): Promise<GlobalComment[]> {
const url = `/api/workspace/published-info/${viewId}/comment`;
const response = await axiosInstance?.get<{
code: number;
@ -276,7 +282,7 @@ export async function getPublishViewComments(viewId: string): Promise<GlobalComm
return Promise.reject(data);
}
export async function getReactions(viewId: string, commentId?: string): Promise<Record<string, Reaction[]>> {
export async function getReactions (viewId: string, commentId?: string): Promise<Record<string, Reaction[]>> {
let url = `/api/workspace/published-info/${viewId}/reaction`;
if (commentId) {
@ -327,7 +333,7 @@ export async function getReactions(viewId: string, commentId?: string): Promise<
return Promise.reject(data);
}
export async function createGlobalCommentOnPublishView(viewId: string, content: string, replyCommentId?: string) {
export async function createGlobalCommentOnPublishView (viewId: string, content: string, replyCommentId?: string) {
const url = `/api/workspace/published-info/${viewId}/comment`;
const response = await axiosInstance?.post<{ code: number; message: string }>(url, {
content,
@ -341,7 +347,7 @@ export async function createGlobalCommentOnPublishView(viewId: string, content:
return Promise.reject(response?.data.message);
}
export async function deleteGlobalCommentOnPublishView(viewId: string, commentId: string) {
export async function deleteGlobalCommentOnPublishView (viewId: string, commentId: string) {
const url = `/api/workspace/published-info/${viewId}/comment`;
const response = await axiosInstance?.delete<{ code: number; message: string }>(url, {
data: {
@ -356,7 +362,7 @@ export async function deleteGlobalCommentOnPublishView(viewId: string, commentId
return Promise.reject(response?.data.message);
}
export async function addReaction(viewId: string, commentId: string, reactionType: string) {
export async function addReaction (viewId: string, commentId: string, reactionType: string) {
const url = `/api/workspace/published-info/${viewId}/reaction`;
const response = await axiosInstance?.post<{ code: number; message: string }>(url, {
comment_id: commentId,
@ -370,7 +376,7 @@ export async function addReaction(viewId: string, commentId: string, reactionTyp
return Promise.reject(response?.data.message);
}
export async function removeReaction(viewId: string, commentId: string, reactionType: string) {
export async function removeReaction (viewId: string, commentId: string, reactionType: string) {
const url = `/api/workspace/published-info/${viewId}/reaction`;
const response = await axiosInstance?.delete<{ code: number; message: string }>(url, {
data: {
@ -386,7 +392,7 @@ export async function removeReaction(viewId: string, commentId: string, reaction
return Promise.reject(response?.data.message);
}
export async function getWorkspaces(): Promise<Workspace[]> {
export async function getWorkspaces (): Promise<Workspace[]> {
const query = new URLSearchParams({
include_member_count: 'true',
});
@ -436,7 +442,7 @@ export interface WorkspaceFolder {
children: WorkspaceFolder[];
}
function iterateFolder(folder: WorkspaceFolder): FolderView {
function iterateFolder (folder: WorkspaceFolder): FolderView {
return {
id: folder.view_id,
name: folder.name,
@ -450,7 +456,7 @@ function iterateFolder(folder: WorkspaceFolder): FolderView {
};
}
export async function getWorkspaceFolder(workspaceId: string): Promise<FolderView> {
export async function getWorkspaceFolder (workspaceId: string): Promise<FolderView> {
const url = `/api/workspace/${workspaceId}/folder`;
const response = await axiosInstance?.get<{
code: number;
@ -473,7 +479,7 @@ export interface DuplicatePublishViewPayload {
dest_view_id: string;
}
export async function duplicatePublishView(workspaceId: string, payload: DuplicatePublishViewPayload) {
export async function duplicatePublishView (workspaceId: string, payload: DuplicatePublishViewPayload) {
const url = `/api/workspace/${workspaceId}/published-duplicate`;
const res = await axiosInstance?.post<{
@ -487,3 +493,247 @@ export async function duplicatePublishView(workspaceId: string, payload: Duplica
return Promise.reject(res?.data.message);
}
export async function createTemplate (template: UploadTemplatePayload) {
const url = '/api/template-center/template';
const response = await axiosInstance?.post<{
code: number;
message: string;
}>(url, template);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function updateTemplate (viewId: string, template: UploadTemplatePayload) {
const url = `/api/template-center/template/${viewId}`;
const response = await axiosInstance?.put<{
code: number;
message: string;
}>(url, template);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function getTemplates ({
categoryId,
nameContains,
}: {
categoryId?: string;
nameContains?: string;
}) {
const url = `/api/template-center/template`;
const response = await axiosInstance?.get<{
code: number;
data?: {
templates: TemplateSummary[];
};
message: string;
}>(url, {
params: {
category_id: categoryId,
name_contains: nameContains,
},
});
const data = response?.data;
if (data?.code === 0 && data.data) {
return data.data.templates;
}
return Promise.reject(data);
}
export async function getTemplateById (viewId: string) {
const url = `/api/template-center/template/${viewId}`;
const response = await axiosInstance?.get<{
code: number;
data?: Template;
message: string;
}>(url);
const data = response?.data;
if (data?.code === 0 && data.data) {
return data.data;
}
return Promise.reject(data);
}
export async function deleteTemplate (viewId: string) {
const url = `/api/template-center/template/${viewId}`;
const response = await axiosInstance?.delete<{
code: number;
message: string;
}>(url);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function getTemplateCategories () {
const url = '/api/template-center/category';
const response = await axiosInstance?.get<{
code: number;
data?: {
categories: TemplateCategory[]
};
message: string;
}>(url);
const data = response?.data;
if (data?.code === 0 && data.data) {
return data.data.categories;
}
return Promise.reject(data);
}
export async function addTemplateCategory (category: TemplateCategoryFormValues) {
const url = '/api/template-center/category';
const response = await axiosInstance?.post<{
code: number;
message: string;
}>(url, category);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function updateTemplateCategory (id: string, category: TemplateCategoryFormValues) {
const url = `/api/template-center/category/${id}`;
const response = await axiosInstance?.put<{
code: number;
message: string;
}>(url, category);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function deleteTemplateCategory (categoryId: string) {
const url = `/api/template-center/category/${categoryId}`;
const response = await axiosInstance?.delete<{
code: number;
message: string;
}>(url);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function getTemplateCreators () {
const url = '/api/template-center/creator';
const response = await axiosInstance?.get<{
code: number;
data?: {
creators: TemplateCreator[];
};
message: string;
}>(url);
const data = response?.data;
if (data?.code === 0 && data.data) {
return data.data.creators;
}
return Promise.reject(data);
}
export async function createTemplateCreator (creator: TemplateCreatorFormValues) {
const url = '/api/template-center/creator';
const response = await axiosInstance?.post<{
code: number;
message: string;
}>(url, creator);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function updateTemplateCreator (creatorId: string, creator: TemplateCreatorFormValues) {
const url = `/api/template-center/creator/${creatorId}`;
const response = await axiosInstance?.put<{
code: number;
message: string;
}>(url, creator);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function deleteTemplateCreator (creatorId: string) {
const url = `/api/template-center/creator/${creatorId}`;
const response = await axiosInstance?.delete<{
code: number;
message: string;
}>(url);
if (response?.data.code === 0) {
return;
}
return Promise.reject(response?.data.message);
}
export async function uploadFileToCDN (file: File) {
const url = '/api/template-center/avatar';
const formData = new FormData();
console.log(file);
formData.append('avatar', file);
const response = await axiosInstance?.request<{
code: number;
data?: {
file_id: string;
};
message: string;
}>({
method: 'PUT',
url,
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
const data = response?.data;
if (data?.code === 0 && data.data) {
return axiosInstance?.defaults.baseURL + '/api/template-center/avatar/' + data.data.file_id;
}
return Promise.reject(data);
}

View File

@ -1,4 +1,4 @@
export function blobToBytes(blob: Blob): Promise<Uint8Array> {
export function blobToBytes (blob: Blob): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader();

View File

@ -13,6 +13,11 @@ import { APIService } from '@/application/services/js-services/http';
import { AFService, AFServiceConfig } from '@/application/services/services.type';
import { emit, EventType } from '@/application/session';
import { afterAuth, AUTH_CALLBACK_URL, withSignIn } from '@/application/session/sign_in';
import {
TemplateCategoryFormValues,
TemplateCreatorFormValues,
UploadTemplatePayload,
} from '@/application/template.type';
import { nanoid } from 'nanoid';
import * as Y from 'yjs';
import { DuplicatePublishView } from '@/application/types';
@ -36,15 +41,15 @@ export class AFClientService implements AFService {
private cacheDatabaseRowFolder: Map<string, Y.Map<YDoc>> = new Map();
constructor(config: AFServiceConfig) {
constructor (config: AFServiceConfig) {
APIService.initAPIService(config.cloudConfig);
}
getClientId() {
getClientId () {
return this.clientId;
}
async getPublishViewMeta(namespace: string, publishName: string) {
async getPublishViewMeta (namespace: string, publishName: string) {
const name = `${namespace}_${publishName}`;
const isLoaded = this.publishViewLoaded.has(name);
@ -56,7 +61,7 @@ export class AFClientService implements AFService {
namespace,
publishName,
},
isLoaded ? StrategyType.CACHE_FIRST : StrategyType.CACHE_AND_NETWORK
isLoaded ? StrategyType.CACHE_FIRST : StrategyType.CACHE_AND_NETWORK,
);
if (!viewMeta) {
@ -66,7 +71,7 @@ export class AFClientService implements AFService {
return viewMeta;
}
async getPublishView(namespace: string, publishName: string) {
async getPublishView (namespace: string, publishName: string) {
const name = `${namespace}_${publishName}`;
const isLoaded = this.publishViewLoaded.has(name);
@ -91,7 +96,7 @@ export class AFClientService implements AFService {
namespace,
publishName,
},
isLoaded ? StrategyType.CACHE_FIRST : StrategyType.CACHE_AND_NETWORK
isLoaded ? StrategyType.CACHE_FIRST : StrategyType.CACHE_AND_NETWORK,
);
if (!isLoaded) {
@ -103,7 +108,7 @@ export class AFClientService implements AFService {
return doc;
}
async getPublishDatabaseViewRows(namespace: string, publishName: string) {
async getPublishDatabaseViewRows (namespace: string, publishName: string) {
const name = `${namespace}_${publishName}`;
if (!this.publishViewLoaded.has(name) || !this.cacheDatabaseRowDocMap.has(name)) {
@ -133,7 +138,7 @@ export class AFClientService implements AFService {
};
}
async getPublishInfo(viewId: string) {
async getPublishInfo (viewId: string) {
if (this.publishViewInfo.has(viewId)) {
return this.publishViewInfo.get(viewId) as {
namespace: string;
@ -159,7 +164,7 @@ export class AFClientService implements AFService {
return data;
}
async loginAuth(url: string) {
async loginAuth (url: string) {
try {
console.log('loginAuth', url);
await APIService.signInWithUrl(url);
@ -173,45 +178,45 @@ export class AFClientService implements AFService {
}
@withSignIn()
async signInMagicLink({ email }: { email: string; redirectTo: string }) {
async signInMagicLink ({ email }: { email: string; redirectTo: string }) {
return await APIService.signInWithMagicLink(email, AUTH_CALLBACK_URL);
}
@withSignIn()
async signInGoogle(_: { redirectTo: string }) {
async signInGoogle (_: { redirectTo: string }) {
return APIService.signInGoogle(AUTH_CALLBACK_URL);
}
@withSignIn()
async signInGithub(_: { redirectTo: string }) {
async signInGithub (_: { redirectTo: string }) {
return APIService.signInGithub(AUTH_CALLBACK_URL);
}
@withSignIn()
async signInDiscord(_: { redirectTo: string }) {
async signInDiscord (_: { redirectTo: string }) {
return APIService.signInDiscord(AUTH_CALLBACK_URL);
}
async getWorkspaces() {
async getWorkspaces () {
const data = APIService.getWorkspaces();
return data;
}
async getWorkspaceFolder(workspaceId: string) {
async getWorkspaceFolder (workspaceId: string) {
const data = await APIService.getWorkspaceFolder(workspaceId);
return data;
}
async getCurrentUser() {
async getCurrentUser () {
const data = await APIService.getCurrentUser();
await APIService.getWorkspaces();
return data;
}
async duplicatePublishView(params: DuplicatePublishView) {
async duplicatePublishView (params: DuplicatePublishView) {
return APIService.duplicatePublishView(params.workspaceId, {
dest_view_id: params.spaceViewId,
published_view_id: params.viewId,
@ -219,27 +224,87 @@ export class AFClientService implements AFService {
});
}
createCommentOnPublishView(viewId: string, content: string, replyCommentId: string | undefined): Promise<void> {
createCommentOnPublishView (viewId: string, content: string, replyCommentId: string | undefined): Promise<void> {
return APIService.createGlobalCommentOnPublishView(viewId, content, replyCommentId);
}
deleteCommentOnPublishView(viewId: string, commentId: string): Promise<void> {
deleteCommentOnPublishView (viewId: string, commentId: string): Promise<void> {
return APIService.deleteGlobalCommentOnPublishView(viewId, commentId);
}
getPublishViewGlobalComments(viewId: string): Promise<GlobalComment[]> {
getPublishViewGlobalComments (viewId: string): Promise<GlobalComment[]> {
return APIService.getPublishViewComments(viewId);
}
getPublishViewReactions(viewId: string, commentId?: string): Promise<Record<string, Reaction[]>> {
getPublishViewReactions (viewId: string, commentId?: string): Promise<Record<string, Reaction[]>> {
return APIService.getReactions(viewId, commentId);
}
addPublishViewReaction(viewId: string, commentId: string, reactionType: string): Promise<void> {
addPublishViewReaction (viewId: string, commentId: string, reactionType: string): Promise<void> {
return APIService.addReaction(viewId, commentId, reactionType);
}
removePublishViewReaction(viewId: string, commentId: string, reactionType: string): Promise<void> {
removePublishViewReaction (viewId: string, commentId: string, reactionType: string): Promise<void> {
return APIService.removeReaction(viewId, commentId, reactionType);
}
async getTemplateCategories () {
return APIService.getTemplateCategories();
}
async getTemplateCreators () {
return APIService.getTemplateCreators();
}
async createTemplate (template: UploadTemplatePayload) {
return APIService.createTemplate(template);
}
async updateTemplate (id: string, template: UploadTemplatePayload) {
return APIService.updateTemplate(id, template);
}
async getTemplateById (id: string) {
return APIService.getTemplateById(id);
}
async getTemplates (params: {
categoryId?: string;
nameContains?: string;
}) {
return APIService.getTemplates(params);
}
async deleteTemplate (id: string) {
return APIService.deleteTemplate(id);
}
async addTemplateCategory (category: TemplateCategoryFormValues) {
return APIService.addTemplateCategory(category);
}
async updateTemplateCategory (categoryId: string, category: TemplateCategoryFormValues) {
return APIService.updateTemplateCategory(categoryId, category);
}
async deleteTemplateCategory (categoryId: string) {
return APIService.deleteTemplateCategory(categoryId);
}
async updateTemplateCreator (creatorId: string, creator: TemplateCreatorFormValues) {
return APIService.updateTemplateCreator(creatorId, creator);
}
async createTemplateCreator (creator: TemplateCreatorFormValues) {
return APIService.createTemplateCreator(creator);
}
async deleteTemplateCreator (creatorId: string) {
return APIService.deleteTemplateCreator(creatorId);
}
async uploadFileToCDN (file: File) {
return APIService.uploadFileToCDN(file);
}
}

View File

@ -1,6 +1,13 @@
import { YDoc } from '@/application/collab.type';
import { GlobalComment, Reaction } from '@/application/comment.type';
import { ViewMeta } from '@/application/db/tables/view_metas';
import {
Template,
TemplateCategory,
TemplateCategoryFormValues,
TemplateCreator, TemplateCreatorFormValues, TemplateSummary,
UploadTemplatePayload,
} from '@/application/template.type';
import * as Y from 'yjs';
import { DuplicatePublishView, FolderView, User, Workspace } from '@/application/types';
@ -24,11 +31,12 @@ export interface PublishService {
getPublishDatabaseViewRows: (
namespace: string,
publishName: string,
rowIds?: string[]
rowIds?: string[],
) => Promise<{
rows: Y.Map<YDoc>;
destroy: () => void;
}>;
getPublishViewGlobalComments: (viewId: string) => Promise<GlobalComment[]>;
createCommentOnPublishView: (viewId: string, content: string, replyCommentId?: string) => Promise<void>;
deleteCommentOnPublishView: (viewId: string, commentId: string) => Promise<void>;
@ -46,4 +54,22 @@ export interface PublishService {
getWorkspaceFolder: (workspaceId: string) => Promise<FolderView>;
getCurrentUser: () => Promise<User>;
duplicatePublishView: (params: DuplicatePublishView) => Promise<void>;
getTemplateCategories: () => Promise<TemplateCategory[]>;
addTemplateCategory: (category: TemplateCategoryFormValues) => Promise<void>;
deleteTemplateCategory: (categoryId: string) => Promise<void>;
getTemplateCreators: () => Promise<TemplateCreator[]>;
createTemplateCreator: (creator: TemplateCreatorFormValues) => Promise<void>;
deleteTemplateCreator: (creatorId: string) => Promise<void>;
getTemplateById: (id: string) => Promise<Template>;
getTemplates: (params: {
categoryId?: string;
nameContains?: string;
}) => Promise<TemplateSummary[]>;
deleteTemplate: (id: string) => Promise<void>;
createTemplate: (template: UploadTemplatePayload) => Promise<void>;
updateTemplate: (id: string, template: UploadTemplatePayload) => Promise<void>;
updateTemplateCategory: (categoryId: string, category: TemplateCategoryFormValues) => Promise<void>;
updateTemplateCreator: (creatorId: string, creator: TemplateCreatorFormValues) => Promise<void>;
uploadFileToCDN: (file: File) => Promise<string>;
}

View File

@ -1,6 +1,12 @@
import { YDoc } from '@/application/collab.type';
import { GlobalComment, Reaction } from '@/application/comment.type';
import { AFService } from '@/application/services/services.type';
import {
Template, TemplateCategory,
TemplateCategoryFormValues, TemplateCreator,
TemplateCreatorFormValues, TemplateSummary,
UploadTemplatePayload,
} from '@/application/template.type';
import { nanoid } from 'nanoid';
import { YMap } from 'yjs/dist/src/types/YMap';
import { DuplicatePublishView, FolderView, User, Workspace } from '@/application/types';
@ -10,45 +16,45 @@ export class AFClientService implements AFService {
private clientId: string = 'tauri';
async getPublishView(_namespace: string, _publishName: string) {
async getPublishView (_namespace: string, _publishName: string) {
return Promise.reject('Method not implemented');
}
async getPublishInfo(_viewId: string) {
async getPublishInfo (_viewId: string) {
return Promise.reject('Method not implemented');
}
async getPublishViewMeta(_namespace: string, _publishName: string) {
async getPublishViewMeta (_namespace: string, _publishName: string) {
return Promise.reject('Method not implemented');
}
getClientId(): string {
getClientId (): string {
return '';
}
loginAuth(_: string): Promise<void> {
loginAuth (_: string): Promise<void> {
return Promise.reject('Method not implemented');
}
signInDiscord(_params: { redirectTo: string }): Promise<void> {
signInDiscord (_params: { redirectTo: string }): Promise<void> {
return Promise.reject('Method not implemented');
}
signInGithub(_params: { redirectTo: string }): Promise<void> {
signInGithub (_params: { redirectTo: string }): Promise<void> {
return Promise.reject('Method not implemented');
}
signInGoogle(_params: { redirectTo: string }): Promise<void> {
signInGoogle (_params: { redirectTo: string }): Promise<void> {
return Promise.reject('Method not implemented');
}
signInMagicLink(_params: { email: string; redirectTo: string }): Promise<void> {
signInMagicLink (_params: { email: string; redirectTo: string }): Promise<void> {
return Promise.reject('Method not implemented');
}
getPublishDatabaseViewRows(
getPublishDatabaseViewRows (
_namespace: string,
_publishName: string
_publishName: string,
): Promise<{
rows: YMap<YDoc>;
destroy: () => void;
@ -56,43 +62,99 @@ export class AFClientService implements AFService {
return Promise.reject('Method not implemented');
}
duplicatePublishView(_params: DuplicatePublishView): Promise<void> {
duplicatePublishView (_params: DuplicatePublishView): Promise<void> {
return Promise.reject('Method not implemented');
}
getCurrentUser(): Promise<User> {
getCurrentUser (): Promise<User> {
return Promise.reject('Method not implemented');
}
getWorkspaceFolder(_workspaceId: string): Promise<FolderView> {
getWorkspaceFolder (_workspaceId: string): Promise<FolderView> {
return Promise.reject('Method not implemented');
}
getWorkspaces(): Promise<Workspace[]> {
getWorkspaces (): Promise<Workspace[]> {
return Promise.reject('Method not implemented');
}
addPublishViewReaction(_viewId: string, _commentId: string, _reactionType: string): Promise<void> {
addPublishViewReaction (_viewId: string, _commentId: string, _reactionType: string): Promise<void> {
return Promise.reject('Method not implemented');
}
createCommentOnPublishView(_viewId: string, _content: string, _replyCommentId: string | undefined): Promise<void> {
createCommentOnPublishView (_viewId: string, _content: string, _replyCommentId: string | undefined): Promise<void> {
return Promise.reject('Method not implemented');
}
deleteCommentOnPublishView(_viewId: string, _commentId: string): Promise<void> {
deleteCommentOnPublishView (_viewId: string, _commentId: string): Promise<void> {
return Promise.reject('Method not implemented');
}
getPublishViewGlobalComments(_viewId: string): Promise<GlobalComment[]> {
getPublishViewGlobalComments (_viewId: string): Promise<GlobalComment[]> {
return Promise.resolve([]);
}
getPublishViewReactions(_viewId: string, _commentId: string | undefined): Promise<Record<string, Reaction[]>> {
getPublishViewReactions (_viewId: string, _commentId: string | undefined): Promise<Record<string, Reaction[]>> {
return Promise.reject('Method not implemented');
}
removePublishViewReaction(_viewId: string, _commentId: string, _reactionType: string): Promise<void> {
removePublishViewReaction (_viewId: string, _commentId: string, _reactionType: string): Promise<void> {
return Promise.reject('Method not implemented');
}
addTemplateCategory (_category: TemplateCategoryFormValues): Promise<void> {
return Promise.reject('Method not implemented');
}
createTemplate (_template: UploadTemplatePayload): Promise<void> {
return Promise.reject('Method not implemented');
}
createTemplateCreator (_creator: TemplateCreatorFormValues): Promise<void> {
return Promise.reject('Method not implemented');
}
deleteTemplate (_id: string): Promise<void> {
return Promise.reject('Method not implemented');
}
deleteTemplateCategory (_categoryId: string): Promise<void> {
return Promise.reject('Method not implemented');
}
deleteTemplateCreator (_creatorId: string): Promise<void> {
return Promise.reject('Method not implemented');
}
getTemplateById (_id: string): Promise<Template> {
return Promise.reject('Method not implemented');
}
getTemplateCategories (): Promise<TemplateCategory[]> {
return Promise.resolve([]);
}
getTemplateCreators (): Promise<TemplateCreator[]> {
return Promise.resolve([]);
}
getTemplates (_params: { categoryId?: string; nameContains?: string }): Promise<TemplateSummary[]> {
return Promise.resolve([]);
}
updateTemplate (_id: string, _template: UploadTemplatePayload): Promise<void> {
return Promise.reject('Method not implemented');
}
updateTemplateCategory (_categoryId: string, _category: TemplateCategoryFormValues): Promise<void> {
return Promise.reject('Method not implemented');
}
updateTemplateCreator (_creatorId: string, _creator: TemplateCreatorFormValues): Promise<void> {
return Promise.reject('Method not implemented');
}
uploadFileToCDN (_file: File): Promise<string> {
return Promise.resolve('');
}
}

View File

@ -24,43 +24,44 @@ const localChanges = new WeakMap<YjsEditor, LocalChange[]>();
// eslint-disable-next-line @typescript-eslint/no-redeclare
export const YjsEditor = {
connected(editor: YjsEditor): boolean {
connected (editor: YjsEditor): boolean {
return connectSet.has(editor);
},
connect(editor: YjsEditor): void {
connect (editor: YjsEditor): void {
editor.connect();
},
disconnect(editor: YjsEditor): void {
disconnect (editor: YjsEditor): void {
editor.disconnect();
},
applyRemoteEvents(editor: YjsEditor, events: Array<YEvent>, transaction: Transaction): void {
applyRemoteEvents (editor: YjsEditor, events: Array<YEvent>, transaction: Transaction): void {
editor.applyRemoteEvents(events, transaction);
},
localChanges(editor: YjsEditor): LocalChange[] {
localChanges (editor: YjsEditor): LocalChange[] {
return localChanges.get(editor) ?? [];
},
storeLocalChange(editor: YjsEditor, op: Operation): void {
storeLocalChange (editor: YjsEditor, op: Operation): void {
editor.storeLocalChange(op);
},
flushLocalChanges(editor: YjsEditor): void {
flushLocalChanges (editor: YjsEditor): void {
editor.flushLocalChanges();
},
};
export function withYjs<T extends Editor>(
export function withYjs<T extends Editor> (
editor: T,
doc: Y.Doc,
opts?: {
localOrigin: CollabOrigin;
}
readSummary?: boolean;
},
): T & YjsEditor {
const { localOrigin = CollabOrigin.Local } = opts ?? {};
const { localOrigin = CollabOrigin.Local, readSummary } = opts ?? {};
const e = editor as T & YjsEditor;
const { apply, onChange } = e;
@ -73,7 +74,11 @@ export function withYjs<T extends Editor>(
return;
}
e.children = content.children;
if (readSummary) {
e.children = content.children.slice(0, 10);
} else {
e.children = content.children;
}
Editor.normalize(editor, { force: true });
};

View File

@ -10,10 +10,12 @@ import {
BlockData,
BlockType,
} from '@/application/collab.type';
import { sortTableCells } from '@/application/slate-yjs/utils/table';
import { BlockJson } from '@/application/slate-yjs/utils/types';
import { TableCellNode } from '@/components/editor/editor.type';
import { Element, Text } from 'slate';
export function yDataToSlateContent({
export function yDataToSlateContent ({
blocks,
rootId,
childrenMap,
@ -24,7 +26,7 @@ export function yDataToSlateContent({
textMap: YTextMap;
rootId: string;
}): Element | undefined {
function traverse(id: string) {
function traverse (id: string) {
const block = blocks.get(id)?.toJSON() as BlockJson;
if (!block) {
@ -38,7 +40,13 @@ export function yDataToSlateContent({
const slateNode = blockToSlateNode(block);
slateNode.children = children;
if (slateNode.type === BlockType.TableBlock) {
slateNode.children = sortTableCells(children as TableCellNode[]);
} else if (slateNode.type === BlockType.TableCell) {
slateNode.children = children.slice(0, 1);
} else {
slateNode.children = children;
}
if (slateNode.type === BlockType.Page) {
return slateNode;
@ -100,7 +108,7 @@ export function yDataToSlateContent({
return result;
}
export function yDocToSlateContent(doc: YDoc): Element | undefined {
export function yDocToSlateContent (doc: YDoc): Element | undefined {
const sharedRoot = doc.getMap(YjsEditorKey.data_section) as YSharedRoot;
if (!sharedRoot || sharedRoot.size === 0) return;
@ -120,7 +128,7 @@ export function yDocToSlateContent(doc: YDoc): Element | undefined {
});
}
export function blockToSlateNode(block: BlockJson): Element {
export function blockToSlateNode (block: BlockJson): Element {
const data = block.data;
let blockData;
@ -144,7 +152,7 @@ export interface YDelta {
attributes?: Record<string, string | number | undefined | boolean>;
}
export function deltaInsertToSlateNode({ attributes, insert }: YDelta): Element | Text | Element[] {
export function deltaInsertToSlateNode ({ attributes, insert }: YDelta): Element | Text | Element[] {
const matchInlines = transformToInlineElement({
insert,
attributes,
@ -164,7 +172,7 @@ export function deltaInsertToSlateNode({ attributes, insert }: YDelta): Element
};
}
function dealWithEmptyAttribute(attributes: Record<string, string | number | undefined | boolean>) {
function dealWithEmptyAttribute (attributes: Record<string, string | number | undefined | boolean>) {
for (const key in attributes) {
if (!attributes[key]) {
delete attributes[key];
@ -172,7 +180,7 @@ function dealWithEmptyAttribute(attributes: Record<string, string | number | und
}
}
export function transformToInlineElement(op: YDelta): Element[] {
export function transformToInlineElement (op: YDelta): Element[] {
const attributes = op.attributes;
if (!attributes) return [];

View File

@ -0,0 +1,16 @@
import { TableCellNode } from '@/components/editor/editor.type';
import { isUndefined } from 'lodash-es';
export function sortTableCells (cells: TableCellNode[]): TableCellNode[] {
return cells.sort((a, b) => {
if (isUndefined(a.data.colPosition) || isUndefined(a.data.rowPosition) || isUndefined(b.data.colPosition) || isUndefined(b.data.rowPosition)) {
return 0;
}
if (a.data.colPosition === b.data.colPosition) {
return a.data.rowPosition - b.data.rowPosition;
}
return a.data.colPosition - b.data.colPosition;
});
}

View File

@ -0,0 +1,83 @@
export enum TemplateCategoryType {
ByUseCase,
ByFeature,
}
export enum TemplateIcon {
project = 'project',
engineering = 'engineering',
startups = 'startups',
schools = 'schools',
marketing = 'marketing',
management = 'management',
humanResources = 'human-resources',
sales = 'sales',
teamMeetings = 'team-meetings',
ai = 'ai',
docs = 'docs',
wiki = 'wiki',
database = 'database',
kanban = 'kanban',
}
export interface TemplateCategoryFormValues {
name: string;
icon: TemplateIcon;
bg_color: string;
description: string;
category_type: TemplateCategoryType,
priority: number;
}
export interface TemplateCategory extends TemplateCategoryFormValues {
id: string;
}
export interface TemplateCreatorFormValues {
name: string;
avatar_url: string;
account_links?: {
link_type: string;
url: string;
}[];
}
export interface TemplateCreator {
id: string;
name: string;
avatar_url: string;
upload_template_count?: number;
account_links?: {
link_type: string;
url: string;
}[];
}
export interface UploadTemplatePayload {
view_id: string;
name: string;
description: string;
view_url: string;
about: string;
category_ids: string[];
creator_id: string;
is_new_template: boolean;
is_featured: boolean;
related_view_ids: string[];
}
export interface TemplateSummary {
view_id: string;
name: string;
description: string;
view_url: string;
categories: TemplateCategory[];
creator: TemplateCreator;
is_new_template: boolean;
is_featured: boolean;
}
export interface Template extends TemplateSummary {
about: string;
related_templates: TemplateSummary[];
}

View File

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="7.5" y="4" width="1" height="8" rx="0.5" fill="currentColor"/>
<rect x="12" y="7.5" width="1" height="8" rx="0.5" transform="rotate(90 12 7.5)" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 286 B

View File

@ -1,4 +1,24 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.44667 3.33333L12.6667 6.55333V12.6667H3.33333V3.33333H9.44667ZM9.44667 2H3.33333C2.6 2 2 2.6 2 3.33333V12.6667C2 13.4 2.6 14 3.33333 14H12.6667C13.4 14 14 13.4 14 12.6667V6.55333C14 6.2 13.86 5.86 13.6067 5.61333L10.3867 2.39333C10.14 2.14 9.8 2 9.44667 2ZM4.66667 10H11.3333V11.3333H4.66667V10ZM4.66667 7.33333H11.3333V8.66667H4.66667V7.33333ZM4.66667 4.66667H9.33333V6H4.66667V4.66667Z"
fill="currentColor"/>
<g id="File-Favourite--Streamline-Solar-Ar" clip-path="url(#clip0_41_59)">
<path id="Vector" d="M9.36746 14.3244H6.63259V15.35H9.36746V14.3244ZM1.67559 9.36744V6.63256H0.650025V9.36744H1.67559ZM14.3244 9.06863V9.36744H15.35V9.06863H14.3244ZM9.97678 2.94813L12.6835 5.38413L13.3695 4.62181L10.6629 2.18581L9.97678 2.94813ZM15.35 9.06863C15.35 7.91419 15.3603 7.18331 15.069 6.52931L14.1322 6.94656C14.3141 7.35494 14.3244 7.82363 14.3244 9.06863H15.35ZM12.6835 5.38413C13.6088 6.21694 13.9503 6.53819 14.1322 6.94656L15.069 6.52931C14.7778 5.87531 14.2276 5.39406 13.3695 4.62181L12.6835 5.38413ZM6.65296 1.67563C7.73446 1.67563 8.14259 1.68356 8.50628 1.82313L8.87371 0.865626C8.29134 0.642126 7.65677 0.650063 6.65296 0.650063V1.67563ZM10.6629 2.18581C9.92034 1.5175 9.45615 1.08906 8.87371 0.865626L8.50628 1.82313C8.87015 1.96275 9.17703 2.22838 9.97678 2.94813L10.6629 2.18581ZM6.63259 14.3244C5.32884 14.3244 4.40265 14.3233 3.69996 14.2288C3.01209 14.1364 2.61577 13.9629 2.32646 13.6736L1.60121 14.3988C2.1129 14.9104 2.76171 15.1375 3.56334 15.2453C4.35021 15.3511 5.35784 15.35 6.63259 15.35V14.3244ZM0.650025 9.36744C0.650025 10.6422 0.648962 11.6498 0.754712 12.4367C0.862525 13.2383 1.08952 13.8871 1.60121 14.3988L2.32646 13.6736C2.03709 13.3843 1.86365 12.9879 1.77115 12.3001C1.67671 11.5974 1.67559 10.6712 1.67559 9.36744H0.650025ZM9.36746 15.35C10.6421 15.35 11.6498 15.3511 12.4366 15.2453C13.2383 15.1375 13.8871 14.9104 14.3988 14.3988L13.6736 13.6736C13.3842 13.9629 12.9879 14.1364 12.3 14.2288C11.5974 14.3233 10.6711 14.3244 9.36746 14.3244V15.35ZM14.3244 9.36744C14.3244 10.6712 14.3233 11.5974 14.2288 12.3001C14.1364 12.9879 13.9629 13.3843 13.6736 13.6736L14.3988 14.3988C14.9104 13.8871 15.1375 13.2383 15.2453 12.4367C15.3511 11.6498 15.35 10.6422 15.35 9.36744H14.3244ZM1.67559 6.63256C1.67559 5.32888 1.67671 4.40263 1.77115 3.7C1.86365 3.01213 2.03709 2.61581 2.32646 2.32644L1.60121 1.60125C1.08959 2.11294 0.862525 2.76175 0.754712 3.56338C0.648962 4.35019 0.650025 5.35781 0.650025 6.63256H1.67559ZM6.65296 0.650063C5.37134 0.650063 4.35877 0.648938 3.56871 0.754688C2.76427 0.862376 2.11327 1.08919 1.60121 1.60125L2.32646 2.32644C2.6154 2.0375 3.0129 1.86381 3.70477 1.77119C4.41096 1.67669 5.34246 1.67563 6.65296 1.67563V0.650063Z" fill="url(#paint0_linear_41_59)"/>
<path id="Vector_2" d="M8.68372 1.50469V3.214C8.68372 4.8255 8.68372 5.63131 9.18434 6.13194C9.68503 6.63256 10.4908 6.63256 12.1023 6.63256H14.8372" stroke="url(#paint1_linear_41_59)"/>
<path id="Vector_3" d="M5.36486 8.69913C5.62467 8.233 5.75461 8 5.94879 8C6.14298 8 6.27292 8.233 6.53273 8.69913L6.59998 8.81975C6.67373 8.95219 6.71067 9.01831 6.76823 9.06206C6.82579 9.10575 6.89748 9.122 7.04086 9.15438L7.17136 9.18394C7.67586 9.29812 7.92817 9.35512 7.98823 9.54819C8.04823 9.74119 7.87623 9.94225 7.53229 10.3445L7.44329 10.4486C7.34554 10.5628 7.29667 10.6199 7.27467 10.6906C7.25273 10.7614 7.26011 10.8376 7.27486 10.9901L7.28836 11.1289C7.34029 11.6656 7.36636 11.9339 7.20923 12.0532C7.05204 12.1724 6.81592 12.0637 6.34354 11.8462L6.22129 11.7899C6.08704 11.7281 6.01998 11.6973 5.94879 11.6973C5.87767 11.6973 5.81054 11.7281 5.67629 11.7899L5.55411 11.8462C5.08173 12.0637 4.84554 12.1724 4.68842 12.0532C4.53129 11.9339 4.55729 11.6656 4.60929 11.1289L4.62273 10.9901C4.63754 10.8376 4.64492 10.7614 4.62292 10.6906C4.60092 10.6199 4.55204 10.5628 4.45429 10.4486L4.36536 10.3445C4.02136 9.94225 3.84942 9.74119 3.90942 9.54819C3.96942 9.35512 4.22173 9.29812 4.72623 9.18394L4.85673 9.15438C5.00011 9.122 5.07179 9.10575 5.12936 9.06206C5.18692 9.01837 5.22386 8.95219 5.29767 8.81975L5.36486 8.69913Z" stroke="url(#paint2_linear_41_59)"/>
</g>
<defs>
<linearGradient id="paint0_linear_41_59" x1="8.00002" y1="0.650028" x2="8.00002" y2="15.35" gradientUnits="userSpaceOnUse">
<stop stop-color="#8032FF"/>
<stop offset="1" stop-color="#EF35FF"/>
</linearGradient>
<linearGradient id="paint1_linear_41_59" x1="11.7605" y1="1.50469" x2="11.7605" y2="6.63256" gradientUnits="userSpaceOnUse">
<stop stop-color="#8032FF"/>
<stop offset="1" stop-color="#EF35FF"/>
</linearGradient>
<linearGradient id="paint2_linear_41_59" x1="5.94882" y1="8" x2="5.94882" y2="12.1023" gradientUnits="userSpaceOnUse">
<stop stop-color="#8032FF"/>
<stop offset="1" stop-color="#EF35FF"/>
</linearGradient>
<clipPath id="clip0_41_59">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,4 +1,17 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.58008 10.0468L6.88675 8.3735L6.90675 8.3535C8.06675 7.06016 8.89341 5.5735 9.38008 4.00016H11.3334V2.66683H6.66675V1.3335H5.33341V2.66683H0.666748V3.9935H8.11341C7.66675 5.28016 6.96008 6.50016 6.00008 7.56683C5.38008 6.88016 4.86675 6.12683 4.46008 5.3335H3.12675C3.61341 6.42016 4.28008 7.44683 5.11341 8.3735L1.72008 11.7202L2.66675 12.6668L6.00008 9.3335L8.07341 11.4068L8.58008 10.0468ZM12.3334 6.66683H11.0001L8.00008 14.6668H9.33341L10.0801 12.6668H13.2467L14.0001 14.6668H15.3334L12.3334 6.66683ZM10.5867 11.3335L11.6667 8.44683L12.7467 11.3335H10.5867Z"
fill="currentColor"/>
<defs>
<linearGradient id="paint0_linear_41_51" x1="8.00002" y1="0.72" x2="8.00002" y2="15.28"
gradientUnits="userSpaceOnUse">
<stop stop-color="#8032FF"/>
<stop offset="1" stop-color="#EF35FF"/>
</linearGradient>
</defs>
<g id="Translate-Text--Streamline-Sharp">
<g id="translate-text--options-text-translate">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd"
d="M10.3003 2.0252H6.38474V0.72H5.07954V2.0252H1.164V3.3304H2.47663C2.5607 5.00003 3.35339 6.55824 4.65933 7.6095L2.39906 9.33788L3.19188 10.3747L5.73214 8.43216L7.29344 9.62611L8.08638 8.58933L6.80495 7.6095C8.11089 6.55824 8.90352 5.00003 8.98765 3.3304H10.3003V2.0252ZM5.89668 6.66323L5.73214 6.78908L5.5676 6.66323C4.51602 5.85915 3.86893 4.64185 3.78393 3.3304H7.68034C7.59535 4.64185 6.94826 5.85915 5.89668 6.66323ZM10.6918 7.24594H10.2187L10.0716 7.69555L7.72225 14.8741L8.9627 15.28L9.57661 13.4042H12.9817L13.5956 15.28L14.836 14.8741L12.4868 7.69555L12.3395 7.24594H10.6918ZM12.5545 12.099H10.0038L11.1649 8.55114H11.3935L12.5545 12.099Z"
fill="url(#paint0_linear_41_51)"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Book">
<path id="Vector"
d="M16.25 1.875H5.61719C4.24766 1.875 3.13047 2.98594 3.125 4.35469V16.8578C3.125 16.8633 3.125 16.8695 3.125 16.875V17.5C3.125 17.8453 3.40469 18.125 3.75 18.125H15C15.3453 18.125 15.625 17.8453 15.625 17.5C15.625 17.1547 15.3453 16.875 15 16.875H4.375V16.8609C4.37812 16.1813 4.93125 15.6281 5.60938 15.625H16.25C16.5953 15.625 16.875 15.3453 16.875 15V2.5C16.875 2.15469 16.5953 1.875 16.25 1.875ZM15.625 14.375H5.60703C5.15859 14.3766 4.73828 14.4977 4.375 14.707V4.36172C4.37656 4.02969 4.50703 3.71875 4.74219 3.48516C4.97656 3.25313 5.28672 3.125 5.61953 3.125H15.625V14.375Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 790 B

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="ChatCircleText">
<path id="Vector"
d="M13.125 8.7496C13.125 8.91536 13.0592 9.07433 12.9419 9.19154C12.8247 9.30875 12.6658 9.3746 12.5 9.3746H7.5C7.33424 9.3746 7.17527 9.30875 7.05806 9.19154C6.94085 9.07433 6.875 8.91536 6.875 8.7496C6.875 8.58384 6.94085 8.42487 7.05806 8.30766C7.17527 8.19045 7.33424 8.1246 7.5 8.1246H12.5C12.6658 8.1246 12.8247 8.19045 12.9419 8.30766C13.0592 8.42487 13.125 8.58384 13.125 8.7496ZM12.5 10.6246H7.5C7.33424 10.6246 7.17527 10.6904 7.05806 10.8077C6.94085 10.9249 6.875 11.0838 6.875 11.2496C6.875 11.4154 6.94085 11.5743 7.05806 11.6915C7.17527 11.8087 7.33424 11.8746 7.5 11.8746H12.5C12.6658 11.8746 12.8247 11.8087 12.9419 11.6915C13.0592 11.5743 13.125 11.4154 13.125 11.2496C13.125 11.0838 13.0592 10.9249 12.9419 10.8077C12.8247 10.6904 12.6658 10.6246 12.5 10.6246ZM18.125 9.9996C18.1253 11.4024 17.7624 12.7813 17.0717 14.0022C16.381 15.2231 15.3859 16.2444 14.1834 16.9667C12.9808 17.6889 11.6118 18.0875 10.2095 18.1237C8.80719 18.1598 7.41942 17.8323 6.18125 17.173L3.52109 18.0598C3.30085 18.1332 3.0645 18.1439 2.83854 18.0905C2.61257 18.0372 2.40593 17.922 2.24176 17.7578C2.07759 17.5937 1.96239 17.387 1.90906 17.1611C1.85573 16.9351 1.86639 16.6987 1.93984 16.4785L2.82656 13.8183C2.24699 12.7287 1.92328 11.5213 1.88 10.2879C1.83672 9.05441 2.075 7.82731 2.57677 6.6997C3.07854 5.57209 3.8306 4.57362 4.77587 3.78006C5.72114 2.9865 6.83477 2.41872 8.03224 2.11981C9.22971 1.8209 10.4795 1.79873 11.6868 2.05496C12.8942 2.3112 14.0272 2.83911 15.0001 3.59864C15.9729 4.35816 16.7599 5.32933 17.3014 6.43842C17.8428 7.54752 18.1245 8.76539 18.125 9.9996ZM16.875 9.9996C16.8747 8.94501 16.6318 7.90462 16.1651 6.95893C15.6983 6.01324 15.0203 5.18759 14.1834 4.54587C13.3466 3.90415 12.3733 3.46356 11.3389 3.25818C10.3045 3.0528 9.23671 3.08814 8.21815 3.36147C7.1996 3.6348 6.25757 4.13878 5.46496 4.83443C4.67235 5.53009 4.0504 6.39876 3.64724 7.37324C3.24407 8.34772 3.07048 9.40189 3.13992 10.4542C3.20935 11.5065 3.51994 12.5287 4.04766 13.4418C4.09195 13.5184 4.11945 13.6036 4.12834 13.6917C4.13723 13.7798 4.1273 13.8688 4.09922 13.9527L3.125 16.8746L6.04688 15.9004C6.11052 15.8787 6.17729 15.8676 6.24453 15.8676C6.3543 15.8678 6.46208 15.8969 6.55703 15.9519C7.60219 16.5566 8.78817 16.8754 9.99566 16.8762C11.2031 16.8769 12.3895 16.5597 13.4354 15.9563C14.4814 15.3529 15.3499 14.4847 15.9537 13.439C16.5575 12.3933 16.8753 11.2071 16.875 9.9996Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,4 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 8L8.11538 9.5L13.5 4.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 8.5V11.8889C13 12.1836 12.8829 12.4662 12.6746 12.6746C12.4662 12.8829 12.1836 13 11.8889 13H4.11111C3.81643 13 3.53381 12.8829 3.32544 12.6746C3.11706 12.4662 3 12.1836 3 11.8889V4.11111C3 3.81643 3.11706 3.53381 3.32544 3.32544C3.53381 3.11706 3.81643 3 4.11111 3H10.2222" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<g clip-path="url(#clip0_41_77)">
<path d="M1.16284 8C1.16284 4.77687 1.16284 3.16537 2.16409 2.16406C3.1654 1.16281 4.7769 1.16281 8.00003 1.16281C11.2231 1.16281 12.8347 1.16281 13.8359 2.16406C14.8372 3.16537 14.8372 4.77687 14.8372 8C14.8372 11.2231 14.8372 12.8346 13.8359 13.8359C12.8347 14.8372 11.2231 14.8372 8.00003 14.8372C4.7769 14.8372 3.1654 14.8372 2.16409 13.8359C1.16284 12.8347 1.16284 11.2231 1.16284 8Z"
stroke="currentColor"/>
<path d="M5.60699 8.34187L6.97443 9.7093L10.393 6.29068" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 740 B

View File

@ -1,4 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 8L8.11538 9.5L13.5 4.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 8C13.5 11.0376 11.0376 13.5 8 13.5C4.96243 13.5 2.5 11.0376 2.5 8C2.5 4.96243 4.96243 2.5 8 2.5C8.81896 2.5 9.59612 2.679 10.2945 3" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M1.48633 11.8316L3.01897 13.3642L6.08424 10.299" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round"/>
<path d="M1.48633 4.16841L3.01897 5.70105L6.08424 2.63577" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round"/>
<path d="M9.14948 3.40208H15.28" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.14948 8H15.28" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.14948 12.5979H15.28" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 707 B

View File

@ -0,0 +1,12 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1068_187542)">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M7.88381 0.0605549C6.89196 -0.05967 5.88886 0.163768 5.04181 0.693609C4.25349 1.18671 3.64467 1.91745 3.30135 2.77774C2.87262 2.82504 2.45508 2.94713 2.06781 3.13888C1.63324 3.35405 1.24531 3.6527 0.92616 4.01779C0.281611 4.75512 -0.0436335 5.7183 0.0219743 6.69544C0.087582 7.67257 0.538668 8.58362 1.276 9.22817C1.65376 9.55839 2.09079 9.8048 2.55861 9.95778C2.77382 9.08534 3.5616 8.43839 4.50049 8.43839H5.00049V7.93839C5.00049 6.83382 5.89592 5.93839 7.00049 5.93839C8.10506 5.93839 9.00049 6.83382 9.00049 7.93839V8.43839H9.50049C10.474 8.43839 11.2851 9.13397 11.4638 10.0553C12.0005 9.93492 12.5014 9.67863 12.9162 9.30595C13.5042 8.77758 13.878 8.05195 13.9669 7.26645C14.0558 6.48096 13.8536 5.69013 13.3985 5.04371C12.9811 4.45071 12.3775 4.01701 11.6866 3.80943C11.5613 2.88615 11.1436 2.02521 10.4923 1.35427C9.79633 0.637401 8.87567 0.18078 7.88381 0.0605549ZM3.75049 10.4384C3.75049 10.0242 4.08628 9.68839 4.50049 9.68839H6.25049V7.93839C6.25049 7.52417 6.58628 7.18839 7.00049 7.18839C7.4147 7.18839 7.75049 7.52417 7.75049 7.93839V9.68839H9.50049C9.9147 9.68839 10.2505 10.0242 10.2505 10.4384C10.2505 10.8526 9.9147 11.1884 9.50049 11.1884H7.75049V12.9384C7.75049 13.3526 7.4147 13.6884 7.00049 13.6884C6.58628 13.6884 6.25049 13.3526 6.25049 12.9384V11.1884H4.50049C4.08628 11.1884 3.75049 10.8526 3.75049 10.4384Z"
fill="currentColor"/>
</g>
<defs>
<clipPath id="clip0_1068_187542">
<rect width="14" height="14" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,12 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Columns">
<g id="Vector">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M8.125 2.5C8.81536 2.5 9.375 3.05964 9.375 3.75V16.25C9.375 16.9404 8.81536 17.5 8.125 17.5H5C4.30964 17.5 3.75 16.9404 3.75 16.25V3.75C3.75 3.05964 4.30964 2.5 5 2.5H8.125ZM8.125 16.25V3.75H5V16.25H8.125Z"
fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15 2.5C15.6904 2.5 16.25 3.05964 16.25 3.75V16.25C16.25 16.9404 15.6904 17.5 15 17.5H11.875C11.1846 17.5 10.625 16.9404 10.625 16.25V3.75C10.625 3.05964 11.1846 2.5 11.875 2.5H15ZM15 16.25V3.75H11.875V16.25H15Z"
fill="currentColor"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 828 B

View File

@ -1,12 +1,5 @@
<svg width="35" height="34" viewBox="0 0 35 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25.5 21.834C25.5 21.2817 25.9477 20.834 26.5 20.834C27.0523 20.834 27.5 21.2817 27.5 21.834V22.834H28.5C29.0523 22.834 29.5 23.2817 29.5 23.834C29.5 24.3863 29.0523 24.834 28.5 24.834H26.5C25.9477 24.834 25.5 24.3863 25.5 23.834V21.834Z"
fill="currentColor"/>
<path d="M26.5 29.834C29.8137 29.834 32.5 27.1477 32.5 23.834C32.5 20.5203 29.8137 17.834 26.5 17.834C23.1863 17.834 20.5 20.5203 20.5 23.834C20.5 27.1477 23.1863 29.834 26.5 29.834ZM26.5 27.834C24.2909 27.834 22.5 26.0431 22.5 23.834C22.5 21.6248 24.2909 19.834 26.5 19.834C28.7091 19.834 30.5 21.6248 30.5 23.834C30.5 26.0431 28.7091 27.834 26.5 27.834Z"
fill="currentColor"/>
<path d="M25.5 21.834C25.5 21.2817 25.9477 20.834 26.5 20.834C27.0523 20.834 27.5 21.2817 27.5 21.834V22.834H28.5C29.0523 22.834 29.5 23.2817 29.5 23.834C29.5 24.3863 29.0523 24.834 28.5 24.834H26.5C25.9477 24.834 25.5 24.3863 25.5 23.834V21.834Z"
stroke="currentColor" stroke-width="0.342857"/>
<path d="M26.5 29.834C29.8137 29.834 32.5 27.1477 32.5 23.834C32.5 20.5203 29.8137 17.834 26.5 17.834C23.1863 17.834 20.5 20.5203 20.5 23.834C20.5 27.1477 23.1863 29.834 26.5 29.834ZM26.5 27.834C24.2909 27.834 22.5 26.0431 22.5 23.834C22.5 21.6248 24.2909 19.834 26.5 19.834C28.7091 19.834 30.5 21.6248 30.5 23.834C30.5 26.0431 28.7091 27.834 26.5 27.834Z"
stroke="currentColor" stroke-width="0.342857"/>
<path d="M12.734 6.50065V6.60065H12.834H22.1673H22.2673V6.50065C22.2673 5.91155 22.7449 5.43398 23.334 5.43398C23.9231 5.43398 24.4007 5.91155 24.4007 6.50065V6.60065H24.5007H26.834C28.0675 6.60065 29.0673 7.60055 29.0673 8.83398V15.734H8.16732H8.06732V15.834V26.334V26.434H8.16732H18.734V28.5673H8.16732C6.93388 28.5673 5.93398 27.5674 5.93398 26.334V8.83399C5.93398 7.60055 6.93384 6.60065 8.16728 6.60065H10.5007H10.6007V6.50065C10.6007 5.91155 11.0782 5.43398 11.6673 5.43398C12.2564 5.43398 12.734 5.91155 12.734 6.50065ZM26.834 13.6007H26.934V13.5007V8.83398V8.73398H26.834H24.5007H24.4007V8.83398C24.4007 9.42309 23.9231 9.90065 23.334 9.90065C22.7449 9.90065 22.2673 9.42309 22.2673 8.83398V8.73398H22.1673H12.834H12.734V8.83398C12.734 9.42309 12.2564 9.90065 11.6673 9.90065C11.0782 9.90065 10.6007 9.42309 10.6007 8.83398V8.73398H10.5007H8.16732H8.06732V8.83398V13.5007V13.6007H8.16732H26.834Z"
fill="currentColor" stroke="currentColor" stroke-width="0.2"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M1.80951 8C1.80951 9.64182 2.46172 11.2164 3.62266 12.3773C4.7836 13.5383 6.35817 14.1905 7.99998 14.1905C9.6418 14.1905 11.2164 13.5383 12.3773 12.3773C13.5383 11.2164 14.1905 9.64182 14.1905 8C14.1905 6.35818 13.5383 4.78361 12.3773 3.62267C11.2164 2.46173 9.6418 1.80952 7.99998 1.80952C6.35817 1.80952 4.7836 2.46173 3.62266 3.62267C2.46172 4.78361 1.80951 6.35818 1.80951 8Z"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.00001 4.28571V8H5.21429" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 689 B

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="CurrencyCircleDollar">
<path id="Vector"
d="M10 1.875C8.39303 1.875 6.82214 2.35152 5.486 3.24431C4.14985 4.1371 3.10844 5.40605 2.49348 6.8907C1.87852 8.37535 1.71762 10.009 2.03112 11.5851C2.34463 13.1612 3.11846 14.6089 4.25476 15.7452C5.39106 16.8815 6.8388 17.6554 8.4149 17.9689C9.99099 18.2824 11.6247 18.1215 13.1093 17.5065C14.594 16.8916 15.8629 15.8502 16.7557 14.514C17.6485 13.1779 18.125 11.607 18.125 10C18.1227 7.84581 17.266 5.78051 15.7427 4.25727C14.2195 2.73403 12.1542 1.87727 10 1.875ZM10 16.875C8.64026 16.875 7.31105 16.4718 6.18046 15.7164C5.04987 14.9609 4.16868 13.8872 3.64833 12.6309C3.12798 11.3747 2.99183 9.99237 3.2571 8.65875C3.52238 7.32513 4.17716 6.10013 5.13864 5.13864C6.10013 4.17716 7.32514 3.52237 8.65876 3.2571C9.99238 2.99183 11.3747 3.12798 12.631 3.64833C13.8872 4.16868 14.9609 5.04987 15.7164 6.18045C16.4718 7.31104 16.875 8.64025 16.875 10C16.8729 11.8227 16.1479 13.5702 14.8591 14.8591C13.5702 16.1479 11.8227 16.8729 10 16.875ZM13.125 11.5625C13.125 12.1427 12.8945 12.6991 12.4843 13.1093C12.0741 13.5195 11.5177 13.75 10.9375 13.75H10.625V14.375C10.625 14.5408 10.5592 14.6997 10.4419 14.8169C10.3247 14.9342 10.1658 15 10 15C9.83424 15 9.67527 14.9342 9.55806 14.8169C9.44085 14.6997 9.375 14.5408 9.375 14.375V13.75H8.125C7.95924 13.75 7.80027 13.6842 7.68306 13.5669C7.56585 13.4497 7.5 13.2908 7.5 13.125C7.5 12.9592 7.56585 12.8003 7.68306 12.6831C7.80027 12.5658 7.95924 12.5 8.125 12.5H10.9375C11.1861 12.5 11.4246 12.4012 11.6004 12.2254C11.7762 12.0496 11.875 11.8111 11.875 11.5625C11.875 11.3139 11.7762 11.0754 11.6004 10.8996C11.4246 10.7238 11.1861 10.625 10.9375 10.625H9.0625C8.48234 10.625 7.92594 10.3945 7.51571 9.9843C7.10547 9.57406 6.875 9.01766 6.875 8.4375C6.875 7.85734 7.10547 7.30094 7.51571 6.8907C7.92594 6.48047 8.48234 6.25 9.0625 6.25H9.375V5.625C9.375 5.45924 9.44085 5.30027 9.55806 5.18306C9.67527 5.06585 9.83424 5 10 5C10.1658 5 10.3247 5.06585 10.4419 5.18306C10.5592 5.30027 10.625 5.45924 10.625 5.625V6.25H11.875C12.0408 6.25 12.1997 6.31585 12.3169 6.43306C12.4342 6.55027 12.5 6.70924 12.5 6.875C12.5 7.04076 12.4342 7.19973 12.3169 7.31694C12.1997 7.43415 12.0408 7.5 11.875 7.5H9.0625C8.81386 7.5 8.57541 7.59877 8.39959 7.77459C8.22378 7.9504 8.125 8.18886 8.125 8.4375C8.125 8.68614 8.22378 8.9246 8.39959 9.10041C8.57541 9.27623 8.81386 9.375 9.0625 9.375H10.9375C11.5177 9.375 12.0741 9.60547 12.4843 10.0157C12.8945 10.4259 13.125 10.9823 13.125 11.5625Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Database">
<path id="Vector"
d="M10 1.875C5.79453 1.875 2.5 3.79688 2.5 6.25V13.75C2.5 16.2031 5.79453 18.125 10 18.125C14.2055 18.125 17.5 16.2031 17.5 13.75V6.25C17.5 3.79688 14.2055 1.875 10 1.875ZM16.25 10C16.25 10.7516 15.6344 11.518 14.5617 12.1031C13.3539 12.7617 11.7336 13.125 10 13.125C8.26641 13.125 6.64609 12.7617 5.43828 12.1031C4.36563 11.518 3.75 10.7516 3.75 10V8.7C5.08281 9.87187 7.36172 10.625 10 10.625C12.6383 10.625 14.9172 9.86875 16.25 8.7V10ZM5.43828 4.14688C6.64609 3.48828 8.26641 3.125 10 3.125C11.7336 3.125 13.3539 3.48828 14.5617 4.14688C15.6344 4.73203 16.25 5.49844 16.25 6.25C16.25 7.00156 15.6344 7.76797 14.5617 8.35312C13.3539 9.01172 11.7336 9.375 10 9.375C8.26641 9.375 6.64609 9.01172 5.43828 8.35312C4.36563 7.76797 3.75 7.00156 3.75 6.25C3.75 5.49844 4.36563 4.73203 5.43828 4.14688ZM14.5617 15.8531C13.3539 16.5117 11.7336 16.875 10 16.875C8.26641 16.875 6.64609 16.5117 5.43828 15.8531C4.36563 15.268 3.75 14.5016 3.75 13.75V12.45C5.08281 13.6219 7.36172 14.375 10 14.375C12.6383 14.375 14.9172 13.6187 16.25 12.45V13.75C16.25 14.5016 15.6344 15.268 14.5617 15.8531Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,6 +1,14 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8889 3.5H4.11111C3.49746 3.5 3 3.94772 3 4.5V11.5C3 12.0523 3.49746 12.5 4.11111 12.5H11.8889C12.5025 12.5 13 12.0523 13 11.5V4.5C13 3.94772 12.5025 3.5 11.8889 3.5Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2.5V4.58181" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 2.5V4.58181" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 6.5H13" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<g clip-path="url(#clip0_41_21)">
<path d="M13.8933 4.53334V3.49334C13.8933 2.72752 13.2725 2.10667 12.5067 2.10667H2.8C2.03417 2.10667 1.41333 2.72752 1.41333 3.49334V13.2C1.41333 13.9659 2.03411 14.5867 2.8 14.5867H5.22666"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.4266 0.720001V3.49333" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.88 0.720001V3.49333" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.41333 6.26666H4.88" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.4666 11.4667L10.4266 10.6347V9.03999" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round"/>
<path d="M6.26666 10.4267C6.26666 13.6291 9.73333 15.6305 12.5067 14.0293C13.7938 13.2862 14.5867 11.9129 14.5867 10.4267C14.5867 7.22426 11.12 5.22282 8.34666 6.82399C7.05954 7.56709 6.26666 8.94045 6.26666 10.4267Z"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<g clip-path="url(#clip0_51_33)">
<path d="M7.99998 1.16281V6.63256M7.99998 6.63256L10.0511 4.58138M7.99998 6.63256L5.94885 4.58138"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.16284 8.68369H3.32359C3.94247 8.68369 4.2519 8.68369 4.5239 8.80881C4.7959 8.93387 4.99728 9.16887 5.40003 9.63869L5.81397 10.1217C6.21672 10.5915 6.41815 10.8265 6.69015 10.9516C6.96215 11.0767 7.27159 11.0767 7.8904 11.0767H8.10965C8.72847 11.0767 9.0379 11.0767 9.3099 10.9516C9.58197 10.8265 9.78328 10.5915 10.1861 10.1217L10.6 9.63869C11.0028 9.16887 11.2042 8.93387 11.4762 8.80881C11.7482 8.68369 12.0576 8.68369 12.6765 8.68369H14.8372"
stroke="currentColor" stroke-linecap="round"/>
<path d="M11.4186 1.24956C12.5297 1.35888 13.2777 1.60588 13.8359 2.16413C14.8372 3.16544 14.8372 4.77694 14.8372 8.00006C14.8372 11.2231 14.8372 12.8347 13.8359 13.8359C12.8347 14.8372 11.2231 14.8372 8.00003 14.8372C4.77697 14.8372 3.1654 14.8372 2.16415 13.8359C1.16284 12.8347 1.16284 11.2231 1.16284 8.00006C1.16284 4.77694 1.16284 3.16544 2.16415 2.16413C2.72234 1.60588 3.47028 1.35888 4.58147 1.24956"
stroke="currentColor" stroke-linecap="round"/>
</g>
<defs>
<clipPath id="clip0_51_33">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 13H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.8849 3.36289C11.1173 3.13054 11.4324 3 11.761 3C11.9237 3 12.0848 3.03205 12.2351 3.09431C12.3855 3.15658 12.5221 3.24784 12.6371 3.36289C12.7522 3.47794 12.8434 3.61453 12.9057 3.76485C12.968 3.91517 13 4.07629 13 4.23899C13 4.4017 12.968 4.56281 12.9057 4.71314C12.8434 4.86346 12.7522 5.00004 12.6371 5.11509L5.33627 12.4159L3 13L3.58407 10.6637L10.8849 3.36289Z"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 661 B

View File

@ -0,0 +1,11 @@
<svg fill="currentColor" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 310 310" xml:space="preserve">
<g id="XMLID_834_">
<path id="XMLID_835_" d="M81.703,165.106h33.981V305c0,2.762,2.238,5,5,5h57.616c2.762,0,5-2.238,5-5V165.765h39.064
c2.54,0,4.677-1.906,4.967-4.429l5.933-51.502c0.163-1.417-0.286-2.836-1.234-3.899c-0.949-1.064-2.307-1.673-3.732-1.673h-44.996
V71.978c0-9.732,5.24-14.667,15.576-14.667c1.473,0,29.42,0,29.42,0c2.762,0,5-2.239,5-5V5.037c0-2.762-2.238-5-5-5h-40.545
C187.467,0.023,186.832,0,185.896,0c-7.035,0-31.488,1.381-50.804,19.151c-21.402,19.692-18.427,43.27-17.716,47.358v37.752H81.703
c-2.762,0-5,2.238-5,5v50.844C76.703,162.867,78.941,165.106,81.703,165.106z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 818 B

View File

@ -0,0 +1,15 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_54_39)">
<path d="M9.35439 14.2642H6.64556V15.28H9.35439V14.2642ZM1.73577 9.35441V6.64558H0.719971V9.35441H1.73577ZM14.2641 9.05844V9.35441H15.2799V9.05844H14.2641ZM9.95789 2.99623L12.6388 5.40903L13.3183 4.65398L10.6375 2.24118L9.95789 2.99623ZM15.2799 9.05844C15.2799 7.915 15.2901 7.19109 15.0016 6.54332L14.0738 6.95659C14.2539 7.36108 14.2641 7.8253 14.2641 9.05844H15.2799ZM12.6388 5.40903C13.5554 6.23392 13.8936 6.55211 14.0738 6.95659L15.0016 6.54332C14.7132 5.89554 14.1682 5.41888 13.3183 4.65398L12.6388 5.40903ZM6.66574 1.73585C7.73694 1.73585 8.14118 1.74372 8.5014 1.88195L8.86534 0.933568C8.28851 0.712197 7.65999 0.720059 6.66574 0.720059V1.73585ZM10.6375 2.24118C9.90199 1.57923 9.44223 1.15488 8.86534 0.933568L8.5014 1.88195C8.86181 2.02024 9.16576 2.28334 9.95789 2.99623L10.6375 2.24118ZM6.64556 14.2642C5.35422 14.2642 4.43686 14.2631 3.74086 14.1695C3.05954 14.0779 2.667 13.9061 2.38044 13.6195L1.6621 14.3379C2.16891 14.8446 2.81155 15.0695 3.60554 15.1763C4.38492 15.2811 5.38295 15.28 6.64556 15.28V14.2642ZM0.719971 9.35441C0.719971 10.617 0.718919 11.615 0.823662 12.3944C0.930447 13.1884 1.15529 13.8311 1.6621 14.3379L2.38044 13.6195C2.09382 13.333 1.92204 12.9404 1.83042 12.2591C1.73688 11.5631 1.73577 10.6457 1.73577 9.35441H0.719971ZM9.35439 15.28C10.6169 15.28 11.615 15.2811 12.3943 15.1763C13.1883 15.0695 13.831 14.8446 14.3378 14.3379L13.6195 13.6195C13.3329 13.9061 12.9403 14.0779 12.259 14.1695C11.5631 14.2631 10.6457 14.2642 9.35439 14.2642V15.28ZM14.2641 9.35441C14.2641 10.6457 14.2631 11.5631 14.1695 12.2591C14.0779 12.9404 13.9061 13.333 13.6195 13.6195L14.3378 14.3379C14.8445 13.8311 15.0694 13.1884 15.1762 12.3944C15.281 11.615 15.2799 10.617 15.2799 9.35441H14.2641ZM1.73577 6.64558C1.73577 5.35431 1.73688 4.43688 1.83042 3.74095C1.92204 3.05963 2.09382 2.66709 2.38044 2.38047L1.6621 1.66219C1.15535 2.169 0.930447 2.81164 0.823662 3.60563C0.718919 4.38494 0.719971 5.38297 0.719971 6.64558H1.73577ZM6.66574 0.720059C5.39632 0.720059 4.3934 0.718944 3.61086 0.823687C2.81409 0.930349 2.16929 1.155 1.6621 1.66219L2.38044 2.38047C2.66663 2.09428 3.06034 1.92225 3.74563 1.83051C4.44509 1.73691 5.36772 1.73585 6.66574 1.73585V0.720059Z"
fill="currentColor"/>
<path d="M8.67712 1.56655V3.25958C8.67712 4.85574 8.67712 5.65387 9.17298 6.14973C9.6689 6.64559 10.467 6.64559 12.0632 6.64559H14.772"
stroke="currentColor"/>
<path d="M5.62968 12.4019V9.01585M5.62968 9.01585L4.27527 10.2856M5.62968 9.01585L6.9841 10.2856"
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_54_39">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="GraduationCap">
<path id="Vector"
d="M19.6686 6.94833L10.2936 1.94833C10.2031 1.90018 10.1023 1.875 9.9998 1.875C9.89736 1.875 9.79648 1.90018 9.70605 1.94833L0.331055 6.94833C0.231058 7.00163 0.14743 7.0811 0.0891172 7.17825C0.0308042 7.27541 0 7.38659 0 7.4999C0 7.61321 0.0308042 7.72439 0.0891172 7.82154C0.14743 7.91869 0.231058 7.99817 0.331055 8.05146L2.4998 9.20849V12.9913C2.49916 13.2983 2.61214 13.5947 2.81699 13.8233C3.84043 14.9632 6.1334 16.8749 9.9998 16.8749C11.2818 16.8855 12.5542 16.6533 13.7498 16.1905V18.7499C13.7498 18.9157 13.8157 19.0746 13.9329 19.1918C14.0501 19.309 14.209 19.3749 14.3748 19.3749C14.5406 19.3749 14.6995 19.309 14.8167 19.1918C14.934 19.0746 14.9998 18.9157 14.9998 18.7499V15.5866C15.8148 15.1161 16.5513 14.5212 17.1826 13.8233C17.3875 13.5947 17.5005 13.2983 17.4998 12.9913V9.20849L19.6686 8.05146C19.7686 7.99817 19.8522 7.91869 19.9105 7.82154C19.9688 7.72439 19.9996 7.61321 19.9996 7.4999C19.9996 7.38659 19.9688 7.27541 19.9105 7.17825C19.8522 7.0811 19.7686 7.00163 19.6686 6.94833ZM9.9998 15.6249C6.61934 15.6249 4.63105 13.9733 3.7498 12.9913V9.8749L9.70605 13.0515C9.79648 13.0996 9.89736 13.1248 9.9998 13.1248C10.1023 13.1248 10.2031 13.0996 10.2936 13.0515L13.7498 11.2085V14.8288C12.7654 15.2882 11.5248 15.6249 9.9998 15.6249ZM16.2498 12.9882C15.8752 13.4039 15.456 13.7772 14.9998 14.1015V10.5413L16.2498 9.8749V12.9882ZM14.6873 9.29208L14.6701 9.28193L10.2951 6.94833C10.1491 6.87378 9.97974 6.85954 9.82338 6.9087C9.66702 6.95786 9.53623 7.06647 9.45918 7.21114C9.38213 7.35581 9.365 7.52495 9.41147 7.68213C9.45794 7.83931 9.56429 7.97194 9.70762 8.05146L13.3592 9.9999L9.9998 11.7913L1.95293 7.4999L9.9998 3.20849L18.0467 7.4999L14.6873 9.29208Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,7 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="inbox">
<path id="Vector"
d="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.89 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3ZM19 19H5V16H8.56C9.25 17.19 10.53 18 12.01 18C13.49 18 14.76 17.19 15.46 16H19V19ZM19 14H14.01C14.01 15.1 13.11 16 12.01 16C10.91 16 10.01 15.1 10.01 14H5V5H19V14Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 468 B

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z"
fill="currentColor"/>
<path d="M18 5C17.4477 5 17 5.44772 17 6C17 6.55228 17.4477 7 18 7C18.5523 7 19 6.55228 19 6C19 5.44772 18.5523 5 18 5Z"
fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M1.65396 4.27606C1 5.55953 1 7.23969 1 10.6V13.4C1 16.7603 1 18.4405 1.65396 19.7239C2.2292 20.8529 3.14708 21.7708 4.27606 22.346C5.55953 23 7.23969 23 10.6 23H13.4C16.7603 23 18.4405 23 19.7239 22.346C20.8529 21.7708 21.7708 20.8529 22.346 19.7239C23 18.4405 23 16.7603 23 13.4V10.6C23 7.23969 23 5.55953 22.346 4.27606C21.7708 3.14708 20.8529 2.2292 19.7239 1.65396C18.4405 1 16.7603 1 13.4 1H10.6C7.23969 1 5.55953 1 4.27606 1.65396C3.14708 2.2292 2.2292 3.14708 1.65396 4.27606ZM13.4 3H10.6C8.88684 3 7.72225 3.00156 6.82208 3.0751C5.94524 3.14674 5.49684 3.27659 5.18404 3.43597C4.43139 3.81947 3.81947 4.43139 3.43597 5.18404C3.27659 5.49684 3.14674 5.94524 3.0751 6.82208C3.00156 7.72225 3 8.88684 3 10.6V13.4C3 15.1132 3.00156 16.2777 3.0751 17.1779C3.14674 18.0548 3.27659 18.5032 3.43597 18.816C3.81947 19.5686 4.43139 20.1805 5.18404 20.564C5.49684 20.7234 5.94524 20.8533 6.82208 20.9249C7.72225 20.9984 8.88684 21 10.6 21H13.4C15.1132 21 16.2777 20.9984 17.1779 20.9249C18.0548 20.8533 18.5032 20.7234 18.816 20.564C19.5686 20.1805 20.1805 19.5686 20.564 18.816C20.7234 18.5032 20.8533 18.0548 20.9249 17.1779C20.9984 16.2777 21 15.1132 21 13.4V10.6C21 8.88684 20.9984 7.72225 20.9249 6.82208C20.8533 5.94524 20.7234 5.49684 20.564 5.18404C20.1805 4.43139 19.5686 3.81947 18.816 3.43597C18.5032 3.27659 18.0548 3.14674 17.1779 3.0751C16.2777 3.00156 15.1132 3 13.4 3Z"
fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,4 +1,4 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.734 6.50065V6.60065H12.834H22.1673H22.2673V6.50065C22.2673 5.91155 22.7449 5.43398 23.334 5.43398C23.9231 5.43398 24.4007 5.91155 24.4007 6.50065V6.60065H24.5007H26.834C28.0675 6.60065 29.0673 7.60055 29.0673 8.83398V15.734H8.16732H8.06732V15.834V26.334V26.434H8.16732H19.734V28.5673H8.16732C6.93388 28.5673 5.93398 27.5674 5.93398 26.334V8.83399C5.93398 7.60055 6.93384 6.60065 8.16728 6.60065H10.5007H10.6007V6.50065C10.6007 5.91155 11.0782 5.43398 11.6673 5.43398C12.2564 5.43398 12.734 5.91155 12.734 6.50065ZM26.834 13.6007H26.934V13.5007V8.83398V8.73398H26.834H24.5007H24.4007V8.83398C24.4007 9.42309 23.9231 9.90065 23.334 9.90065C22.7449 9.90065 22.2673 9.42309 22.2673 8.83398V8.73398H22.1673H12.834H12.734V8.83398C12.734 9.42309 12.2564 9.90065 11.6673 9.90065C11.0782 9.90065 10.6007 9.42309 10.6007 8.83398V8.73398H10.5007H8.16732H8.06732V8.83398V13.5007V13.6007H8.16732H26.834ZM27.6602 18.999C27.7937 18.7678 28.0893 18.6886 28.3205 18.8221L29.3308 19.4054C29.562 19.5389 29.6412 19.8345 29.5077 20.0657L25.1827 27.5568L23.3352 26.4901L27.6602 18.999ZM22.7054 27.7046L24.4459 28.7094L22.5708 29.9475L22.7054 27.7046Z"
fill="currentColor" stroke="currentColor" stroke-width="0.2"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M8.29141 4.50217V7.66669L10.9209 9.24422C11.3053 9.4751 11.2956 10.0356 10.9035 10.2531C10.7215 10.354 10.4994 10.3502 10.321 10.243L7.40911 8.49586C7.2338 8.39053 7.12659 8.20097 7.12665 7.99646V4.50217C7.1271 4.05385 7.61269 3.77414 8.00073 3.99868C8.18045 4.10269 8.29121 4.29452 8.29141 4.50217ZM14.6976 2.75502C14.376 2.75502 14.1152 3.01576 14.1152 3.33741V4.64777C13.653 4.11197 13.1812 3.59583 12.6505 3.05859C8.84665 -0.745725 2.35092 0.994418 0.958239 6.19085C-0.43445 11.3873 4.32042 16.1427 9.517 14.7506C10.6358 14.4508 11.6626 13.8778 12.5049 13.0828C12.8311 12.7746 12.7013 12.2289 12.2713 12.1006C12.0717 12.041 11.8555 12.0924 11.7042 12.2355C8.44153 15.3102 3.07387 13.7 2.04238 9.33712C1.01089 4.97421 5.0892 1.13078 9.38333 2.41894C10.3051 2.69546 11.144 3.1961 11.825 3.87611C12.4176 4.47596 12.9366 5.05398 13.4601 5.66693H11.7857C11.3374 5.66738 11.0577 6.15298 11.2822 6.54101C11.3862 6.72074 11.5781 6.83149 11.7857 6.8317H14.6976C15.0193 6.83168 15.28 6.57095 15.28 6.24931V3.33741C15.28 3.01576 15.0193 2.75502 14.6976 2.75502Z"
fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Lightbulb">
<path id="Vector"
d="M13.7501 18.125C13.7501 18.2908 13.6843 18.4498 13.567 18.567C13.4498 18.6842 13.2909 18.75 13.1251 18.75H6.8751C6.70934 18.75 6.55037 18.6842 6.43316 18.567C6.31595 18.4498 6.2501 18.2908 6.2501 18.125C6.2501 17.9593 6.31595 17.8003 6.43316 17.6831C6.55037 17.5659 6.70934 17.5 6.8751 17.5H13.1251C13.2909 17.5 13.4498 17.5659 13.567 17.6831C13.6843 17.8003 13.7501 17.9593 13.7501 18.125ZM16.8751 8.12504C16.8778 9.16695 16.6424 10.1957 16.1869 11.1328C15.7315 12.0699 15.0679 12.8905 14.247 13.5321C14.0935 13.6497 13.9689 13.8009 13.8828 13.9741C13.7967 14.1473 13.7513 14.3379 13.7501 14.5313V15C13.7501 15.3316 13.6184 15.6495 13.384 15.8839C13.1496 16.1183 12.8316 16.25 12.5001 16.25H7.5001C7.16858 16.25 6.85064 16.1183 6.61622 15.8839C6.3818 15.6495 6.2501 15.3316 6.2501 15V14.5313C6.24997 14.3402 6.20603 14.1517 6.12166 13.9802C6.03728 13.8088 5.91472 13.6589 5.76338 13.5422C4.94448 12.9045 4.28139 12.0887 3.8243 11.1568C3.36722 10.2249 3.12812 9.20128 3.1251 8.16332C3.10479 4.43989 6.11416 1.3391 9.83448 1.25004C10.7512 1.22795 11.663 1.38946 12.5163 1.72506C13.3696 2.06065 14.1472 2.56356 14.8033 3.20418C15.4593 3.84479 15.9806 4.61017 16.3364 5.45527C16.6922 6.30036 16.8754 7.2081 16.8751 8.12504ZM15.6251 8.12504C15.6253 7.37478 15.4754 6.63205 15.1843 5.94058C14.8932 5.24911 14.4666 4.62287 13.9298 4.09872C13.393 3.57458 12.7568 3.16312 12.0585 2.88856C11.3603 2.61401 10.6142 2.48191 9.86416 2.50004C6.81729 2.57192 4.3587 5.10864 4.3751 8.15551C4.37796 9.00441 4.57385 9.84153 4.94796 10.6036C5.32206 11.3656 5.86459 12.0325 6.53448 12.5539C6.8356 12.788 7.07918 13.0879 7.24655 13.4307C7.41392 13.7734 7.50065 14.1499 7.5001 14.5313V15H12.5001V14.5313C12.501 14.1488 12.5892 13.7715 12.758 13.4283C12.9269 13.0851 13.1719 12.785 13.4743 12.5508C14.1463 12.0257 14.6894 11.354 15.0621 10.5869C15.4349 9.81991 15.6274 8.97785 15.6251 8.12504ZM14.3665 7.39536C14.2044 6.49012 13.7689 5.65626 13.1186 5.00606C12.4682 4.35585 11.6343 3.92051 10.729 3.75864C10.6481 3.74499 10.5652 3.74742 10.4852 3.76579C10.4052 3.78416 10.3296 3.81811 10.2627 3.8657C10.1958 3.91329 10.139 3.97359 10.0954 4.04316C10.0518 4.11272 10.0223 4.19019 10.0087 4.27114C9.99505 4.35208 9.99748 4.43493 10.0159 4.51493C10.0342 4.59494 10.0682 4.67055 10.1158 4.73743C10.1634 4.80432 10.2237 4.86118 10.2932 4.90476C10.3628 4.94835 10.4402 4.9778 10.5212 4.99145C11.8157 5.20942 12.9142 6.30785 13.1337 7.60473C13.1584 7.75029 13.2339 7.8824 13.3467 7.97764C13.4595 8.07288 13.6025 8.1251 13.7501 8.12504C13.7854 8.12483 13.8207 8.12196 13.8556 8.11645C14.0189 8.08856 14.1645 7.99693 14.2604 7.8617C14.3562 7.72647 14.3944 7.55873 14.3665 7.39536Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,13 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M8.68911 5.84996C9.19251 5.09341 9.06598 4.0823 8.39168 3.47312C7.71738 2.86394 6.69866 2.8404 5.99694 3.41779C5.29522 3.99517 5.12213 4.99935 5.59004 5.77835C6.05796 6.55735 7.02577 6.87624 7.86511 6.52796C8.20053 6.38801 8.48717 6.15215 8.68911 5.84996Z"
stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M8.68911 16.1649C9.19251 15.4084 9.06598 14.3972 8.39168 13.7881C7.71738 13.1789 6.69866 13.1553 5.99694 13.7327C5.29522 14.3101 5.12213 15.3143 5.59004 16.0933C6.05796 16.8723 7.02577 17.1912 7.86511 16.8429C8.20053 16.703 8.48717 16.4671 8.68911 16.1649V16.1649Z"
stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11.3111 11.0072C10.8077 10.2506 10.9342 9.23953 11.6085 8.63035C12.2828 8.02117 13.3015 7.99763 14.0032 8.57501C14.705 9.1524 14.8781 10.1566 14.4101 10.9356C13.9422 11.7146 12.9744 12.0335 12.1351 11.6852C11.7997 11.5452 11.513 11.3094 11.3111 11.0072V11.0072Z"
stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 4.22617C8.66863 4.22617 8.4 4.4948 8.4 4.82617C8.4 5.15754 8.66863 5.42617 9 5.42617V4.22617ZM17 5.42617C17.3314 5.42617 17.6 5.15754 17.6 4.82617C17.6 4.4948 17.3314 4.22617 17 4.22617V5.42617ZM5.327 5.42617C5.65837 5.42617 5.927 5.15754 5.927 4.82617C5.927 4.4948 5.65837 4.22617 5.327 4.22617V5.42617ZM3 4.22617C2.66863 4.22617 2.4 4.4948 2.4 4.82617C2.4 5.15754 2.66863 5.42617 3 5.42617V4.22617ZM9 14.5422C8.66863 14.5422 8.4 14.8108 8.4 15.1422C8.4 15.4735 8.66863 15.7422 9 15.7422V14.5422ZM17 15.7422C17.3314 15.7422 17.6 15.4735 17.6 15.1422C17.6 14.8108 17.3314 14.5422 17 14.5422V15.7422ZM5.327 15.7422C5.65837 15.7422 5.927 15.4735 5.927 15.1422C5.927 14.8108 5.65837 14.5422 5.327 14.5422V15.7422ZM3 14.5422C2.66863 14.5422 2.4 14.8108 2.4 15.1422C2.4 15.4735 2.66863 15.7422 3 15.7422V14.5422ZM11 10.5842C11.3314 10.5842 11.6 10.3155 11.6 9.98417C11.6 9.6528 11.3314 9.38417 11 9.38417V10.5842ZM3 9.38417C2.66863 9.38417 2.4 9.6528 2.4 9.98417C2.4 10.3155 2.66863 10.5842 3 10.5842V9.38417ZM14.6719 9.38438C14.3405 9.38438 14.0719 9.653 14.0719 9.98438C14.0719 10.3157 14.3405 10.5844 14.6719 10.5844V9.38438ZM16.9989 10.5844C17.3302 10.5844 17.5989 10.3157 17.5989 9.98438C17.5989 9.653 17.3302 9.38438 16.9989 9.38438V10.5844ZM9 5.42617H17V4.22617H9V5.42617ZM5.327 4.22617H3V5.42617H5.327V4.22617ZM9 15.7422H17V14.5422H9V15.7422ZM5.327 14.5422H3V15.7422H5.327V14.5422ZM11 9.38417H3V10.5842H11V9.38417ZM14.6719 10.5844H16.9989V9.38438H14.6719V10.5844Z"
fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 8C7.32843 8 8 7.32843 8 6.5C8 5.67157 7.32843 5 6.5 5C5.67157 5 5 5.67157 5 6.5C5 7.32843 5.67157 8 6.5 8Z"
fill="currentColor"/>
<path d="M5 10C5 9.44772 5.44772 9 6 9H7C7.55228 9 8 9.44771 8 10V18C8 18.5523 7.55228 19 7 19H6C5.44772 19 5 18.5523 5 18V10Z"
fill="currentColor"/>
<path d="M11 19H12C12.5523 19 13 18.5523 13 18V13.5C13 12 16 11 16 13V18.0004C16 18.5527 16.4477 19 17 19H18C18.5523 19 19 18.5523 19 18V12C19 10 17.5 9 15.5 9C13.5 9 13 10.5 13 10.5V10C13 9.44771 12.5523 9 12 9H11C10.4477 9 10 9.44772 10 10V18C10 18.5523 10.4477 19 11 19Z"
fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20 1C21.6569 1 23 2.34315 23 4V20C23 21.6569 21.6569 23 20 23H4C2.34315 23 1 21.6569 1 20V4C1 2.34315 2.34315 1 4 1H20ZM20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20Z"
fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="MegaphoneSimple">
<path id="Vector"
d="M17.8547 6.7707L4.1 2.55195C3.91383 2.49765 3.71758 2.48742 3.52678 2.52205C3.33597 2.55668 3.15584 2.63523 3.00062 2.75148C2.84541 2.86774 2.71938 3.01852 2.63249 3.19189C2.5456 3.36526 2.50024 3.55647 2.5 3.75039V15.0004C2.5 15.3319 2.6317 15.6499 2.86612 15.8843C3.10054 16.1187 3.41848 16.2504 3.75 16.2504C3.86953 16.2504 3.98845 16.2333 4.10313 16.1996L10.625 14.198V15.0004C10.625 15.3319 10.7567 15.6499 10.9911 15.8843C11.2255 16.1187 11.5435 16.2504 11.875 16.2504H14.375C14.7065 16.2504 15.0245 16.1187 15.2589 15.8843C15.4933 15.6499 15.625 15.3319 15.625 15.0004V12.6645L17.8547 11.9809C18.1127 11.9033 18.3391 11.7449 18.5003 11.529C18.6615 11.3131 18.749 11.0511 18.75 10.7816V7.96914C18.7488 7.69982 18.6612 7.438 18.5 7.22224C18.3388 7.00648 18.1126 6.8482 17.8547 6.7707ZM10.625 12.891L3.75 15.0004V3.75039L10.625 5.85977V12.891ZM14.375 15.0004H11.875V13.8145L14.375 13.0473V15.0004ZM17.5 10.7816H17.4914L11.875 12.5066V6.24414L17.4914 7.96289H17.5V10.7754V10.7816Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Monitor">
<path id="Vector"
d="M16.25 3.125H3.75C3.25272 3.125 2.77581 3.32254 2.42417 3.67417C2.07254 4.02581 1.875 4.50272 1.875 5V13.75C1.875 14.2473 2.07254 14.7242 2.42417 15.0758C2.77581 15.4275 3.25272 15.625 3.75 15.625H16.25C16.7473 15.625 17.2242 15.4275 17.5758 15.0758C17.9275 14.7242 18.125 14.2473 18.125 13.75V5C18.125 4.50272 17.9275 4.02581 17.5758 3.67417C17.2242 3.32254 16.7473 3.125 16.25 3.125ZM16.875 13.75C16.875 13.9158 16.8092 14.0747 16.6919 14.1919C16.5747 14.3092 16.4158 14.375 16.25 14.375H3.75C3.58424 14.375 3.42527 14.3092 3.30806 14.1919C3.19085 14.0747 3.125 13.9158 3.125 13.75V5C3.125 4.83424 3.19085 4.67527 3.30806 4.55806C3.42527 4.44085 3.58424 4.375 3.75 4.375H16.25C16.4158 4.375 16.5747 4.44085 16.6919 4.55806C16.8092 4.67527 16.875 4.83424 16.875 5V13.75ZM13.125 17.5C13.125 17.6658 13.0592 17.8247 12.9419 17.9419C12.8247 18.0592 12.6658 18.125 12.5 18.125H7.5C7.33424 18.125 7.17527 18.0592 7.05806 17.9419C6.94085 17.8247 6.875 17.6658 6.875 17.5C6.875 17.3342 6.94085 17.1753 7.05806 17.0581C7.17527 16.9408 7.33424 16.875 7.5 16.875H12.5C12.6658 16.875 12.8247 16.9408 12.9419 17.0581C13.0592 17.1753 13.125 17.3342 13.125 17.5Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,8 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 4L12.5 4" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 8H12.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 12H12.5" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="4" cy="4" r="0.5" fill="#333333"/>
<circle cx="4" cy="8" r="0.5" fill="#333333"/>
<circle cx="4" cy="12" r="0.5" fill="#333333"/>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M5.5238 4.28571H13.5714" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.5238 8H13.5714" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.5238 11.7143H13.5714" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.42859 4.28571H2.43401" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.42859 8H2.43401" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.42859 11.7143H2.43401" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 748 B

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Notepad">
<path id="Vector"
d="M13.125 10C13.125 10.1658 13.0592 10.3247 12.9419 10.4419C12.8247 10.5592 12.6658 10.625 12.5 10.625H7.5C7.33424 10.625 7.17527 10.5592 7.05806 10.4419C6.94085 10.3247 6.875 10.1658 6.875 10C6.875 9.83424 6.94085 9.67527 7.05806 9.55806C7.17527 9.44085 7.33424 9.375 7.5 9.375H12.5C12.6658 9.375 12.8247 9.44085 12.9419 9.55806C13.0592 9.67527 13.125 9.83424 13.125 10ZM12.5 11.875H7.5C7.33424 11.875 7.17527 11.9408 7.05806 12.0581C6.94085 12.1753 6.875 12.3342 6.875 12.5C6.875 12.6658 6.94085 12.8247 7.05806 12.9419C7.17527 13.0592 7.33424 13.125 7.5 13.125H12.5C12.6658 13.125 12.8247 13.0592 12.9419 12.9419C13.0592 12.8247 13.125 12.6658 13.125 12.5C13.125 12.3342 13.0592 12.1753 12.9419 12.0581C12.8247 11.9408 12.6658 11.875 12.5 11.875ZM16.875 3.125V15.625C16.875 16.288 16.6116 16.9239 16.1428 17.3928C15.6739 17.8616 15.038 18.125 14.375 18.125H5.625C4.96196 18.125 4.32607 17.8616 3.85723 17.3928C3.38839 16.9239 3.125 16.288 3.125 15.625V3.125C3.125 2.95924 3.19085 2.80027 3.30806 2.68306C3.42527 2.56585 3.58424 2.5 3.75 2.5H5.625V1.875C5.625 1.70924 5.69085 1.55027 5.80806 1.43306C5.92527 1.31585 6.08424 1.25 6.25 1.25C6.41576 1.25 6.57473 1.31585 6.69194 1.43306C6.80915 1.55027 6.875 1.70924 6.875 1.875V2.5H9.375V1.875C9.375 1.70924 9.44085 1.55027 9.55806 1.43306C9.67527 1.31585 9.83424 1.25 10 1.25C10.1658 1.25 10.3247 1.31585 10.4419 1.43306C10.5592 1.55027 10.625 1.70924 10.625 1.875V2.5H13.125V1.875C13.125 1.70924 13.1908 1.55027 13.3081 1.43306C13.4253 1.31585 13.5842 1.25 13.75 1.25C13.9158 1.25 14.0747 1.31585 14.1919 1.43306C14.3092 1.55027 14.375 1.70924 14.375 1.875V2.5H16.25C16.4158 2.5 16.5747 2.56585 16.6919 2.68306C16.8092 2.80027 16.875 2.95924 16.875 3.125ZM15.625 3.75H14.375V4.375C14.375 4.54076 14.3092 4.69973 14.1919 4.81694C14.0747 4.93415 13.9158 5 13.75 5C13.5842 5 13.4253 4.93415 13.3081 4.81694C13.1908 4.69973 13.125 4.54076 13.125 4.375V3.75H10.625V4.375C10.625 4.54076 10.5592 4.69973 10.4419 4.81694C10.3247 4.93415 10.1658 5 10 5C9.83424 5 9.67527 4.93415 9.55806 4.81694C9.44085 4.69973 9.375 4.54076 9.375 4.375V3.75H6.875V4.375C6.875 4.54076 6.80915 4.69973 6.69194 4.81694C6.57473 4.93415 6.41576 5 6.25 5C6.08424 5 5.92527 4.93415 5.80806 4.81694C5.69085 4.69973 5.625 4.54076 5.625 4.375V3.75H4.375V15.625C4.375 15.9565 4.5067 16.2745 4.74112 16.5089C4.97554 16.7433 5.29348 16.875 5.625 16.875H14.375C14.7065 16.875 15.0245 16.7433 15.2589 16.5089C15.4933 16.2745 15.625 15.9565 15.625 15.625V3.75Z"
fill="currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icons 16 / docs">
<g id="Group 1321314145">
<path id="Vector" d="M9.08889 2V5.81818C9.08889 6.42067 9.5764 6.90909 10.1778 6.90909H12.3556M4.18889 14H11.8111C12.4125 14 12.9 13.5116 12.9 12.9091V7.09091C12.9 6.61883 12.7472 6.15948 12.4644 5.78182L10.2867 2.87273C9.87538 2.32333 9.22991 2 8.54444 2H4.18889C3.58751 2 3.1 2.48842 3.1 3.09091V12.9091C3.1 13.5116 3.58751 14 4.18889 14Z" stroke="#747B84" stroke-width="1.09091"/>
<g id="Vector_2">
<path d="M5.27777 10.7273C4.97708 10.7273 4.73332 10.9715 4.73332 11.2727C4.73332 11.574 4.97708 11.8182 5.27777 11.8182H7.45554C7.75623 11.8182 7.99999 11.574 7.99999 11.2727C7.99999 10.9715 7.75623 10.7273 7.45554 10.7273H5.27777Z" fill="#747B84"/>
<path d="M4.73332 9.09091C4.73332 8.78966 4.97708 8.54546 5.27777 8.54546H9.63332C9.93401 8.54546 10.1778 8.78966 10.1778 9.09091C10.1778 9.39216 9.93401 9.63637 9.63332 9.63637H5.27777C4.97708 9.63637 4.73332 9.39216 4.73332 9.09091Z" fill="#747B84"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Some files were not shown because too many files have changed in this diff Show More