diff --git a/locales.js b/locales.js
index 20e6d11..4db2020 100644
--- a/locales.js
+++ b/locales.js
@@ -7,6 +7,12 @@ export const en_EN = {
LBL_SHOW_HIDE: 'Show/Hide',
LBL_OPEN_FILE: 'Open File',
LBL_QUIT: 'Quit',
+
+ LBL_SHARING_MODAL_TITLE: 'Share',
+ LBL_SHARING_MODAL_EMAIL_INPUT_LABEL: 'Enter the email(s) of the individuals you want to share the text with (separate each email with ,)',
+ LBL_SHARING_MODAL_SUBMIT_ACTION: 'Share',
+ LBL_SHARING_MODAL_CANCEL_ACTION: 'Cancel',
+ LBL_SHARING_BUTTON: 'Share',
};
export const fa_FA = {
@@ -18,4 +24,10 @@ export const fa_FA = {
LBL_SHOW_HIDE: 'نمایش/ پنهان',
LBL_OPEN_FILE: 'باز کردن فایل',
LBL_QUIT: 'خروج',
+
+ LBL_SHARING_MODAL_TITLE: 'اشتراک گذاری',
+ LBL_SHARING_MODAL_EMAIL_INPUT_LABEL: 'ایمیل/ایمیلهایی که میخواهید متن با آنان به اشتراک گذاشته شود را وارد کنید. (برای جدا سازی چندین ایمیل از , استفاده کنید.)',
+ LBL_SHARING_MODAL_SUBMIT_ACTION: 'اشتراک گذاری',
+ LBL_SHARING_MODAL_CANCEL_ACTION: 'انصراف',
+ LBL_SHARING_BUTTON: 'اشتراک گذاری',
};
diff --git a/src/components/loaderForm/index.js b/src/components/main/Collabora/Iframe/LoaderForm.js
similarity index 98%
rename from src/components/loaderForm/index.js
rename to src/components/main/Collabora/Iframe/LoaderForm.js
index 289812a..7e1eb59 100644
--- a/src/components/loaderForm/index.js
+++ b/src/components/main/Collabora/Iframe/LoaderForm.js
@@ -5,7 +5,7 @@ export default function LoaderForm(props) {
useEffect(() => {
formElem.current.submit();
- });
+ }, []);
return (
diff --git a/src/components/main/Collabora/Iframe/index.js b/src/components/main/Collabora/Iframe/index.js
new file mode 100644
index 0000000..0e439de
--- /dev/null
+++ b/src/components/main/Collabora/Iframe/index.js
@@ -0,0 +1,24 @@
+import React, {forwardRef, useEffect} from 'react';
+import collaboraIframeHandler from '../shared/collaboraIframeHandler';
+import LoaderForm from './LoaderForm';
+
+// eslint-disable-next-line react/display-name
+export default forwardRef(({wopiUrl, accessToken}, ref) => {
+ useEffect(() => {
+ collaboraIframeHandler.initialize(ref.current);
+ }, []);
+
+ return (
+
+ );
+});
diff --git a/src/components/main/Collabora/ShareAccessManager/Modal/index.js b/src/components/main/Collabora/ShareAccessManager/Modal/index.js
new file mode 100644
index 0000000..4c26ed1
--- /dev/null
+++ b/src/components/main/Collabora/ShareAccessManager/Modal/index.js
@@ -0,0 +1,45 @@
+import React, {useState} from 'react';
+import useCore from '../../../../../hooks/core';
+
+import './style.scss';
+
+export default function Modal({onSubmit, onCancel}) {
+ const {_} = useCore();
+
+ function handleOnSubmit(e) {
+ e.preventDefault();
+
+ onSubmit(emails);
+ }
+
+ const [emails, setEmails] = useState('');
+
+ return (
+
+
+
+
+ {_('LBL_SHARING_MODAL_TITLE')}
+
+
+
+
+
+ );
+}
diff --git a/src/components/main/Collabora/ShareAccessManager/Modal/style.scss b/src/components/main/Collabora/ShareAccessManager/Modal/style.scss
new file mode 100644
index 0000000..27cfcf8
--- /dev/null
+++ b/src/components/main/Collabora/ShareAccessManager/Modal/style.scss
@@ -0,0 +1,75 @@
+@import '../../../../../styles/variables';
+
+.ShareAccessManagerModal {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+
+ background-color: rgba(0,0,0,0.5);
+
+ &__content {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ margin: auto;
+ width: 100%;
+ max-width: 400px;
+ background-color: white;
+
+ padding: 10px;
+ box-sizing: border-box;
+ }
+
+ &__header {
+ text-align: center;
+
+ margin-bottom: 15px;
+ }
+
+ &__form-field {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+
+ &-input {
+ padding: 5px;
+ }
+ }
+
+ &__form-actions {
+ display: flex;
+ gap: 10px;
+ margin-top: 15px;
+ }
+
+ &__form-action {
+ background-color: transparent;
+ border: none;
+ transition: all 300ms ease-in-out;
+ font-family: 'Vazir';
+ font-weight: 700;
+ border-radius: 40px;
+ cursor: pointer;
+ padding: 5px 20px;
+
+ &--primary {
+ background-color: $primary-color;
+ color: white;
+ }
+
+ &--cancel {
+ color: $danger-color;
+ background-color: white;
+ }
+
+ &:hover {
+ transform: scale(1.1);
+ }
+ &:active {
+ transform: scale(0.95);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/main/Collabora/ShareAccessManager/assets/share.png b/src/components/main/Collabora/ShareAccessManager/assets/share.png
new file mode 100644
index 0000000..8aa4f80
Binary files /dev/null and b/src/components/main/Collabora/ShareAccessManager/assets/share.png differ
diff --git a/src/components/main/Collabora/ShareAccessManager/index.js b/src/components/main/Collabora/ShareAccessManager/index.js
new file mode 100644
index 0000000..fe4a22a
--- /dev/null
+++ b/src/components/main/Collabora/ShareAccessManager/index.js
@@ -0,0 +1,63 @@
+import React, {useEffect, useRef, useState} from 'react';
+import Modal from './Modal';
+
+import './style.scss';
+import share from './assets/share.png';
+import useCore from '../../../../hooks/core';
+import collaboraIframeHandler from '../shared/collaboraIframeHandler';
+
+
+function getPostMessageContent(sharingValue) {
+ const SHARE_PREFIX = 'SHARE_PREF_';
+ const UNO_COMMAND = '.uno:InsertBookmark';
+
+ return {'MessageId': 'Send_UNO_Command',
+ 'Values': {
+ 'Command': UNO_COMMAND,
+ 'Args': {
+ 'Bookmark': {
+ 'type': 'string',
+ 'value': `${SHARE_PREFIX}${sharingValue}`
+ },
+ }
+ }
+ };
+}
+
+export default function ShareFileManager({children}) {
+ const {_} = useCore();
+ const iframeRef = useRef(null);
+ const [shouldShowSharingModal, setShouldShowSharingModal] = useState(false);
+
+ useEffect(() => {
+ collaboraIframeHandler.onReady(()=>{
+ collaboraIframeHandler.postMessage(iframeRef.current, {'MessageId': 'Insert_Button',
+ 'Values': {'id': 'startSharing', 'imgurl': share, 'hint': '', 'mobile': false, 'label': _('LBL_SHARING_BUTTON'), 'insertBefore': 'Save'}
+ });
+ });
+
+ collaboraIframeHandler.onMessage((msg)=>{
+ if(msg.MessageId === 'Clicked_Button' && msg.Values?.Id === 'startSharing') {
+ setShouldShowSharingModal(true);
+ }
+ });
+ }, []);
+
+ function handleModalCancel() {
+ setShouldShowSharingModal(false);
+ }
+
+ function handleModalSubmit(emails) {
+ setShouldShowSharingModal(false);
+
+ const postMessageContent = getPostMessageContent(`[${emails}]`);
+ collaboraIframeHandler.postMessage(iframeRef.current, postMessageContent);
+ }
+
+ const modalContent = shouldShowSharingModal ?
: null;
+
+ return
+ {modalContent}
+ {children(iframeRef)}
+
;
+}
diff --git a/src/components/main/Collabora/ShareAccessManager/style.scss b/src/components/main/Collabora/ShareAccessManager/style.scss
new file mode 100644
index 0000000..e8e699d
--- /dev/null
+++ b/src/components/main/Collabora/ShareAccessManager/style.scss
@@ -0,0 +1,4 @@
+.ShareAccessManager {
+ height: 100%;
+ position: relative;
+}
\ No newline at end of file
diff --git a/src/components/main/Collabora/index.js b/src/components/main/Collabora/index.js
new file mode 100644
index 0000000..55218db
--- /dev/null
+++ b/src/components/main/Collabora/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import Iframe from './Iframe';
+import ShareFileManager from './ShareAccessManager';
+
+export default function Collabora({accessToken, wopiUrl}) {
+ return (
+
+ {(ref) => }
+
+ );
+}
diff --git a/src/components/main/Collabora/shared/collaboraIframeHandler.js b/src/components/main/Collabora/shared/collaboraIframeHandler.js
new file mode 100644
index 0000000..91126ff
--- /dev/null
+++ b/src/components/main/Collabora/shared/collaboraIframeHandler.js
@@ -0,0 +1,50 @@
+const onReadyCBs = [];
+const onMessageCbs = [];
+
+const collaboraIframeHandler = {
+ isReady: false,
+ initialize(iframe) {
+ window.addEventListener('message', (event)=>{
+ try {
+ const msg = JSON.parse(event.data);
+
+ if (!msg) {
+ return;
+ }
+
+ if (msg.MessageId === 'App_LoadingStatus' && msg.Values?.Status === 'Document_Loaded') {
+ this.postMessage(iframe, {'MessageId': 'Host_PostmessageReady'});
+
+ this.isReady = true;
+ onReadyCBs.forEach(cb => cb());
+ return;
+ }
+
+ onMessageCbs.forEach(cb => cb(msg));
+ } catch (e) {
+ // Not a Collabora message
+ console.error(e.message);
+ }
+ }, false);
+ },
+ onReady(cb) {
+ if(!this.isReady) {
+ onReadyCBs.push(cb);
+ return;
+ }
+
+ cb();
+ },
+ onMessage(cb) {
+ onMessageCbs.push(cb);
+ },
+ postMessage(iframe, data) {
+ if(!iframe) {
+ return;
+ }
+ console.log(data);
+ iframe.contentWindow.postMessage(JSON.stringify(data), '*');
+ }
+};
+
+export default collaboraIframeHandler;
diff --git a/src/components/main/index.js b/src/components/main/index.js
index eb5ffd5..c622c3f 100644
--- a/src/components/main/index.js
+++ b/src/components/main/index.js
@@ -1,11 +1,11 @@
import React, {useEffect, useState} from 'react';
-import LoaderForm from '../loaderForm';
import axios from 'axios';
import useCore from '../../hooks/core';
import {useCustomDialog} from '../../hooks/customDialog';
import './index.scss';
import CreateFile from '../createFile';
import BrowseFile from '../browseFile';
+import Collabora from './Collabora';
export default function Main(props) {
const [filePath, setFilePath] = useState(props.data ? props.data.path : null);
@@ -20,8 +20,7 @@ export default function Main(props) {
const [urlSrc, setUrlSrc] = useState(null);
const [wopiUrl, setWopiUrl] = useState('');
const [accessToken, setAccessToken] = useState(null);
- const [loading, setLoading] = useState(false);
- const iframeRef = React.useRef();
+ const [isLoaded, setIsLoaded] = useState(false);
let tray = null;
@@ -135,27 +134,15 @@ export default function Main(props) {
const locationOrigin = window.location.origin;
const wopiSrc = `${locationOrigin}/wopi/files/${fileId}`;
setWopiUrl(`${urlSrc}WOPISrc=${wopiSrc}`);
- setLoading(true);
+ setIsLoaded(true);
})
.catch((error) => {
console.log(error);
});
}
- if (loading) {
- return (
-
- );
+ if (isLoaded) {
+ return
;
}
return (
diff --git a/src/index.js b/src/index.js
index 5fcbcfe..932a7e8 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,6 +2,8 @@ import React from 'react';
import {CoreProvider} from './hooks/core';
import Main from './components/main';
+import './styles/fonts.scss';
+
export default function App(props) {
return (
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index a1cfb3f..7936be9 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -1,24 +1,3 @@
$primary-color: #1430af;
$secondary-color: #37d5d6;
-
-@font-face {
- font-family: Vazir;
- font-style: normal;
- font-weight: normal;
- src: url('../../fonts/vaziri/Vazir.eot');
- src: url('../../fonts/vaziri/Vazir.eot?#iefix') format('embedded-opentype');
- src: url('../../fonts/vaziri/Vazir.woff2') format('woff2');
- src: url('../../fonts/vaziri/Vazir.woff') format('woff');
- src: url('../../fonts/vaziri/Vazir.ttf') format('truetype');
-}
-
-@font-face {
- font-family: Vazir;
- font-style: normal;
- font-weight: bold;
- src: url('../../fonts/vaziri/Vazir-Bold.eot');
- src: url('../../fonts/vaziri/Vazir-Bold.eot?#iefix') format('embedded-opentype');
- src: url('../../fonts/vaziri/Vazir-Bold.woff2') format('woff2');
- src: url('../../fonts/vaziri/Vazir-Bold.woff') format('woff');
- src: url('../../fonts/vaziri/Vazir-Bold.ttf') format('truetype');
-}
+$danger-color: #c0392b;
diff --git a/src/styles/fonts.scss b/src/styles/fonts.scss
new file mode 100644
index 0000000..7ecdf90
--- /dev/null
+++ b/src/styles/fonts.scss
@@ -0,0 +1,21 @@
+@font-face {
+ font-family: Vazir;
+ font-style: normal;
+ font-weight: normal;
+ src: url('../fonts/vaziri/Vazir.eot');
+ src: url('../fonts/vaziri/Vazir.eot?#iefix') format('embedded-opentype');
+ src: url('../fonts/vaziri/Vazir.woff2') format('woff2');
+ src: url('../fonts/vaziri/Vazir.woff') format('woff');
+ src: url('../fonts/vaziri/Vazir.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: Vazir;
+ font-style: normal;
+ font-weight: bold;
+ src: url('../fonts/vaziri/Vazir-Bold.eot');
+ src: url('../fonts/vaziri/Vazir-Bold.eot?#iefix') format('embedded-opentype');
+ src: url('../fonts/vaziri/Vazir-Bold.woff2') format('woff2');
+ src: url('../fonts/vaziri/Vazir-Bold.woff') format('woff');
+ src: url('../fonts/vaziri/Vazir-Bold.ttf') format('truetype');
+}
\ No newline at end of file