aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/apis/google_docs/GoogleApiClientUtils.ts26
-rw-r--r--src/client/documents/Documents.ts7
-rw-r--r--src/client/views/MainView.tsx26
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx51
4 files changed, 44 insertions, 66 deletions
diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts
index 61df69d5c..689009254 100644
--- a/src/client/apis/google_docs/GoogleApiClientUtils.ts
+++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts
@@ -27,11 +27,14 @@ export namespace GoogleApiClientUtils {
export type Identifier = string;
export type Reference = Identifier | CreateOptions;
- export type TextContent = string | string[];
+ export interface Content {
+ text: string | string[];
+ links: docs_v1.Schema$Request[];
+ }
export type IdHandler = (id: Identifier) => any;
export type CreationResult = Opt<Identifier>;
export type ReadLinesResult = Opt<{ title?: string, bodyLines?: string[] }>;
- export type ReadResult = { title?: string, body?: string };
+ export type ReadResult = { title: string, body: string };
export interface CreateOptions {
service: Service;
@@ -50,7 +53,7 @@ export namespace GoogleApiClientUtils {
export interface WriteOptions {
mode: WriteMode;
- content: TextContent;
+ content: Content;
reference: Reference;
index?: number; // if excluded, will compute the last index of the document and append the content there
}
@@ -165,28 +168,24 @@ export namespace GoogleApiClientUtils {
}
};
- export const read = async (options: ReadOptions): Promise<ReadResult> => {
+ export const read = async (options: ReadOptions): Promise<Opt<ReadResult>> => {
return retrieve({ ...options, service: Service.Documents }).then(document => {
- let result: ReadResult = {};
if (document) {
- let title = document.title;
+ let title = document.title!;
let body = Utils.extractText(document, options.removeNewlines);
- result = { title, body };
+ return { title, body };
}
- return result;
});
};
- export const readLines = async (options: ReadOptions): Promise<ReadLinesResult> => {
+ export const readLines = async (options: ReadOptions): Promise<Opt<ReadLinesResult>> => {
return retrieve({ ...options, service: Service.Documents }).then(document => {
- let result: ReadLinesResult = {};
if (document) {
let title = document.title;
let bodyLines = Utils.extractText(document).split("\n");
options.removeNewlines && (bodyLines = bodyLines.filter(line => line.length));
- result = { title, bodyLines };
+ return { title, bodyLines };
}
- return result;
});
};
@@ -227,7 +226,7 @@ export namespace GoogleApiClientUtils {
});
index = 1;
}
- const text = options.content;
+ const text = options.content.text;
text.length && requests.push({
insertText: {
text: isArray(text) ? text.join("\n") : text,
@@ -237,6 +236,7 @@ export namespace GoogleApiClientUtils {
if (!requests.length) {
return undefined;
}
+ requests.push(...options.content.links);
let replies: any = await update({ documentId: identifier, requests });
if ("errors" in replies) {
console.log("Write operation failed:");
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 47df17329..e40e095d6 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -496,10 +496,13 @@ export namespace Docs {
* @param title an optional title to give to the highest parent document in the hierarchy
*/
export function DocumentHierarchyFromJson(input: any, title?: string): Opt<Doc> {
- if (input === null || ![...primitives, "object"].includes(typeof input)) {
+ if (input === undefined || input === null || ![...primitives, "object"].includes(typeof input)) {
return undefined;
}
- let parsed: any = typeof input === "string" ? JSONUtils.tryParse(input) : input;
+ let parsed = input;
+ if (typeof input === "string") {
+ parsed = JSONUtils.tryParse(input);
+ }
let converted: Doc;
if (typeof parsed === "object" && !(parsed instanceof Array)) {
converted = convertObject(parsed, title);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b35b2d331..ab87f0c7b 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -122,32 +122,6 @@ export class MainView extends React.Component {
componentWillMount() {
var tag = document.createElement('script');
- let requests: docs_v1.Schema$Request[] =
- [{
- updateTextStyle: {
- fields: "*",
- range: {
- startIndex: 1,
- endIndex: 15
- },
- textStyle: {
- bold: true,
- link: { url: window.location.href },
- foregroundColor: {
- color: {
- rgbColor: {
- red: 1.0,
- green: 0.0,
- blue: 0.0
- }
- }
- }
- }
- }
- }];
- let documentId = "1xBwN4akVePW_Zp8wbiq0WNjlzGAE2PyNVvwzFbUyv3I";
- GoogleApiClientUtils.Docs.setStyle({ documentId, requests });
-
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d6ba1700a..02bee2f82 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -12,7 +12,7 @@ import { DateField } from '../../../new_fields/DateField';
import { Doc, DocListCast, Opt, WidthSym } from "../../../new_fields/Doc";
import { Copy, Id } from '../../../new_fields/FieldSymbols';
import { List } from '../../../new_fields/List';
-import { RichTextField, ToPlainText, FromPlainText } from "../../../new_fields/RichTextField";
+import { RichTextField } from "../../../new_fields/RichTextField";
import { BoolCast, Cast, NumCast, StrCast, DateCast } from "../../../new_fields/Types";
import { createSchema, makeInterface } from "../../../new_fields/Schema";
import { Utils } from '../../../Utils';
@@ -37,12 +37,11 @@ import { DocumentDecorations } from '../DocumentDecorations';
import { DictationManager } from '../../util/DictationManager';
import { ReplaceStep } from 'prosemirror-transform';
import { DocumentType } from '../../documents/DocumentTypes';
+import { RichTextUtils } from '../../../new_fields/RichTextUtils';
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
-export const Blank = `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`;
-
export interface FormattedTextBoxProps {
isOverlay?: boolean;
hideOnLeave?: boolean;
@@ -61,7 +60,7 @@ export const GoogleRef = "googleDocId";
type RichTextDocument = makeInterface<[typeof richTextSchema]>;
const RichTextDocument = makeInterface(richTextSchema);
-type PullHandler = (exportState: GoogleApiClientUtils.ReadResult, dataDoc: Doc) => void;
+type PullHandler = (exportState: Opt<GoogleApiClientUtils.ReadResult>, dataDoc: Doc) => void;
@observer
export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) {
@@ -363,7 +362,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._reactionDisposer = reaction(
() => {
const field = this.dataDoc ? Cast(this.dataDoc[this.props.fieldKey], RichTextField) : undefined;
- return field ? field.Data : Blank;
+ return field ? field.Data : RichTextUtils.Initialize();
},
incomingValue => {
if (this._editorView && !this._applyingChange) {
@@ -431,7 +430,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
pushToGoogleDoc = async () => {
- this.pullFromGoogleDoc(async (exportState: GoogleApiClientUtils.ReadResult, dataDoc: Doc) => {
+ this.pullFromGoogleDoc(async (exportState: Opt<GoogleApiClientUtils.ReadResult>, dataDoc: Doc) => {
let modes = GoogleApiClientUtils.WriteMode;
let mode = modes.Replace;
let reference: Opt<GoogleApiClientUtils.Reference> = Cast(this.dataDoc[GoogleRef], "string");
@@ -440,9 +439,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
reference = { service: GoogleApiClientUtils.Service.Documents, title: StrCast(this.dataDoc.title) };
}
let redo = async () => {
- let data = Cast(this.dataDoc.data, RichTextField);
- if (this._editorView && reference && data) {
- let content = data[ToPlainText]();
+ if (this._editorView && reference) {
+ let content = RichTextUtils.GoogleDocs.Convert(this._editorView.state);
let response = await GoogleApiClientUtils.Docs.write({ reference, content, mode });
response && (this.dataDoc[GoogleRef] = response.documentId);
let pushSuccess = response !== undefined && !("errors" in response);
@@ -451,7 +449,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
};
let undo = () => {
- let content = exportState.body;
+ if (!exportState) {
+ return;
+ }
+ let content = {
+ text: exportState.body,
+ links: []
+ };
if (reference && content) {
GoogleApiClientUtils.Docs.write({ reference, content, mode });
}
@@ -464,20 +468,20 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
pullFromGoogleDoc = async (handler: PullHandler) => {
let dataDoc = this.dataDoc;
let documentId = StrCast(dataDoc[GoogleRef]);
- let exportState: GoogleApiClientUtils.ReadResult = {};
+ let exportState: Opt<GoogleApiClientUtils.ReadResult>;
if (documentId) {
exportState = await GoogleApiClientUtils.Docs.read({ identifier: documentId });
}
UndoManager.RunInBatch(() => handler(exportState, dataDoc), Pulls);
}
- updateState = (exportState: GoogleApiClientUtils.ReadResult, dataDoc: Doc) => {
+ updateState = (exportState: Opt<GoogleApiClientUtils.ReadResult>, dataDoc: Doc) => {
let pullSuccess = false;
if (exportState !== undefined && exportState.body !== undefined && exportState.title !== undefined) {
const data = Cast(dataDoc.data, RichTextField);
if (data instanceof RichTextField) {
pullSuccess = true;
- dataDoc.data = new RichTextField(data[FromPlainText](exportState.body));
+ dataDoc.data = RichTextUtils.Synthesize(exportState.body, data);
setTimeout(() => {
if (this._editorView) {
let state = this._editorView.state;
@@ -495,18 +499,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
DocumentDecorations.Instance.startPullOutcome(pullSuccess);
}
- checkState = (exportState: GoogleApiClientUtils.ReadResult, dataDoc: Doc) => {
- if (exportState !== undefined && exportState.body !== undefined && exportState.title !== undefined) {
- let data = Cast(dataDoc.data, RichTextField);
- if (data) {
- let storedPlainText = data[ToPlainText]() + "\n";
- let receivedPlainText = exportState.body;
- let storedTitle = dataDoc.title;
- let receivedTitle = exportState.title;
- let unchanged = storedPlainText === receivedPlainText && storedTitle === receivedTitle;
- dataDoc.unchanged = unchanged;
- DocumentDecorations.Instance.setPullState(unchanged);
- }
+ checkState = (exportState: Opt<GoogleApiClientUtils.ReadResult>, dataDoc: Doc) => {
+ if (exportState && this._editorView) {
+ let storedPlainText = RichTextUtils.ToPlainText(this._editorView.state) + "\n";
+ let receivedPlainText = exportState.body;
+ let storedTitle = dataDoc.title;
+ let receivedTitle = exportState.title;
+ let unchanged = storedPlainText === receivedPlainText && storedTitle === receivedTitle;
+ dataDoc.unchanged = unchanged;
+ DocumentDecorations.Instance.setPullState(unchanged);
}
}