/* eslint-disable max-lines */ require('./editPage.less'); const React = require('react'); const _ = require('lodash'); const createClass = require('create-react-class'); import {makePatches, applyPatches, stringifyPatches, parsePatches} from '@sanity/diff-match-patch'; import { md5 } from 'hash-wasm'; import { gzipSync, strToU8 } from 'fflate'; import request from '../../utils/request-middleware.js'; const { Meta } = require('vitreum/headtags'); const Nav = require('naturalcrit/nav/nav.jsx'); const BaseEditPage = require('../basePages/editPage/editPage.jsx'); const LockNotification = require('./lockNotification/lockNotification.jsx'); import Markdown from 'naturalcrit/markdown.js'; const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js'); const { printCurrentBrew, fetchThemeBundle } = require('../../../../shared/helpers.js'); import { updateHistory, versionHistoryGarbageCollection } from '../../utils/versionHistory.js'; const googleDriveIcon = require('../../googleDrive.svg'); const EditPage = createClass({ displayName : 'EditPage', getDefaultProps : function() { return { brew : DEFAULT_BREW_LOAD }; }, getInitialState : function() { return { alertTrashedGoogleBrew : this.props.brew.trashed, alertLoginToTransfer : false, saveGoogle : this.props.brew.googleId ? true : false, confirmGoogleTransfer : false, error : null, displayLockMessage : this.props.brew.lock || false, }; }, componentDidMount : function(){ }, handleGoogleClick : function(){ if(!global.account?.googleId) { this.setState({ alertLoginToTransfer : true }); return; } this.setState((prevState)=>({ confirmGoogleTransfer : !prevState.confirmGoogleTransfer, error : null })); }, closeAlerts : function(event){ event.stopPropagation(); //Only handle click once so alert doesn't reopen this.setState({ alertTrashedGoogleBrew : false, alertLoginToTransfer : false, confirmGoogleTransfer : false }); }, toggleGoogleStorage : function(){ this.setState((prevState)=>({ saveGoogle : !prevState.saveGoogle, error : null }), ()=>this.trySave(true)); }, save : async function(){ if(this.debounceSave && this.debounceSave.cancel) this.debounceSave.cancel(); const brewState = this.state.brew; // freeze the current state const preSaveSnapshot = { ...brewState }; this.setState((prevState)=>({ isSaving : true, error : null, htmlErrors : Markdown.validate(prevState.brew.text) })); await updateHistory(this.state.brew).catch(console.error); await versionHistoryGarbageCollection().catch(console.error); //Prepare content to send to server const brew = { ...brewState }; brew.text = brew.text.normalize('NFC'); this.savedBrew.text = this.savedBrew.text.normalize('NFC'); brew.pageCount = ((brew.renderer=='legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1; brew.patches = stringifyPatches(makePatches(encodeURI(this.savedBrew.text), encodeURI(brew.text))); brew.hash = await md5(this.savedBrew.text); //brew.text = undefined; - Temporary parallel path brew.textBin = undefined; const compressedBrew = gzipSync(strToU8(JSON.stringify(brew))); const transfer = this.state.saveGoogle == _.isNil(this.state.brew.googleId); const params = `${transfer ? `?${this.state.saveGoogle ? 'saveToGoogle' : 'removeFromGoogle'}=true` : ''}`; const res = await request .put(`/api/update/${brew.editId}${params}`) .set('Content-Encoding', 'gzip') .set('Content-Type', 'application/json') .send(compressedBrew) .catch((err)=>{ console.log('Error Updating Local Brew'); this.setState({ error: err }); }); if(!res) return; this.savedBrew = { ...preSaveSnapshot, googleId : res.body.googleId ? res.body.googleId : null, editId : res.body.editId, shareId : res.body.shareId, version : res.body.version }; this.setState((prevState) => ({ brew: { ...prevState.brew, googleId : res.body.googleId ? res.body.googleId : null, editId : res.body.editId, shareId : res.body.shareId, version : res.body.version }, isSaving : false, }), ()=>{ this.setState({ unsavedChanges : this.hasChanges() }); }); history.replaceState(null, null, `/edit/${this.savedBrew.editId}`); }, renderGoogleDriveIcon : function(){ return Google Drive icon {this.state.confirmGoogleTransfer &&
{ this.state.saveGoogle ? `Would you like to transfer this brew from your Google Drive storage back to the Homebrewery?` : `Would you like to transfer this brew from the Homebrewery to your personal Google Drive storage?` }
Yes
No
} {this.state.alertLoginToTransfer &&
You must be signed in to a Google account to transfer between the homebrewery and Google Drive!
Sign In
Not Now
} {this.state.alertTrashedGoogleBrew &&
This brew is currently in your Trash folder on Google Drive!
If you want to keep it, make sure to move it before it is deleted permanently!
OK
}
; }, processShareId : function() { return this.state.brew.googleId && !this.state.brew.stubbed ? this.state.brew.googleId + this.state.brew.shareId : this.state.brew.shareId; }, getRedditLink : function(){ const shareLink = this.processShareId(); const systems = this.props.brew.systems.length > 0 ? ` [${this.props.brew.systems.join(' - ')}]` : ''; const title = `${this.props.brew.title} ${systems}`; const text = `Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out. **[Homebrewery Link](${global.config.baseUrl}/share/${shareLink})**`; return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title.toWellFormed())}&text=${encodeURIComponent(text)}`; }, renderNavbar : function(){ const shareLink = this.processShareId(); return <> {this.renderGoogleDriveIcon()} share view {navigator.clipboard.writeText(`${global.config.baseUrl}/share/${shareLink}`);}}> copy url post to reddit ; }, render : function(){ return {(welcomeText, brew, save) => { return <> {this.props.brew.lock && } }} ; } }); module.exports = EditPage;