1
0
Fork 0
mirror of https://github.com/anyproto/anytype-ts.git synced 2025-06-08 05:57:02 +09:00

Merge branch 'main' of github.com:anyproto/anytype-ts into feature/JS-5614-webclipper-auth

This commit is contained in:
Andrew Simachev 2025-01-07 10:20:06 +01:00
commit ffe80f19ec
No known key found for this signature in database
GPG key ID: 1DFE44B21443F0EF
55 changed files with 795 additions and 1557 deletions

View file

@ -175,7 +175,7 @@ class MenuManager {
submenu: [
{
label: `${Util.translate('electronMenuReleaseNotes')} (${app.getVersion()})`,
click: () => Util.send(this.win, 'popup', 'help', { preventResize: true, data: { document: 'whatsNew' } })
click: () => Util.send(this.win, 'popup', 'help', { data: { document: 'whatsNew' } })
},
{
label: Util.translate('electronMenuShortcuts'), accelerator: 'Ctrl+Space',

View file

@ -0,0 +1,3 @@
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 3.75879C9.58579 3.75879 9.25 4.09458 9.25 4.50879V10.0088H3.75C3.33579 10.0088 3 10.3446 3 10.7588C3 11.173 3.33579 11.5088 3.75 11.5088H9.25V17.0088C9.25 17.423 9.58579 17.7588 10 17.7588C10.4142 17.7588 10.75 17.423 10.75 17.0088V11.5088H16.25C16.6642 11.5088 17 11.173 17 10.7588C17 10.3446 16.6642 10.0088 16.25 10.0088H10.75V4.50879C10.75 4.09458 10.4142 3.75879 10 3.75879Z" fill="#B6B6B6"/>
</svg>

After

Width:  |  Height:  |  Size: 553 B

View file

@ -0,0 +1,4 @@
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.3794 12.2588L16.3179 16.1972C16.5607 16.4401 16.5607 16.8338 16.3179 17.0767C16.075 17.3195 15.6813 17.3195 15.4384 17.0767L11.5 13.1382L12.3794 12.2588Z" fill="#B6B6B6"/>
<circle cx="8.75" cy="9.50879" r="4.625" stroke="#B6B6B6" stroke-width="1.25"/>
</svg>

After

Width:  |  Height:  |  Size: 407 B

View file

@ -53,7 +53,6 @@ export default {
relationEdit: [
'select',
'searchObject',
'dataviewDate',
'dataviewObjectValues',
'dataviewObjectList'
],
@ -66,6 +65,5 @@ export default {
widget: [ 'searchObject', 'select' ],
dataviewTemplate: [ 'previewObject' ],
table: [ 'select2', 'blockColor', 'blockBackground' ],
navigation: [ 'quickCapture', 'space' ],
dataviewContext: [ 'typeSuggest', 'searchObject' ]
};

View file

@ -31,6 +31,7 @@ export default () => {
{ com: `${cmd} + 0`, name: translate('popupShortcutMainBasics18') },
{ com: `Ctrl + Tab, Ctrl + Shift + Tab`, name: translate('popupShortcutMainBasics20') },
{ com: `${cmd} + Shift + M`, name: translate('popupShortcutMainBasics21') },
{ com: `${cmd} + ${alt} + L`, name: translate('popupShortcutMainBasics22') },
]
},

View file

@ -1186,6 +1186,7 @@
"popupShortcutMainBasics19": "Open the Quick Capture menu",
"popupShortcutMainBasics20": "Switch to the next/previous Space",
"popupShortcutMainBasics21": "Switch color mode (light/dark)",
"popupShortcutMainBasics22": "Lock the app with a PIN code",
"popupShortcutMainStructuring": "Structuring",
"popupShortcutMainStructuring1": "Create a new text block",
"popupShortcutMainStructuring2": "Create a line break within a block of text",
@ -1444,11 +1445,6 @@
"menuDataviewCreateSomethingWentWrong": "Oops - something went wrong!",
"menuDataviewDateDateFormat": "Date format",
"menuDataviewDateTimeFormat": "Time format",
"menuDataviewDate12Hour": "12 hour",
"menuDataviewDate24Hour": "24 hour",
"menuDataviewFileValuesFindAFile": "Find a file...",
"menuDataviewFilterValuesChecked": "Checked",
@ -1800,8 +1796,6 @@
"phrasePlaceholder": "Please enter your Key",
"navigationAccount": "Spaces",
"spaceAccessType0": "Private Space",
"spaceAccessType1": "Entry Space",
"spaceAccessType2": "Shared Space",
@ -2283,6 +2277,9 @@
"formulaCheckboxNotEmpty": "Count checked",
"formulaCheckboxNotEmptyShort": "Checked",
"formulaCheckboxPercentEmpty": "Percentage unchecked",
"formulaCheckboxPercentNotEmpty": "Percentage checked"
"formulaCheckboxPercentNotEmpty": "Percentage checked",
"timeFormat12": "12 hour",
"timeFormat24": "24 hour"
}

View file

@ -1,6 +1,6 @@
.formWrapper.isFixed { padding: 0px 0px 90px 0px; position: sticky; z-index: 11; bottom: 0px; width: 100%; background: var(--color-bg-primary); }
.formWrapper.isFixed { padding: 0px 0px 16px 0px; position: sticky; z-index: 11; bottom: 0px; width: 100%; background: var(--color-bg-primary); }
.form {
padding: 0px 0px 10px 0px; border: 1px solid var(--color-shape-tertiary); background-color: var(--color-bg-primary); border-radius: 12px; position: relative;

View file

@ -104,6 +104,9 @@
}
.message.canExpand.isExpanded {
.text { -webkit-line-clamp: unset; }
.reply {
.text { @include clamp; -webkit-line-clamp: 10; }
}
.expand::after { transform: rotateZ(180deg); margin-top: 2px; }
}
.message:hover, .message.hover {

View file

@ -24,7 +24,6 @@
@import "./title";
@import "./toast";
@import "./tooltip";
@import "./navigation";
@import "./hightlight";
@import "./progressBar";
@import "./share";

View file

@ -53,9 +53,7 @@
.headerBanner.withMenu:after { content: ''; position: absolute; right: 10px; top: 12px; width: 8px; height: 8px; background-image: url('~img/arrow/button/black.svg'); }
.headerBanner.withMenu.active:after { transform: rotateZ(180deg); }
.sync { -webkit-app-region: no-drag; flex-shrink: 0; }
.icon { -webkit-app-region: no-drag; flex-shrink: 0; }
.icon.more { background-image: url('~img/icon/header/more.svg'); }
.icon.settings { background-image: url('~img/icon/header/settings.svg'); }
.icon.expand { display: none; background-image: url('~img/icon/header/expand.svg'); }
@ -67,18 +65,18 @@
}
.header:not(.withSidebar) {
.side.left { padding-left: 120px; }
.side.left { padding-left: 156px; }
}
html:not(.platformMac) {
.header:not(.withSidebar) {
.side.left { padding-left: 52px; }
.side.left { padding-left: 88px; }
}
}
body.isFullScreen {
.header:not(.withSidebar) {
.side.left { padding-left: 52px; }
.side.left { padding-left: 88px; }
}
}

View file

@ -1,27 +0,0 @@
@import "~scss/_mixins";
.navigationPanel {
background: rgba(134, 134, 134, 0.7); backdrop-filter: blur(32px); border-radius: 16px; position: fixed; left: 0px; padding: 12px 16px; bottom: 24px;
z-index: 105; transition-property: opacity, visibility; transition-duration: 0.16s; transition-timing-function: $easeInQuint;
}
.navigationPanel.hide { visibility: hidden; z-index: 0; opacity: 0; }
.navigationPanel.hide * { pointer-events: none; }
.navigationPanel.sidebarAnimation { transition-property: left; }
.navigationPanel {
.inner { display: flex; flex-direction: row; gap: 0px 20px; align-items: center; justify-content: center; position: relative; z-index: 1; }
.iconWrap {
width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center;
position: relative; transition: $transitionAllCommon;
}
.iconWrap:not(.disabled):hover, .iconWrap.active { background-color: rgba(37, 37, 37, 0.15); }
.icon { width: 20px; height: 20px; z-index: 1; }
.icon.back, .icon.forward { background-image: url('~img/icon/navigation/back.svg'); }
.icon.forward { transform: rotateZ('180deg'); }
.icon.plus { background-image: url('~img/icon/navigation/plus.svg'); }
.icon.graph { background-image: url('~img/icon/navigation/graph.svg'); }
.icon.search { background-image: url('~img/icon/navigation/search.svg'); }
}

View file

@ -8,13 +8,14 @@
.sidebarAnimation { transition: width $transitionSidebarTime linear; }
#sidebarToggle {
position: fixed; left: 84px; top: 12px; backdrop-filter: blur(20px);
background-image: url('~img/icon/widget/toggle0.svg'); z-index: 22; -webkit-app-region: no-drag; transition: none;
}
#sidebarToggle.sidebarAnimation { transition: left $transitionSidebarTime linear; }
#sidebarToggle,
#sidebarSync { position: fixed; top: 12px; z-index: 22; -webkit-app-region: no-drag; transition: none; }
#sidebarToggle { backdrop-filter: blur(20px); left: 84px; background-image: url('~img/icon/widget/toggle0.svg'); }
#sidebarToggle.sidebarAnimation, #sidebarSync.sidebarAnimation { transition: left $transitionSidebarTime linear; }
#sidebarToggle:hover, #sidebarToggle.hover { background-color: var(--color-shape-highlight-medium) !important; background-image: url('~img/icon/widget/toggle1.svg'); }
.sidebar { position: fixed; z-index: 21; user-select: none; transition: none; top: 0px; left: 0px; height: 100%; }
.sidebar.anim { transition-property: width; transition-duration: $transitionSidebarTime; transition-timing-function: linear; }
.sidebar.withVault { left: $vaultWidthCollapsed; }

View file

@ -14,7 +14,6 @@ html.printMedia {
.header,
.footer,
.notifications,
#navigationPanel,
#sidebar,
.sidebarDummy,
.progress,

View file

@ -5,7 +5,6 @@
.menuWrap.fromPopup,
.menuWrap.fromHeader,
.menuWrap.fromSidebar,
.menuWrap.fromNavigation { z-index: 103; }
.menuWrap.fromOnboarding { z-index: 1001; }
.menuWrap.fixed { position: fixed; }

View file

@ -25,7 +25,7 @@ html.bodyIndex, html.bodyAuth {
--shadow: 0px 0px 0px 1px var(--color-button-stroke) !important;
body { background: var(--color-bg-primary); color: var(--color-text-secondary); overflow: hidden; }
#navigationPanel, #notifications, #sidebar, #vault, #sidebarToggle, .shareTooltip { display: none !important; }
#notifications, #sidebar, #vault, #sidebarToggle, .shareTooltip { display: none !important; }
.popup {
.innerWrap { background: var(--color-popup) !important;; box-shadow: var(--shadow) !important; color: var(--color-text-primary) !important; }

View file

@ -4,7 +4,6 @@
#vault,
#sidebar,
#sidebarToggle,
#navigationPanel,
#sidebarDummy { display: none; }
body { background: #000; }

View file

@ -1,7 +1,7 @@
@import "~scss/_mixins";
.bodyMainVoid {
.navigationPanel, #sidebar { display: none; }
#sidebar { display: none; }
}
.pageMainVoid {

View file

@ -322,13 +322,6 @@ html.themeDark {
}
}
/* Navigation */
.navigationPanel { background-color: rgba(0, 0, 0, 0.6); }
.navigationPanel {
.iconWrap:not(.disabled):hover, .iconWrap.active { background-color: rgba(255, 255, 255, 0.1); }
}
/* Notifications */
.notifications {

View file

@ -1,42 +0,0 @@
@import "~scss/_mixins";
.widget.widgetButtons { padding: 8px; }
.widget.widgetButtons {
.icon.remove { display: none !important; }
.body {
.item { padding: 4px 8px; display: flex; align-items: center; justify-content: space-between; position: relative; }
.item::before {
content: ""; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; background: var(--color-shape-highlight-medium); z-index: 1; pointer-events: none;
border-radius: 6px; opacity: 0;
}
.item:hover::before, .item.hover::before { opacity: 1; }
.item {
.side { display: flex; flex-direction: row; align-items: center; }
.side.left { gap: 0px 6px; }
.side.right { justify-content: flex-end; padding-left: 6px; overflow: hidden; }
.side.right {
.btn { background-image: linear-gradient(90deg, #2aa7ee, #27c941); background-clip: text; -webkit-text-fill-color: transparent; font-weight: 500; }
}
.name { display: flex; gap: 0px 8px; @include text-overflow-nw; }
.icon { width: 20px; height: 20px; flex-shrink: 0; }
.icon.member { background-image: url('~img/icon/widget/button/member.svg'); }
.icon.all { background-image: url('~img/icon/widget/button/all.svg'); }
.icon.chat { background-image: url('~img/icon/widget/button/chat.svg'); }
.cnt { color: var(--color-text-secondary); }
}
.item:hover {
.side.right {
.icon.more { opacity: 1; }
}
}
}
.body.withCnt {
.side.left { width: calc(100% - 30px); }
}
}

View file

@ -116,6 +116,5 @@
}
@import "./space";
@import "./buttons";
@import "./tree";
@import "./view/common";

View file

@ -1,33 +1,70 @@
@import "~scss/_mixins";
.widget.widgetSpace { padding: 16px; }
.widget.widgetSpace { padding: 8px; }
.widget.widgetSpace {
.icon.remove { display: none !important; }
.body { display: flex; flex-direction: row; align-items: center; gap: 0px 12px; justify-content: stretch; }
.body {
.side.left { display: flex; flex-direction: row; align-items: center; gap: 0px 12px; width: 100%; }
.side.left {
.iconObject { flex-shrink: 0; }
.iconObject:not(.withOption) { background-color: var(--color-shape-tertiary); }
.sides { display: flex; flex-direction: row; align-items: center; gap: 0px 12px; justify-content: stretch; padding: 4px 4px 4px 8px; }
.sides {
.side.left { display: flex; flex-direction: row; align-items: center; gap: 0px 6px; width: 100%; }
.side.left {
.iconObject { flex-shrink: 0; }
.iconObject:not(.withOption) { background-color: var(--color-shape-tertiary); }
.txt { flex-grow: 1; width: calc(100% - 52px) }
.name { @include text-paragraph; @include text-overflow-nw; font-weight: 600; }
.txt { flex-grow: 1; width: calc(100% - 52px) }
.name { @include text-paragraph; @include text-overflow-nw; font-weight: 600; }
}
.side.right { flex-shrink: 0; display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: 0px 4px; }
.side.right {
.cnt {
@include text-very-small; background-color: var(--color-control-active); color: var(--color-control-bg); border-radius: 50%; min-width: 18px;
text-align: center; font-weight: 500; height: 18px; line-height: 18px; display: none; padding: 0px 2px; flex-shrink: 0;
}
.icon { width: 24px; height: 24px; flex-shrink: 0; }
.icon.search { background-image: url('~img/icon/widget/button/search.svg'); }
.icon.plus { background-image: url('~img/icon/widget/button/plus.svg'); }
.icon.graph { background-image: url('~img/icon/menu/action/graph0.svg'); }
}
}
.side.right { flex-shrink: 0; display: flex; flex-direction: row; align-items: center; justify-content: flex-end; }
.side.right {
.cnt {
@include text-very-small; background-color: var(--color-control-accent); color: var(--color-control-bg); border-radius: 50%; min-width: 18px;
text-align: center; font-weight: 500; height: 18px; line-height: 18px; display: none; padding: 0px 2px;
.buttons {
.item { padding: 4px 8px; display: flex; align-items: center; justify-content: space-between; position: relative; }
.item::before {
content: ""; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; background: var(--color-shape-highlight-medium); z-index: 1; pointer-events: none;
border-radius: 6px; opacity: 0;
}
.item:hover::before, .item.hover::before { opacity: 1; }
.item {
.side { display: flex; flex-direction: row; align-items: center; }
.side.left { gap: 0px 6px; }
.name { display: flex; gap: 0px 8px; @include text-overflow-nw; }
.icon { width: 20px; height: 20px; flex-shrink: 0; }
.icon.member { background-image: url('~img/icon/widget/button/member.svg'); }
.icon.all { background-image: url('~img/icon/widget/button/all.svg'); }
.icon.chat { background-image: url('~img/icon/widget/button/chat.svg'); }
.cnt { color: var(--color-text-secondary); }
}
.item:hover {
.side.right {
.icon.more { opacity: 1; }
}
}
}
}
.body.withCnt {
.side.left { width: calc(100% - 30px); }
.side.right {
.cnt { display: block; }
.sides {
.side.left { width: calc(100% - 30px); }
.side.right {
.cnt { display: block; }
}
}
}
}

View file

@ -8,7 +8,7 @@ import { Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'mobx-react';
import { configure, spy } from 'mobx';
import { enableLogging } from 'mobx-logger';
import { Page, SelectionProvider, DragProvider, Progress, Toast, Preview as PreviewIndex, Navigation, ListPopup, ListMenu, ListNotification, Sidebar, Vault, ShareTooltip, Loader } from 'Component';
import { Page, SelectionProvider, DragProvider, Progress, Toast, Preview as PreviewIndex, ListPopup, ListMenu, ListNotification, Sidebar, Vault, Loader } from 'Component';
import { I, C, S, U, J, M, keyboard, Storage, analytics, dispatcher, translate, Renderer, focus, Preview, Mark, Animation, Onboarding, Survey, Encode, Decode, sidebar } from 'Lib';
require('pdfjs-dist/build/pdf.worker.entry.js');
@ -139,7 +139,6 @@ class RoutePage extends React.Component<RouteComponentProps> {
<ListPopup key="listPopup" {...this.props} />
<ListMenu key="listMenu" {...this.props} />
<Navigation ref={ref => S.Common.refSet('navigation', ref)} key="navigation" {...this.props} />
<Sidebar key="sidebar" {...this.props} />
<Page {...this.props} isPopup={false} />
</DragProvider>

View file

@ -180,7 +180,6 @@ const BlockType = observer(class BlockType extends React.Component<I.BlockCompon
const { block } = this.props;
const element = `#block-${block.id} #item-menu`;
const obj = $(element);
const items = this.getItems();
S.Menu.open('typeSuggest', {
element: `#block-${block.id} #item-menu`,
@ -192,7 +191,6 @@ const BlockType = observer(class BlockType extends React.Component<I.BlockCompon
data: {
filter: '',
filters: [
{ relationKey: 'id', condition: I.FilterCondition.NotIn, value: items.map(it => it.id) },
{ relationKey: 'recommendedLayout', condition: I.FilterCondition.In, value: U.Object.getPageLayouts() },
{ relationKey: 'uniqueKey', condition: I.FilterCondition.NotEqual, value: J.Constant.typeKey.template }
],

View file

@ -1845,17 +1845,19 @@ const EditorPage = observer(class EditorPage extends React.Component<Props, Stat
const block = S.Block.getLeaf(rootId, focused);
const selection = S.Common.getRef('selectionProvider');
let url = U.Common.matchUrl(data.text);
let isLocal = false;
if (!data.html) {
let url = U.Common.matchUrl(data.text);
let isLocal = false;
if (!url) {
url = U.Common.matchLocalPath(data.text);
isLocal = true;
};
if (!url) {
url = U.Common.matchLocalPath(data.text);
isLocal = true;
};
if (block && url && !block.isTextTitle() && !block.isTextDescription()) {
this.onPasteUrl(url, isLocal);
return;
if (block && url && !block.isTextTitle() && !block.isTextDescription()) {
this.onPasteUrl(url, isLocal);
return;
};
};
let id = '';

View file

@ -113,7 +113,6 @@ const Input = forwardRef<InputRef, Props>(({
};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
console.log('V1', e.target.value, 'V2', value);
setValue(e.target.value);
handleEvent(onChange, e);
};

View file

@ -1,6 +1,6 @@
import React, { forwardRef, useRef, useEffect, useImperativeHandle } from 'react';
import { I, S, U, J, Renderer, keyboard, sidebar, Preview, translate } from 'Lib';
import { Icon, Sync } from 'Component';
import { Icon } from 'Component';
import HeaderAuthIndex from './auth';
import HeaderMainObject from './main/object';
@ -52,19 +52,32 @@ const Header = forwardRef<{}, Props>((props, ref) => {
};
const renderLeftIcons = (onOpen?: () => void) => {
const object = S.Detail.get(rootId, rootId, J.Relation.template);
const isTypeOrRelation = U.Object.isTypeOrRelationLayout(object.layout);
const showMenu = !isTypeOrRelation;
const canSync = showMenu && !object.templateIsBundled && !U.Object.isParticipantLayout(object.layout);
const cmd = keyboard.cmdSymbol();
const alt = keyboard.altSymbol();
const isWin = U.Common.isPlatformWindows();
const isLinux = U.Common.isPlatformLinux();
const cb = isWin || isLinux ? `${alt} + ←` : `${cmd} + [`;
const cf = isWin || isLinux ? `${alt} + →` : `${cmd} + ]`;
const buttons: any[] = [
{ id: 'expand', name: translate('commonOpenObject'), onClick: onOpen || onExpand },
{ id: 'back', name: translate('commonBack'), caption: cb, onClick: () => keyboard.onBack(), disabled: !keyboard.checkBack() },
{ id: 'forward', name: translate('commonForward'), caption: cf, onClick: () => keyboard.onForward(), disabled: !keyboard.checkForward() },
];
return (
<>
<Icon
className="expand withBackground"
tooltip={translate('commonOpenObject')}
onClick={onOpen || onExpand}
/>
{canSync ? <Sync id="button-header-sync" onClick={onSync} /> : ''}
{buttons.map(item => {
const cn = [ item.id, 'withBackground' ];
if (item.disabled) {
cn.push('disabled');
};
return (
<Icon key={item.id} className={cn.join(' ')} onClick={e => item.onClick(e)} />
);
})}
</>
);
};
@ -153,15 +166,6 @@ const Header = forwardRef<{}, Props>((props, ref) => {
});
};
const onSync = () => {
menuOpen('syncStatus', '#button-header-sync', {
subIds: [ 'syncStatusInfo' ],
data: {
rootId,
}
});
};
const getContainer = () => {
return (isPopup ? '.popup' : '') + ' .header';
};

View file

@ -69,7 +69,6 @@ import Toast from './util/toast';
import Marker from './util/marker';
import Sync from './util/sync';
import LoadMore from './util/loadMore';
import Navigation from './util/navigation';
import Icon from './util/icon';
import IconObject from './util/iconObject';
@ -157,7 +156,6 @@ export {
Title,
Label,
Error,
Navigation,
Notification,
Icon,

View file

@ -16,7 +16,6 @@ const MenuBlockRelationEdit = observer(class MenuBlockRelationEdit extends React
super(props);
this.onRelationType = this.onRelationType.bind(this);
this.onDateSettings = this.onDateSettings.bind(this);
this.onObjectType = this.onObjectType.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onOpen = this.onOpen.bind(this);
@ -299,27 +298,6 @@ const MenuBlockRelationEdit = observer(class MenuBlockRelationEdit extends React
});
};
onDateSettings (e: any) {
e.preventDefault();
e.stopPropagation();
const { param, getId } = this.props;
const { data } = param;
const relation = this.getRelation();
if (relation && relation.isReadonlyRelation) {
return;
};
this.menuOpen('dataviewDate', {
element: `#${getId()} #item-date-settings`,
onClose: () => {
S.Menu.close('select');
},
data,
});
};
onKeyDown (e: any) {
keyboard.shortcut('enter', e, (pressed: string) => {
this.onSubmit(e);

View file

@ -1,200 +0,0 @@
import * as React from 'react';
import $ from 'jquery';
import { observer } from 'mobx-react';
import { MenuItemVertical } from 'Component';
import { I, C, S, U, keyboard, translate } from 'Lib';
const MenuDataviewDate = observer(class MenuDataviewDate extends React.Component<I.Menu> {
_isMounted = false;
n = -1;
constructor (props: I.Menu) {
super(props);
this.rebind = this.rebind.bind(this);
};
render () {
const sections = this.getSections();
const Section = (item: any) => (
<div>
{item.name ? <div className="sectionName">{item.name}</div> : ''}
<div className="items">
{item.children.map((action: any, i: number) => (
<MenuItemVertical
key={i}
{...action}
onMouseEnter={e => this.onMouseEnter(e, action)}
/>
))}
</div>
</div>
);
return (
<div className="items">
{sections.map((item: any, i: number) => (
<Section key={i} {...item} />
))}
</div>
);
};
componentDidMount () {
this._isMounted = true;
this.rebind();
};
componentDidUpdate () {
this.props.setActive();
this.props.position();
};
componentWillUnmount () {
this._isMounted = false;
};
rebind () {
this.unbind();
$(window).on('keydown.menu', e => this.props.onKeyDown(e));
window.setTimeout(() => this.props.setActive(), 15);
};
unbind () {
$(window).off('keydown.menu');
};
getSections () {
const { param } = this.props;
const { data } = param;
const { getView, relationId } = data;
const relation = S.Record.getRelationById(relationId);
const dateOptions = this.getOptions('dateFormat');
const timeOptions = this.getOptions('timeFormat');
if (!relation) {
return [];
};
let df = null;
let tf = null;
let dateFormat = null;
let timeFormat = null;
if (getView) {
const view = getView();
const vr = view.getRelation(relation.relationKey);
if (vr) {
df = vr.dateFormat;
tf = vr.timeFormat;
};
} else {
df = relation.dateFormat;
tf = relation.timeFormat;
};
dateFormat = dateOptions.find(it => it.id == df) || dateOptions[0];
timeFormat = timeOptions.find(it => it.id == tf) || timeOptions[0];
let sections = [
{
id: 'date', name: translate('menuDataviewDateDateFormat'), children: [
{ id: 'dateFormat', name: dateFormat?.name, arrow: true }
]
},
{
id: 'time', name: translate('menuDataviewDateTimeFormat'), children: [
{ id: 'timeFormat', name: timeFormat?.name, arrow: true }
]
},
];
sections = U.Menu.sectionsMap(sections);
return sections;
};
getItems () {
const sections = this.getSections();
let items: any[] = [];
for (const section of sections) {
items = items.concat(section.children);
};
return items;
};
getOptions (key: string) {
let options: any[] = [];
switch (key) {
case 'dateFormat': {
options = U.Menu.dateFormatOptions();
break;
};
case 'timeFormat': {
options = U.Menu.timeFormatOptions();
break;
};
};
return options;
};
onOver (e: any, item: any) {
const { param, getId, getSize, close } = this.props;
const { data, classNameWrap } = param;
const { rootId, blockId, relationKey, getView } = data;
const options = this.getOptions(item.itemId);
let relation = null;
let view = null;
let value = null;
if (getView) {
view = getView();
relation = view.getRelation(relationKey);
} else {
relation = S.Record.getRelationByKey(relationKey);
};
if (relation) {
value = options.find(it => it.id == relation[item.itemId]);
} else if (options.length) {
value = options[0];
};
S.Menu.open('select', {
element: `#${getId()} #item-${item.id}`,
offsetX: getSize().width,
offsetY: -38,
isSub: true,
passThrough: true,
classNameWrap,
data: {
rebind: this.rebind,
value: value.id,
options,
onSelect: (e: any, el: any) => {
if (view) {
relation[item.itemId] = el.id;
C.BlockDataviewViewRelationReplace(rootId, blockId, view.id, relationKey, relation);
};
close();
}
}
});
};
onMouseEnter (e: any, item: any) {
if (!keyboard.isMouseDisabled) {
this.props.setActive(item, false);
this.onOver(e, item);
};
};
});
export default MenuDataviewDate;

View file

@ -48,7 +48,7 @@ const MenuHelp = forwardRef<I.MenuRef, I.Menu>((props, ref) => {
switch (item.id) {
case 'whatsNew': {
S.Popup.open('help', { preventResize: true, data: { document: item.document } });
S.Popup.open('help', { data: { document: item.document } });
break;
};

View file

@ -64,7 +64,6 @@ import MenuDataviewCalendar from './dataview/calendar';
import MenuDataviewCalendarDay from './dataview/calendar/day';
import MenuDataviewOptionList from './dataview/option/list';
import MenuDataviewOptionEdit from './dataview/option/edit';
import MenuDataviewDate from './dataview/date';
import MenuDataviewText from './dataview/text';
import MenuDataviewSource from './dataview/source';
import MenuDataviewContext from './dataview/context';
@ -145,7 +144,6 @@ const Components: any = {
dataviewViewLayout: MenuDataviewViewLayout,
dataviewCalendar: MenuDataviewCalendar,
dataviewCalendarDay: MenuDataviewCalendarDay,
dataviewDate: MenuDataviewDate,
dataviewText: MenuDataviewText,
dataviewSource: MenuDataviewSource,
dataviewContext: MenuDataviewContext,
@ -452,14 +450,7 @@ const Menu = observer(class Menu extends React.Component<I.Menu, State> {
};
getBorderBottom () {
const { id } = this.props;
let ret = Number(window.AnytypeGlobalConfig?.menuBorderBottom) || 80;
if ([ 'help', 'onboarding', 'searchObjectWidgetAdd' ].includes(id)) {
ret = 16;
};
return ret;
return Number(window.AnytypeGlobalConfig?.menuBorderBottom) || J.Size.menuBorder;
};
getBorderLeft () {

View file

@ -201,14 +201,6 @@ class MenuQuickCapture extends React.Component<I.Menu, State> {
this.unbind();
$(window).on('keydown.menu', e => this.onKeyDown(e));
window.setTimeout(() => setActive(), 15);
if (S.Common.navigationMenu == I.NavigationMenuMode.Hover) {
$(`#${getId()}`).off(`mouseleave`).on(`mouseleave`, () => {
if (!this.state.isExpanded) {
close();
};
});
};
};
unbind () {
@ -465,7 +457,7 @@ class MenuQuickCapture extends React.Component<I.Menu, State> {
U.Object.openAuto(object);
U.Object.setLastUsedDate(object.id, U.Date.now());
analytics.createObject(object.type, object.layout, analytics.route.navigation, message.middleTime);
analytics.createObject(object.type, object.layout, '', message.middleTime);
analytics.event('SelectObjectType', { objectType: object.type });
});
};
@ -507,7 +499,7 @@ class MenuQuickCapture extends React.Component<I.Menu, State> {
const canPin = type.isInstalled;
const canDefault = type.isInstalled && !U.Object.isInSetLayouts(item.recommendedLayout) && (type.id != S.Common.type);
const canDelete = type.isInstalled && S.Block.isAllowed(item.restrictions, [ I.RestrictionObject.Delete ]);
const route = analytics.route.navigation;
const route = '';
let options: any[] = [
canPin ? { id: 'pin', name: (isPinned ? translate('menuQuickCaptureUnpin') : translate('menuQuickCapturePin')) } : null,

View file

@ -1,6 +1,5 @@
import React, { forwardRef, useState, useRef, useEffect } from 'react';
import $ from 'jquery';
import raf from 'raf';
import * as Docs from 'Docs';
import { Label, Icon, Cover, Button } from 'Component';
import { I, U, J, translate, Action } from 'Lib';
@ -25,15 +24,6 @@ const PopupHelp = forwardRef<{}, I.Popup>((props, ref) => {
cn.push('withCover');
};
const rebind = () => {
unbind();
$(window).off('resize.popupHelp').on('resize.popupHelp', () => resize());
};
const unbind = () => {
$(window).off('resize.help');
};
const getSections = (): any[] => {
const list = blocks.filter(it => it.type != I.BlockType.Cover);
const sections: any[] = [];
@ -84,23 +74,7 @@ const PopupHelp = forwardRef<{}, I.Popup>((props, ref) => {
setPage(page + dir);
};
const resize = () => {
const obj = $(`#${getId()}-innerWrap`);
const loader = obj.find('#loader');
loader.css({ width: obj.width(), height: obj.height() });
position();
raf(() => { obj.css({ top: J.Size.header + 20, marginTop: 0 }); });
};
useEffect(() => {
rebind();
resize();
U.Common.renderLinks($(nodeRef.current));
return () => unbind();
});
useEffect(() => U.Common.renderLinks($(nodeRef.current)));
return (
<div

View file

@ -1,4 +1,4 @@
import * as React from 'react';
import React, { forwardRef, useEffect } from 'react';
import $ from 'jquery';
import raf from 'raf';
import { RouteComponentProps } from 'react-router';
@ -8,89 +8,45 @@ import { Page } from 'Component';
interface Props extends I.Popup, RouteComponentProps<any> {};
const PopupPage = observer(class PopupPage extends React.Component<Props> {
const PopupPage = observer(forwardRef<{}, Props>((props, ref) => {
const { param, getId } = props;
const { data } = param;
const { matchPopup } = data;
_isMounted = false;
ref = null;
render () {
const { param } = this.props;
const { data } = param;
const { matchPopup } = data;
return (
<div id="wrap">
<Page
ref={ref => this.ref = ref}
{...this.props}
rootId={matchPopup.params.id}
isPopup={true}
matchPopup={matchPopup}
/>
</div>
);
const rebind = () => {
unbind();
$(`#${getId()}`).find('.innerWrap').on('scroll.common', () => S.Menu.resizeAll());
};
componentDidMount () {
const { param } = this.props;
const { data } = param;
const { matchPopup } = data;
const unbind = () => {
$(`#${getId()}`).find('.innerWrap').off('scroll.common');
};
this._isMounted = true;
this.rebind();
this.resize();
useEffect(() => {
rebind();
historyPopup.pushMatch(matchPopup);
};
componentWillUnmount () {
this._isMounted = false;
this.unbind();
historyPopup.clear();
keyboard.setWindowTitle();
};
rebind () {
if (!this._isMounted) {
return;
return () => {
unbind();
historyPopup.clear();
keyboard.setWindowTitle();
};
this.unbind();
const { getId } = this.props;
const win = $(window);
const obj = $(`#${getId()}`);
}, []);
win.on('resize.popupPage', () => this.resize());
obj.find('.innerWrap').on('scroll.common', () => S.Menu.resizeAll());
};
return (
<div id="wrap">
<Page
{...props}
rootId={matchPopup.params.id}
isPopup={true}
matchPopup={matchPopup}
/>
</div>
);
unbind () {
const { getId } = this.props;
const win = $(window);
const obj = $(`#${getId()}`);
win.off('resize.popupPage');
obj.find('.innerWrap').off('scroll.common');
};
resize () {
if (!this._isMounted) {
return;
};
const { getId, position } = this.props;
const obj = $(`#${getId()}-innerWrap`);
const loader = obj.find('#loader');
const hh = J.Size.header;
loader.css({ width: obj.width(), height: obj.height() });
position();
raf(() => { obj.css({ top: hh + 20, marginTop: 0 }); });
};
});
}));
export default PopupPage;

View file

@ -7,17 +7,12 @@ const PopupSettingsPagePersonal = observer(class PopupSettingsPagePersonal exten
render () {
const { getId } = this.props;
const { config, interfaceLang, navigationMenu, linkStyle, fullscreenObject, hideSidebar, showRelativeDates, showVault, dateFormat, timeFormat, } = S.Common;
const { config, interfaceLang, linkStyle, fullscreenObject, hideSidebar, showRelativeDates, showVault, dateFormat, timeFormat, } = S.Common;
const { hideTray, hideMenuBar, languages } = config;
const canHideMenu = U.Common.isPlatformWindows() || U.Common.isPlatformLinux();
const interfaceLanguages = U.Menu.getInterfaceLanguages();
const spellingLanguages = U.Menu.getSpellingLanguages();
const navigationMenuModes: I.Option[] = [
{ id: I.NavigationMenuMode.Click, name: translate('popupSettingsPersonalNavigationMenuClick') },
{ id: I.NavigationMenuMode.Hover, name: translate('popupSettingsPersonalNavigationMenuHover') },
{ id: I.NavigationMenuMode.Context, name: translate('popupSettingsPersonalNavigationMenuContext') },
];
const linkStyles: I.Option[] = [
{ id: I.LinkCardStyle.Card, name: translate('menuBlockLinkSettingsStyleCard') },
{ id: I.LinkCardStyle.Text, name: translate('menuBlockLinkSettingsStyleText') },
@ -64,22 +59,6 @@ const PopupSettingsPagePersonal = observer(class PopupSettingsPagePersonal exten
<Label className="section" text={translate('popupSettingsPersonalSectionEditor')} />
<div className="actionItems">
<div className="item">
<Label text={translate('popupSettingsPersonalNavigationMenu')} />
<Select
id="navigationMenu"
value={navigationMenu}
options={navigationMenuModes}
onChange={v => {
S.Common.navigationMenuSet(v);
analytics.event('ChangeShowQuickCapture', { type: v });
}}
arrowClassName="black"
menuParam={{ horizontal: I.MenuDirection.Right }}
/>
</div>
<div className="item">
<Label text={translate('popupSettingsPersonalLinkStyle')} />

View file

@ -2,7 +2,7 @@ import * as React from 'react';
import $ from 'jquery';
import raf from 'raf';
import { observer } from 'mobx-react';
import { Icon } from 'Component';
import { Icon, Sync } from 'Component';
import { I, U, J, S, keyboard, Preview, sidebar } from 'Lib';
import SidebarWidget from './widget';
@ -34,7 +34,6 @@ const Sidebar = observer(class Sidebar extends React.Component {
render() {
const { showVault, showObject } = S.Common;
const cn = [ 'sidebar' ];
const cmd = keyboard.cmdSymbol();
return (
@ -48,10 +47,12 @@ const Sidebar = observer(class Sidebar extends React.Component {
onContextMenu={this.onToggleContext}
/>
<Sync id="sidebarSync" onClick={this.onSync} />
<div
ref={node => this.node = node}
id="sidebar"
className={cn.join(' ')}
className="sidebar"
>
{showObject ? <SidebarObject ref={ref => this.refObject = ref} {...this.props} /> : <SidebarWidget {...this.props} ref={ref => this.refWidget = ref} />}
<div className="resize-h" draggable={true} onDragStart={this.onResizeStart}>
@ -201,6 +202,17 @@ const Sidebar = observer(class Sidebar extends React.Component {
U.Menu.sidebarContext('#sidebarToggle');
};
onSync = () => {
S.Menu.closeAllForced(null, () => S.Menu.open('syncStatus', {
element: '#sidebarSync',
className: 'fixed',
classNameWrap: 'fromSidebar',
data: {
rootId: keyboard.getRootId(),
},
}));
};
});
export default Sidebar;

View file

@ -142,14 +142,6 @@ const SidebarWidget = observer(class SidebarWidget extends React.Component<{}, S
isEditing={isEditing}
/>
</DropTarget>
<Widget
block={new M.Block({ id: 'buttons', type: I.BlockType.Widget, content: { layout: I.WidgetLayout.Buttons } })}
disableContextMenu={true}
onDragStart={this.onDragStart}
onDragOver={this.onDragOver}
isEditing={isEditing}
/>
</React.Fragment>
) : ''}

View file

@ -1,158 +0,0 @@
import React, { forwardRef, useRef, useImperativeHandle } from 'react';
import $ from 'jquery';
import { observer } from 'mobx-react';
import { Icon } from 'Component';
import { I, S, U, J, keyboard, Preview, translate, analytics } from 'Lib';
interface NavigationRefProps {
position: (sw: number, animate: boolean) => void;
};
const Navigation = observer(forwardRef<NavigationRefProps>((_, ref) => {
const nodeRef = useRef(null);
const timeoutPlus = useRef(0);
const { navigationMenu } = S.Common;
const cmd = keyboard.cmdSymbol();
const alt = keyboard.altSymbol();
const isWin = U.Common.isPlatformWindows();
const isLinux = U.Common.isPlatformLinux();
const cb = isWin || isLinux ? `${alt} + ←` : `${cmd} + [`;
const cf = isWin || isLinux ? `${alt} + →` : `${cmd} + ]`;
const canWrite = U.Space.canMyParticipantWrite();
const onBack = () => {
keyboard.onBack();
};
const onForward = () => {
keyboard.onForward();
};
const onAdd = (e: any) => {
e.altKey ? keyboard.onQuickCapture(false) : keyboard.pageCreate({}, analytics.route.navigation);
};
const onGraph = () => {
U.Object.openAuto({ id: keyboard.getRootId(), layout: I.ObjectLayout.Graph });
};
const onSearch = () => {
keyboard.onSearchPopup(analytics.route.navigation);
};
const position = (sidebarWidth: number, animate: boolean) => {
const node = $(nodeRef.current);
const { ww } = U.Common.getWindowDimensions();
const width = node.outerWidth();
const x = (ww - sidebarWidth) / 2 - width / 2 + sidebarWidth;
if (animate) {
node.addClass('sidebarAnimation');
};
node.css({ left: `${x / ww * 100}%` });
if (animate) {
window.setTimeout(() => node.removeClass('sidebarAnimation'), J.Constant.delay.sidebar);
};
};
const onTooltipShow = (e: any, text: string, caption?: string) => {
const t = Preview.tooltipCaption(text, caption);
if (t) {
Preview.tooltipShow({ text: t, element: $(e.currentTarget), typeY: I.MenuDirection.Top });
};
};
let buttonPlus: any = null;
if (canWrite) {
buttonPlus = { id: 'plus', tooltip: translate('commonCreateNewObject'), caption: `${cmd} + N / ${cmd} + ${alt} + N` };
switch (navigationMenu) {
case I.NavigationMenuMode.Context: {
buttonPlus.onClick = onAdd;
buttonPlus.onContextMenu = () => keyboard.onQuickCapture(false);
break;
};
case I.NavigationMenuMode.Click: {
buttonPlus.onClick = () => keyboard.onQuickCapture(false);
break;
};
case I.NavigationMenuMode.Hover: {
buttonPlus.onClick = onAdd;
buttonPlus.onMouseEnter = e => {
window.clearTimeout(timeoutPlus.current);
timeoutPlus.current = window.setTimeout(() => {
keyboard.onQuickCapture(false, { isSub: true, passThrough: false });
}, 1000);
};
buttonPlus.onMouseLeave = () => window.clearTimeout(timeoutPlus.current);
break;
};
};
};
const buttons: any[] = [
{ id: 'back', tooltip: translate('commonBack'), caption: cb, onClick: onBack, disabled: !keyboard.checkBack() },
{ id: 'forward', tooltip: translate('commonForward'), caption: cf, onClick: onForward, disabled: !keyboard.checkForward() },
buttonPlus,
{ id: 'graph', tooltip: translate('commonGraph'), caption: `${cmd} + ${alt} + O`, onClick: onGraph },
{ id: 'search', tooltip: translate('commonSearch'), caption: `${cmd} + S`, onClick: onSearch },
].filter(it => it).map(it => {
if (!it.onMouseEnter && !it.disabled) {
it.onMouseEnter = e => {
window.clearTimeout(timeoutPlus.current);
onTooltipShow(e, it.tooltip, it.caption);
};
};
if (!it.onMouseLeave) {
it.onMouseLeave = () => Preview.tooltipHide(false);
};
return it;
});
useImperativeHandle(ref, () => ({
position,
}));
return (
<div
ref={nodeRef}
id="navigationPanel"
className="navigationPanel"
>
<div className="inner">
{buttons.map(item => {
const cn = [ 'iconWrap' ];
if (item.disabled) {
cn.push('disabled');
};
return (
<div
key={item.id}
id={`button-navigation-${item.id}`}
className={cn.join(' ')}
onClick={e => {
window.clearTimeout(timeoutPlus.current);
item.onClick(e);
}}
onContextMenu={item.onContextMenu}
onMouseEnter={item.onMouseEnter}
onMouseLeave={item.onMouseLeave}
>
<Icon className={item.id} />
</div>
);
})}
</div>
</div>
);
}));
export default Navigation;

View file

@ -296,7 +296,7 @@ const Vault = observer(class Vault extends React.Component {
classNameWrap: 'fromSidebar',
element: `#vault #item-${item.id}`,
vertical: I.MenuDirection.Center,
route: analytics.route.navigation,
route: analytics.route.vault,
});
};

View file

@ -1,90 +0,0 @@
import React, { forwardRef } from 'react';
import { observer } from 'mobx-react';
import { Icon } from 'Component';
import { I, S, U, sidebar, translate } from 'Lib';
const WidgetButtons = observer(forwardRef<{}, I.WidgetComponent>((props, ref) => {
const getItems = () => {
const space = U.Space.getSpaceview();
const ret = [
{ id: 'all', name: translate('commonAllContent') },
];
if (space.isShared) {
ret.unshift({ id: 'member', name: translate('commonMembers') });
};
if (space.chatId && U.Object.isAllowedChat()) {
ret.push({ id: 'chat', name: translate('commonMainChat') });
};
return ret;
};
const onClick = (e: any, item: any) => {
e.preventDefault();
e.stopPropagation();
switch (item.id) {
case 'member': {
S.Popup.open('settings', { data: { page: 'spaceShare', isSpace: true }, className: 'isSpace' });
break;
};
case 'all': {
sidebar.objectContainerToggle();
break;
};
case 'chat': {
U.Object.openAuto({ id: S.Block.workspace, layout: I.ObjectLayout.Chat });
break;
};
};
};
const items = getItems();
const space = U.Space.getSpaceview();
const participants = U.Space.getParticipantsList([ I.ParticipantStatus.Active ]);
return (
<div className="body">
{items.map((item, i) => {
let button = null;
let cnt = null;
if (item.id == 'member') {
if (space.isShared) {
cnt = <div className="cnt">{participants.length}</div>;
} else {
button = <div className="btn">{translate('commonShare')}</div>;
};
};
return (
<div
key={i}
id={`item-${item.id}`}
className="item"
onClick={e => onClick(e, item)}
>
<div className="side left">
<Icon className={item.id} />
<div className="name">
{item.name}
{cnt}
</div>
</div>
<div className="side right">
{button}
</div>
</div>
);
})}
</div>
);
}));
export default WidgetButtons;

View file

@ -1,4 +1,4 @@
import * as React from 'react';
import React, { forwardRef, useRef, useEffect, useState, MouseEvent } from 'react';
import $ from 'jquery';
import raf from 'raf';
import { observer } from 'mobx-react';
@ -6,7 +6,6 @@ import { Icon, ObjectName, DropTarget } from 'Component';
import { C, I, S, U, J, translate, Storage, Action, analytics, Dataview, keyboard, Relation } from 'Lib';
import WidgetSpace from './space';
import WidgetButtons from './buttons';
import WidgetView from './view';
import WidgetTree from './tree';
@ -19,340 +18,118 @@ interface Props extends I.WidgetComponent {
onDragOver?: (e: React.MouseEvent, blockId: string) => void;
};
const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
const WidgetIndex = observer(forwardRef<{}, Props>((props, ref) => {
node = null;
ref = null;
timeout = 0;
subId = '';
const { block, isPreview, isEditing, className, setEditing, onDragStart, onDragOver, setPreview } = props;
const { viewId } = block.content;
const { root, widgets } = S.Block;
const childrenIds = S.Block.getChildrenIds(widgets, block.id);
const child = childrenIds.length ? S.Block.getLeaf(widgets, childrenIds[0]) : null;
const targetId = child ? child.getTargetObjectId() : '';
constructor (props: Props) {
super(props);
this.onSetPreview = this.onSetPreview.bind(this);
this.onRemove = this.onRemove.bind(this);
this.onClick = this.onClick.bind(this);
this.onOptions = this.onOptions.bind(this);
this.onToggle = this.onToggle.bind(this);
this.onDragEnd = this.onDragEnd.bind(this);
this.onContext = this.onContext.bind(this);
this.onCreateClick = this.onCreateClick.bind(this);
this.onCreate = this.onCreate.bind(this);
this.isSystemTarget = this.isSystemTarget.bind(this);
this.getData = this.getData.bind(this);
this.getLimit = this.getLimit.bind(this);
this.getTraceId = this.getTraceId.bind(this);
this.sortFavorite = this.sortFavorite.bind(this);
this.canCreate = this.canCreate.bind(this);
const isSystemTarget = (): boolean => {
return child ? isSystemTargetId(child.getTargetObjectId()) : false;
};
render () {
const { block, isPreview, isEditing, className, onDragStart, onDragOver, setPreview } = this.props;
const child = this.getTargetBlock();
const root = '';
const childrenIds = S.Block.getChildrenIds(root, root);
const { viewId } = block.content;
const object = this.getObject();
const favCnt = this.getFavoriteIds().length;
const limit = this.getLimit(block.content);
const isSystemTargetId = (id: string): boolean => {
return U.Menu.isSystemWidget(id);
};
let layout = block.content.layout;
if (object) {
const layoutOptions = U.Menu.getWidgetLayoutOptions(object.id, object.layout).map(it => it.id);
if (layoutOptions.length && !layoutOptions.includes(layout)) {
layout = layoutOptions[0];
};
};
const hasChild = ![ I.WidgetLayout.Space, I.WidgetLayout.Buttons ].includes(layout);
if (!child && hasChild) {
const getObject = () => {
if (!child) {
return null;
};
const canWrite = U.Space.canMyParticipantWrite();
const { targetBlockId } = child?.content || {};
const cn = [ 'widget' ];
const withSelect = !this.isSystemTarget() && (!isPreview || !U.Common.isPlatformMac());
const childKey = `widget-${child?.id}-${layout}`;
const canCreate = this.canCreate();
const canDrop = object && !this.isSystemTarget() && !isEditing && S.Block.isAllowed(object.restrictions, [ I.RestrictionObject.Block ]);
const isFavorite = targetBlockId == J.Constant.widgetId.favorite;
const props = {
...this.props,
ref: ref => this.ref = ref,
key: childKey,
parent: block,
block: child,
canCreate,
isSystemTarget: this.isSystemTarget,
getData: this.getData,
getLimit: this.getLimit,
getTraceId: this.getTraceId,
sortFavorite: this.sortFavorite,
addGroupLabels: this.addGroupLabels,
onContext: this.onContext,
onCreate: this.onCreate,
};
if (className) {
cn.push(className);
};
if (isPreview) {
cn.push('isPreview');
};
if (withSelect) {
cn.push('withSelect');
};
let head = null;
let content = null;
let back = null;
let buttons = null;
let targetTop = null;
let targetBot = null;
let isDraggable = canWrite;
if (isPreview) {
back = (
<div className="iconWrap back">
<Icon
className="back"
onClick={() => {
setPreview('');
analytics.event('ScreenHome', { view: 'Widget' });
}}
/>
</div>
);
isDraggable = false;
let object = null;
if (isSystemTargetId(targetId)) {
object = {
id: targetId,
name: translate(U.Common.toCamelCase(`widget-${targetId}`)),
};
} else {
buttons = (
<div className="buttons">
{isEditing ? (
<div className="iconWrap more">
<Icon className="options" tooltip={translate('widgetOptions')} onClick={this.onOptions} />
</div>
) : ''}
{canCreate ? (
<div className="iconWrap create">
<Icon className="plus" tooltip={translate('commonCreateNewObject')} onClick={this.onCreateClick} />
</div>
) : ''}
<div className="iconWrap collapse">
<Icon className="collapse" tooltip={translate('widgetToggle')} onClick={this.onToggle} />
</div>
</div>
);
object = S.Detail.get(widgets, targetId);
};
return object;
};
const getLimit = ({ limit, layout }): number => {
if (isPreview) {
return J.Constant.limit.menuRecords;
};
if (hasChild) {
const onClick = this.isSystemTarget() ? this.onSetPreview : this.onClick;
const options = U.Menu.getWidgetLimitOptions(layout).map(it => Number(it.id));
head = (
<div className="head" onClick={onClick}>
{back}
<div className="clickable">
<ObjectName object={object} />
{isFavorite && (favCnt > limit) ? <span className="count">{favCnt}</span> : ''}
</div>
{buttons}
</div>
);
if (canDrop) {
head = (
<DropTarget
cacheKey={[ block.id, object.id ].join('-')}
id={object.id}
rootId={targetBlockId}
targetContextId={object.id}
dropType={I.DropType.Menu}
canDropMiddle={true}
className="targetHead"
>
{head}
</DropTarget>
);
};
targetTop = (
<DropTarget
{...this.props}
isTargetTop={true}
rootId={S.Block.widgets}
id={block.id}
dropType={I.DropType.Widget}
canDropMiddle={false}
onClick={onClick}
/>
);
targetBot = (
<DropTarget
{...this.props}
isTargetBottom={true}
rootId={S.Block.widgets}
id={block.id}
dropType={I.DropType.Widget}
canDropMiddle={false}
/>
);
if (!limit || !options.includes(limit)) {
limit = options[0];
};
switch (layout) {
case I.WidgetLayout.Space: {
cn.push('widgetSpace');
content = <WidgetSpace {...props} />;
return limit;
};
isDraggable = false;
break;
};
const object = getObject();
const limit = getLimit(block.content);
const [ dummy, setDummy ] = useState(0);
const nodeRef = useRef(null);
const childRef = useRef(null);
const subId = useRef('');
const timeout = useRef(0);
const recordIds = S.Record.getRecords(subId.current).filter(it => !it.isArchived && !it.isDeleted).map(it => it.id)
const isFavorite = targetId == J.Constant.widgetId.favorite;
const favCnt = isFavorite ? recordIds.length : 0;
case I.WidgetLayout.Buttons: {
cn.push('widgetButtons');
content = <WidgetButtons {...props} />;
isDraggable = false;
break;
};
case I.WidgetLayout.Link: {
cn.push('widgetLink');
break;
};
case I.WidgetLayout.Tree: {
cn.push('widgetTree');
content = <WidgetTree {...props} />;
break;
};
case I.WidgetLayout.List:
case I.WidgetLayout.Compact:
case I.WidgetLayout.View: {
cn.push('widgetView');
content = <WidgetView {...props} />;
break;
};
let layout = block.content.layout;
if (object) {
const layoutOptions = U.Menu.getWidgetLayoutOptions(object.id, object.layout).map(it => it.id);
if (layoutOptions.length && !layoutOptions.includes(layout)) {
layout = layoutOptions[0];
};
return (
<div
ref={node => this.node = node}
id={`widget-${block.id}`}
className={cn.join(' ')}
draggable={isDraggable}
onDragStart={e => onDragStart(e, block.id)}
onDragOver={e => onDragOver ? onDragOver(e, block.id) : null}
onDragEnd={this.onDragEnd}
onContextMenu={this.onOptions}
>
<Icon className="remove" inner={<div className="inner" />} onClick={this.onRemove} />
{head}
<div id="wrapper" className="contentWrapper">
{content}
</div>
<div className="dimmer" />
{targetTop}
{targetBot}
</div>
);
};
componentDidMount(): void {
this.rebind();
this.forceUpdate();
};
const hasChild = ![ I.WidgetLayout.Space ].includes(layout);
const canWrite = U.Space.canMyParticipantWrite();
const cn = [ 'widget' ];
const withSelect = !isSystemTarget() && (!isPreview || !U.Common.isPlatformMac());
const childKey = `widget-${child?.id}-${layout}`;
const canDrop = object && !isSystemTarget() && !isEditing && S.Block.isAllowed(object.restrictions, [ I.RestrictionObject.Block ]);
componentDidUpdate(): void {
this.initToggle();
};
componentWillUnmount(): void {
this.unbind();
window.clearTimeout(this.timeout);
};
unbind () {
const { block } = this.props;
const unbind = () => {
const events = [ 'updateWidgetData', 'updateWidgetViews' ];
$(window).off(events.map(it => `${it}.${block.id}`).join(' '));
};
rebind () {
const { block } = this.props;
const rebind = () => {
const win = $(window);
this.unbind();
unbind();
win.on(`updateWidgetData.${block.id}`, () => this.ref && this.ref.updateData && this.ref.updateData());
win.on(`updateWidgetViews.${block.id}`, () => this.ref && this.ref.updateViews && this.ref.updateViews());
win.on(`updateWidgetData.${block.id}`, () => childRef.current?.updateData && childRef.current?.updateData());
win.on(`updateWidgetViews.${block.id}`, () => childRef.current?.updateViews && childRef.current?.updateViews());
};
getTargetBlock (): I.Block {
const { widgets } = S.Block;
const { block } = this.props;
const childrenIds = S.Block.getChildrenIds(widgets, block.id);
return childrenIds.length ? S.Block.getLeaf(widgets, childrenIds[0]) : null;
};
getObject () {
const { widgets } = S.Block;
const child = this.getTargetBlock();
if (!child) {
return null;
};
const id = child.getTargetObjectId();
let object = null;
if (this.isSystemTargetId(id)) {
object = { id, name: translate(U.Common.toCamelCase(`widget-${id}`)) };
} else {
object = S.Detail.get(widgets, id);
};
return object;
};
onRemove (e: React.MouseEvent): void {
const onRemove = (e: MouseEvent): void => {
e.stopPropagation();
Action.removeWidget(this.props.block.id, this.getObject());
Action.removeWidget(block.id, object);
};
onClick (e: React.MouseEvent): void {
const onClick = (e: MouseEvent): void => {
if (!e.button) {
U.Object.openEvent(e, { ...this.getObject(), _routeParam_: { viewId: this.props.block.content.viewId } });
U.Object.openEvent(e, { ...object, _routeParam_: { viewId: block.content.viewId } });
};
};
onCreateClick (e: React.MouseEvent): void {
const onCreateClick = (e: MouseEvent): void => {
e.preventDefault();
e.stopPropagation();
this.onCreate({ route: analytics.route.widget });
onCreate({ route: analytics.route.widget });
};
onCreate (param?: any): void {
const onCreate = (param?: any): void => {
param = param || {};
const { block } = this.props;
const { viewId, layout } = block.content;
const object = this.getObject();
const route = param.route || analytics.route.widget;
if (!object) {
@ -373,7 +150,7 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
};
if (isSetOrCollection) {
const rootId = this.getRootId();
const rootId = getRootId();
if (!rootId) {
return;
};
@ -434,7 +211,7 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
const newObject = message.details;
if (isFavorite) {
Action.setIsFavorite([ newObject.id ], true, analytics.route.widget);
Action.setIsFavorite([ newObject.id ], true, route);
};
if (isCollection) {
@ -442,11 +219,11 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
};
U.Object.openConfig(newObject);
analytics.createObject(newObject.type, newObject.layout, param.route, message.middleTime);
analytics.createObject(newObject.type, newObject.layout, route, message.middleTime);
});
};
onOptions (e: React.MouseEvent): void {
const onOptions = (e: MouseEvent): void => {
e.preventDefault();
e.stopPropagation();
@ -454,14 +231,11 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
return;
};
const { block, setEditing } = this.props;
const object = this.getObject();
const node = $(this.node);
if (!object || object._empty_) {
return;
};
const node = $(nodeRef.current);
const { x, y } = keyboard.mouse.page;
S.Menu.open('widget', {
@ -481,9 +255,8 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
});
};
initToggle () {
const { block, isPreview } = this.props;
const node = $(this.node);
const initToggle = () => {
const node = $(nodeRef.current);
const innerWrap = node.find('#innerWrap');
const icon = node.find('.icon.collapse');
const isClosed = Storage.checkToggle('widget', block.id);
@ -496,32 +269,30 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
};
};
onToggle (e: any) {
const onToggle = (e: any) => {
e.preventDefault();
e.stopPropagation();
const { block } = this.props;
const isClosed = Storage.checkToggle('widget', block.id);
isClosed ? this.open() : this.close();
isClosed ? open() : close();
Storage.setToggle('widget', block.id, !isClosed);
};
open () {
const { block } = this.props;
const node = $(this.node);
const open = () => {
const node = $(nodeRef.current);
const icon = node.find('.icon.collapse');
const innerWrap = node.find('#innerWrap').show();
const wrapper = node.find('#wrapper').css({ height: 'auto' });
const height = wrapper.outerHeight();
const minHeight = this.getMinHeight();
const minHeight = getMinHeight();
node.addClass('isClosed');
icon.removeClass('isClosed');
wrapper.css({ height: minHeight });
if (this.ref && this.ref.onOpen) {
this.ref.onOpen();
if (childRef.current?.onOpen) {
childRef.current?.onOpen();
};
raf(() => {
@ -529,8 +300,8 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
innerWrap.css({ opacity: 1 });
});
window.clearTimeout(this.timeout);
this.timeout = window.setTimeout(() => {
window.clearTimeout(timeout.current);
timeout.current = window.setTimeout(() => {
const isClosed = Storage.checkToggle('widget', block.id);
if (!isClosed) {
@ -540,13 +311,12 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
}, J.Constant.delay.widget);
};
close () {
const { block } = this.props;
const node = $(this.node);
const close = () => {
const node = $(nodeRef.current);
const icon = node.find('.icon.collapse');
const innerWrap = node.find('#innerWrap');
const wrapper = node.find('#wrapper');
const minHeight = this.getMinHeight();
const minHeight = getMinHeight();
wrapper.css({ height: wrapper.outerHeight() });
icon.addClass('isClosed');
@ -557,8 +327,8 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
wrapper.css({ height: minHeight });
});
window.clearTimeout(this.timeout);
this.timeout = window.setTimeout(() => {
window.clearTimeout(timeout.current);
timeout.current = window.setTimeout(() => {
const isClosed = Storage.checkToggle('widget', block.id);
if (isClosed) {
@ -568,21 +338,17 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
}, J.Constant.delay.widget);
};
getMinHeight () {
return [ I.WidgetLayout.List, I.WidgetLayout.Compact, I.WidgetLayout.Tree ].includes(this.props.block.content.layout) ? 8 : 0;
const getMinHeight = () => {
return [ I.WidgetLayout.List, I.WidgetLayout.Compact, I.WidgetLayout.Tree ].includes(block.content.layout) ? 8 : 0;
};
getData (subId: string, callBack?: () => void) {
const { block } = this.props;
const child = this.getTargetBlock();
const getData = (subscriptionId: string, callBack?: () => void) => {
if (!child) {
return;
};
this.subId = subId;
subId.current = subscriptionId;
const { targetBlockId } = child.content;
const space = U.Space.getSpaceview();
const templateType = S.Record.getTemplateType();
const sorts = [];
@ -590,13 +356,13 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
{ relationKey: 'layout', condition: I.FilterCondition.NotIn, value: U.Object.getFileAndSystemLayouts() },
{ relationKey: 'type', condition: I.FilterCondition.NotEqual, value: templateType?.id },
];
let limit = this.getLimit(block.content);
let limit = getLimit(block.content);
if (targetBlockId != J.Constant.widgetId.recentOpen) {
if (targetId != J.Constant.widgetId.recentOpen) {
sorts.push({ relationKey: 'lastModifiedDate', type: I.SortType.Desc });
};
switch (targetBlockId) {
switch (targetId) {
case J.Constant.widgetId.favorite: {
filters.push({ relationKey: 'isFavorite', condition: I.FilterCondition.Equal, value: true });
limit = 0;
@ -626,7 +392,7 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
};
U.Data.searchSubscribe({
subId,
subId: subId.current,
filters,
sorts,
limit,
@ -638,21 +404,11 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
});
};
getFavoriteIds (): string[] {
return S.Record.getRecords(this.subId).filter(it => !it.isArchived && !it.isDeleted).map(it => it.id);
};
getFavoriteBlockIds (): string[] {
const { root } = S.Block;
const ids = S.Block.getChildren(root, root, it => it.isLink()).map(it => it.getTargetObjectId());
const items = ids.map(id => S.Detail.get(root, id)).filter(it => !it.isArchived && !it.isDeleted).map(it => it.id);
return items;
};
sortFavorite (records: string[]): string[] {
const { block, isPreview } = this.props;
const ids = this.getFavoriteBlockIds();
const sortFavorite = (records: string[]): string[] => {
const ids = S.Block.getChildren(root, root, it => it.isLink()).
map(it => it.getTargetObjectId()).
map(id => S.Detail.get(root, id)).
filter(it => !it.isArchived && !it.isDeleted).map(it => it.id);
let sorted = U.Common.objectCopy(records || []).sort((c1: string, c2: string) => {
const i1 = ids.indexOf(c1);
@ -664,17 +420,13 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
});
if (!isPreview) {
sorted = sorted.slice(0, this.getLimit(block.content));
sorted = sorted.slice(0, getLimit(block.content));
};
return sorted;
};
onSetPreview () {
const { block, isPreview, setPreview } = this.props;
const object = this.getObject();
const child = this.getTargetBlock();
const onSetPreview = () => {
if (!child) {
return;
};
@ -687,51 +439,34 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
if (!isPreview) {
blockId = block.id;
event = 'SelectHomeTab';
data.tab = this.isSystemTarget() ? object.name : analytics.typeMapper(object.type);
data.tab = isSystemTarget() ? object.name : analytics.typeMapper(object.type);
};
setPreview(blockId);
analytics.event(event, data);
};
onDragEnd () {
const { block } = this.props;
const { layout } = block.content;
const onDragEnd = () => {
analytics.event('ReorderWidget', {
layout,
params: { target: this.getObject() }
params: { target: object }
});
};
isSystemTarget (): boolean {
const target = this.getTargetBlock();
return target ? this.isSystemTargetId(target.getTargetObjectId()) : false;
};
isSystemTargetId (id: string): boolean {
return U.Menu.isSystemWidget(id);
};
canCreate (): boolean {
const object = this.getObject();
const { block, isEditing } = this.props;
const canCreateHandler = (): boolean => {
if (!object || isEditing || !U.Space.canMyParticipantWrite()) {
return false;
};
const { layout } = block.content;
const target = this.getTargetBlock();
const layoutWithPlus = [ I.WidgetLayout.List, I.WidgetLayout.Tree, I.WidgetLayout.Compact, I.WidgetLayout.View ].includes(layout);
const isRecent = target ? [ J.Constant.widgetId.recentOpen, J.Constant.widgetId.recentEdit ].includes(target.getTargetObjectId()) : null;
const isRecent = [ J.Constant.widgetId.recentOpen, J.Constant.widgetId.recentEdit ].includes(targetId);
if (isRecent || !layoutWithPlus) {
return false;
};
if (U.Object.isInSetLayouts(object.layout)) {
const rootId = this.getRootId();
const rootId = getRootId();
const typeId = Dataview.getTypeId(rootId, J.Constant.blockId.dataview, object.id);
const type = S.Record.getTypeById(typeId);
const layouts = U.Object.getFileLayouts().concat(I.ObjectLayout.Participant);
@ -755,28 +490,15 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
return true;
};
getRootId (): string {
const target = this.getTargetBlock();
return target ? [ target.getTargetObjectId(), 'widget', target.id ].join('-') : '';
const getRootId = (): string => {
return child ? [ targetId, 'widget', child.id ].join('-') : '';
};
getTraceId (): string {
const target = this.getTargetBlock();
return target ? [ 'widget', target.id ].join('-') : '';
const getTraceId = (): string => {
return child ? [ 'widget', child.id ].join('-') : '';
};
getLimit ({ limit, layout }): number {
const { isPreview } = this.props;
const options = U.Menu.getWidgetLimitOptions(layout).map(it => Number(it.id));
if (!limit || !options.includes(limit)) {
limit = options[0];
};
return isPreview ? J.Constant.limit.menuRecords : limit;
};
addGroupLabels (records: any[], widgetId: string) {
const addGroupLabels = (records: any[], widgetId: string) => {
let relationKey;
if (widgetId == J.Constant.widgetId.recentOpen) {
relationKey = 'lastOpenedDate';
@ -787,7 +509,7 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
return U.Data.groupDateSections(records, relationKey, { type: '', links: [] });
};
onContext (param: any) {
const onContext = (param: any) => {
const { node, element, withElement, subId, objectId, data } = param;
const menuParam: any = {
@ -816,6 +538,200 @@ const WidgetIndex = observer(class WidgetIndex extends React.Component<Props> {
S.Menu.open('dataviewContext', menuParam);
};
});
const canCreate = canCreateHandler();
const childProps = {
...props,
ref: childRef,
key: childKey,
parent: block,
block: child,
canCreate,
isSystemTarget: isSystemTarget,
getData,
getLimit,
getTraceId,
sortFavorite,
addGroupLabels,
onContext,
onCreate,
};
export default WidgetIndex;
if (className) {
cn.push(className);
};
if (isPreview) {
cn.push('isPreview');
};
if (withSelect) {
cn.push('withSelect');
};
let head = null;
let content = null;
let back = null;
let buttons = null;
let targetTop = null;
let targetBot = null;
let isDraggable = canWrite;
if (isPreview) {
back = (
<div className="iconWrap back">
<Icon
className="back"
onClick={() => {
setPreview('');
analytics.event('ScreenHome', { view: 'Widget' });
}}
/>
</div>
);
isDraggable = false;
} else {
buttons = (
<div className="buttons">
{isEditing ? (
<div className="iconWrap more">
<Icon className="options" tooltip={translate('widgetOptions')} onClick={onOptions} />
</div>
) : ''}
{canCreate ? (
<div className="iconWrap create">
<Icon className="plus" tooltip={translate('commonCreateNewObject')} onClick={onCreateClick} />
</div>
) : ''}
<div className="iconWrap collapse">
<Icon className="collapse" tooltip={translate('widgetToggle')} onClick={onToggle} />
</div>
</div>
);
};
if (hasChild) {
const onClickHandler = isSystemTarget() ? onSetPreview : onClick;
head = (
<div className="head" onClick={onClickHandler}>
{back}
<div className="clickable">
<ObjectName object={object} />
{favCnt > limit ? <span className="count">{favCnt}</span> : ''}
</div>
{buttons}
</div>
);
if (canDrop) {
head = (
<DropTarget
cacheKey={[ block.id, object.id ].join('-')}
id={object.id}
rootId={targetId}
targetContextId={object.id}
dropType={I.DropType.Menu}
canDropMiddle={true}
className="targetHead"
>
{head}
</DropTarget>
);
};
targetTop = (
<DropTarget
{...props}
isTargetTop={true}
rootId={S.Block.widgets}
id={block.id}
dropType={I.DropType.Widget}
canDropMiddle={false}
onClick={onClickHandler}
/>
);
targetBot = (
<DropTarget
{...props}
isTargetBottom={true}
rootId={S.Block.widgets}
id={block.id}
dropType={I.DropType.Widget}
canDropMiddle={false}
/>
);
};
switch (layout) {
case I.WidgetLayout.Space: {
cn.push('widgetSpace');
content = <WidgetSpace {...childProps} />;
isDraggable = false;
break;
};
case I.WidgetLayout.Link: {
cn.push('widgetLink');
break;
};
case I.WidgetLayout.Tree: {
cn.push('widgetTree');
content = <WidgetTree {...childProps} />;
break;
};
case I.WidgetLayout.List:
case I.WidgetLayout.Compact:
case I.WidgetLayout.View: {
cn.push('widgetView');
content = <WidgetView {...childProps} />;
break;
};
};
useEffect(() => {
rebind();
setDummy(dummy + 1);
return () => {
unbind();
window.clearTimeout(timeout.current);
};
}, []);
useEffect(() => initToggle());
return (
<div
ref={nodeRef}
id={`widget-${block.id}`}
className={cn.join(' ')}
draggable={isDraggable}
onDragStart={e => onDragStart(e, block.id)}
onDragOver={e => onDragOver ? onDragOver(e, block.id) : null}
onDragEnd={onDragEnd}
onContextMenu={onOptions}
>
<Icon className="remove" inner={<div className="inner" />} onClick={onRemove} />
{head}
<div id="wrapper" className="contentWrapper">
{content}
</div>
<div className="dimmer" />
{targetTop}
{targetBot}
</div>
);
}));
export default WidgetIndex;

View file

@ -1,15 +1,23 @@
import React, { forwardRef, MouseEvent } from 'react';
import { observer } from 'mobx-react';
import { IconObject, ObjectName } from 'Component';
import { I, S, U } from 'Lib';
import { Icon, IconObject, ObjectName } from 'Component';
import { I, S, U, translate, sidebar, keyboard, analytics } from 'Lib';
const WidgetSpace = observer(forwardRef<I.WidgetComponent>(() => {
const space = U.Space.getSpaceview();
const participants = U.Space.getParticipantsList([ I.ParticipantStatus.Active, I.ParticipantStatus.Joining, I.ParticipantStatus.Removing ]);
const members = participants.filter(it => it.isActive);
const requestCnt = participants.filter(it => it.isJoining || it.isRemoving).length;
const isSpaceOwner = U.Space.isMyOwner();
const cn = [ 'body' ];
const cmd = keyboard.cmdSymbol();
const alt = keyboard.altSymbol();
const buttons = [
U.Object.isAllowedChat() ? { id: 'chat', name: translate('commonMainChat') } : null,
space.isShared ? { id: 'member', name: translate('commonMembers') } : null,
{ id: 'all', name: translate('commonAllContent') },
].filter(it => it);
if (isSpaceOwner && requestCnt) {
cn.push('withCnt');
@ -29,25 +37,95 @@ const WidgetSpace = observer(forwardRef<I.WidgetComponent>(() => {
openSettings('spaceShare');
};
const onSearch = (e: MouseEvent) => {
e.stopPropagation();
keyboard.onSearchPopup(analytics.route.widget);
};
const onCreate = (e: MouseEvent) => {
e.stopPropagation();
keyboard.pageCreate({}, analytics.route.widget);
};
const onGraph = (e: MouseEvent) => {
e.stopPropagation();
U.Object.openAuto({ id: keyboard.getRootId(), layout: I.ObjectLayout.Graph });
};
const onButtonClick = (e: any, item: any) => {
e.preventDefault();
e.stopPropagation();
switch (item.id) {
case 'member': {
S.Popup.open('settings', { data: { page: 'spaceShare', isSpace: true }, className: 'isSpace' });
break;
};
case 'all': {
sidebar.objectContainerToggle();
break;
};
case 'chat': {
U.Object.openAuto({ id: S.Block.workspace, layout: I.ObjectLayout.Chat });
break;
};
};
};
return (
<div
className={cn.join(' ')}
onClick={onSettings}
>
<div className="side left">
<IconObject
id="widget-space-icon"
object={{ ...space, layout: I.ObjectLayout.SpaceView }}
size={32}
iconSize={32}
menuParam={{ className: 'fixed' }}
/>
<div className="txt">
<ObjectName object={space} />
<div className="sides">
<div className="side left">
<IconObject
id="widget-space-icon"
object={{ ...space, layout: I.ObjectLayout.SpaceView }}
size={18}
iconSize={18}
menuParam={{ className: 'fixed' }}
/>
<div className="txt">
<ObjectName object={space} />
</div>
</div>
<div className="side right">
<Icon className="search withBackground" onClick={onSearch} tooltip={translate('commonSearch')} tooltipCaption={`${cmd} + S`} />
<Icon className="plus withBackground" onClick={onCreate} tooltip={translate('commonCreateNewObject')} tooltipCaption={`${cmd} + N`} />
<Icon className="graph withBackground" onClick={onGraph} tooltip={translate('commonGraph')} tooltipCaption={`${cmd} + ${alt} + O`} />
<div className="cnt" onClick={onRequest}>{requestCnt}</div>
</div>
</div>
<div className="side right">
<div className="cnt" onClick={onRequest}>{requestCnt}</div>
<div className="buttons">
{buttons.map((item, i) => {
let cnt = null;
if (item.id == 'member') {
cnt = <div className="cnt">{members.length}</div>;
};
return (
<div
key={i}
id={`item-${item.id}`}
className="item"
onClick={e => onButtonClick(e, item)}
>
<div className="side left">
<Icon className={item.id} />
<div className="name">
{item.name}
{cnt}
</div>
</div>
<div className="side right" />
</div>
);
})}
</div>
</div>
);

View file

@ -23,7 +23,7 @@ const WidgetTree = observer(forwardRef<WidgetTreeRefProps, I.WidgetComponent>((p
const listRef = useRef(null);
const deletedIds = new Set(S.Record.getRecordIds(J.Constant.subId.deleted, ''));
const object = S.Detail.get(S.Block.widgets, targetId);
const subKey = `widget${block.id}`;
const subKey = block ? `widget${block.id}` : '';
const links = useRef([]);
const top = useRef(0);
const branches = useRef([]);
@ -366,7 +366,7 @@ const WidgetTree = observer(forwardRef<WidgetTreeRefProps, I.WidgetComponent>((p
getData(getSubId(), initCache);
} else {
initCache();
C.ObjectShow(block.getTargetObjectId(), getTraceId(), U.Router.getRouteSpaceId());
C.ObjectShow(targetId, getTraceId(), U.Router.getRouteSpaceId());
};
return () => unsubscribe();

View file

@ -1,4 +1,4 @@
import * as React from 'react';
import React, { forwardRef, useState, useRef, useEffect, useImperativeHandle } from 'react';
import { observer } from 'mobx-react';
import { Select, Label, Button } from 'Component';
import { I, C, M, S, U, J, Dataview, Relation, keyboard, translate, analytics } from 'Lib';
@ -9,188 +9,28 @@ import WidgetViewBoard from './board';
import WidgetViewCalendar from './calendar';
import WidgetViewGraph from './graph';
interface State {
isLoading: boolean;
interface WidgetViewRefProps {
updateData: () => void;
updateViews: () => void;
onOpen: () => void;
};
const WidgetView = observer(class WidgetView extends React.Component<I.WidgetComponent, State> {
const WidgetView = observer(forwardRef<WidgetViewRefProps, I.WidgetComponent>((props, ref: any) => {
node = null;
state = {
isLoading: false,
};
refSelect = null;
refChild = null;
const { parent, block, isSystemTarget, onCreate, getData, getTraceId, getLimit, sortFavorite } = props;
const { viewId, limit, layout } = parent.content;
const targetId = block ? block.getTargetObjectId() : '';
const [ isLoading, setIsLoading ] = useState(false);
const nodeRef = useRef(null);
const selectRef = useRef(null);
const childRef = useRef(null);
const rootId = block ? [ targetId, 'widget', block.id ].join('-') : '';
const subId = S.Record.getSubId(rootId, J.Constant.blockId.dataview);
const object = S.Detail.get(S.Block.widgets, targetId);
const view = Dataview.getView(rootId, J.Constant.blockId.dataview, viewId);
const viewType = view ? view.type : I.ViewType.List;
constructor (props: I.WidgetComponent) {
super(props);
this.getView = this.getView.bind(this);
this.getViewType = this.getViewType.bind(this);
this.getSubId = this.getSubId.bind(this);
this.getRecordIds = this.getRecordIds.bind(this);
this.getObject = this.getObject.bind(this);
this.getLimit = this.getLimit.bind(this);
this.reload = this.reload.bind(this);
this.onChangeView = this.onChangeView.bind(this);
};
render (): React.ReactNode {
const { parent, block, isSystemTarget, onCreate } = this.props;
const { viewId, limit, layout } = parent.content;
const { targetBlockId } = block.content;
const { isLoading } = this.state;
const rootId = this.getRootId();
const subId = this.getSubId();
const records = this.getRecordIds();
const length = records.length;
const views = S.Record.getViews(rootId, J.Constant.blockId.dataview).map(it => ({ ...it, name: it.name || translate('defaultNamePage') }));
const viewType = this.getViewType();
const cn = [ 'innerWrap' ];
const showEmpty = ![ I.ViewType.Calendar, I.ViewType.Board ].includes(viewType);
const canCreate = this.props.canCreate && this.isAllowedObject();
const props = {
...this.props,
ref: ref => this.refChild = ref,
reload: this.reload,
getRecordIds: this.getRecordIds,
getView: this.getView,
getViewType: this.getViewType,
getObject: this.getObject,
getViewLimit: this.getLimit,
rootId,
subId,
};
let content = null;
let viewSelect = null;
if (!isSystemTarget() && (views.length > 1)) {
viewSelect = (
<Select
ref={ref => this.refSelect = ref}
id={`select-view-${rootId}`}
value={viewId}
options={views}
onChange={this.onChangeView}
arrowClassName="light"
menuParam={{
width: 300,
className: 'fixed',
classNameWrap: 'fromSidebar',
}}
/>
);
};
if (!isLoading && !length && showEmpty) {
content = (
<div className="emptyWrap">
<Label className="empty" text={canCreate ? translate('widgetEmptyLabelCreate') : translate('widgetEmptyLabel')} />
{canCreate ? (
<Button
text={translate('commonCreateObject')}
color="blank"
className="c28"
onClick={() => onCreate({ route: analytics.route.inWidget })}
/>
) : ''}
</div>
);
} else {
if (layout == I.WidgetLayout.View) {
cn.push(`view${I.ViewType[viewType]}`);
switch (viewType) {
default: {
content = <WidgetViewList {...props} />;
break;
};
case I.ViewType.Gallery: {
content = <WidgetViewGallery {...props} />;
break;
};
case I.ViewType.Board: {
content = <WidgetViewBoard {...props} />;
break;
};
case I.ViewType.Calendar: {
content = <WidgetViewCalendar {...props} />;
break;
};
case I.ViewType.Graph: {
content = <WidgetViewGraph {...props} />;
break;
};
};
} else {
cn.push('viewList');
content = <WidgetViewList {...props} />;
};
};
return (
<div
ref={node => this.node = node}
id="innerWrap"
className={cn.join(' ')}
>
{viewSelect ? <div id="viewSelect">{viewSelect}</div> : ''}
{content}
</div>
);
};
componentDidMount (): void {
const { block, isSystemTarget, getData, getTraceId } = this.props;
const { targetBlockId } = block.content;
if (isSystemTarget()) {
getData(this.getSubId());
} else {
this.setState({ isLoading: true });
C.ObjectShow(targetBlockId, getTraceId(), U.Router.getRouteSpaceId(), () => {
this.setState({ isLoading: false });
const view = this.getView();
if (view) {
this.load(view.id);
};
});
};
};
componentDidUpdate (): void {
const { parent, isSystemTarget } = this.props;
const { viewId } = parent.content;
const view = Dataview.getView(this.getRootId(), J.Constant.blockId.dataview);
if (!isSystemTarget() && view && viewId && (viewId != view.id)) {
const ref = this.refSelect;
if (ref) {
const selectValue = ref.getValue();
if (viewId != selectValue) {
ref.setValue(viewId);
};
};
this.load(viewId);
};
};
componentWillUnmount(): void {
C.ObjectSearchUnsubscribe([ this.getSubId() ]);
};
updateData () {
const { block, isSystemTarget, getData } = this.props;
const targetId = block.getTargetObjectId();
const rootId = this.getRootId();
const updateData = () =>{
const srcObject = S.Detail.get(targetId, targetId);
const srcBlock = S.Block.getLeaf(targetId, J.Constant.blockId.dataview);
@ -208,54 +48,35 @@ const WidgetView = observer(class WidgetView extends React.Component<I.WidgetCom
};
if (isSystemTarget()) {
getData(this.getSubId());
getData(subId);
} else {
const view = Dataview.getView(this.getRootId(), J.Constant.blockId.dataview);
const view = Dataview.getView(subId, J.Constant.blockId.dataview);
if (view) {
this.load(view.id);
load(view.id);
};
};
};
updateViews () {
const { block } = this.props;
const { targetBlockId } = block.content;
const views = U.Common.objectCopy(S.Record.getViews(targetBlockId, J.Constant.blockId.dataview)).map(it => new M.View(it));
const rootId = this.getRootId();
const updateViews = () => {
const views = U.Common.objectCopy(S.Record.getViews(targetId, J.Constant.blockId.dataview)).map(it => new M.View(it));
if (!views.length || (targetBlockId != keyboard.getRootId())) {
if (!views.length || (targetId != keyboard.getRootId())) {
return;
};
S.Record.viewsClear(rootId, J.Constant.blockId.dataview);
S.Record.viewsSet(rootId, J.Constant.blockId.dataview, views);
this.refSelect?.setOptions(views);
selectRef.current?.setOptions(views);
};
getSubId () {
return S.Record.getSubId(this.getRootId(), J.Constant.blockId.dataview);
};
getRootId = (): string => {
const { block } = this.props;
const { targetBlockId } = block.content;
return [ targetBlockId, 'widget', block.id ].join('-');
};
load (viewId: string) {
const subId = this.getSubId();
if (this.refChild && this.refChild.load) {
this.refChild.load();
S.Record.metaSet(this.getSubId(), '', { viewId });
const load = (viewId: string) => {
if (childRef.current?.load) {
childRef.current?.load();
S.Record.metaSet(subId, '', { viewId });
return;
};
const rootId = this.getRootId();
const blockId = J.Constant.blockId.dataview;
const object = this.getObject();
const setOf = Relation.getArrayValue(object.setOf);
const isCollection = U.Object.isCollectionLayout(object.layout);
@ -264,91 +85,63 @@ const WidgetView = observer(class WidgetView extends React.Component<I.WidgetCom
return;
};
const limit = this.getLimit();
const view = this.getView();
const view = getView();
if (!view) {
return;
};
Dataview.getData({
rootId,
blockId,
blockId: J.Constant.blockId.dataview,
newViewId: viewId,
sources: setOf,
limit,
filters: this.getFilters(),
limit: getLimitHandler(),
filters: getFilters(),
collectionId: (isCollection ? object.id : ''),
keys: J.Relation.sidebar.concat([ view.groupRelationKey, view.coverRelationKey ]).concat(J.Relation.cover),
});
};
reload () {
this.load(this.props.parent.content.viewId);
};
getFilters () {
const view = this.getView();
const getFilters = () => {
if (!view) {
return [];
};
let filters: I.Filter[] = [];
if (this.refChild && this.refChild.getFilters) {
filters = filters.concat(this.refChild.getFilters());
if (childRef.current?.getFilters) {
filters = filters.concat(childRef.current?.getFilters());
};
return filters;
};
getView () {
return Dataview.getView(this.getRootId(), J.Constant.blockId.dataview, this.props.parent.content.viewId);
const getView = () => {
return Dataview.getView(rootId, J.Constant.blockId.dataview, parent.content.viewId);
};
getViewType () {
const view = this.getView();
return view ? view.type : I.ViewType.List;
};
getObject () {
return S.Detail.get(S.Block.widgets, this.props.block.getTargetObjectId());
};
getLimit (): number {
const { parent, getLimit } = this.props;
const { layout } = parent.content;
const viewType = this.getViewType();
const getLimitHandler = (): number => {
let limit = getLimit(parent.content);
if ((layout == I.WidgetLayout.View) && (viewType == I.ViewType.Calendar)) {
limit = 1000;
};
return limit;
};
onChangeView (viewId: string) {
C.BlockWidgetSetViewId(S.Block.widgets, this.props.parent.id, viewId);
const onChangeView = (viewId: string) => {
C.BlockWidgetSetViewId(S.Block.widgets, parent.id, viewId);
};
getRecordIds () {
const { parent, block, sortFavorite } = this.props;
const { targetBlockId } = block.content;
const rootId = this.getRootId();
const subId = this.getSubId();
const getRecordIds = () => {
const records = S.Record.getRecordIds(subId, '');
const views = S.Record.getViews(rootId, J.Constant.blockId.dataview);
const viewId = parent.content.viewId || (views.length ? views[0].id : '');
const ret = Dataview.applyObjectOrder(rootId, J.Constant.blockId.dataview, viewId, '', U.Common.objectCopy(records));
return (targetBlockId == J.Constant.widgetId.favorite) ? sortFavorite(ret) : ret;
return (targetId == J.Constant.widgetId.favorite) ? sortFavorite(ret) : ret;
};
isAllowedObject () {
const { isSystemTarget } = this.props;
const rootId = this.getRootId();
const object = this.getObject();
const isAllowedObject = () => {
const isCollection = U.Object.isCollectionLayout(object.layout);
if (isSystemTarget()) {
@ -364,7 +157,7 @@ const WidgetView = observer(class WidgetView extends React.Component<I.WidgetCom
return true;
};
const sources = this.getSources();
const sources = getSources();
if (!sources.length) {
return false;
};
@ -382,26 +175,162 @@ const WidgetView = observer(class WidgetView extends React.Component<I.WidgetCom
return isAllowed;
};
getSources (): string[] {
const object = this.getObject();
const getSources = (): string[] => {
if (U.Object.isCollectionLayout(object.layout)) {
return [];
};
const rootId = this.getRootId();
const types = Relation.getSetOfObjects(rootId, object.id, I.ObjectLayout.Type).map(it => it.id);
const relations = Relation.getSetOfObjects(rootId, object.id, I.ObjectLayout.Relation).map(it => it.id);
return [].concat(types).concat(relations);
};
onOpen () {
if (this.refChild && this.refChild.onOpen) {
this.refChild.onOpen();
const onOpen = () => {
if (childRef.current?.onOpen) {
childRef.current?.onOpen();
};
};
});
const records = getRecordIds();
const length = records.length;
const views = S.Record.getViews(rootId, J.Constant.blockId.dataview).map(it => ({ ...it, name: it.name || translate('defaultNamePage') }));
const cn = [ 'innerWrap' ];
const showEmpty = ![ I.ViewType.Calendar, I.ViewType.Board ].includes(viewType);
const canCreate = props.canCreate && isAllowedObject();
const childProps = {
...props,
ref: childRef,
rootId,
subId,
reload: () => load(viewId),
getRecordIds,
getView: () => view,
getViewType: () => viewType,
getObject: () => object,
getViewLimit: getLimitHandler,
};
let content = null;
let viewSelect = null;
if (!isSystemTarget() && (views.length > 1)) {
viewSelect = (
<Select
ref={selectRef}
id={`select-view-${rootId}`}
value={viewId}
options={views}
onChange={onChangeView}
arrowClassName="light"
menuParam={{
width: 300,
className: 'fixed',
classNameWrap: 'fromSidebar',
}}
/>
);
};
if (!isLoading && !length && showEmpty) {
content = (
<div className="emptyWrap">
<Label className="empty" text={canCreate ? translate('widgetEmptyLabelCreate') : translate('widgetEmptyLabel')} />
{canCreate ? (
<Button
text={translate('commonCreateObject')}
color="blank"
className="c28"
onClick={() => onCreate({ route: analytics.route.inWidget })}
/>
) : ''}
</div>
);
} else {
if (layout == I.WidgetLayout.View) {
cn.push(`view${I.ViewType[viewType]}`);
switch (viewType) {
default: {
content = <WidgetViewList {...childProps} />;
break;
};
case I.ViewType.Gallery: {
content = <WidgetViewGallery {...childProps} />;
break;
};
case I.ViewType.Board: {
content = <WidgetViewBoard {...childProps} />;
break;
};
case I.ViewType.Calendar: {
content = <WidgetViewCalendar {...childProps} />;
break;
};
case I.ViewType.Graph: {
content = <WidgetViewGraph {...childProps} />;
break;
};
};
} else {
cn.push('viewList');
content = <WidgetViewList {...childProps} />;
};
};
useEffect(() => {
if (isSystemTarget()) {
getData(subId);
} else {
setIsLoading(true);
C.ObjectShow(targetId, getTraceId(), U.Router.getRouteSpaceId(), () => {
setIsLoading(false);
const view = getView();
if (view) {
load(view.id);
};
});
};
return () => {
C.ObjectSearchUnsubscribe([ subId ]);
};
}, []);
useEffect(() => {
if (!isSystemTarget() && view && viewId && (viewId != view.id)) {
if (selectRef.current) {
if (viewId != selectRef.current.getValue()) {
selectRef.current.setValue(viewId);
};
};
load(viewId);
};
});
useImperativeHandle(ref, () => ({
updateData,
updateViews,
onOpen,
}));
return (
<div
ref={nodeRef}
id="innerWrap"
className={cn.join(' ')}
>
{viewSelect ? <div id="viewSelect">{viewSelect}</div> : ''}
{content}
</div>
);
}));
export default WidgetView;

View file

@ -199,7 +199,7 @@ export default {
vertical: I.MenuDirection.Bottom,
horizontal: I.MenuDirection.Right,
stickToElementEdge: I.MenuDirection.None,
highlightElements: [ '#menuSyncStatus', '#button-header-sync' ],
highlightElements: [ '#menuSyncStatus', '#sidebarSync' ],
offsetY: 14,
}
},

View file

@ -8,7 +8,6 @@ export enum WidgetLayout {
View = 4,
Space = 100,
Buttons = 101,
};
export interface WidgetComponent {

View file

@ -242,13 +242,6 @@ export enum NetworkMode {
Custom = 2,
};
export enum NavigationMenuMode {
None = 0,
Context = 1,
Click = 2,
Hover = 3,
};
export enum InterfaceStatus {
Ok = 'ok',
Error = 'error',

View file

@ -17,7 +17,6 @@ class Analytics {
public route = {
block: 'Block',
navigation: 'Navigation',
onboarding: 'Onboarding',
collection: 'Collection',
set: 'Set',
@ -425,11 +424,6 @@ class Analytics {
break;
};
case 'ChangeShowQuickCapture': {
data.type = I.NavigationMenuMode[data.type];
break;
};
case 'SelectUsecase': {
data.type = Number(data.type) || 0;
data.type = I.Usecase[data.type];

View file

@ -180,7 +180,7 @@ class Keyboard {
// Shortcuts
this.shortcut('ctrl+space', e, () => {
S.Popup.open('shortcut', { preventResize: true });
S.Popup.open('shortcut', {});
});
// Print
@ -241,6 +241,14 @@ class Keyboard {
Action.themeSet(!theme ? 'dark' : '');
});
// Lock the app
this.shortcut(`${cmd}+alt+l`, e, () => {
const pin = Storage.getPin();
if (pin) {
Renderer.send('pinCheck');
};
});
// Object id
this.shortcut(`${cmd}+shift+\\`, e, () => {
S.Popup.open('confirm', {
@ -263,12 +271,6 @@ class Keyboard {
this.pageCreate({}, analytics.route.shortcut);
});
// Quick capture menu
this.shortcut(`${cmd}+alt+n`, e, () => {
e.preventDefault();
this.onQuickCapture(true);
});
// Lock/Unlock
this.shortcut(`ctrl+shift+l`, e, () => {
this.onToggleLock();
@ -297,7 +299,7 @@ class Keyboard {
return;
};
const flags = [ I.ObjectFlag.SelectTemplate, I.ObjectFlag.DeleteEmpty ];
const flags = [ I.ObjectFlag.SelectType, I.ObjectFlag.SelectTemplate, I.ObjectFlag.DeleteEmpty ];
U.Object.create('', '', details, I.BlockPosition.Bottom, '', flags, route, message => {
U.Object.openConfig(message.details);
@ -860,47 +862,6 @@ class Keyboard {
});
};
menuFromNavigation (id: string, param: Partial<I.MenuParam>, data: any) {
const menuParam = Object.assign({
element: '#navigationPanel',
className: 'fixed',
classNameWrap: 'fromNavigation',
type: I.MenuType.Horizontal,
horizontal: I.MenuDirection.Center,
vertical: I.MenuDirection.Top,
noFlipY: true,
offsetY: -12,
data,
}, param);
if (S.Menu.isOpen(id)) {
S.Menu.open(id, menuParam);
} else {
S.Popup.close('search', () => {
S.Menu.closeAll(J.Menu.navigation, () => {
S.Menu.open(id, menuParam);
});
});
};
};
onQuickCapture (shortcut: boolean, param?: Partial<I.MenuParam>) {
param = param || {};
if ((S.Common.navigationMenu != I.NavigationMenuMode.Hover) && S.Menu.isOpen('quickCapture')) {
S.Menu.close('quickCapture');
return;
};
const button = $('#button-navigation-plus');
this.menuFromNavigation('quickCapture', {
...param,
onOpen: () => button.addClass('active'),
onClose: () => button.removeClass('active'),
}, { isExpanded: shortcut });
};
onLock (rootId: string, v: boolean, route?: string) {
const block = S.Block.getLeaf(rootId, rootId);
if (!block) {
@ -1067,14 +1028,11 @@ class Keyboard {
return;
};
this.setPinChecked(false);
if (this.isMain()) {
S.Common.redirectSet(U.Router.getRoute());
};
U.Router.go('/auth/pin-check', { replace: true, animate: true });
Renderer.send('pin-check');
Renderer.send('pinCheck');
}, S.Common.pinTime);
};

View file

@ -1,5 +1,5 @@
import $ from 'jquery';
import { I, U, J, analytics } from 'Lib';
import { I, U, J } from 'Lib';
const Tags = {};
for (const i in I.MarkType) {

View file

@ -19,6 +19,7 @@ class Sidebar {
loader: JQuery<HTMLElement> = null;
dummy: JQuery<HTMLElement> = null;
toggleButton: JQuery<HTMLElement> = null;
syncButton: JQuery<HTMLElement> = null;
vault: JQuery<HTMLElement> = null;
isAnimating = false;
timeoutAnim = 0;
@ -60,6 +61,7 @@ class Sidebar {
this.loader = this.page.find('#loader');
this.dummy = $('#sidebarDummy');
this.toggleButton = $('#sidebarToggle');
this.syncButton = $('#sidebarSync');
if (vault) {
this.vault = $(vault.node);
@ -223,11 +225,17 @@ class Sidebar {
const vw = isClosed || !showVault || !keyboard.isMain() ? 0 : J.Size.vault.width;
const pageWidth = ww - width - vw;
const ho = keyboard.isMainHistory() ? J.Size.history.panel : 0;
const navigation = S.Common.getRef('navigation');
let toggleX = 16;
let syncX = 52;
if ((width && showVault) || (U.Common.isPlatformMac() && !isFullScreen)) {
toggleX = 84;
syncX = 120;
if (width) {
syncX = J.Size.vault.width + width - 40;
};
};
this.header.css({ width: '' }).removeClass('withSidebar');
@ -239,8 +247,8 @@ class Sidebar {
this.page.toggleClass('sidebarAnimation', animate);
this.dummy.toggleClass('sidebarAnimation', animate);
this.toggleButton.toggleClass('sidebarAnimation', animate);
this.syncButton.toggleClass('sidebarAnimation', animate);
navigation?.position(width + vw, animate);
this.header.toggleClass('withSidebar', !!width);
this.page.css({ width: pageWidth });
@ -248,6 +256,7 @@ class Sidebar {
this.header.css({ width: pageWidth - ho });
this.footer.css({ width: pageWidth - ho });
this.toggleButton.css({ left: toggleX });
this.syncButton.css({ left: syncX });
$(window).trigger('sidebarResize');
};

View file

@ -1054,8 +1054,8 @@ class UtilMenu {
timeFormatOptions () {
return [
{ id: I.TimeFormat.H12, name: translate('menuDataviewDate12Hour') },
{ id: I.TimeFormat.H24, name: translate('menuDataviewDate24Hour') },
{ id: I.TimeFormat.H12, name: translate('timeFormat12') },
{ id: I.TimeFormat.H24, name: translate('timeFormat24') },
];
};

View file

@ -149,7 +149,6 @@ class UtilObject {
};
param = param || {};
param.preventResize = true;
param.data = Object.assign(param.data || {}, { matchPopup: { params } });
if (object._routeParam_) {
@ -485,7 +484,8 @@ class UtilObject {
isAllowedChat () {
const { config, space } = S.Common;
return config.experimental || (J.Constant.chatSpaceId.includes(space));
const spaceview = U.Space.getSpaceview();
return spaceview.chatId && (config.experimental || J.Constant.chatSpaceId.includes(space));
};
openDateByTimestamp (relationKey: string, t: number, method?: string) {

View file

@ -37,7 +37,6 @@ class CommonStore {
public notionToken = '';
public showRelativeDatesValue = null;
public fullscreenObjectValue = null;
public navigationMenuValue = null;
public linkStyleValue = null;
public dateFormatValue = null;
public timeFormatValue = null;
@ -97,7 +96,6 @@ class CommonStore {
defaultType: observable,
isFullScreen: observable,
fullscreenObjectValue: observable,
navigationMenuValue: observable,
linkStyleValue: observable,
isOnlineValue: observable,
showVaultValue: observable,
@ -133,7 +131,6 @@ class CommonStore {
nativeThemeSet: action,
spaceSet: action,
spaceStorageSet: action,
navigationMenuSet: action,
linkStyleSet: action,
dateFormatSet: action,
timeFormatSet: action,
@ -233,14 +230,6 @@ class CommonStore {
return this.boolGet('showRelativeDates');
};
get navigationMenu (): I.NavigationMenuMode {
let ret = this.navigationMenuValue;
if (ret === null) {
ret = Storage.get('navigationMenu');
};
return Number(ret) || I.NavigationMenuMode.Hover;
};
get linkStyle (): I.LinkCardStyle {
let ret = this.linkStyleValue;
if (ret === null) {
@ -495,13 +484,7 @@ class CommonStore {
this.languages = v;
};
navigationMenuSet (v: I.NavigationMenuMode) {
v = Number(v);
this.navigationMenuValue = v;
Storage.set('navigationMenu', v);
};
linkStyleSet (v: I.NavigationMenuMode) {
linkStyleSet (v: I.LinkCardStyle) {
v = Number(v);
this.linkStyleValue = v;
Storage.set('linkStyle', v);

View file

@ -72,10 +72,6 @@ class PopupStore {
};
Preview.previewHide(true);
if (this.checkShowDimmer(this.popupList)) {
$('#navigationPanel').addClass('hide');
};
};
get (id: string): I.Popup {
@ -141,10 +137,6 @@ class PopupStore {
const filtered = this.popupList.filter(it => it.id != id);
if (!this.checkShowDimmer(filtered)) {
$('#navigationPanel').removeClass('hide');
};
if (force) {
this.popupList = filtered;