1
0
Fork 0
mirror of https://github.com/anyproto/anytype-ts.git synced 2025-06-09 09:35:02 +09:00
This commit is contained in:
Andrew Simachev 2024-02-08 20:56:55 +01:00
commit f36210e3e4
No known key found for this signature in database
GPG key ID: 49A163D0D14E6FD8
42 changed files with 756 additions and 473 deletions

View file

@ -134,11 +134,7 @@
};
sendToActiveTab = async (msg) => {
const tab = await getActiveTab();
console.log('[sendToActiveTab]', tab, msg);
await sendToTab(tab, msg);
await sendToTab(await getActiveTab(), msg);
};
sendToTab = async (tab, msg) => {
@ -146,6 +142,8 @@
return;
};
msg.url = tab.url;
const response = await chrome.tabs.sendMessage(tab.id, msg);
console.log('[sendToTab]', tab, msg, response);

View file

@ -137,7 +137,7 @@ class MenuManager {
label: Util.translate('electronMenuHelp'),
submenu: [
{
label: Util.translate('electronMenuReleaseNotes') + ` (${app.getVersion()})`,
label: `${Util.translate('electronMenuReleaseNotes')} (${app.getVersion()})`,
click: () => Util.send(this.win, 'popup', 'help', { preventResize: true, data: { document: 'whatsNew' } })
},
{
@ -228,6 +228,13 @@ class MenuManager {
Separator,
{
label: 'Experience gallery',
click: () => Util.send(this.win, 'popup', 'usecase', {})
},
Separator,
{ label: 'Export templates', click: () => Util.send(this.win, 'commandGlobal', 'exportTemplates') },
{ label: 'Export objects', click: () => Util.send(this.win, 'commandGlobal', 'exportObjects') },
{ label: 'Export localstore', click: () => Util.send(this.win, 'commandGlobal', 'exportLocalstore') },

View file

@ -1,18 +1,42 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import $ from 'jquery';
import { C, UtilCommon, UtilRouter } from 'Lib';
import Popup from './popup';
import Iframe from './iframe';
import Util from './lib/util';
import Extension from 'json/extension.json';
import * as Store from 'Store';
import './scss/common.scss';
declare global {
interface Window {
isExtension: boolean;
Electron: any;
$: any;
Anytype: any;
isWebVersion: boolean;
AnytypeGlobalConfig: any;
}
};
window.$ = $;
window.isExtension = true;
window.Electron = {
currentWindow: () => ({ windowId: 1 }),
Api: () => {},
};
window.Anytype = {
Store,
Lib: {
C,
UtilCommon,
UtilRouter,
},
};
window.AnytypeGlobalConfig = {
emojiUrl: Extension.clipper.emojiUrl,
menuBorderTop: 16,
@ -32,6 +56,8 @@ if (Util.isIframe()) {
component = <Iframe />;
};
console.log(window.Anytype);
if (!rootId) {
console.error('[Entry] rootId is not defined');
} else {

View file

@ -1,12 +1,11 @@
import * as React from 'react';
import * as hs from 'history';
import $ from 'jquery';
import { Router, Route, Switch } from 'react-router-dom';
import { RouteComponentProps } from 'react-router';
import { Provider } from 'mobx-react';
import { configure } from 'mobx';
import { ListMenu } from 'Component';
import { dispatcher, C, UtilCommon, UtilRouter } from 'Lib';
import { UtilRouter } from 'Lib';
import { commonStore, authStore, blockStore, detailStore, dbStore, menuStore, popupStore, extensionStore } from 'Store';
import Index from './iframe/index';
@ -41,28 +40,6 @@ const rootStore = {
extensionStore,
};
declare global {
interface Window {
Electron: any;
$: any;
Anytype: any;
isWebVersion: boolean;
AnytypeGlobalConfig: any;
}
};
window.$ = $;
window.$ = $;
window.Anytype = {
Store: rootStore,
Lib: {
C,
UtilCommon,
dispatcher,
Storage,
},
};
class RoutePage extends React.Component<RouteComponentProps> {
render () {
const { match } = this.props;
@ -118,6 +95,7 @@ class Iframe extends React.Component {
break;
case 'clickMenu': {
extensionStore.setTabUrl(msg.url);
extensionStore.setHtml(msg.html);
sendResponse({});

View file

@ -88,7 +88,7 @@ const Create = observer(class Create extends React.Component<I.PageComponent, St
);
};
componentDidMount(): void {
componentDidMount (): void {
const spaces = dbStore.getSpaces().map(it => ({ ...it, id: it.targetSpaceId, object: it, iconSize: 16 })).filter(it => it);
if (this.refSpace && spaces.length) {
@ -105,7 +105,7 @@ const Create = observer(class Create extends React.Component<I.PageComponent, St
};
initBlocks () {
const { html } = extensionStore;
const { html, tabUrl } = extensionStore;
if (!html || (html == this.html)) {
return;
@ -113,7 +113,7 @@ const Create = observer(class Create extends React.Component<I.PageComponent, St
this.html = html;
C.BlockPreview(html, (message: any) => {
C.BlockPreview(html, tabUrl, (message: any) => {
if (message.error.code) {
return;
};
@ -167,13 +167,14 @@ const Create = observer(class Create extends React.Component<I.PageComponent, St
};
onSave () {
const { html, tabUrl } = extensionStore;
const { object } = this.state;
if (!object) {
return;
};
C.BlockPaste (object.id, '', { from: 0, to: 0 }, [], false, { html: this.html }, () => {
C.BlockPaste(object.id, '', { from: 0, to: 0 }, [], false, { html }, tabUrl, () => {
this.onClose();
});
};

View file

@ -1,12 +1,11 @@
import * as React from 'react';
import * as hs from 'history';
import $ from 'jquery';
import { Router, Route, Switch } from 'react-router-dom';
import { RouteComponentProps } from 'react-router';
import { Provider } from 'mobx-react';
import { configure } from 'mobx';
import { ListMenu } from 'Component';
import { dispatcher, C, UtilCommon, UtilRouter } from 'Lib';
import { UtilRouter } from 'Lib';
import { commonStore, authStore, blockStore, detailStore, dbStore, menuStore, popupStore, extensionStore } from 'Store';
import Extension from 'json/extension.json';
@ -45,27 +44,6 @@ const rootStore = {
extensionStore,
};
declare global {
interface Window {
Electron: any;
$: any;
Anytype: any;
isWebVersion: boolean;
AnytypeGlobalConfig: any;
}
};
window.$ = $;
window.Anytype = {
Store: rootStore,
Lib: {
C,
UtilCommon,
dispatcher,
Storage,
},
};
class RoutePage extends React.Component<RouteComponentProps> {
render () {
const { match } = this.props;

View file

@ -81,4 +81,6 @@ html.anytypeWebclipper-popup {
.inner { border-color: var(--color-ice) !important; box-shadow: 0px 0px 0px 1px var(--color-ice) !important; }
.input { border: unset !important; box-shadow: unset !important; }
}
.passThrough { pointer-events: all; }
}

View file

@ -3,7 +3,6 @@
.blocks {
.block.blockFeatured {
@include text-common; line-height: 28px; color: var(--color-text-secondary); padding: 0px 0px 24px 0px; white-space: nowrap; display: flex;
margin-top: -3px;
}
.block.blockFeatured {
.icon.checkbox { width: 20px; height: 20px; vertical-align: middle; margin-top: -4px; background-image: url('~img/icon/dataview/checkbox0.svg'); }
@ -58,6 +57,7 @@
.iconObject * { position: static; vertical-align: middle; margin: 0px; }
.name { display: none; }
.empty { padding: 0px 4px; }
.more { margin-top: 2px; }
}
.cellContent.c-object, .cellContent.c-file {
@ -72,6 +72,10 @@
.cellContent.c-checkbox {
.icon { margin: 0px 5px 0px 0px; }
}
.cellContent.c-longText {
.name { display: inline-block; vertical-align: top; max-width: 220px; @include text-overflow-nw; }
}
}
.block.blockFeatured > .wrapMenu:hover > .icon.dnd { opacity: 1; }

View file

@ -75,7 +75,7 @@ html.platformWindows, html.platformLinux {
.txt { vertical-align: middle; display: inline-block; line-height: 1; }
.flex { display: flex; }
.nw { white-space: nowrap; }
.through { pointer-events: none; }
.passThrough { pointer-events: none; }
.rel { position: relative; }
.disabled { opacity: 0.5; cursor: default !important; }
.dis { cursor: default !important; }

View file

@ -69,7 +69,7 @@
.tab:last-child { margin: 0px; }
}
.titleWrapper { display: flex; gap: 0 6px; padding: 8px 14px; align-items: center; }
.titleWrapper { display: flex; gap: 0 6px; padding: 8px 14px 0px; align-items: center; }
.titleWrapper {
.icon.back { width: 20px; height: 20px; background-image: url('~img/arrow/menu.svg'); transform: rotateZ(180deg); }
.title { @include text-common; font-weight: 600; color: var(--color-text-primary); padding: 0; }
@ -270,4 +270,4 @@ html.platformWindows {
@import "./dataview/source.scss";
@import "./dataview/text.scss";
@import "./dataview/view.scss";
@import "./dataview/template.scss";
@import "./dataview/template.scss";

View file

@ -6,7 +6,7 @@
.content { padding-top: 12px; padding-bottom: 0px; transition: none; }
.wrap { height: 100%; display: flex; flex-direction: column; }
.items { height: calc(100% - 34px); }
.items { height: calc(100% - 28px); }
.item {
.name { @include text-overflow-nw; width: calc(100% - 26px); }
}
@ -14,6 +14,7 @@
}
.menu.menuDataviewFileValues {
.titleWrapper,
.content { padding-bottom: 0px; }
.item { display: flex; color: var(--color-text-secondary); }

View file

@ -33,7 +33,6 @@
.menu.menuDataviewObjectValues { width: 288px; }
.menu.menuDataviewObjectValues {
.titleWrapper { padding-bottom: 0px; }
.content { padding: 0px; }
.item:not(.add) { padding: 4px 16px 4px 12px; }

View file

@ -72,8 +72,7 @@
}
}
.menu.menuDataviewOptionList.featuredRelation {
.titleWrapper { padding-bottom: 0px; }
.menu.menuDataviewOptionList.fromFeatured {
.filter { padding-top: 8px; }
.item {
.buttons,

View file

@ -1,8 +1,8 @@
@import "~scss/_vars";
.menus {
.menu.menuDataviewText { box-shadow: 0px 0px; background: transparent; }
.menu.menuDataviewText {
.menu.menuDataviewText:not(.fromFeatured) { box-shadow: 0px 0px; background: transparent; }
.menu.menuDataviewText:not(.fromFeatured) {
.content { overflow: visible !important; max-height: none; height: 100%; transition: $transitionAllCommon; padding: 0px; }
.editableWrap { height: 100%; }
@ -16,9 +16,13 @@
#input { padding: 5px 8px; }
#placeholder { padding: 5px 8px; }
}
.menu.menuDataviewText.show {
.menu.menuDataviewText.show:not(.fromFeatured) {
#input { box-shadow: 0px 0px 0px 2px var(--color-system-accent-50); }
}
.menu.menuDataviewText.fromFeatured {
.content { padding: 8px 14px; }
}
}
html.platformWindows {
@ -27,4 +31,4 @@ html.platformWindows {
#input { overflow: overlay; }
}
}
}
}

View file

@ -27,7 +27,6 @@
}
.menu.menuDataviewViewSettings {
.content { padding-top: 0; }
.filter.isName { margin-bottom: 4px; }
}

View file

@ -73,7 +73,6 @@
/* Links, Backlinks */
.menu.menuSelect.featuredLinks {
.titleWrapper { padding-bottom: 0px; }
.item {
.info { width: 100%; }
.iconObject { margin: 0px; background-color: var(--color-shape-highlight-medium); }

View file

@ -137,7 +137,7 @@
}
}
.phraseWrapper { border-radius: 12px; background-color: var(--color-shape-tertiary); padding: 16px 12px; line-height: unset; }
.phraseWrapper { border-radius: 12px; background-color: var(--color-shape-tertiary); padding: 16px 44px; line-height: unset; }
.phraseWrapper {
.phraseInnerWrapper { min-height: unset; display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; word-break: unset; }
.word { font-size: 12px; line-height: 18px; font-weight: 500; margin: 0; }

View file

@ -2,54 +2,70 @@
.popups {
.popup.popupUsecase {
.innerWrap { width: 816px; padding: 32px 56px; }
.innerWrap { width: 816px; max-height: calc(100% - 128px); }
.titleWrap {
margin: 0px 0px 40px 0px; display: flex; flex-direction: row; align-items: center; justify-content: stretch; gap: 0px 16px;
}
.titleWrap {
.side.left { flex-grow: 1; display: flex; flex-direction: column; gap: 8px 0px; }
.side.right { flex-shrink: 0; }
.page { padding: 32px 56px; }
.title { @include text-header1; }
.label { @include text-small; color: var(--color-text-secondary); }
}
.screenWrap {
height: 480px; background: var(--color-shape-highlight-light); margin: 0px -56px 20px -56px; padding: 20px 56px; overflow: hidden;
position: relative;
}
.screenWrap {
.swiper { height: 100%; overflow: visible; }
.swiper-slide { display: flex; align-items: center; justify-content: center; }
.screen {
width: 100%; box-shadow: 0px 2px 28px 0px rgba(0, 0, 0, 0.20); background-size: contain;
background-position: center; background-repeat: no-repeat; border-radius: 6px; background-color: var(--color-bg-primary);
}
.icon.arrow {
position: absolute; width: 44px; height: 44px; top: 50%; margin-top: -22px; background-color: var(--color-bg-primary); z-index: 1;
border-radius: 50%; box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.2); background-image: url('~img/arrow/usecase.svg'); background-size: 20px;
transition: $transitionAllCommon; border: 1px solid var(--color-shape-primary);
}
.icon.arrow.hide { opacity: 0; }
.icon.arrow.left { left: 24px; transform: rotateZ(180deg); }
.icon.arrow.right { right: 24px; }
}
.footerWrap { display: flex; flex-direction: row; align-items: flex-start; justify-content: stretch; }
.footerWrap {
.side { max-height: 240px; overflow: auto; }
.side.left { flex-grow: 1; padding-right: 16px; }
.side.right { flex-shrink: 0; width: 220px; padding-left: 16px; }
.side.right {
.tags {
.tagItem { @include text-small; margin: 0px 8px 8px 0px; background: var(--color-shape-highlight-medium); color: var(--color-text-secondary); }
.page.pageList {
.items { display: grid; gap: 32px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.item {
.picture {
aspect-ratio: 16/9; background-size: cover; background-repeat: no-repeat; background-position: center; border-radius: 8px;
margin: 0px 0px 12px 0px;
}
.name { @include text-paragraph; @include clamp1; margin: 0px 0px 4px 0px; font-weight: 600; }
.descr { @include text-small; @include clamp2; }
}
}
.page.pageItem {
.titleWrap {
margin: 0px 0px 40px 0px; display: flex; flex-direction: row; align-items: center; justify-content: stretch; gap: 0px 16px;
}
.titleWrap {
.side.left { flex-grow: 1; display: flex; flex-direction: column; gap: 8px 0px; }
.side.right { flex-shrink: 0; }
.title { @include text-header1; }
.label { @include text-small; color: var(--color-text-secondary); }
}
.screenWrap {
height: 480px; background: var(--color-shape-highlight-light); margin: 0px -56px 20px -56px; padding: 20px 56px; overflow: hidden;
position: relative;
}
.screenWrap {
.swiper { height: 100%; overflow: visible; }
.swiper-slide { display: flex; align-items: center; justify-content: center; }
.screen {
width: 100%; box-shadow: 0px 2px 28px 0px rgba(0, 0, 0, 0.20); background-size: contain;
background-position: center; background-repeat: no-repeat; border-radius: 6px; background-color: var(--color-bg-primary);
}
.icon.arrow {
position: absolute; width: 44px; height: 44px; top: 50%; margin-top: -22px; background-color: var(--color-bg-primary); z-index: 1;
border-radius: 50%; box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.2); background-image: url('~img/arrow/usecase.svg'); background-size: 20px;
transition: $transitionAllCommon; border: 1px solid var(--color-shape-primary);
}
.icon.arrow.hide { opacity: 0; }
.icon.arrow.left { left: 24px; transform: rotateZ(180deg); }
.icon.arrow.right { right: 24px; }
}
.footerWrap { display: flex; flex-direction: row; align-items: flex-start; justify-content: stretch; }
.footerWrap {
.side { max-height: 240px; overflow: auto; }
.side.left { flex-grow: 1; padding-right: 16px; }
.side.right { flex-shrink: 0; width: 220px; padding-left: 16px; }
.side.right {
.tags {
.tagItem { @include text-small; margin: 0px 8px 8px 0px; background: var(--color-shape-highlight-medium); color: var(--color-text-secondary); }
}
.label { @include text-small; color: var(--color-text-secondary); margin: 0px 0px 8px 0px; }
.label:last-child { margin: 0px; }
}
.label { @include text-small; color: var(--color-text-secondary); margin: 0px 0px 8px 0px; }
.label:last-child { margin: 0px; }
}
}

View file

@ -112,8 +112,10 @@
/* PopupUsecase */
.popup.popupUsecase {
.screenWrap {
.icon.arrow { background-color: var(--color-bg-secondary); background-image: url('#{$themePath}/arrow/usecase.svg'); }
.page.pageItem {
.screenWrap {
.icon.arrow { background-color: var(--color-bg-secondary); background-image: url('#{$themePath}/arrow/usecase.svg'); }
}
}
}

View file

@ -55,6 +55,7 @@ interface State {
declare global {
interface Window {
isExtension: boolean;
$: any;
Electron: any;
Anytype: any;

View file

@ -595,27 +595,83 @@ const BlockFeatured = observer(class BlockFeatured extends React.Component<Props
return;
};
const { isPopup, rootId, readonly } = this.props;
const { isPopup, rootId, block, readonly } = this.props;
const storeId = this.getStoreId();
const object = detailStore.get(rootId, storeId, [ relationKey ]);
const relation = dbStore.getRelationByKey(relationKey);
if (readonly || relation.isReadonlyValue) {
return;
};
let menuId: string = '';
let menuParam: any = {};
let menuData: any = {};
switch (relation.format) {
case I.RelationType.Object: {
this.onCellObject(e, relationKey);
menuId = 'dataviewObjectValues';
menuParam.subIds = [ 'dataviewObjectList' ];
menuData = {
value: Relation.getArrayValue(object[relationKey]),
filters: []
};
break;
};
case I.RelationType.Date: {
this.onCellDate(e, relationKey);
let value = null;
let isEmpty = false;
if (object[relationKey]) {
value = Number(object[relationKey]);
} else {
value = Number(UtilDate.now());
isEmpty = true;
};
menuId = 'dataviewCalendar';
menuData = {
value,
isEmpty
};
break;
};
case I.RelationType.Select:
case I.RelationType.MultiSelect: {
this.onCellSelect(e, relationKey);
menuId = 'dataviewOptionList';
menuData = {
value: Relation.getArrayValue(object[relationKey]),
canAdd: true,
maxCount: relation.maxCount,
};
break;
};
case I.RelationType.File: {
menuId = 'dataviewFileValues';
menuParam = {
width: 280,
subIds: [ 'dataviewFileList' ],
};
menuData = {
value: object[relationKey] || [],
subId: rootId,
};
break;
};
case I.RelationType.Number:
case I.RelationType.LongText: {
menuId = 'dataviewText';
menuParam.width = 288;
menuData.value = object[relationKey] || '';
break;
};
@ -659,6 +715,56 @@ const BlockFeatured = observer(class BlockFeatured extends React.Component<Props
break;
};
};
if (menuId) {
this.onCellMenu(relationKey, menuId, menuParam, menuData);
};
};
onCellMenu (relationKey: string, menuId: string, param: any, data: any) {
const { rootId, block } = this.props;
const storeId = this.getStoreId();
const object = detailStore.get(rootId, storeId, [ relationKey ]);
const relation = dbStore.getRelationByKey(relationKey);
const elementId = Relation.cellId(PREFIX + block.id, relationKey, object.id);
if (!relation) {
return;
};
let menuParam = {
element: `#${elementId}`,
className: 'fromFeatured',
horizontal: I.MenuDirection.Left,
offsetY: 4,
noFlipX: true,
title: relation.name,
onClose: () => {
menuStore.closeAll();
},
data: {
rootId,
blockId: block.id,
relation: observable.box(relation),
onChange: (v: any, callBack?: () => void) => {
const details = [
{ key: relationKey, value: Relation.formatValue(relation, v, true) },
];
C.ObjectSetDetails(rootId, details);
if (callBack) {
callBack();
};
}
}
};
menuParam = Object.assign(menuParam, param);
menuParam.data = Object.assign(menuParam.data, data);
menuStore.closeAll(Constant.menuIds.cell, () => {
menuStore.open(menuId, menuParam);
});
};
onLinks (e: React.MouseEvent, relationKey: string) {
@ -700,122 +806,6 @@ const BlockFeatured = observer(class BlockFeatured extends React.Component<Props
});
};
onCellObject (e: React.MouseEvent, relationKey: string) {
const { rootId, block } = this.props;
const storeId = this.getStoreId();
const object = detailStore.get(rootId, storeId, [ relationKey ]);
const relation = dbStore.getRelationByKey(relationKey);
const value = Relation.getArrayValue(object[relationKey]);
const elementId = Relation.cellId(PREFIX + block.id, relationKey, object.id);
const filters = [];
menuStore.closeAll(Constant.menuIds.cell, () => {
menuStore.open('dataviewObjectValues', {
element: `#${elementId}`,
horizontal: I.MenuDirection.Left,
offsetY: 4,
noFlipX: true,
title: relation.name,
subIds: [ 'dataviewObjectList' ],
onClose: () => {
menuStore.closeAll();
},
data: {
rootId,
value,
filters,
types: relation.objectTypes,
relation: observable.box(relation),
onChange: (v: any, callBack?: () => void) => {
const details = [
{ key: relationKey, value: Relation.formatValue(relation, v, true) },
];
C.ObjectSetDetails(rootId, details);
if (callBack) {
callBack();
};
}
}
});
});
};
onCellDate (e: React.MouseEvent, relationKey: string) {
const { rootId, block } = this.props;
const storeId = this.getStoreId();
const object = detailStore.get(rootId, storeId, [ relationKey ]);
const relation = dbStore.getRelationByKey(relationKey);
const elementId = Relation.cellId(PREFIX + block.id, relationKey, object.id);
let value = null;
let isEmpty = false;
if (object[relationKey]) {
value = Number(object[relationKey]);
} else {
value = Number(UtilDate.now());
isEmpty = true;
};
menuStore.closeAll(Constant.menuIds.cell, () => {
menuStore.open('dataviewCalendar', {
element: `#${elementId}`,
horizontal: I.MenuDirection.Left,
offsetY: 4,
noFlipX: true,
title: relation.name,
data: {
value,
isEmpty,
onChange: (v: number) => {
const details = [
{ key: relationKey, value: Relation.formatValue(relation, v, true) },
];
C.ObjectSetDetails(rootId, details);
}
}
});
});
};
onCellSelect (e: React.MouseEvent, relationKey: string) {
const { rootId, block } = this.props;
const storeId = this.getStoreId();
const object = detailStore.get(rootId, storeId, [ relationKey ]);
const relation = dbStore.getRelationByKey(relationKey);
const value = Relation.getArrayValue(object[relationKey]);
const elementId = Relation.cellId(PREFIX + block.id, relationKey, object.id);
menuStore.closeAll(Constant.menuIds.cell, () => {
menuStore.open('dataviewOptionList', {
element: `#${elementId}`,
className: 'featuredRelation',
horizontal: I.MenuDirection.Left,
noFlipY: true,
offsetY: 4,
title: relation.name,
onClose: () => {
menuStore.closeAll();
},
data: {
rootId: rootId,
blockId: block.id,
value,
relation: observable.box(relation),
maxCount: relation.maxCount,
canAdd: true,
onChange: (v) => {
const details = [
{ key: relationKey, value: Relation.formatValue(relation, v, true) },
];
C.ObjectSetDetails(rootId, details);
}
},
});
});
};
elementMapper (relation: any, item: any) {
item = UtilCommon.objectCopy(item);

View file

@ -170,7 +170,7 @@ const DragProvider = observer(class DragProvider extends React.Component<Props>
// String items drop
if (items && items.length) {
UtilCommon.getDataTransferString(items, (html: string) => {
C.BlockPaste(rootId, targetId, { from: 0, to: 0 }, [], false, { html });
C.BlockPaste(rootId, targetId, { from: 0, to: 0 }, [], false, { html }, '');
});
this.clearState();

View file

@ -1691,7 +1691,7 @@ const EditorPage = observer(class EditorPage extends React.Component<Props, Stat
let from = 0;
let to = 0;
C.BlockPaste(rootId, focused, range, selection.get(I.SelectType.Block, true), data.anytype.range.to > 0, { ...data, anytype: data.anytype.blocks }, (message: any) => {
C.BlockPaste(rootId, focused, range, selection.get(I.SelectType.Block, true), data.anytype.range.to > 0, { ...data, anytype: data.anytype.blocks }, '', (message: any) => {
if (message.error.code) {
return;
};

View file

@ -165,8 +165,10 @@ class Input extends React.Component<Props, State> {
};
this.isFocused = true;
keyboard.setFocus(true);
this.addClass('isFocused');
keyboard.setFocus(true);
keyboard.disableSelection(true);
};
onBlur (e: any) {
@ -175,8 +177,10 @@ class Input extends React.Component<Props, State> {
};
this.isFocused = false;
keyboard.setFocus(false);
this.removeClass('isFocused');
keyboard.setFocus(false);
keyboard.disableSelection(false);
};
onPaste (e: any) {

View file

@ -3,7 +3,7 @@ import $ from 'jquery';
import { observer } from 'mobx-react';
import { AutoSizer, CellMeasurer, InfiniteLoader, List, CellMeasurerCache } from 'react-virtualized';
import { Filter, MenuItemVertical, Icon, Loader } from 'Component';
import { I, UtilCommon, Relation, keyboard, UtilData, UtilObject, UtilFile, translate } from 'Lib';
import { I, UtilCommon, Relation, keyboard, UtilData, UtilObject, UtilFile, translate, Action, C } from 'Lib';
import { commonStore, menuStore, dbStore } from 'Store';
import Constant from 'json/constant.json';
@ -12,6 +12,7 @@ interface State {
};
const HEIGHT = 28;
const HEIGHT_DIV = 16;
const MENU_ID = 'dataviewFileValues';
const LIMIT_HEIGHT = 20;
@ -36,6 +37,8 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
this.loadMoreRows = this.loadMoreRows.bind(this);
this.onClick = this.onClick.bind(this);
this.onUpload = this.onUpload.bind(this);
this.onChange = this.onChange.bind(this);
this.onFilterChange = this.onFilterChange.bind(this);
this.onScroll = this.onScroll.bind(this);
};
@ -49,6 +52,7 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
const rowRenderer = (param: any) => {
const item: any = items[param.index];
if (!item) {
return null;
};
@ -56,10 +60,17 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
const type = dbStore.getTypeById(item.type);
let content = null;
if (item.id == 'add') {
if (item.isDiv) {
content = (
<div id="item-add" className="item add" onMouseEnter={e => this.onOver(e, item)} onClick={e => this.onClick(e, item)} style={param.style}>
<Icon className="plus" />
<div className="separator" style={param.style}>
<div className="inner" />
</div>
);
} else
if (item.id == 'upload') {
content = (
<div id="item-upload" className="item upload" onMouseEnter={e => this.onOver(e, item)} onClick={this.onUpload} style={param.style}>
<Icon className="upload" />
<div className="name">{item.name}</div>
</div>
);
@ -118,7 +129,7 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
height={height}
deferredMeasurmentCache={this.cache}
rowCount={items.length}
rowHeight={HEIGHT}
rowHeight={({ index }) => this.getRowHeight(items[index])}
rowRenderer={rowRenderer}
onRowsRendered={onRowsRendered}
overscanRowCount={LIMIT_HEIGHT}
@ -149,16 +160,14 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
const { filter } = data;
if (filter != this.filter) {
this.n = -1;
this.offset = 0;
this.filter = filter;
this.load(true);
this.reload();
return;
};
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: HEIGHT,
defaultHeight: i => this.getRowHeight(items[i]),
keyMapper: i => (items[i] || {}).id,
});
@ -195,7 +204,20 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
const { data } = param;
const value = Relation.getArrayValue(data.value);
return UtilCommon.objectCopy(this.items).filter(it => it && !it._empty_ && !it.isArchived && !it.isDeleted && !value.includes(it.id));
let items = UtilCommon.objectCopy(this.items).filter(it => it && !it._empty_ && !it.isArchived && !it.isDeleted && !value.includes(it.id));
items = items.concat([
{ isDiv: true },
{ id: 'upload', name: translate('commonUpload') },
]);
return items;
};
reload () {
this.n = -1;
this.offset = 0;
this.load(true);
};
load (clear: boolean, callBack?: (message: any) => void) {
@ -265,9 +287,7 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
};
onClick (e: any, item: any) {
const { param, close, position } = this.props;
const { data } = param;
const { onChange, maxCount } = data;
const { close } = this.props;
e.preventDefault();
e.stopPropagation();
@ -277,8 +297,27 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
return;
};
this.onChange(item.id);
};
onUpload () {
Action.openFile([], paths => {
C.FileUpload(commonStore.space, '', paths[0], I.FileType.None, {}, (message: any) => {
if (!message.error.code) {
this.onChange(message.objectId);
this.reload();
};
});
});
};
onChange (id) {
const { param, position } = this.props;
const { data } = param;
const { onChange, maxCount } = data;
let value = Relation.getArrayValue(data.value);
value.push(item.id);
value.push(id);
value = UtilCommon.arrayUnique(value);
if (maxCount) {
@ -292,11 +331,20 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
});
};
getRowHeight (item: any) {
if (item.isDiv) {
return HEIGHT_DIV;
};
return HEIGHT;
};
resize () {
const { getId, position } = this.props;
const items = this.getItems();
const obj = $(`#${getId()} .content`);
const height = Math.max(HEIGHT * 2, Math.min(360, items.length * HEIGHT + 58));
const offset = 58;
const itemsHeight = items.reduce((res: number, current: any) => { return res + this.getRowHeight(current); }, offset);
const height = Math.max(HEIGHT + offset, Math.min(360, itemsHeight));
obj.css({ height: height });
position();

View file

@ -49,9 +49,10 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
);
const Item = SortableElement((item: any) => {
let content = null;
const cn = [ 'item' ];
let content = null;
switch (item.layout) {
default:
case I.ObjectLayout.File: {
@ -70,7 +71,7 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
return (
<div id={'item-' + item.id} className={cn.join(' ')}>
<Handle />
<div className="clickable" onClick={e => UtilObject.openPopup(item)}>
<div className="clickable" onClick={() => UtilObject.openPopup(item)} onContextMenu={e => this.onMore(e, item)}>
{content}
</div>
<div className="buttons">
@ -95,11 +96,6 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
ref={node => this.node = node}
className="items"
>
<div className="section">
<MenuItemVertical id="add" icon="plus" name={translate('commonAdd')} onClick={this.onAdd} />
<MenuItemVertical id="upload" icon="upload" name={translate('commonUpload')} onClick={this.onUpload} />
</div>
{value.length ? (
<div className="section">
<List
@ -116,6 +112,10 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
/>
</div>
) : ''}
<div className="section">
<MenuItemVertical id="add" icon="plus" name={translate('commonAdd')} onClick={this.onAdd} />
</div>
</div>
);
};
@ -172,6 +172,13 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
onChange: (value: string[], callBack?: () => void) => {
this.save(value);
if (callBack) {
callBack();
};
},
onUpload: (id: string, callBack?: () => void) => {
this.add(id);
if (callBack) {
callBack();
};
@ -217,7 +224,7 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
element.addClass('active');
menuStore.open('select', {
element: element.find('.icon.more'),
element,
horizontal: I.MenuDirection.Center,
classNameWrap: classNameWrap,
onClose: () => {
@ -226,12 +233,18 @@ const MenuDataviewFileValues = observer(class MenuDataviewFileValues extends Rea
data: {
value: '',
options: [
{ id: 'open', icon: 'expand', name: translate('commonOpen') },
{ id: 'download', icon: 'download', name: translate('commonDownload') },
{ isDiv: true },
{ id: 'remove', icon: 'remove', name: translate('commonDelete') },
],
onSelect: (event: any, el: any) => {
switch (el.id) {
case 'open': {
UtilObject.openPopup(item);
break;
};
case 'download': {
let url = '';
switch (item.layout) {

View file

@ -248,7 +248,7 @@ const Menu = observer(class Menu extends React.Component<I.Menu, State> {
};
if (passThrough) {
cd.push('through');
cd.push('passThrough');
};
const Tab = (item: any) => (

View file

@ -596,7 +596,7 @@ class MenuQuickCapture extends React.Component<I.Menu, State> {
const object = message.details;
C.BlockPaste (object.id, '', { from: 0, to: 0 }, [], false, { html, text }, () => {
C.BlockPaste (object.id, '', { from: 0, to: 0 }, [], false, { html, text }, '', () => {
UtilObject.openAuto(object);
});
});

View file

@ -42,7 +42,7 @@ class PageMainImport extends React.Component<I.PageComponent, State> {
componentDidMount (): void {
const search = this.getSearch();
C.DownloadManifest(search.source, (message: any) => {
C.GalleryDownloadManifest(search.source, (message: any) => {
if (message.error.code) {
this.setState({ error: message.error.description });
} else {

View file

@ -0,0 +1,202 @@
import * as React from 'react';
import $ from 'jquery';
import { Title, Label, Button, Tag, Icon, Loader, Error } from 'Component';
import { I, C, UtilCommon, UtilFile, UtilDate, translate, Renderer, analytics } from 'Lib';
import { menuStore, dbStore } from 'Store';
import { Swiper, SwiperSlide } from 'swiper/react';
import Constant from 'json/constant.json';
interface State {
isLoading: boolean;
error: string;
};
class PopupUsecasePageItem extends React.Component<I.PopupUsecase, State> {
node = null;
swiper = null;
refButton = null;
state = {
isLoading: false,
error: '',
};
constructor (props: I.PopupUsecase) {
super(props);
this.onMenu = this.onMenu.bind(this);
this.onAuthor = this.onAuthor.bind(this);
this.onSwiper = this.onSwiper.bind(this);
};
render () {
const { isLoading, error } = this.state;
const object = this.getObject();
const author = this.getAuthor();
const screenshots = object.screenshots || [];
const categories = (object.categories || []).slice(0, 10);
return (
<div ref={ref => this.node = ref}>
{isLoading ? <Loader id="loader" /> : ''}
<div className="titleWrap">
<div className="side left">
<Title text={object.title} />
<Label text={UtilCommon.sprintf(translate('popupUsecaseAuthor'), author)} onClick={this.onAuthor} />
</div>
<div className="side right">
<Button ref={ref => this.refButton = ref} id="button-install" text={translate('popupUsecaseInstall')} arrow={true} onClick={this.onMenu} />
</div>
</div>
<Error text={error} />
<div className="screenWrap">
<Swiper
spaceBetween={20}
slidesPerView={1}
onSlideChange={() => this.checkArrows()}
onSwiper={swiper => this.onSwiper(swiper)}
>
{screenshots.map((url: string, i: number) => (
<SwiperSlide key={i}>
<img className="screen" src={url} />
</SwiperSlide>
))}
</Swiper>
<Icon id="arrowLeft" className="arrow left" onClick={() => this.onArrow(-1)} />
<Icon id="arrowRight" className="arrow right" onClick={() => this.onArrow(1)} />
</div>
<div className="footerWrap">
<div className="side left">
<Label text={object.description} />
</div>
<div className="side right">
<div className="tags">
{categories.map((name: string, i: number) => (
<Tag key={i} text={name} />
))}
</div>
<Label text={UtilCommon.sprintf(translate('popupUsecaseUpdated'), UtilDate.date(UtilDate.dateFormat(I.DateFormat.MonthAbbrBeforeDay), UtilDate.now()))} />
<Label text={UtilFile.size(object.size)} />
</div>
</div>
</div>
);
};
componentDidMount(): void {
const object = this.getObject();
window.setTimeout(() => this.checkArrows(), 10);
analytics.event('ScreenGalleryInstall', { name: object.name });
};
onSwiper (swiper) {
this.swiper = swiper;
};
onArrow (dir: number) {
dir < 0 ? this.swiper.slidePrev() : this.swiper.slideNext();
};
checkArrows () {
const node = $(this.node);
const arrowLeft = node.find('#arrowLeft');
const arrowRight = node.find('#arrowRight');
const idx = this.swiper.activeIndex;
const length = (this.swiper.slides || []).length;
!idx ? arrowLeft.addClass('hide') : arrowLeft.removeClass('hide');
idx >= length - 1 ? arrowRight.addClass('hide') : arrowRight.removeClass('hide');
};
onMenu () {
const { getId, close } = this.props;
const object = this.getObject();
const cb = (spaceId: string, isNew: boolean) => {
C.ObjectImportExperience(spaceId, object.downloadLink, object.title, isNew, (message: any) => {
if (!message.error.code) {
analytics.event('GalleryInstall', { name: object.name });
};
});
close();
};
menuStore.open('select', {
element: `#${getId()} #button-install`,
offsetY: 2,
noFlipX: true,
className: 'spaceSelect',
data: {
options: this.getSpaceOptions(),
noVirtualisation: true,
noScroll: true,
onSelect: (e: any, item: any) => {
const isNew = item.id == 'add';
this.setState({ isLoading: true });
analytics.event('ClickGalleryInstallSpace', { type: isNew ? 'New' : 'Existing' });
if (isNew) {
C.WorkspaceCreate({ name: object.title, iconOption: UtilCommon.rand(1, Constant.iconCnt) }, I.Usecase.None, (message: any) => {
if (!message.error.code) {
cb(message.objectId, true);
} else {
this.setState({ isLoading: false, error: message.error.description });
};
});
} else {
cb(item.targetSpaceId, false);
};
},
}
});
analytics.event('ClickGalleryInstall', { name: object.name });
};
getSpaceOptions (): any[] {
const list: any[] = dbStore.getSpaces().map(it => ({ ...it, iconSize: 48, object: it }));
if (list.length < Constant.limit.space) {
list.unshift({ id: 'add', icon: 'add', name: translate('popupUsecaseSpaceCreate') });
};
list.unshift({ name: translate('popupUsecaseMenuLabel'), isSection: true });
return list;
};
onAuthor () {
const object = this.getObject();
if (object.author) {
Renderer.send('urlOpen', object.author);
};
};
getObject (): any {
const { param } = this.props;
const { data } = param;
return data.object || {};
};
getAuthor (): string {
const object = this.getObject();
if (!object.author) {
return '';
};
let a: any = {};
try { a = new URL(object.author); } catch (e) {};
return String(a.pathname || '').replace(/^\//, '');
};
};
export default PopupUsecasePageItem;

View file

@ -0,0 +1,103 @@
import * as React from 'react';
import { I, C } from 'Lib';
import { AutoSizer, CellMeasurer, CellMeasurerCache, List, WindowScroller } from 'react-virtualized';
const HEIGHT = 450;
class PopupUsecasePageList extends React.Component<I.PopupUsecase> {
node = null;
refList = null;
list: any = [];
categories: any = [];
cache: any = {};
constructor (props: I.PopupUsecase) {
super(props);
};
render () {
const Item = (item: any) => {
const screenshot = item.screenshots.length ? item.screenshots[0] : '';
return (
<div className="item" onClick={e => this.onClick(e, item)}>
<div className="picture" style={{ backgroundImage: `url("${screenshot}")` }}></div>
<div className="name">{item.title}</div>
<div className="descr">{item.description}</div>
</div>
);
};
const rowRenderer = (param: any) => {
const item: any = this.list[param.index];
return (
<CellMeasurer
key={param.key}
parent={param.parent}
cache={this.cache}
columnIndex={0}
rowIndex={param.index}
hasFixedWidth={() => {}}
>
<Item key={item.id} {...item} index={param.index} style={param.style} />
</CellMeasurer>
);
};
return (
<div ref={ref => this.node = ref}>
<div className="items">
{this.list.map((item: any) => (
<Item key={item.id} {...item} />
))}
<WindowScroller scrollElement={$('#popupUsecase-innerWrap').get(0)}>
{({ height, isScrolling, registerChild, scrollTop }) => (
<AutoSizer disableHeight={true} className="scrollArea">
{({ width }) => (
<List
ref={ref => this.refList = ref}
autoHeight={true}
height={Number(height) || 0}
width={Number(width) || 0}
deferredMeasurmentCache={this.cache}
rowCount={length}
rowHeight={HEIGHT}
rowRenderer={rowRenderer}
isScrolling={isScrolling}
scrollTop={scrollTop}
/>
)}
</AutoSizer>
)}
</WindowScroller>
</div>
</div>
);
};
componentDidMount (): void {
C.GalleryDownloadIndex((message: any) => {
this.categories = message.categories;
this.list = message.list;
this.forceUpdate();
});
};
componentDidUpdate (): void {
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: HEIGHT,
keyMapper: i => this.list[i].id,
});
this.props.position();
};
onClick (e: any, item: any) {
this.props.onPage('item', { object: item });
};
};
export default PopupUsecasePageList;

View file

@ -1,202 +1,66 @@
import * as React from 'react';
import $ from 'jquery';
import { Title, Label, Button, Tag, Icon, Loader, Error } from 'Component';
import { I, C, UtilCommon, UtilFile, UtilDate, translate, Renderer, analytics } from 'Lib';
import { menuStore, dbStore } from 'Store';
import { Swiper, SwiperSlide } from 'swiper/react';
import Constant from 'json/constant.json';
import { observer } from 'mobx-react';
import { I, UtilCommon } from 'Lib';
interface State {
isLoading: boolean;
error: string;
import PopupUsecasePageList from './page/usecase/list';
import PopupUsecasePageItem from './page/usecase/item';
const Components: any = {
list: PopupUsecasePageList,
item: PopupUsecasePageItem,
};
class PopupUsecase extends React.Component<I.Popup, State> {
const PopupUsecase = observer(class PopupUsecase extends React.Component<I.PopupUsecase> {
node = null;
swiper = null;
refButton = null;
state = {
isLoading: false,
error: '',
};
ref = null;
constructor (props: I.Popup) {
constructor (props: I.PopupUsecase) {
super(props);
this.onMenu = this.onMenu.bind(this);
this.onAuthor = this.onAuthor.bind(this);
this.onSwiper = this.onSwiper.bind(this);
this.onPage = this.onPage.bind(this);
};
render () {
const { isLoading, error } = this.state;
const object = this.getObject();
const author = this.getAuthor();
const screenshots = object.screenshots || [];
const categories = (object.categories || []).slice(0, 10);
const { param } = this.props;
const { data } = param;
const page = data.page || 'list';
let content = null;
if (Components[page]) {
const Component = Components[page];
content = (
<Component
ref={ref => this.ref = ref}
{...this.props}
onPage={this.onPage}
/>
);
};
return (
<div ref={ref => this.node = ref}>
{isLoading ? <Loader id="loader" /> : ''}
<div className="titleWrap">
<div className="side left">
<Title text={object.title} />
<Label text={UtilCommon.sprintf(translate('popupUsecaseAuthor'), author)} onClick={this.onAuthor} />
</div>
<div className="side right">
<Button ref={ref => this.refButton = ref} id="button-install" text={translate('popupUsecaseInstall')} arrow={true} onClick={this.onMenu} />
</div>
</div>
<Error text={error} />
<div className="screenWrap">
<Swiper
spaceBetween={20}
slidesPerView={1}
onSlideChange={() => this.checkArrows()}
onSwiper={swiper => this.onSwiper(swiper)}
>
{screenshots.map((url: string, i: number) => (
<SwiperSlide key={i}>
<img className="screen" src={url} />
</SwiperSlide>
))}
</Swiper>
<Icon id="arrowLeft" className="arrow left" onClick={() => this.onArrow(-1)} />
<Icon id="arrowRight" className="arrow right" onClick={() => this.onArrow(1)} />
</div>
<div className="footerWrap">
<div className="side left">
<Label text={object.description} />
</div>
<div className="side right">
<div className="tags">
{categories.map((name: string, i: number) => (
<Tag key={i} text={name} />
))}
</div>
<Label text={UtilCommon.sprintf(translate('popupUsecaseUpdated'), UtilDate.date(UtilDate.dateFormat(I.DateFormat.MonthAbbrBeforeDay), UtilDate.now()))} />
<Label text={UtilFile.size(object.size)} />
</div>
</div>
<div
ref={ref => this.node = ref}
className={[ 'page', UtilCommon.toCamelCase(`page-${page}`) ].join(' ')}
>
{content}
</div>
);
};
componentDidMount(): void {
const object = this.getObject();
window.setTimeout(() => this.checkArrows(), 10);
analytics.event('ScreenGalleryInstall', { name: object.name });
};
onSwiper (swiper) {
this.swiper = swiper;
};
onArrow (dir: number) {
dir < 0 ? this.swiper.slidePrev() : this.swiper.slideNext();
};
checkArrows () {
const node = $(this.node);
const arrowLeft = node.find('#arrowLeft');
const arrowRight = node.find('#arrowRight');
const idx = this.swiper.activeIndex;
const length = (this.swiper.slides || []).length;
!idx ? arrowLeft.addClass('hide') : arrowLeft.removeClass('hide');
idx >= length - 1 ? arrowRight.addClass('hide') : arrowRight.removeClass('hide');
};
onMenu () {
const { getId, close } = this.props;
const object = this.getObject();
const cb = (spaceId: string, isNew: boolean) => {
C.ObjectImportExperience(spaceId, object.downloadLink, object.title, isNew, (message: any) => {
if (!message.error.code) {
analytics.event('GalleryInstall', { name: object.name });
};
});
close();
};
menuStore.open('select', {
element: `#${getId()} #button-install`,
offsetY: 2,
noFlipX: true,
className: 'spaceSelect',
data: {
options: this.getSpaceOptions(),
noVirtualisation: true,
noScroll: true,
onSelect: (e: any, item: any) => {
const isNew = item.id == 'add';
this.setState({ isLoading: true });
analytics.event('ClickGalleryInstallSpace', { type: isNew ? 'New' : 'Existing' });
if (isNew) {
C.WorkspaceCreate({ name: object.title, iconOption: UtilCommon.rand(1, Constant.iconCnt) }, I.Usecase.None, (message: any) => {
if (!message.error.code) {
cb(message.objectId, true);
} else {
this.setState({ isLoading: false, error: message.error.description });
};
});
} else {
cb(item.targetSpaceId, false);
};
},
}
});
analytics.event('ClickGalleryInstall', { name: object.name });
};
getSpaceOptions (): any[] {
const list: any[] = dbStore.getSpaces().map(it => ({ ...it, iconSize: 48, object: it }));
if (list.length < Constant.limit.space) {
list.unshift({ id: 'add', icon: 'add', name: translate('popupUsecaseSpaceCreate') });
};
list.unshift({ name: translate('popupUsecaseMenuLabel'), isSection: true });
return list;
};
onAuthor () {
const object = this.getObject();
if (object.author) {
Renderer.send('urlOpen', object.author);
};
};
getObject (): any {
const { param } = this.props;
const { data } = param;
const { page } = data;
return data.object || {};
this.onPage(page || 'list');
};
getAuthor (): string {
const object = this.getObject();
if (!object.author) {
return '';
};
let a: any = {};
try { a = new URL(object.author); } catch (e) {};
return String(a.pathname || '').replace(/^\//, '');
onPage (page: string, data?: any): void {
data = data || {};
this.props.param.data = Object.assign(this.props.param.data, { ...data, page });
};
};
});
export default PopupUsecase;

View file

@ -137,7 +137,6 @@ const SelectionProvider = observer(class SelectionProvider extends React.Compone
this.setIsSelecting(true);
keyboard.disablePreview(true);
UtilCommon.clearSelection();
if (isPopup && container.length) {
this.containerOffset = container.offset();
@ -199,6 +198,7 @@ const SelectionProvider = observer(class SelectionProvider extends React.Compone
};
const isPopup = keyboard.isPopup();
this.top = UtilCommon.getScrollContainer(isPopup).scrollTop();
this.checkNodes(e);
this.drawRect(e.pageX, e.pageY);

View file

@ -35,7 +35,7 @@ import {
} from './common';
import { ThreadStatus, ThreadSummary, ThreadDevice, ThreadAccount, ThreadCafe, FilesStatus } from './thread';
import { Progress, ProgressType, ProgressState } from './progress';
import { PopupParam, Popup, PopupSettings } from './popup';
import { PopupParam, Popup, PopupSettings, PopupUsecase } from './popup';
import { Preview, PreviewLink, PreviewType, PreviewSize } from './preview';
import { MenuTab, MenuType, MenuDirection, MenuParam, Menu, MenuItem } from './menu';
import { ObjectLayout, ObjectFlag, RelationType, RelationScope, ObjectOrigin } from './object';
@ -134,6 +134,7 @@ export {
PopupParam,
Popup,
PopupSettings,
PopupUsecase,
Preview,
PreviewLink,

View file

@ -27,3 +27,7 @@ export interface PopupSettings extends Popup {
onExport: (format: I.ExportType, param: any) => void;
onSpaceTypeTooltip: (e: any) => void;
};
export interface PopupUsecase extends Popup {
onPage(page: string, data: any): void;
};

View file

@ -31,12 +31,20 @@ export const LinkPreview = (url: string, callBack?: (message: any) => void) => {
dispatcher.request(LinkPreview.name, request, callBack);
};
export const DownloadManifest = (url: string, callBack?: (message: any) => void) => {
const request = new Rpc.DownloadManifest.Request();
// ---------------------- GALLERY ---------------------- //
export const GalleryDownloadIndex = (callBack?: (message: any) => void) => {
const request = new Commands.Empty();
dispatcher.request(GalleryDownloadIndex.name, request, callBack);
};
export const GalleryDownloadManifest = (url: string, callBack?: (message: any) => void) => {
const request = new Rpc.Gallery.DownloadManifest.Request();
request.setUrl(url);
dispatcher.request(DownloadManifest.name, request, callBack);
dispatcher.request(GalleryDownloadManifest.name, request, callBack);
};
// ---------------------- APP ---------------------- //
@ -379,10 +387,11 @@ export const BlockWidgetSetViewId = (contextId: string, blockId: string, viewId:
dispatcher.request(BlockWidgetSetViewId.name, request, callBack);
};
export const BlockPreview = (html: string, callBack?: (message: any) => void) => {
export const BlockPreview = (html: string, url: string, callBack?: (message: any) => void) => {
const request = new Rpc.Block.Preview.Request();
request.setHtml(html);
request.setUrl(url);
dispatcher.request(BlockPreview.name, request, callBack);
};
@ -517,7 +526,7 @@ export const BlockCut = (contextId: string, blocks: I.Block[], range: I.TextRang
dispatcher.request(BlockCut.name, request, callBack);
};
export const BlockPaste = (contextId: string, focusedId: string, range: I.TextRange, blockIds: string[], isPartOfBlock: boolean, data: any, callBack?: (message: any) => void) => {
export const BlockPaste = (contextId: string, focusedId: string, range: I.TextRange, blockIds: string[], isPartOfBlock: boolean, data: any, url: string, callBack?: (message: any) => void) => {
data = UtilCommon.objectCopy(data);
const request = new Rpc.Block.Paste.Request();
@ -531,6 +540,7 @@ export const BlockPaste = (contextId: string, focusedId: string, range: I.TextRa
request.setHtmlslot(data.html);
request.setAnyslotList((data.anytype || []).map(Mapper.To.Block));
request.setFileslotList((data.files || []).map(Mapper.To.PasteFile));
request.setUrl(url);
dispatcher.request(BlockPaste.name, request, callBack);
};

View file

@ -67,9 +67,12 @@ class Dispatcher {
this.stream.on('end', () => {
console.error('[Dispatcher.stream] end, restarting');
let t = 1000;
let t = 3;
if (this.reconnects == 20) {
t = 5000;
t = 5;
};
if (this.reconnects == 40) {
t = 60;
this.reconnects = 0;
};
@ -77,7 +80,7 @@ class Dispatcher {
this.timeoutStream = window.setTimeout(() => {
this.listenEvents();
this.reconnects++;
}, t);
}, t * 1000);
});
};

View file

@ -538,6 +538,22 @@ export const Mapper = {
};
},
Manifest: (obj: Model.ManifestInfo) => {
return {
id: obj.getId(),
schema: obj.getSchema(),
name: obj.getName(),
author: obj.getAuthor(),
license: obj.getLicense(),
title: obj.getTitle(),
description: obj.getDescription(),
downloadLink: obj.getDownloadlink(),
size: obj.getFilesize(),
screenshots: obj.getScreenshotsList() || [],
categories: obj.getCategoriesList() || [],
};
},
},
//------------------------------------------------------------

View file

@ -423,23 +423,21 @@ export const UnsplashDownload = (response: Rpc.Unsplash.Download.Response) => {
};
};
export const DownloadManifest = (response: Rpc.DownloadManifest.Response) => {
const info = response.getInfo();
export const GalleryDownloadIndex = (response: Rpc.Gallery.DownloadIndex.Response) => {
return {
info: {
id: info.getId(),
schema: info.getSchema(),
name: info.getName(),
author: info.getAuthor(),
license: info.getLicense(),
title: info.getTitle(),
description: info.getDescription(),
downloadLink: info.getDownloadlink(),
size: info.getFilesize(),
screenshots: info.getScreenshotsList() || [],
categories: info.getCategoriesList() || [],
},
categories: (response.getCategoriesList() || []).map((it: Rpc.Gallery.DownloadIndex.Response.Category) => {
return {
name: it.getName(),
list: it.getExperiencesList() || [],
};
}),
list: (response.getExperiencesList() || []).map(Mapper.From.Manifest),
};
};
export const GalleryDownloadManifest = (response: Rpc.Gallery.DownloadManifest.Response) => {
return {
info: Mapper.From.Manifest(response.getInfo()),
};
};

View file

@ -427,10 +427,6 @@ class Keyboard {
if ((route.page == 'main') && !account) {
return false;
};
if ((route.page == 'main') && (route.action == 'usecase')) {
return false;
};
};
};

View file

@ -6,6 +6,7 @@ class ExtensionStore {
public challengeId = '';
public serverPort = '';
public gatewayPort = '';
public tabUrlValue = '';
public htmlValue = '';
constructor() {
@ -19,10 +20,18 @@ class ExtensionStore {
return String(this.htmlValue || '');
};
get tabUrl (): string {
return String(this.tabUrlValue || '');
};
setHtml (v: string) {
this.htmlValue = String(v || '');
};
setTabUrl (v: string) {
this.tabUrlValue = String(v || '');
};
};
export const extensionStore: ExtensionStore = new ExtensionStore();

View file

@ -50,6 +50,14 @@ class PopupStore {
param.data = param.data || {};
// Auto-confirm in extension
if (window.isExtension && (id == 'confirm')) {
if (param.data.onConfirm) {
param.data.onConfirm();
};
return;
};
if (!param.preventMenuClose) {
menuStore.closeAll();
};