add AutoCompletePopup.ts base class

Signed-off-by: Bayram Çiçek <bayram.cicek@collabora.com>
Change-Id: I60e69fcc7eda3c76cf6e3309cdbc6ab777a90292
pull/9012/head
Bayram Çiçek 2024-05-07 17:10:29 +03:00 committed by Szymon Kłos
parent 81722df0ab
commit e92d048926
5 changed files with 145 additions and 90 deletions

View File

@ -382,6 +382,7 @@ COOL_JS_LST =\
src/control/Control.NotebookbarBuilder.js \
src/control/Control.Layers.js \
src/control/Control.Sidebar.js \
src/control/AutoCompletePopup.ts \
src/control/Control.Mention.ts \
src/control/Control.Zotero.js \
src/control/Search.js \

View File

@ -0,0 +1,130 @@
/* -*- js-indent-level: 8 -*- */
/*
* Copyright the Collabora Online contributors.
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* AutoCompletePopup - base class for mention, auto complete and auto fill popup
*/
/* global app */
interface WidgetJSON {
id: string; // unique id of a widget
type: string; // type of widget
enabled: boolean | undefined; // enabled state
visible: boolean | undefined; // visibility state
children: Array<WidgetJSON> | undefined; // child nodes
}
interface JSDialogJSON extends WidgetJSON {
id: string; // unique windowId
jsontype: string; // specifies target componenet, on root level only
action: string | undefined; // optional name of an action
control?: WidgetJSON;
}
interface PopupData extends JSDialogJSON {
isAutoCompletePopup?: boolean;
cancellable?: boolean;
popupParent?: string;
clickToClose?: string;
posx: number;
posy: number;
}
interface Entry {
text: string;
columns: { text: any }[];
row: string;
}
interface MentionWidget extends WidgetJSON {
text: string;
singleclickactivate: boolean;
fireKeyEvents: boolean;
entries: Array<Entry>;
}
interface Point {
x: number;
y: number;
}
interface FireEvent {
data?: any;
}
interface CloseMessageEvent extends FireEvent {
typingMention?: boolean;
}
abstract class AutoCompletePopup {
protected map: ReturnType<typeof L.map>;
protected newPopupData: PopupData;
protected data: MessageEvent<any>;
constructor(map: ReturnType<typeof L.map>) {
this.map = map;
}
onAdd(id: string, bAutoComplete: boolean): void {
this.newPopupData = {
children: [
{
id: 'container',
type: 'container',
enabled: true,
children: new Array<WidgetJSON>(),
vertical: true,
} as any as WidgetJSON,
] as Array<WidgetJSON>,
jsontype: 'dialog',
type: 'modalpopup',
isAutoCompletePopup: bAutoComplete,
cancellable: true,
popupParent: '_POPOVER_',
clickToClose: '_POPOVER_',
id: id,
} as PopupData;
}
getCurrentCursorPosition(): Point {
var currPos = {
x: app.file.textCursor.rectangle.cX1,
y: app.file.textCursor.rectangle.cY2,
};
var origin = this.map.getPixelOrigin();
var panePos = this.map._getMapPanePos();
return new L.Point(
Math.round(currPos.x + panePos.x - origin.x),
Math.round(currPos.y + panePos.y - origin.y),
);
}
closePopup(id: string): void {
var closePopupData = {
jsontype: 'dialog',
type: 'modalpopup',
action: 'close',
id: id,
} as PopupData;
this.map.fire('jsdialog', { data: closePopupData, callback: undefined });
}
abstract sendMentionText(ev: FireEvent): void;
abstract openMentionPopup(ev: FireEvent): void;
abstract callback(
objectType: any,
eventType: any,
object: any,
index: number,
): void;
}
L.Control.AutoCompletePopup = AutoCompletePopup;

View File

@ -635,7 +635,7 @@ L.Control.JSDialog = L.Control.extend({
instance.startX = e.data.posx;
instance.startY = e.data.posy;
instance.updatePos = null;
instance.canHaveFocus = !instance.isSnackbar && instance.id !== 'busypopup' && !instance.isMention;
instance.canHaveFocus = !instance.isSnackbar && instance.id !== 'busypopup' && !instance.isAutoCompletePopup;
instance.isDocumentAreaPopup = instance.popupParent === '_POPOVER_' && instance.posx !== undefined && instance.posy !== undefined;
instance.isPopup = instance.isModalPopUp || instance.isDocumentAreaPopup || instance.isSnackbar;
instance.containerParent = instance.isDocumentAreaPopup ? document.getElementById('document-container'): document.body;

View File

@ -14,52 +14,7 @@
/* global app */
// TODO: duplicate from MessageRouter
interface WidgetJSON {
id: string; // unique id of a widget
type: string; // type of widget
enabled: boolean | undefined; // enabled state
visible: boolean | undefined; // visibility state
children: Array<WidgetJSON> | undefined; // child nodes
}
interface JSDialogJSON extends WidgetJSON {
id: string; // unique windowId
jsontype: string; // specifies target componenet, on root level only
action: string | undefined; // optional name of an action
control?: WidgetJSON;
}
interface PopupData extends JSDialogJSON {
isMention?: boolean;
cancellable?: boolean;
popupParent?: string;
clickToClose?: string;
posx: number;
posy: number;
}
interface Entry {
text: string;
columns: { text: any }[];
row: string;
}
interface MentionWidget extends WidgetJSON {
text: string;
singleclickactivate: boolean;
fireKeyEvents: boolean;
entries: Array<Entry>;
}
interface FireEvent {
data?: any
}
interface CloseMessageEvent extends FireEvent {
typingMention?: boolean;
}
class Mention {
class Mention extends L.Control.AutoCompletePopup {
map: ReturnType<typeof L.map>;
newPopupData: PopupData;
firstChar: string;
@ -67,29 +22,17 @@ class Mention {
itemList: Array<any>;
data: MessageEvent<any>;
constructor(map: ReturnType<typeof L.map>) {
super(map);
this.onAdd(map);
}
onAdd(map: ReturnType<typeof L.map>) {
this.map = map;
this.map.on('openmentionpopup', this.openMentionPopup, this);
this.map.on('closementionpopup', this.closeMentionPopup, this);
this.map.on('closementionpopup', this.closePopup, this);
this.map.on('sendmentiontext', this.sendMentionText, this);
this.newPopupData = {
children: [
{
id: 'container',
type: 'container',
enabled: true,
children: new Array<WidgetJSON>(),
vertical: true,
} as any as WidgetJSON
] as Array<WidgetJSON>,
jsontype: 'dialog',
type: 'modalpopup',
isMention: true,
cancellable: true,
popupParent: '_POPOVER_',
clickToClose: '_POPOVER_',
id: 'mentionPopup',
} as PopupData;
super.onAdd('mentionPopup', true);
this.firstChar = null;
this.users = null;
this.itemList = null;
@ -108,19 +51,6 @@ class Mention {
}
}
getCurrentCursorPosition() {
var currPos = {
x: app.file.textCursor.rectangle.cX1,
y: app.file.textCursor.rectangle.cY2,
};
var origin = this.map.getPixelOrigin();
var panePos = this.map._getMapPanePos();
return new L.Point(
Math.round(currPos.x + panePos.x - origin.x),
Math.round(currPos.y + panePos.y - origin.y),
);
}
openMentionPopup(ev: FireEvent) {
var framePos = this.getCurrentCursorPosition();
this.users = ev.data;
@ -223,14 +153,8 @@ class Mention {
});
}
closeMentionPopup(ev: CloseMessageEvent) {
var closePopupData = {
jsontype: 'dialog',
type: 'modalpopup',
action: 'close',
id: 'mentionPopup',
} as PopupData;
this.map.fire('jsdialog', { data: closePopupData, callback: undefined });
closePopup(ev: CloseMessageEvent) {
super.closePopup('mentionPopup');
if (!ev.typingMention) {
this.map._docLayer._typingMention = false;
this.map._docLayer._mentionText = [];
@ -270,6 +194,6 @@ class Mention {
return false;
}
}
L.control.mention = function () {
return new Mention();
L.control.mention = function (map: any) {
return new Mention(map);
};

View File

@ -210,7 +210,7 @@ L.Control.UIManager = L.Control.extend({
this.map.sidebar = L.control.sidebar({animSpeed: 200});
this.map.addControl(this.map.sidebar);
this.map.addControl(L.control.mention());
this.map.mention = L.control.mention(this.map);
}
this.map.jsdialog = L.control.jsDialog();