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/native-messaging-host

This commit is contained in:
Andrew Simachev 2024-01-03 16:02:43 +01:00
commit 11ee7a57fa
No known key found for this signature in database
GPG key ID: 49A163D0D14E6FD8
36 changed files with 362 additions and 182 deletions

View file

@ -21,6 +21,7 @@
.twitter-tweet, .instagram-media { margin: 0px !important; display: inline-flex !important; }
.gist-file { margin: 0px !important; }
.cp_embed_iframe { border: 0px !important; }
html.align1 .twitter-tweet, body.align1 .instagram-media { justify-content: center; }
html.align2 .twitter-tweet, body.align2 .instagram-media { justify-content: flex-end; }

View file

@ -144,8 +144,6 @@ function createWindow () {
console.error('[Api] method not defined:', cmd);
};
});
};
app.on('ready', () => {

View file

@ -62,10 +62,9 @@ class WindowManager {
win.on('enter-full-screen', () => Util.send(win, 'enter-full-screen'));
win.on('leave-full-screen', () => Util.send(win, 'leave-full-screen'));
win.webContents.on('context-menu', (e, param) => Util.send(win, 'spellcheck', param));
Api.setSpellingLang(win, languages);
Api.setZoom(win, zoom);
win.webContents.on('context-menu', (e, param) => {
Util.send(win, 'spellcheck', param.misspelledWord, param.dictionarySuggestions, param.x, param.y, param.selectionRect);
});
if (hideMenuBar) {
win.setMenuBarVisibility(false);

View file

@ -46,7 +46,11 @@
"https://*.fbcdn.net",
"https://static.cdninstagram.com",
"https://telegram.org",
"https://github.githubassets.com"
"https://github.githubassets.com",
"https://cpwebassets.codepen.io",
"https://cdnjs.cloudflare.com",
"https://*.bilibili.com",
"https://s1.hdslb.com"
],
"font-src": [
@ -99,7 +103,16 @@
"https://*.reddit.com",
"https://www.instagram.com",
"https://t.me",
"https://gist.github.com"
"https://gist.github.com",
"https://codepen.io",
"https://www.facebook.com",
"https://*.bilibili.com",
"https://*.bilibili.tv",
"https://*.bilivideo.cn:*",
"https://*.bilivideo.com",
"https://*.hdslb.com",
"wss://*.bilibili.com:*",
"wss://*.biliapi.net"
],
"script-src-elem": [
@ -128,7 +141,11 @@
"https://static.cdninstagram.com",
"https://telegram.org",
"https://oauth.tg.dev",
"https://gist.github.com"
"https://gist.github.com",
"https://cpwebassets.codepen.io",
"https://codepen.io",
"https://cdnjs.cloudflare.com",
"https://*.hdslb.com"
],
"frame-src": [
@ -147,7 +164,10 @@
"https://embed.reddit.com",
"https://www.facebook.com",
"https://www.instagram.com",
"https://t.me"
"https://t.me",
"https://codepen.io",
"https://cdpn.io",
"https://*.bilibili.com"
],
"worker-src": [

View file

@ -459,6 +459,8 @@
"blockDataviewCreateNew": "Create new Object",
"blockDataviewCreateNewCollection": "Create new Collection",
"blockDataviewCreateNewSet": "Create new Set",
"blockDataviewCreateNewTooltipCollection": "Create new Object in this Collection",
"blockDataviewCreateNewTooltipType": "Create new %s object",
"blockDataviewShowTemplates": "Show Templates",
"blockDataviewSearch": "Search",

View file

@ -28,8 +28,8 @@
.archive { position: absolute; right: 10px; top: 10px; z-index: 1; }
}
.inner.vertical { display: flex; flex-direction: column-reverse; }
.inner.vertical {
.inner.isVertical { display: flex; flex-direction: column-reverse; }
.inner.isVertical {
.side.left { width: 100%; border-radius: 0px; }
.side.right { aspect-ratio: 7/3; width: 100%; border-radius: 0px; border-bottom: 0.05em solid $colorShapeSecondary; }
}
@ -40,7 +40,7 @@
.side.right { width: 28%; min-height: 90px; display: block; position: relative; overflow: hidden; }
}
.inner.withImage.vertical {
.inner.withImage.isVertical {
.side.left { width: 100%; }
.side.right { width: 100%; }
}

View file

@ -92,7 +92,7 @@
> .sides { gap: 0px 16px; display: flex; flex-direction: row; align-items: center; justify-content: stretch; width: 100%; }
> .sides {
> .side { padding: 15px 0px; white-space: nowrap; line-height: 28px; display: flex; flex-direction: row; align-items: center; }
> .side.left { flex-grow: 1; padding-left: 14px; }
> .side.left { flex-grow: 1; padding-left: 14px; max-width: 100%; }
> .side.right { flex-shrink: 0; gap: 0px 4px; justify-content: flex-end; }
> .side.right {
.filter { color: $colorTextPrimary; padding: 0px; }
@ -253,11 +253,6 @@
.icon.plus:hover { background-color: transparent; }
}
.dataviewControls::after { display: none !important; }
.dataviewControls.active {
> .sides {
> .side.right { opacity: 1; }
}
}
.dataviewSelection {
.side.left { @include text-paragraph; }
@ -268,6 +263,12 @@
}
}
.block.blockDataview.isInline.isVertical {
.dataviewControls {
> .sides { flex-direction: column; align-items: flex-start; justify-content: flex-start; }
}
}
.block.blockDataview.showMenu {
.dataviewHead {
.icon.source { opacity: 1; }

View file

@ -11,4 +11,8 @@
canvas.move { cursor: move; }
}
}
.block.blockDataview.isInline {
.viewContent.viewGraph { height: 500px; }
}
}

View file

@ -44,7 +44,10 @@
}
.cellContent.c-select {
.over { display: inline-flex; gap: 6px; align-items: center; }
.over { display: inline; }
.tagItem { margin: 0px 6px 0px 0px; vertical-align: middle; }
.tagItem:last-child { margin-right: 0px; }
.tagItem.isStatus { line-height: 16px; }
.more { margin: 0px; vertical-align: middle; }
}

View file

@ -69,7 +69,7 @@
.iconObject { position: absolute; left: 16px; top: 15px; background-color: $colorShapeTertiary; border-radius: 10px; }
}
.linkCard.c48.withIcon.withCover.vertical {
.linkCard.c48.withIcon.withCover.isVertical {
.sides { min-height: 62px; }
.side.left { padding: 24px 16px 16px 16px; z-index: 10; }
.iconObject { top: -32px; transform: none; }
@ -81,18 +81,18 @@
.side.right { width: 28%; display: block; border: 1px solid $colorShapeSecondary; border-left: 0px; }
}
.linkCard.vertical { display: block; }
.linkCard.vertical {
.linkCard.isVertical { display: block; }
.linkCard.isVertical {
.sides { flex-direction: column-reverse; }
.side.left { width: 100%; border-right-width: 1px; }
.side.right { aspect-ratio: 7/3; width: 100%; border-radius: 12px 12px 0px 0px !important; border: 1px solid $colorShapeSecondary; border-bottom: 0px; }
}
.linkCard.withCover.vertical {
.linkCard.withCover.isVertical {
.side.left { border-radius: 0px 0px 12px 12px !important; }
}
.linkCard.withCover.vertical.text { padding-top: 0px; }
.linkCard.withCover.isVertical.text { padding-top: 0px; }
}
.block.blockLink.text {

View file

@ -12,47 +12,47 @@
smile * { display: inline; vertical-align: middle; }
smile .loaderWrapper { display: inline-block; }
markupCode {
markupcode {
display: inline; font-family: 'Plex'; border-radius: 4px; background: $colorShapeSecondary; padding: 2px 4px;
}
markupEmoji { display: inline; user-select: all; }
markupEmoji * { user-select: all; }
markupEmoji {
markupemoji { display: inline; user-select: all; }
markupemoji * { user-select: all; }
markupemoji {
smile img { vertical-align: top; }
}
markupLink { position: relative; }
markupLink, markupObject { color: inherit; text-decoration: none; border-bottom: 0.075em solid; transition: border-color $transitionCommon; cursor: default; }
markupLink.disabled, markupObject.disabled { border-width: 0px; }
markuplink { position: relative; }
markuplink, markupobject { color: inherit; text-decoration: none; border-bottom: 0.075em solid; transition: border-color $transitionCommon; cursor: default; }
markuplink.disabled, markupobject.disabled { border-width: 0px; }
markupMention { display: inline; user-select: all !important; position: relative; cursor: default; }
markupMention * { user-select: text !important; }
markupMention {
markupmention { display: inline; user-select: all !important; position: relative; cursor: default; }
markupmention * { user-select: text !important; }
markupmention {
smile { display: none; position: relative; z-index: 1; }
.space { width: 6px; height: 20px; margin-top: -4px; vertical-align: middle; display: none; }
name { display: inline; white-space: normal; position: relative; border-bottom: 0.075em solid; border-color: inherit; }
}
markupMention.disabled {
markupmention.disabled {
name { border-width: 0px; }
}
markupMention.withImage {
markupmention.withImage {
smile { display: inline; }
.space { display: inline; }
}
markupMention.withImage.c24 name markupBgcolor:first-child { margin-left: -22px; padding-left: 22px; }
markupMention.withImage.c26 name markupBgcolor:first-child { margin-left: -22px; padding-left: 22px; }
markupMention.withImage.c28 name markupBgcolor:first-child { margin-left: -27px; padding-left: 27px; }
markupMention.withImage.c32 name markupBgcolor:first-child { margin-left: -34px; padding-left: 34px; }
markupMention:hover {
markupmention.withImage.c24 name markupBgcolor:first-child { margin-left: -22px; padding-left: 22px; }
markupmention.withImage.c26 name markupBgcolor:first-child { margin-left: -22px; padding-left: 22px; }
markupmention.withImage.c28 name markupBgcolor:first-child { margin-left: -27px; padding-left: 27px; }
markupmention.withImage.c32 name markupBgcolor:first-child { margin-left: -34px; padding-left: 34px; }
markupmention:hover {
name::before { border-color: $colorTextPrimary; }
}
markupBold { font-weight: 600; }
markupItalic { font-style: italic; }
markupStrike { text-decoration: line-through; }
markupUnderline { border-bottom: 0.05em solid; }
markupbold { font-weight: 600; }
markupitalic { font-style: italic; }
markupstrike { text-decoration: line-through; }
markupunderline { border-bottom: 0.05em solid; }
.markers { display: flex; padding: 1px 0px; }
.markers {

View file

@ -24,43 +24,27 @@
.content { padding: 0px; }
.wrap { height: 100%; }
.items { height: 100%; }
.item.empty { padding: 14px; }
.sectionName { padding: 0px 14px 4px 14px; }
.sectionName::before { content: ""; display: block; width: 100%; height: 1px; margin: 8px 0px 11px 0px; background: $colorShapeSecondary; }
.sectionName.first { padding-top: 4px; }
.sectionName.first::before { display: none; }
.item { padding: 4px 16px; }
.item.add { padding: 6px 16px; }
.item.sides { display: flex; padding: 6px 16px; }
.info {
width: 154px; @include text-overflow-nw; line-height: 20px; border-radius: 4px; transition: background $transitionCommon;
flex-shrink: 0; margin-right: 6px;
}
.cell { width: calc(100% - 160px); white-space: nowrap; }
.cell.c-select {
.tagItem { margin-bottom: 0px; vertical-align: middle; }
}
.item { padding: 4px 16px; }
.item.add { padding: 6px 16px; }
.item.sides { display: flex; padding: 6px 16px; }
.item.empty { padding: 16px; }
.item {
.icon.plus { margin-right: 4px; background-image: url('~img/icon/plus/menu0.svg'); }
}
.item * { }
.item::before { transition: none; }
.cellContent { overflow: hidden; height: 20px; line-height: 20px; }
.cellContent {
.empty { display: block; }
}
.cellContent.c-longText {
.name { -webkit-line-clamp: 1; -webkit-box-orient: vertical; display: -webkit-box; }
}
}
.menu.menuBlockAdd {
.item.isBig {
.iconObject { background-color: $colorShapeTertiary; }
}
@ -105,7 +89,19 @@
.icon.collection { background-image: url('~img/icon/menu/action/block/collection1.svg'); }
}
.icon.arrow { width: 20px !important; height: 20px !important; background-color: unset !important; left: auto !important; top: 50% !important; }
.cell { width: calc(100% - 160px); white-space: nowrap; }
.cell.c-select {
.tagItem { margin-bottom: 0px; vertical-align: middle; }
}
.cellContent { overflow: hidden; height: 20px; line-height: 20px; }
.cellContent {
.empty { display: block; }
}
.cellContent.c-longText {
.name { -webkit-line-clamp: 1; -webkit-box-orient: vertical; display: -webkit-box; }
}
}
}

View file

@ -237,6 +237,10 @@
}
}
.viewContent.viewGraph {
canvas { background: $colorBgPrimary; }
}
.content {
.scrollWrap { background: $colorBgPrimary; }
}

View file

@ -512,8 +512,8 @@ class App extends React.Component<object, State> {
});
};
onSpellcheck (e: any, param: any) {
if (!param.misspelledWord) {
onSpellcheck (e: any, misspelledWord: string, dictionarySuggestions: string[], x: number, y: number, rect: any) {
if (!misspelledWord) {
return;
};
@ -522,34 +522,60 @@ class App extends React.Component<object, State> {
const win = $(window);
const rootId = keyboard.getRootId();
const { focused, range } = focus.state;
const options: any = param.dictionarySuggestions.map(it => ({ id: it, name: it }));
const obj = Mark.cleanHtml($(`#block-${focused} #value`).html());
const value = String(obj.get(0).innerText || '');
const options: any = dictionarySuggestions.map(it => ({ id: it, name: it }));
const element = $(document.elementFromPoint(x, y));
const isInput = element.is('input');
const isTextarea = element.is('textarea');
const isEditable = element.is('.editable');
options.push({ id: 'add-to-dictionary', name: translate('spellcheckAdd') });
menuStore.open('select', {
className: 'fromBlock',
classNameWrap: 'fromPopup',
recalcRect: () => {
const rect = UtilCommon.getSelectionRect();
return rect ? { ...rect, y: rect.y + win.scrollTop() } : null;
},
onOpen: () => { menuStore.close('blockContext'); },
onClose: () => { keyboard.disableContextOpen(false); },
onOpen: () => menuStore.close('blockContext'),
onClose: () => keyboard.disableContextOpen(false),
data: {
options,
onSelect: (e: any, item: any) => {
raf(() => {
focus.apply();
switch (item.id) {
default: {
blockStore.updateContent(rootId, focused, { text: value });
UtilData.blockInsertText(rootId, focused, item.id, range.from, range.to);
if (focused) {
focus.apply();
const obj = Mark.cleanHtml($(`#block-${focused} #value`).html());
const value = String(obj.get(0).innerText || '');
blockStore.updateContent(rootId, focused, { text: value });
UtilData.blockInsertText(rootId, focused, item.id, range.from, range.to);
} else
if (isInput || isTextarea || isEditable) {
let value = '';
if (isInput || isTextarea) {
value = String(element.val());
} else
if (isEditable) {
value = String((element.get(0) as any).innerText || '');
};
;
value = value.replace(new RegExp(`${misspelledWord}`, 'g'), item.id);
if (isInput || isTextarea) {
element.val(value);
} else
if (isEditable) {
element.text(value);
};
};
break;
};
case 'add-to-dictionary': {
Renderer.send('spellcheckAdd', param.misspelledWord);
Renderer.send('spellcheckAdd', misspelledWord);
break;
};

View file

@ -10,7 +10,6 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
_isMounted = false;
node: any = null;
frame = 0;
constructor (props: I.BlockComponent) {
super(props);
@ -262,11 +261,7 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
};
resize () {
if (this.frame) {
raf.cancel(this.frame);
};
this.frame = raf(() => {
window.setTimeout(() => {
if (!this._isMounted) {
return;
};
@ -274,10 +269,8 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
const { getWrapperWidth } = this.props;
const node = $(this.node);
const inner = node.find('.inner');
const rect = (node.get(0) as Element).getBoundingClientRect();
const mw = getWrapperWidth();
rect.width <= mw / 2 ? inner.addClass('vertical') : inner.removeClass('vertical');
inner.width() <= getWrapperWidth() / 2 ? inner.addClass('isVertical') : inner.removeClass('isVertical');
});
};

View file

@ -659,6 +659,15 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
dbStore.recordsSet(subId, '', records);
};
if ([ I.ViewType.Graph ].includes(view.type)) {
const refGraph = this.refView?.refGraph;
if (refGraph) {
refGraph.addNewNode(object.id, '', null, () => {
refGraph.setRootId(object.id);
});
};
};
if ([ I.ViewType.Calendar ].includes(view.type)) {
UtilObject.openPopup(object);
} else {
@ -1334,6 +1343,15 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
};
this.frame = raf(() => {
const { block, getWrapperWidth } = this.props;
if (getWrapperWidth) {
const node = $(this.node);
const obj = $(`#block-${block.id}`);
node.width() <= getWrapperWidth() / 2 ? obj.addClass('isVertical') : obj.removeClass('isVertical');
};
if (this.refControls && this.refControls.resize) {
this.refControls.resize();
};

View file

@ -3,7 +3,7 @@ import $ from 'jquery';
import { observer } from 'mobx-react';
import { observable } from 'mobx';
import { Icon, Button, Filter } from 'Component';
import { C, I, UtilCommon, analytics, Relation, keyboard, translate, UtilObject, UtilMenu } from 'Lib';
import { C, I, UtilCommon, analytics, Relation, keyboard, translate, UtilObject, UtilMenu, Dataview } from 'Lib';
import { menuStore, dbStore, blockStore } from 'Store';
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import Head from './head';
@ -49,6 +49,7 @@ const Controls = observer(class Controls extends React.Component<Props> {
const isAllowedObject = this.props.isAllowedObject();
const isAllowedTemplate = UtilObject.isAllowedTemplate(getTypeId()) || (target && UtilObject.isSetLayout(target.layout) && hasSources);
const cmd = keyboard.cmdSymbol();
const tooltip = Dataview.getCreateTooltip(rootId, block.id, target.id, view.id);
if (isAllowedTemplate) {
buttonWrapCn.push('withSelect');
@ -163,7 +164,7 @@ const Controls = observer(class Controls extends React.Component<Props> {
<Button
id={`button-${block.id}-add-record`}
className="addRecord c28"
tooltip={translate('blockDataviewCreateNew')}
tooltip={tooltip}
text={translate('commonNew')}
onClick={e => onRecordAdd(e, -1)}
/>
@ -263,7 +264,6 @@ const Controls = observer(class Controls extends React.Component<Props> {
} = this.props;
const view = getView();
const obj = $(element);
const node = $(this.node);
const param: any = {
element,
@ -271,12 +271,12 @@ const Controls = observer(class Controls extends React.Component<Props> {
offsetY: 10,
noFlipY: true,
onOpen: () => {
node.addClass('active');
obj.addClass('active');
this.toggleHoverArea(true);
},
onClose: () => {
node.removeClass('active');
obj.removeClass('active');
this.toggleHoverArea(false);
},
onBack: (id) => {
menuStore.replace(id, component, { ...param, noAnimation: true });
@ -416,11 +416,14 @@ const Controls = observer(class Controls extends React.Component<Props> {
return;
};
const { isPopup, isInline } = this.props;
const { block, isPopup, isInline } = this.props;
const container = UtilCommon.getPageContainer(isPopup);
const win = $(window);
const obj = $(`#block-${block.id}`);
const hoverArea = obj.find('.hoverArea');
this.refFilter.setActive(true);
this.toggleHoverArea(true);
if (!isInline) {
this.refFilter.focus();
@ -453,10 +456,19 @@ const Controls = observer(class Controls extends React.Component<Props> {
this.refFilter.setActive(false);
this.refFilter.setValue('');
this.refFilter.blur();
this.toggleHoverArea(false);
this.props.onFilterChange('');
};
toggleHoverArea (v: boolean) {
const { block } = this.props;
const obj = $(`#block-${block.id}`);
const hoverArea = obj.find('.hoverArea');
v ? hoverArea.addClass('active') : hoverArea.removeClass('active');
};
resize () {
if (!this._isMounted) {
return;

View file

@ -33,8 +33,9 @@ const Column = observer(class Column extends React.Component<Props> {
};
render () {
const { rootId, block, id, getSubId, getView, getLimit, value, onDragStartColumn } = this.props;
const { rootId, block, id, getSubId, getView, getLimit, value, onDragStartColumn, getTarget } = this.props;
const view = getView();
const target = getTarget();
const subId = getSubId();
const items = this.getItems();
const { total } = dbStore.getMeta(subId, '');
@ -46,6 +47,7 @@ const Column = observer(class Column extends React.Component<Props> {
const order = (block.content.groupOrder || []).find(it => it.viewId == view.id);
const orderGroup = (order?.groups || []).find(it => it.groupId == id) || {};
const isAllowedObject = this.props.isAllowedObject();
const tooltip = Dataview.getCreateTooltip(rootId, block.id, target.id, view.id);
if (view.groupBackgroundColors) {
cn.push('withColor');
@ -92,7 +94,7 @@ const Column = observer(class Column extends React.Component<Props> {
<div className="side right">
<Icon id={`button-${id}-more`} className="more" tooltip={translate('blockDataviewBoardColumnSettings')} onClick={this.onMore} />
{isAllowedObject ? <Icon className="add" tooltip={translate('blockDataviewCreateNew')} onClick={e => this.onAdd(e, -1)} /> : ''}
{isAllowedObject ? <Icon className="add" tooltip={tooltip} onClick={e => this.onAdd(e, -1)} /> : ''}
</div>
</div>

View file

@ -28,7 +28,7 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
};
render () {
const { className } = this.props;
const { block, className } = this.props;
const cn = [ 'viewContent', className ];
return (
@ -41,6 +41,7 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
key="graph"
{...this.props}
ref={ref => this.refGraph = ref}
id={block.id}
rootId=""
data={this.data}
/>
@ -88,10 +89,15 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
};
load () {
const { getView } = this.props;
const { getView, getSearchIds } = this.props;
const view = getView();
const searchIds = getSearchIds();
const filters = [].concat(view.filters).concat(UtilData.graphFilters()).map(it => Dataview.filterMapper(view, it));
if (searchIds) {
filters.push({ operator: I.FilterOperator.And, relationKey: 'id', condition: I.FilterCondition.In, value: searchIds || [] });
};
this.setLoading(true);
C.ObjectGraph(commonStore.space, filters, 0, [], Constant.graphRelationKeys, (message: any) => {
@ -143,23 +149,25 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
};
resize () {
const { isPopup } = this.props;
const { isPopup, isInline } = this.props;
const node = $(this.node);
if (!node || !node.length) {
return;
};
node.css({ width: 0, height: 0, marginLeft: 0 });
if (!isInline) {
node.css({ width: 0, height: 0, marginLeft: 0 });
const container = UtilCommon.getPageContainer(isPopup);
const cw = container.width();
const ch = container.height();
const mw = cw - PADDING * 2;
const margin = (cw - mw) / 2;
const { top } = node.offset();
const container = UtilCommon.getPageContainer(isPopup);
const cw = container.width();
const ch = container.height();
const mw = cw - PADDING * 2;
const margin = (cw - mw) / 2;
const { top } = node.offset();
node.css({ width: cw, height: Math.max(600, ch - top - 90), marginLeft: -margin - 2 });
node.css({ width: cw, height: Math.max(600, ch - top), marginLeft: -margin - 2 });
};
if (this.refGraph) {
this.refGraph.resize();

View file

@ -489,7 +489,7 @@ const Block = observer(class Block extends React.Component<Props> {
const { rootId, block, readonly } = this.props;
const root = blockStore.getLeaf(rootId, rootId);
if (readonly || !block.isSelectable() || (block.isText() && (focused == block.id)) || block.isTable()) {
if (readonly || !block.isSelectable() || (block.isText() && (focused == block.id)) || block.isTable() || block.isDataview()) {
return;
};

View file

@ -362,7 +362,7 @@ const BlockLink = observer(class BlockLink extends React.Component<I.BlockCompon
UtilCommon.textStyle(name, { border: 0.4 });
icon.length ? card.addClass('withIcon') : card.removeClass('withIcon');
rect.width <= mw / 2 ? card.addClass('vertical') : card.removeClass('vertical');
rect.width <= mw / 2 ? card.addClass('isVertical') : card.removeClass('isVertical');
});
};

View file

@ -344,6 +344,10 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
};
},
onOver: (e: any, item: any) => {
if (menuStore.isAnimating(menuContext.props.id)) {
return;
};
if (!menuContext) {
return;
};

View file

@ -7,7 +7,7 @@ import { I, Mark, keyboard, C, focus, Action, UtilCommon, UtilData, UtilMenu, Ut
import { blockStore, commonStore, dbStore, menuStore, detailStore, popupStore } from 'Store';
import Constant from 'json/constant.json';
const HEIGHT_ITEM = 28;
const HEIGHT_ITEM = 32;
const HEIGHT_SECTION = 42;
const HEIGHT_DESCRIPTION = 56;
const HEIGHT_RELATION = 32;

View file

@ -288,12 +288,10 @@ const MenuBlockContext = observer(class MenuBlockContext extends React.Component
menuParam.data = Object.assign(menuParam.data, {
value: (mark ? mark.param : ''),
onChange: (param: string) => {
if (!mark && !param) {
return;
if (param) {
Storage.set(storageKey, param);
};
Storage.set(storageKey, param);
marks = Mark.toggle(marks, { type, param, range: { from, to } });
menuStore.updateData(this.props.id, { marks });
onChange(marks);

View file

@ -94,7 +94,7 @@ const PageAuthSetup = observer(class PageAuthSetup extends React.Component<I.Pag
const { match } = this.props;
const { account, walletPath } = authStore;
switch (match.params.id) {
switch (match?.params?.id) {
case 'init': {
this.init();
break;

View file

@ -51,6 +51,7 @@ const PageMainGraph = observer(class PageMainGraph extends React.Component<I.Pag
key="graph"
{...this.props}
ref={ref => this.refGraph = ref}
id="global"
rootId={rootId}
data={this.data}
/>

View file

@ -9,6 +9,7 @@ import { commonStore, menuStore } from 'Store';
import Constant from 'json/constant.json';
interface Props {
id?: string;
isPopup?: boolean;
rootId: string;
data: any;
@ -39,19 +40,12 @@ const Graph = observer(class Graph extends React.Component<Props> {
};
render () {
const { isPopup } = this.props;
const id = [ 'graph' ];
if (isPopup) {
id.push('popup');
};
return (
<div
ref={node => this.node = node}
id="graphWrapper"
>
<div id={id.join('-')} />
<div id={this.getId()} />
</div>
);
};
@ -86,15 +80,28 @@ const Graph = observer(class Graph extends React.Component<Props> {
$(window).off(events.map(it => `${it}.graph`).join(' '));
};
getId (): string {
const { id, isPopup } = this.props;
const ret = [ 'graph' ];
if (id) {
ret.push(id);
};
if (isPopup) {
ret.push('popup');
};
return ret.join('-');
};
init () {
const { data, isPopup, rootId } = this.props;
const { data, rootId } = this.props;
const node = $(this.node);
const density = window.devicePixelRatio;
const elementId = `#graph${isPopup ? '-popup' : ''}`;
const elementId = `#${this.getId()}`;
const width = node.width();
const height = node.height();
this.zoom = d3.zoom().scaleExtent([ 1, 6 ]).on('zoom', e => this.onZoom(e));
this.zoom = d3.zoom().scaleExtent([ 0.2, 10 ]).on('zoom', e => this.onZoom(e));
this.edges = (data.edges || []).map(this.edgeMapper);
this.nodes = (data.nodes || []).map(this.nodeMapper);
@ -393,7 +400,7 @@ const Graph = observer(class Graph extends React.Component<Props> {
this.edges.push(this.edgeMapper({ type: I.EdgeType.Link, source: sourceId, target: targetId }));
this.send('onSetEdges', { edges: this.edges });
} else {
this.addNewNode(targetId, target => this.send('onAddNode', { target, sourceId }));
this.addNewNode(targetId, sourceId, null);
};
},
onSelect: (itemId: string) => {
@ -449,12 +456,7 @@ const Graph = observer(class Graph extends React.Component<Props> {
UtilObject.create('', '', {}, I.BlockPosition.Bottom, '', {}, flags, (message: any) => {
UtilObject.openPopup({ id: message.targetId }, {
onClose: () => {
this.addNewNode(message.targetId, target => {
target = Object.assign(target, { x: data.x, y: data.y });
this.send('onAddNode', { target });
});
}
onClose: () => this.addNewNode(message.targetId, '', data),
});
analytics.event('CreateObject', { objectType: commonStore.type, route: 'Graph' });
@ -499,12 +501,20 @@ const Graph = observer(class Graph extends React.Component<Props> {
UtilObject.openAuto(this.nodes.find(d => d.id == id));
};
addNewNode (id: string, cb: (target: any) => void) {
addNewNode (id: string, sourceId?: string, param?: any, callBack?: (object: any) => void) {
UtilObject.getById(id, (object: any) => {
object = this.nodeMapper(object);
if (param) {
object = Object.assign(object, param);
};
this.nodes.push(object);
cb(object);
this.send('onAddNode', { target: object, sourceId });
if (callBack) {
callBack(object);
};
});
};

View file

@ -18,6 +18,8 @@ export enum EmbedProcessor {
Instagram = 13,
Telegram = 14,
GithubGist = 15,
Codepen = 16,
Bilibili = 17,
};
export interface ContentEmbed {

View file

@ -328,7 +328,6 @@ class Dataview {
getTypeId (rootId: string, blockId: string, objectId: string, viewId?: string) {
const view = this.getView(rootId, blockId, viewId);
const types = Relation.getSetOfObjects(rootId, objectId, I.ObjectLayout.Type);
const relations = Relation.getSetOfObjects(rootId, objectId, I.ObjectLayout.Relation);
const isAllowedDefaultType = this.isCollection(rootId, blockId) || !!Relation.getSetOfObjects(rootId, objectId, I.ObjectLayout.Relation).map(it => it.id).length;
@ -359,6 +358,22 @@ class Dataview {
return typeId;
};
getCreateTooltip (rootId: string, blockId: string, objectId: string, viewId: string): string {
const isCollection = this.isCollection(rootId, blockId);
if (isCollection) {
return translate('blockDataviewCreateNewTooltipCollection');
} else {
const typeId = this.getTypeId(rootId, blockId, objectId, viewId);
const type = dbStore.getTypeById(typeId);
if (type) {
return UtilCommon.sprintf(translate('blockDataviewCreateNewTooltipType'), type.name);
};
};
return translate('blockDataviewCreateNew');
};
};
export default new Dataview();

View file

@ -3,19 +3,13 @@ import { I, UtilCommon, analytics } from 'Lib';
import Constant from 'json/constant.json';
const Tags = {};
Tags[I.MarkType.Strike] = 'markupStrike';
Tags[I.MarkType.Code] = 'markupCode';
Tags[I.MarkType.Italic] = 'markupItalic';
Tags[I.MarkType.Bold] = 'markupBold';
Tags[I.MarkType.Underline] = 'markupUnderline';
Tags[I.MarkType.Link] = 'markupLink';
Tags[I.MarkType.Color] = 'markupColor';
Tags[I.MarkType.BgColor] = 'markupBgcolor';
Tags[I.MarkType.Mention] = 'markupMention';
Tags[I.MarkType.Emoji] = 'markupEmoji';
Tags[I.MarkType.Object] = 'markupObject';
for (const i in I.MarkType) {
if (isNaN(Number(i))) {
continue;
};
const LCTags = Object.values(Tags).map(it => String(it).toLowerCase());
Tags[i] = `markup${I.MarkType[i].toLowerCase()}`;
};
const Patterns = {
'-→': '⟶',
@ -461,7 +455,7 @@ class Mark {
const end = p1 == '/';
const offset = Number(text.indexOf(s)) || 0;
const type = LCTags.indexOf(p2);
const type = Object.values(Tags).indexOf(p2);
if (type < 0) {
return;
@ -531,7 +525,8 @@ class Mark {
};
if (check) {
marks = this.adjust(marks, from, -p2.length * 2);
marks = this.adjust(marks, from, -p2.length);
marks = this.adjust(marks, to, -p4.length);
marks.push({ type: item.type, range: { from, to }, param: '' });
text = text.replace(s, replace);

View file

@ -66,6 +66,7 @@ class ScrollOnMove {
const maxScrollX = this.documentWidth - this.viewportWidth;
const maxScrollY = this.documentHeight - this.viewportHeight;
let currentScrollX = 0;
let currentScrollY = 0;
let container;
@ -85,9 +86,10 @@ class ScrollOnMove {
const canScrollDown = (currentScrollY < maxScrollY);
const canScrollLeft = (currentScrollX > 0);
const canScrollRight = (currentScrollX < maxScrollX);
const maxStep = 10;
let nextScrollX = currentScrollX;
let nextScrollY = currentScrollY;
const maxStep = 10;
let intensity = 0;
if (isInLeftEdge && canScrollLeft) {

View file

@ -421,7 +421,7 @@ class UtilData {
const diff = needle.length - (to - from);
const text = UtilCommon.stringInsert(block.content.text, needle, from, to);
const marks = Mark.adjust(block.content.marks, 0, diff);
const marks = Mark.adjust(block.content.marks, from, diff);
this.blockSetText(rootId, blockId, text, marks, true, callBack);
};

View file

@ -1,7 +1,7 @@
import { I, UtilCommon } from 'Lib';
import Constant from 'json/constant.json';
const DOMAINS: any = {};
const DOMAINS: any = {};
DOMAINS[I.EmbedProcessor.Youtube] = [ 'youtube.com', 'youtu.be' ];
DOMAINS[I.EmbedProcessor.Vimeo] = [ 'vimeo.com' ];
DOMAINS[I.EmbedProcessor.GoogleMaps] = [ 'google.[^\/]+/maps' ];
@ -9,13 +9,15 @@ DOMAINS[I.EmbedProcessor.Miro] = [ 'miro.com' ];
DOMAINS[I.EmbedProcessor.Figma] = [ 'figma.com' ];
DOMAINS[I.EmbedProcessor.OpenStreetMap] = [ 'openstreetmap.org\/\#map' ];
DOMAINS[I.EmbedProcessor.Telegram] = [ 't.me' ];
DOMAINS[I.EmbedProcessor.Codepen] = [ 'codepen.io' ];
DOMAINS[I.EmbedProcessor.Bilibili] = [ 'bilibili.com', 'b23.tv'];
const IFRAME_PARAM = 'frameborder="0" scrolling="no" allowfullscreen';
class UtilEmbed {
getHtml (processor: I.EmbedProcessor, content: any): string {
const fn = UtilCommon.toCamelCase(`get-${I.EmbedProcessor[processor]}-html`)
const fn = UtilCommon.toCamelCase(`get-${I.EmbedProcessor[processor]}-html`);
return this[fn] ? this[fn](content) : '';
};
@ -52,9 +54,24 @@ class UtilEmbed {
return `<script src="${content}.js"></script>`;
};
getCodepenHtml (content: string): string {
const a = new URL(content);
const p = a.pathname.split('/');
if (!p.length) {
return '';
};
return `<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="${p[3]}" data-user="${p[1]}"></p>`;
};
getBilibiliHtml (content: string): string {
return `<iframe src="${content}" ${IFRAME_PARAM}></iframe>`;
};
getProcessorByUrl (url: string): I.EmbedProcessor {
let p = null;
for (let i in DOMAINS) {
for (const i in DOMAINS) {
const reg = new RegExp(DOMAINS[i].join('|'), 'gi');
if (url.match(reg)) {
p = Number(i);
@ -132,6 +149,26 @@ class UtilEmbed {
break;
};
case I.EmbedProcessor.Bilibili: {
const { pathname, searchParams } = new URL(url);
if (!pathname) {
break;
};
const a = pathname.split('/');
if (a.length < 3) {
return;
};
const bvid = pathname.split('/')[2];
const [ p = 1, t = 0 ] = [ searchParams.get('p'), searchParams.get('t') ];
if (bvid) {
url = `https://player.bilibili.com/player.html?bvid=${bvid}&p=${p}&t=${t}&high_quality=1&autoplay=0`;
};
break;
};
};
return url;
@ -167,6 +204,11 @@ class UtilEmbed {
libs.push('https://www.instagram.com/embed.js');
break;
};
case I.EmbedProcessor.Codepen: {
libs.push('https://cpwebassets.codepen.io/assets/embed/ei.js');
break;
};
};
return {
@ -184,6 +226,7 @@ class UtilEmbed {
};
};
// Allow to use same origin in iframe sandbox
allowSameOrigin (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Youtube,
@ -196,16 +239,21 @@ class UtilEmbed {
I.EmbedProcessor.Reddit,
I.EmbedProcessor.Instagram,
I.EmbedProcessor.Telegram,
I.EmbedProcessor.Codepen,
I.EmbedProcessor.Bilibili,
].includes(p);
};
// Allow to use presentation mode in iframe sandbox
allowPresentation (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Youtube,
I.EmbedProcessor.Vimeo,
I.EmbedProcessor.Bilibili
].includes(p);
};
// Allow url embedding
allowEmbedUrl (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Youtube,
@ -216,23 +264,29 @@ class UtilEmbed {
I.EmbedProcessor.OpenStreetMap,
I.EmbedProcessor.Telegram,
I.EmbedProcessor.GithubGist,
I.EmbedProcessor.Codepen,
I.EmbedProcessor.Bilibili,
].includes(p);
};
// Pass block data as js code
allowJs (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Chart,
].includes(p);
};
// Allow to use popup mode in iframe sandbox
allowPopup (p: I.EmbedProcessor) {
return [].includes(p);
return [ I.EmbedProcessor.Bilibili ].includes(p);
};
// Allow block resizing
allowBlockResize (p: I.EmbedProcessor) {
return ![ I.EmbedProcessor.Latex, I.EmbedProcessor.Mermaid, I.EmbedProcessor.Chart ].includes(p);
};
// Use iframe height instead of fixed aspect ratio
allowIframeResize (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Twitter,
@ -241,15 +295,18 @@ class UtilEmbed {
I.EmbedProcessor.Instagram,
I.EmbedProcessor.Telegram,
I.EmbedProcessor.GithubGist,
I.EmbedProcessor.Codepen,
].includes(p);
};
// Render blocks on scroll
allowScroll (p: I.EmbedProcessor) {
return ![
I.EmbedProcessor.Latex,
].includes(p);
};
// Render blocks on mount
allowAutoRender (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Latex,
@ -259,23 +316,29 @@ class UtilEmbed {
I.EmbedProcessor.Instagram,
I.EmbedProcessor.Telegram,
I.EmbedProcessor.GithubGist,
I.EmbedProcessor.Codepen,
I.EmbedProcessor.Bilibili,
].includes(p);
};
// Insert html content before loading libs
insertBeforeLoad (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Twitter,
I.EmbedProcessor.Reddit,
I.EmbedProcessor.Instagram,
I.EmbedProcessor.Codepen,
].includes(p);
};
// Use root height instead of iframe scroll height
useRootHeight (p: I.EmbedProcessor) {
return [
I.EmbedProcessor.Twitter,
I.EmbedProcessor.Telegram,
I.EmbedProcessor.Instagram,
I.EmbedProcessor.GithubGist,
I.EmbedProcessor.Codepen,
].includes(p);
};

View file

@ -30,11 +30,11 @@ class UtilMenu {
getBlockText () {
return [
{ id: I.TextStyle.Paragraph, lang: 'Paragraph' },
{ id: I.TextStyle.Header1, lang: 'Header1', aliases: [ 'h1', 'head1' ] },
{ id: I.TextStyle.Header2, lang: 'Header2', aliases: [ 'h2', 'head2' ] },
{ id: I.TextStyle.Header3, lang: 'Header3', aliases: [ 'h3', 'head3' ] },
{ id: I.TextStyle.Quote, lang: 'Quote' },
{ id: I.TextStyle.Callout, lang: 'Callout' },
{ id: I.TextStyle.Header1, lang: 'Header1', aliases: [ 'h1', 'head1', 'header1' ] },
{ id: I.TextStyle.Header2, lang: 'Header2', aliases: [ 'h2', 'head2', 'header2' ] },
{ id: I.TextStyle.Header3, lang: 'Header3', aliases: [ 'h3', 'head3', 'header3' ] },
{ id: I.TextStyle.Quote, lang: 'Quote', aliases: [ 'quote' ] },
{ id: I.TextStyle.Callout, lang: 'Callout', aliases: [ 'callout' ] },
].map((it: any) => {
it.type = I.BlockType.Text;
it.icon = UtilData.blockTextClass(it.id);
@ -44,10 +44,10 @@ class UtilMenu {
getBlockList () {
return [
{ id: I.TextStyle.Checkbox, lang: 'Checkbox', aliases: [ 'todo' ] },
{ id: I.TextStyle.Bulleted, lang: 'Bulleted' },
{ id: I.TextStyle.Numbered, lang: 'Numbered' },
{ id: I.TextStyle.Toggle, lang: 'Toggle' },
{ id: I.TextStyle.Checkbox, lang: 'Checkbox', aliases: [ 'todo', 'checkbox' ] },
{ id: I.TextStyle.Bulleted, lang: 'Bulleted', aliases: [ 'bulleted list' ] },
{ id: I.TextStyle.Numbered, lang: 'Numbered', aliases: [ 'numbered list' ] },
{ id: I.TextStyle.Toggle, lang: 'Toggle', aliases: [ 'toggle' ] },
].map((it: any) => {
it.type = I.BlockType.Text;
it.icon = UtilData.blockTextClass(it.id);
@ -57,13 +57,13 @@ class UtilMenu {
getBlockMedia () {
return [
{ type: I.BlockType.File, id: I.FileType.File, icon: 'mediaFile', lang: 'File' },
{ type: I.BlockType.File, id: I.FileType.Image, icon: 'mediaImage', lang: 'Image' },
{ type: I.BlockType.File, id: I.FileType.Video, icon: 'mediaVideo', lang: 'Video' },
{ type: I.BlockType.File, id: I.FileType.Audio, icon: 'mediaAudio', lang: 'Audio' },
{ type: I.BlockType.File, id: I.FileType.Pdf, icon: 'mediaPdf', lang: 'Pdf' },
{ type: I.BlockType.Bookmark, id: 'bookmark', icon: 'bookmark', lang: 'Bookmark' },
{ type: I.BlockType.Text, id: I.TextStyle.Code, icon: 'code', lang: 'Code' },
{ type: I.BlockType.File, id: I.FileType.File, icon: 'mediaFile', lang: 'File', aliases: [ 'file' ] },
{ type: I.BlockType.File, id: I.FileType.Image, icon: 'mediaImage', lang: 'Image', aliases: [ 'image', 'picture' ] },
{ type: I.BlockType.File, id: I.FileType.Video, icon: 'mediaVideo', lang: 'Video', aliases: [ 'video' ] },
{ type: I.BlockType.File, id: I.FileType.Audio, icon: 'mediaAudio', lang: 'Audio', aliases: [ 'audio' ] },
{ type: I.BlockType.File, id: I.FileType.Pdf, icon: 'mediaPdf', lang: 'Pdf', aliases: [ 'pdf' ] },
{ type: I.BlockType.Bookmark, id: 'bookmark', icon: 'bookmark', lang: 'Bookmark', aliases: [ 'bookmark' ] },
{ type: I.BlockType.Text, id: I.TextStyle.Code, icon: 'code', lang: 'Code', aliases: [ 'code' ] },
].map(this.mapperBlock);
};
@ -92,6 +92,8 @@ class UtilMenu {
{ id: I.EmbedProcessor.Instagram, icon: 'instagram', name: 'Instagram' },
{ id: I.EmbedProcessor.Telegram, icon: 'telegram', name: 'Telegram' },
{ id: I.EmbedProcessor.GithubGist, icon: 'githubGist', name: 'Github Gist' },
{ id: I.EmbedProcessor.Codepen, icon: 'codepen', name: 'Codepen' },
{ id: I.EmbedProcessor.Bilibili, icon: 'bilibili', name: 'Bilibili' },
]);
};
@ -127,12 +129,12 @@ class UtilMenu {
getBlockOther () {
return [
{ type: I.BlockType.Div, id: I.DivStyle.Line, icon: 'divLine', lang: 'Line' },
{ type: I.BlockType.Div, id: I.DivStyle.Dot, icon: 'divDot', lang: 'Dot' },
{ type: I.BlockType.TableOfContents, id: I.BlockType.TableOfContents, icon: 'tableOfContents', lang: 'TableOfContents', aliases: [ 'tc', 'toc' ] },
{ type: I.BlockType.Table, id: I.BlockType.Table, icon: 'table', lang: 'SimpleTable' },
{ type: I.BlockType.Dataview, id: 'collection', icon: 'collection', lang: 'Collection', aliases: [ 'grid', 'table', 'gallery', 'list', 'board', 'kanban' ] },
{ type: I.BlockType.Dataview, id: 'set', icon: 'set', lang: 'Set', aliases: [ 'grid', 'table', 'gallery', 'list', 'board', 'kanban' ] },
{ type: I.BlockType.Div, id: I.DivStyle.Line, icon: 'divLine', lang: 'Line', aliases: [ 'hr', 'line divider' ] },
{ type: I.BlockType.Div, id: I.DivStyle.Dot, icon: 'divDot', lang: 'Dot', aliases: [ 'dot', 'dots divider' ] },
{ type: I.BlockType.TableOfContents, id: I.BlockType.TableOfContents, icon: 'tableOfContents', lang: 'TableOfContents', aliases: [ 'tc', 'toc', 'table of contents'] },
{ type: I.BlockType.Table, id: I.BlockType.Table, icon: 'table', lang: 'SimpleTable', aliases: [ 'table' ] },
{ type: I.BlockType.Dataview, id: 'collection', icon: 'collection', lang: 'Collection', aliases: [ 'grid', 'table', 'gallery', 'list', 'board', 'kanban', 'inline collection' ] },
{ type: I.BlockType.Dataview, id: 'set', icon: 'set', lang: 'Set', aliases: [ 'grid', 'table', 'gallery', 'list', 'board', 'kanban', 'inline set' ] },
].map(this.mapperBlock);
};

View file

@ -422,7 +422,7 @@ class BlockStore {
};
updateMarkup (rootId: string) {
const blocks = UtilCommon.objectCopy(this.getBlocks(rootId, it => it.isText()));
const blocks = this.getBlocks(rootId, it => it.isText());
for (const block of blocks) {
let marks = block.content.marks || [];
@ -431,6 +431,7 @@ class BlockStore {
continue;
};
marks = UtilCommon.objectCopy(marks);
marks.sort(Mark.sort);
let { text } = block.content;

View file

@ -164,7 +164,7 @@ class MenuStore {
};
isAnimating (id: string): boolean {
return this.isAnimatingFlag.get(id);
return !!this.isAnimatingFlag.get(id);
};
closeAll (ids?: string[], callBack?: () => void) {