Temporary folder (part 2)

This commit is contained in:
benweet 2018-03-14 00:42:26 +00:00
parent 53f2076585
commit 88cf11972f
13 changed files with 206 additions and 221 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="button-bar"> <div class="button-bar">
<div class="button-bar__inner button-bar__inner--top"> <div class="button-bar__inner button-bar__inner--top">
<button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showNavigationBar }" @click="toggleNavigationBar()" v-title="'Toggle navigation bar'"> <button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showNavigationBar }" v-if="!light" @click="toggleNavigationBar()" v-title="'Toggle navigation bar'">
<icon-navigation-bar></icon-navigation-bar> <icon-navigation-bar></icon-navigation-bar>
</button> </button>
<button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showSidePreview }" tour-step-anchor="editor" @click="toggleSidePreview()" v-title="'Toggle side preview'"> <button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showSidePreview }" tour-step-anchor="editor" @click="toggleSidePreview()" v-title="'Toggle side preview'">
@ -26,12 +26,17 @@
</template> </template>
<script> <script>
import { mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
export default { export default {
computed: mapGetters('data', [ computed: {
...mapState([
'light',
]),
...mapGetters('data', [
'layoutSettings', 'layoutSettings',
]), ]),
},
methods: mapActions('data', [ methods: mapActions('data', [
'toggleNavigationBar', 'toggleNavigationBar',
'toggleEditor', 'toggleEditor',

View File

@ -19,7 +19,7 @@
<icon-close></icon-close> <icon-close></icon-close>
</button> </button>
</div> </div>
<div class="explorer__tree" :class="{'explorer__tree--new-item': !newChildNode.isNil}" v-if="!light" tabindex="0"> <div class="explorer__tree" :class="{'explorer__tree--new-item': !newChildNode.isNil}" v-if="!light" tabindex="0" @keyup.delete="deleteItem()">
<explorer-node :node="rootNode" :depth="0"></explorer-node> <explorer-node :node="rootNode" :depth="0"></explorer-node>
</div> </div>
</div> </div>

View File

@ -169,7 +169,7 @@ export default {
perform: () => this.newItem(false), perform: () => this.newItem(false),
}, { }, {
name: 'New folder', name: 'New folder',
disabled: !this.node.isFolder || this.node.isTrash, disabled: !this.node.isFolder || this.node.isTrash || this.node.isTemp,
perform: () => this.newItem(true), perform: () => this.newItem(true),
}, { }, {
type: 'separator', type: 'separator',
@ -179,7 +179,6 @@ export default {
perform: () => this.setEditingId(this.node.item.id), perform: () => this.setEditingId(this.node.item.id),
}, { }, {
name: 'Delete', name: 'Delete',
disabled: this.node.isTrash || this.node.item.parentId === 'trash',
perform: () => this.deleteItem(), perform: () => this.deleteItem(),
}], }],
}) })

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="modal" @keydown.esc="onEscape" @keydown.tab="onTab"> <div class="modal" @keydown.esc="onEscape" @keydown.tab="onTab">
<component :is="currentModalComponent" v-if="currentModalComponent"></component> <component v-if="currentModalComponent" :is="currentModalComponent"></component>
<modal-inner v-else aria-label="Dialog"> <modal-inner v-else aria-label="Dialog">
<div class="modal__content" v-html="config.content"></div> <div class="modal__content" v-html="config.content"></div>
<div class="modal__button-bar"> <div class="modal__button-bar">
@ -56,8 +56,6 @@ const getTabbables = container => container.querySelectorAll('a[href], button, .
// Filter enabled and visible element // Filter enabled and visible element
.cl_filter(el => !el.disabled && el.offsetParent !== null && !el.classList.contains('not-tabbable')); .cl_filter(el => !el.disabled && el.offsetParent !== null && !el.classList.contains('not-tabbable'));
const kebabCase = str => str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, match => `-${match.toLowerCase()}`);
export default { export default {
components: { components: {
ModalInner, ModalInner,
@ -102,11 +100,15 @@ export default {
'config', 'config',
]), ]),
currentModalComponent() { currentModalComponent() {
if (!this.condig.modal) { if (this.config.type) {
return ''; let componentName = this.config.type[0].toUpperCase();
componentName += this.config.type.slice(1);
componentName += 'Modal';
if (this.$options.components[componentName]) {
return componentName;
} }
}
return `${kebabCase(this.config.modal)}-modal`; return null;
}, },
}, },
methods: { methods: {

View File

@ -108,9 +108,7 @@ export default {
} }
this.titleFakeElt.textContent = this.title; this.titleFakeElt.textContent = this.title;
const width = this.titleFakeElt.getBoundingClientRect().width + 2; // 2px for the caret const width = this.titleFakeElt.getBoundingClientRect().width + 2; // 2px for the caret
return width < this.styles.titleMaxWidth return Math.min(width, this.styles.titleMaxWidth);
? width
: this.styles.titleMaxWidth;
}, },
titleScrolling() { titleScrolling() {
const result = this.titleHover && !this.titleFocus; const result = this.titleHover && !this.titleFocus;
@ -220,7 +218,7 @@ export default {
float: left; float: left;
&.navigation-bar__inner--button { &.navigation-bar__inner--button {
margin-right: 15px; margin-right: 12px;
} }
} }

View File

@ -25,7 +25,7 @@ export default {
]), ]),
showSponsorButton() { showSponsorButton() {
const type = this.$store.getters['modal/config'].type; const type = this.$store.getters['modal/config'].type;
return !this.$store.getters.isSponsor && type !== 'sponsor' && type !== 'signInForSponsorship'; return !this.$store.getters.isSponsor && type !== 'SponsorModal' && type !== 'signInForSponsorship';
}, },
}, },
methods: { methods: {

View File

@ -5,7 +5,6 @@ import welcomeFile from '../data/welcomeFile.md';
const dbVersion = 1; const dbVersion = 1;
const dbStoreName = 'objects'; const dbStoreName = 'objects';
const fileIdToOpen = utils.queryParams.fileId;
const exportWorkspace = utils.queryParams.exportWorkspace; const exportWorkspace = utils.queryParams.exportWorkspace;
const resetApp = utils.queryParams.reset; const resetApp = utils.queryParams.reset;
const deleteMarkerMaxAge = 1000; const deleteMarkerMaxAge = 1000;
@ -100,151 +99,6 @@ const localDbSvc = {
hashMap, hashMap,
connection: null, connection: null,
/**
* Create the connection and start syncing.
*/
init() {
return Promise.resolve()
.then(() => {
// Reset the app if reset flag was passed
if (resetApp) {
return Promise.all(
Object.keys(store.getters['data/workspaces'])
.map(workspaceId => localDbSvc.removeWorkspace(workspaceId)),
)
.then(() => utils.localStorageDataIds.forEach((id) => {
// Clean data stored in localStorage
localStorage.removeItem(`data/${id}`);
}))
.then(() => {
location.reload();
throw new Error('reload');
});
}
// Create the connection
this.connection = new Connection();
// Load the DB
return localDbSvc.sync();
})
.then(() => {
// If exportWorkspace parameter was provided
if (exportWorkspace) {
const backup = JSON.stringify(store.getters.allItemMap);
const blob = new Blob([backup], {
type: 'text/plain;charset=utf-8',
});
FileSaver.saveAs(blob, 'StackEdit workspace.json');
return;
}
// Save welcome file content hash if not done already
const hash = utils.hash(welcomeFile);
const welcomeFileHashes = store.getters['data/localSettings'].welcomeFileHashes;
if (!welcomeFileHashes[hash]) {
store.dispatch('data/patchLocalSettings', {
welcomeFileHashes: {
...welcomeFileHashes,
[hash]: 1,
},
});
}
// If app was last opened 7 days ago and synchronization is off
if (!store.getters['workspace/syncToken'] &&
(store.state.workspace.lastFocus + utils.cleanTrashAfter < Date.now())
) {
// Clean files
store.getters['file/items']
.filter(file => file.parentId === 'trash') // If file is in the trash
.forEach(file => store.dispatch('deleteFile', file.id));
}
// Enable sponsorship
if (utils.queryParams.paymentSuccess) {
location.hash = ''; // PaymentSuccess param is always on its own
store.dispatch('modal/paymentSuccess');
const sponsorToken = store.getters['workspace/sponsorToken'];
// Force check sponsorship after a few seconds
const currentDate = Date.now();
if (sponsorToken && sponsorToken.expiresOn > currentDate - checkSponsorshipAfter) {
store.dispatch('data/setGoogleToken', {
...sponsorToken,
expiresOn: currentDate - checkSponsorshipAfter,
});
}
}
// Sync local DB periodically
utils.setInterval(() => localDbSvc.sync(), 1000);
if (fileIdToOpen) {
store.commit('file/setCurrentId', fileIdToOpen);
}
// watch current file changing
store.watch(
() => store.getters['file/current'].id,
() => {
// See if currentFile is real, ie it has an ID
const currentFile = store.getters['file/current'];
// If current file has no ID, get the most recent file
if (!currentFile.id) {
const recentFile = store.getters['file/lastOpened'];
// Set it as the current file
if (recentFile.id) {
store.commit('file/setCurrentId', recentFile.id);
} else {
// If still no ID, create a new file
store.dispatch('createFile', {
name: 'Welcome file',
text: welcomeFile,
})
// Set it as the current file
.then(newFile => store.commit('file/setCurrentId', newFile.id));
}
} else {
Promise.resolve()
// Load contentState from DB
.then(() => localDbSvc.loadContentState(currentFile.id))
// Load syncedContent from DB
.then(() => localDbSvc.loadSyncedContent(currentFile.id))
// Load content from DB
.then(() => localDbSvc.loadItem(`${currentFile.id}/content`))
.then(
() => {
// Set last opened file
store.dispatch('data/setLastOpenedId', currentFile.id);
// Cancel new discussion
store.commit('discussion/setCurrentDiscussionId');
// Open the gutter if file contains discussions
store.commit('discussion/setCurrentDiscussionId',
store.getters['discussion/nextDiscussionId']);
// Add the fileId to the queryParams
utils.setQueryParams({
...utils.queryParams,
fileId: currentFile.id,
});
},
(err) => {
// Failure (content is not available), go back to previous file
const lastOpenedFile = store.getters['file/lastOpened'];
store.commit('file/setCurrentId', lastOpenedFile.id);
throw err;
},
)
.catch((err) => {
console.error(err); // eslint-disable-line no-console
store.dispatch('notification/error', err);
});
}
}, {
immediate: true,
});
});
},
/** /**
* Sync data items stored in the localStorage. * Sync data items stored in the localStorage.
*/ */
@ -485,6 +339,142 @@ const localDbSvc = {
localStorage.removeItem(`${id}/lastWindowFocus`); localStorage.removeItem(`${id}/lastWindowFocus`);
}); });
}, },
/**
* Create the connection and start syncing.
*/
init() {
return Promise.resolve()
.then(() => {
// Reset the app if reset flag was passed
if (resetApp) {
return Promise.all(
Object.keys(store.getters['data/workspaces'])
.map(workspaceId => localDbSvc.removeWorkspace(workspaceId)),
)
.then(() => utils.localStorageDataIds.forEach((id) => {
// Clean data stored in localStorage
localStorage.removeItem(`data/${id}`);
}))
.then(() => {
location.reload();
throw new Error('reload');
});
}
// Create the connection
this.connection = new Connection();
// Load the DB
return localDbSvc.sync();
})
.then(() => {
// If exportWorkspace parameter was provided
if (exportWorkspace) {
const backup = JSON.stringify(store.getters.allItemMap);
const blob = new Blob([backup], {
type: 'text/plain;charset=utf-8',
});
FileSaver.saveAs(blob, 'StackEdit workspace.json');
return;
}
// Save welcome file content hash if not done already
const hash = utils.hash(welcomeFile);
const welcomeFileHashes = store.getters['data/localSettings'].welcomeFileHashes;
if (!welcomeFileHashes[hash]) {
store.dispatch('data/patchLocalSettings', {
welcomeFileHashes: {
...welcomeFileHashes,
[hash]: 1,
},
});
}
// If app was last opened 7 days ago and synchronization is off
if (!store.getters['workspace/syncToken'] &&
(store.state.workspace.lastFocus + utils.cleanTrashAfter < Date.now())
) {
// Clean files
store.getters['file/items']
.filter(file => file.parentId === 'trash') // If file is in the trash
.forEach(file => store.dispatch('deleteFile', file.id));
}
// Enable sponsorship
if (utils.queryParams.paymentSuccess) {
location.hash = ''; // PaymentSuccess param is always on its own
store.dispatch('modal/paymentSuccess');
const sponsorToken = store.getters['workspace/sponsorToken'];
// Force check sponsorship after a few seconds
const currentDate = Date.now();
if (sponsorToken && sponsorToken.expiresOn > currentDate - checkSponsorshipAfter) {
store.dispatch('data/setGoogleToken', {
...sponsorToken,
expiresOn: currentDate - checkSponsorshipAfter,
});
}
}
// Sync local DB periodically
utils.setInterval(() => localDbSvc.sync(), 1000);
// watch current file changing
store.watch(
() => store.getters['file/current'].id,
() => {
// See if currentFile is real, ie it has an ID
const currentFile = store.getters['file/current'];
// If current file has no ID, get the most recent file
if (!currentFile.id) {
const recentFile = store.getters['file/lastOpened'];
// Set it as the current file
if (recentFile.id) {
store.commit('file/setCurrentId', recentFile.id);
} else {
// If still no ID, create a new file
store.dispatch('createFile', {
name: 'Welcome file',
text: welcomeFile,
})
// Set it as the current file
.then(newFile => store.commit('file/setCurrentId', newFile.id));
}
} else {
Promise.resolve()
// Load contentState from DB
.then(() => localDbSvc.loadContentState(currentFile.id))
// Load syncedContent from DB
.then(() => localDbSvc.loadSyncedContent(currentFile.id))
// Load content from DB
.then(() => localDbSvc.loadItem(`${currentFile.id}/content`))
.then(
() => {
// Set last opened file
store.dispatch('data/setLastOpenedId', currentFile.id);
// Cancel new discussion
store.commit('discussion/setCurrentDiscussionId');
// Open the gutter if file contains discussions
store.commit('discussion/setCurrentDiscussionId',
store.getters['discussion/nextDiscussionId']);
},
(err) => {
// Failure (content is not available), go back to previous file
const lastOpenedFile = store.getters['file/lastOpened'];
store.commit('file/setCurrentId', lastOpenedFile.id);
throw err;
},
)
.catch((err) => {
console.error(err); // eslint-disable-line no-console
store.dispatch('notification/error', err);
});
}
}, {
immediate: true,
});
});
},
}; };
const loader = type => fileId => localDbSvc.loadItem(`${fileId}/${type}`) const loader = type => fileId => localDbSvc.loadItem(`${fileId}/${type}`)

View File

@ -4,16 +4,17 @@ import utils from './utils';
import editorSvc from './editorSvc'; import editorSvc from './editorSvc';
const origin = utils.queryParams.origin; const origin = utils.queryParams.origin;
const existingFileId = utils.queryParams.fileId;
const fileName = utils.queryParams.fileName; const fileName = utils.queryParams.fileName;
const contentText = utils.queryParams.contentText; const contentText = utils.queryParams.contentText;
const contentProperties = utils.queryParams.contentProperties; const contentProperties = utils.queryParams.contentProperties;
export default { export default {
closed: false,
close() { close() {
if (origin && window.parent) { if (!this.closed && origin && window.parent) {
window.parent.postMessage({ type: 'close' }, origin); window.parent.postMessage({ type: 'close' }, origin);
} }
this.closed = true;
}, },
init() { init() {
if (!origin || !window.parent) { if (!origin || !window.parent) {
@ -21,64 +22,39 @@ export default {
} }
store.commit('setLight', true); store.commit('setLight', true);
return Promise.resolve()
.then(() => {
const file = store.state.file.itemMap[existingFileId];
if (file) {
// If file exists, check that the origin site has created it
const fileCreation = store.getters['data/fileCreations'][file.id];
if (fileCreation && fileCreation.origin === origin) {
return file;
}
}
// Create a new temp file
return store.dispatch('createFile', { return store.dispatch('createFile', {
name: fileName, name: fileName,
text: contentText, text: contentText,
properties: contentProperties, properties: contentProperties,
parentId: 'temp', parentId: 'temp',
});
}) })
.then((file) => { .then((file) => {
const fileItemMap = store.state.file.itemMap; const fileItemMap = store.state.file.itemMap;
// Sanitize file creations // Sanitize file creations
const fileCreations = {}; const lastCreated = {};
Object.entries(store.getters['data/fileCreations']).forEach(([id, fileCreation]) => { Object.entries(store.getters['data/lastCreated']).forEach(([id, createdOn]) => {
if (fileItemMap[id]) { if (fileItemMap[id] && fileItemMap[id].parentId === 'temp') {
fileCreations[id] = fileCreation; lastCreated[id] = createdOn;
} }
}); });
// Track file creation from the origin site // Track file creation from other site
fileCreations[file.id] = { lastCreated[file.id] = {
created: Date.now(), created: Date.now(),
origin,
}; };
// List temp files // Keep only the last 10 temp files created by other sites
const tempFileCreations = []; Object.entries(lastCreated)
Object.entries(fileCreations).forEach(([id, fileCreation]) => { .sort(([, createdOn1], [, createdOn2]) => createdOn2 - createdOn1)
if (fileItemMap[id].parentId === 'temp') {
tempFileCreations.push({
id,
created: fileCreation.created,
});
}
});
// Keep only the last 10 temp files
tempFileCreations
.sort((fileCreation1, fileCreation2) => fileCreation2.created - fileCreation1.created)
.splice(10) .splice(10)
.forEach((fileCreation) => { .forEach(([id]) => {
delete fileCreations[fileCreation.id]; delete lastCreated[id];
store.dispatch('deleteFile', fileCreation.id); store.dispatch('deleteFile', id);
}); });
// Store file creations and open the file // Store file creations and open the file
store.dispatch('data/setFileCreations', fileCreations); store.dispatch('data/setLastCreated', lastCreated);
store.commit('file/setCurrentId', file.id); store.commit('file/setCurrentId', file.id);
const onChange = cledit.Utils.debounce(() => { const onChange = cledit.Utils.debounce(() => {
@ -86,7 +62,7 @@ export default {
if (currentFile.id !== file.id) { if (currentFile.id !== file.id) {
// Close editor if file has changed for some reason // Close editor if file has changed for some reason
this.close(); this.close();
} else if (editorSvc.previewCtx.html != null) { } else if (!this.closed && editorSvc.previewCtx.html != null) {
const content = store.getters['content/current']; const content = store.getters['content/current'];
const properties = utils.computeProperties(content.properties); const properties = utils.computeProperties(content.properties);
window.parent.postMessage({ window.parent.postMessage({

View File

@ -170,7 +170,7 @@ export default {
...getters.templates, ...getters.templates,
...additionalTemplates, ...additionalTemplates,
}), }),
fileCreations: getter('fileCreations'), lastCreated: getter('lastCreated'),
lastOpened: getter('lastOpened'), lastOpened: getter('lastOpened'),
lastOpenedIds: (state, getters, rootState) => { lastOpenedIds: (state, getters, rootState) => {
const lastOpened = { const lastOpened = {
@ -262,7 +262,7 @@ export default {
}); });
commit('setItem', itemTemplate('templates', dataToCommit)); commit('setItem', itemTemplate('templates', dataToCommit));
}, },
setFileCreations: setter('fileCreations'), setLastCreated: setter('lastCreated'),
setLastOpenedId: ({ getters, commit, dispatch, rootState }, fileId) => { setLastOpenedId: ({ getters, commit, dispatch, rootState }, fileId) => {
const lastOpened = { ...getters.lastOpened }; const lastOpened = { ...getters.lastOpened };
lastOpened[fileId] = Date.now(); lastOpened[fileId] = Date.now();

View File

@ -69,17 +69,26 @@ export default {
}, },
getters: { getters: {
nodeStructure: (state, getters, rootState, rootGetters) => { nodeStructure: (state, getters, rootState, rootGetters) => {
const rootNode = new Node(emptyFolder(), [], true, true);
// Create Trash node
const trashFolderNode = new Node(emptyFolder(), [], true); const trashFolderNode = new Node(emptyFolder(), [], true);
trashFolderNode.item.id = 'trash'; trashFolderNode.item.id = 'trash';
trashFolderNode.item.name = 'Trash'; trashFolderNode.item.name = 'Trash';
trashFolderNode.noDrag = true; trashFolderNode.noDrag = true;
trashFolderNode.isTrash = true; trashFolderNode.isTrash = true;
trashFolderNode.parentNode = rootNode;
// Create Temp node
const tempFolderNode = new Node(emptyFolder(), [], true); const tempFolderNode = new Node(emptyFolder(), [], true);
tempFolderNode.item.id = 'temp'; tempFolderNode.item.id = 'temp';
tempFolderNode.item.name = 'Temp'; tempFolderNode.item.name = 'Temp';
tempFolderNode.noDrag = true; tempFolderNode.noDrag = true;
tempFolderNode.noDrop = true; tempFolderNode.noDrop = true;
tempFolderNode.isTemp = true; tempFolderNode.isTemp = true;
tempFolderNode.parentNode = rootNode;
// Fill nodeMap with all file and folder nodes
const nodeMap = { const nodeMap = {
trash: trashFolderNode, trash: trashFolderNode,
temp: tempFolderNode, temp: tempFolderNode,
@ -96,7 +105,8 @@ export default {
]; ];
nodeMap[item.id] = new Node(item, locations); nodeMap[item.id] = new Node(item, locations);
}); });
const rootNode = new Node(emptyFolder(), [], true, true);
// Build the tree
Object.entries(nodeMap).forEach(([, node]) => { Object.entries(nodeMap).forEach(([, node]) => {
let parentNode = nodeMap[node.item.parentId]; let parentNode = nodeMap[node.item.parentId];
if (!parentNode || !parentNode.isFolder) { if (!parentNode || !parentNode.isFolder) {
@ -110,8 +120,11 @@ export default {
} else { } else {
parentNode.files.push(node); parentNode.files.push(node);
} }
node.parentNode = parentNode;
}); });
rootNode.sortChildren(); rootNode.sortChildren();
// Add Trash and Temp nodes
rootNode.folders.unshift(tempFolderNode); rootNode.folders.unshift(tempFolderNode);
tempFolderNode.files.forEach((node) => { tempFolderNode.files.forEach((node) => {
node.noDrop = true; node.noDrop = true;
@ -119,7 +132,8 @@ export default {
if (trashFolderNode.files.length) { if (trashFolderNode.files.length) {
rootNode.folders.unshift(trashFolderNode); rootNode.folders.unshift(trashFolderNode);
} }
// Add a fake file at the end of the root folder to allow drag and drop into it.
// Add a fake file at the end of the root folder to allow drag and drop into it
rootNode.files.push(fakeFileNode); rootNode.files.push(fakeFileNode);
return { return {
nodeMap, nodeMap,

View File

@ -1,7 +1,7 @@
const minPadding = 20; const minPadding = 20;
const editorTopPadding = 10; const editorTopPadding = 10;
const navigationBarEditButtonsWidth = (36 * 14) + 8; // 14 buttons + 1 spacer const navigationBarEditButtonsWidth = (36 * 14) + 8; // 14 buttons + 1 spacer
const navigationBarLeftButtonWidth = 38 + 4 + 15; const navigationBarLeftButtonWidth = 38 + 4 + 12;
const navigationBarRightButtonWidth = 38 + 8; const navigationBarRightButtonWidth = 38 + 8;
const navigationBarSpinnerWidth = 24 + 8 + 5; // 5 for left margin const navigationBarSpinnerWidth = 24 + 8 + 5; // 5 for left margin
const navigationBarLocationWidth = 20; const navigationBarLocationWidth = 20;
@ -23,7 +23,8 @@ const constants = {
function computeStyles(state, getters, layoutSettings = getters['data/layoutSettings'], styles = { function computeStyles(state, getters, layoutSettings = getters['data/layoutSettings'], styles = {
showNavigationBar: layoutSettings.showNavigationBar showNavigationBar: layoutSettings.showNavigationBar
|| !layoutSettings.showEditor || !layoutSettings.showEditor
|| state.content.revisionContent, || state.content.revisionContent
|| state.light,
showStatusBar: layoutSettings.showStatusBar, showStatusBar: layoutSettings.showStatusBar,
showEditor: layoutSettings.showEditor, showEditor: layoutSettings.showEditor,
showSidePreview: layoutSettings.showSidePreview && layoutSettings.showEditor, showSidePreview: layoutSettings.showSidePreview && layoutSettings.showEditor,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB