Merge pull request #17 from doocs/feature-night-mode

Feature night mode
This commit is contained in:
JimQing 2020-05-17 23:05:22 +08:00 committed by GitHub
commit 32cd4f63d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 168 additions and 57 deletions

View File

@ -155,7 +155,7 @@ section {
margin: 10px 8px; margin: 10px 8px;
color: #333; color: #333;
position: relative; position: relative;
background-color: rgba(0, 0, 0, 0.03); background-color: rgb(238,238,238);
border: 1px solid #f0f0f0; border: 1px solid #f0f0f0;
border-radius: 2px; border-radius: 2px;
display: flex; display: flex;
@ -228,6 +228,6 @@ section {
} }
.CodeMirror-scroll, .preview-wrapper { .CodeMirror-scroll, .preview-wrapper {
overflow: unset!important; overflow: unset;
overflow-y: scroll!important; overflow-y: scroll;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -20,13 +20,18 @@
background-color: @nightCodeMirrorColor; background-color: @nightCodeMirrorColor;
box-shadow: inset 0 0 0 1px rgba(100, 37, 37, 0.102); box-shadow: inset 0 0 0 1px rgba(100, 37, 37, 0.102);
} }
.preview { .output_night {
background-color: @nightPreviewColor; .preview {
box-shadow: 0 0 70px rgba(0, 0, 0, 0.3); background-color: @nightPreviewColor;
} box-shadow: 0 0 70px rgba(0, 0, 0, 0.3);
.preview-wrapper { }
background-color: @nightCodeMirrorColor; .preview-wrapper {
box-shadow: inset 0 0 0 1px rgba(233, 231, 231, 0.102); background-color: @nightCodeMirrorColor;
box-shadow: inset 0 0 0 1px rgba(233, 231, 231, 0.102);
}
.code-snippet__fix {
background-color: rgb(238,238,238);
}
} }
.cm-s-style-mirror .CodeMirror-matchingbracket { .cm-s-style-mirror .CodeMirror-matchingbracket {
color: @nightWhiteColor!important; color: @nightWhiteColor!important;
@ -60,7 +65,7 @@
color: @nightWhiteColor; color: @nightWhiteColor;
} }
} }
.insert__dialog, .about__dialog { .insert__dialog, .about__dialog, .reset__dialog {
.el-dialog { .el-dialog {
background-color: @nightBgColor; background-color: @nightBgColor;
} }

View File

@ -64,6 +64,7 @@
<div class="mode__switch" v-if="!nightMode" @click="themeChanged"></div> <div class="mode__switch" v-if="!nightMode" @click="themeChanged"></div>
<div class="mode__switch mode__switch_black" v-else @click="themeChanged"></div> <div class="mode__switch mode__switch_black" v-else @click="themeChanged"></div>
</el-tooltip> </el-tooltip>
<resetDialog :showResetConfirm="showResetConfirm" @confirm="confirmReset" @close="cancelReset"/>
</el-container> </el-container>
</template> </template>
@ -81,6 +82,7 @@ import {
} from '../../scripts/converter' } from '../../scripts/converter'
import config from '../../scripts/config' import config from '../../scripts/config'
import DEFAULT_CSS_CONTENT from '../../scripts/themes/default-theme-css' import DEFAULT_CSS_CONTENT from '../../scripts/themes/default-theme-css'
import resetDialog from '../codeMirror/resetDialog'
import {mapState, mapMutations} from 'vuex' import {mapState, mapMutations} from 'vuex'
export default { export default {
name: 'editor-header', name: 'editor-header',
@ -88,11 +90,15 @@ export default {
return { return {
config: config, config: config,
citeStatus: false, citeStatus: false,
showResetConfirm: false,
selectFont: '', selectFont: '',
selectSize: '', selectSize: '',
selectColor: '' selectColor: ''
}; };
}, },
components: {
resetDialog
},
computed: { computed: {
effect() { effect() {
return this.nightMode ? 'dark' : 'light' return this.nightMode ? 'dark' : 'light'
@ -165,28 +171,32 @@ export default {
}, },
// //
copy() { copy() {
let clipboardDiv = document.getElementById('output') this.$emit('startCopy');
solveWeChatImage() setTimeout(() => {
this.setHtml(solveHtml()) let clipboardDiv = document.getElementById('output')
solveWeChatImage()
this.setHtml(solveHtml(this.nightMode))
clipboardDiv.focus() clipboardDiv.focus()
window.getSelection().removeAllRanges() window.getSelection().removeAllRanges()
let range = document.createRange() let range = document.createRange()
range.setStartBefore(clipboardDiv.firstChild) range.setStartBefore(clipboardDiv.firstChild)
range.setEndAfter(clipboardDiv.lastChild) range.setEndAfter(clipboardDiv.lastChild)
window.getSelection().addRange(range) window.getSelection().addRange(range)
document.execCommand('copy') document.execCommand('copy')
// //
this.$notify({ this.$notify({
showClose: true, showClose: true,
message: '已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴', message: '已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴',
offset: 80, offset: 80,
duration: 1600, duration: 1600,
type: 'success' type: 'success'
}) })
clipboardDiv.innerHTML = this.output; // clipboardDiv.innerHTML = this.output; //
this.$emit('refresh') this.$emit('refresh');
this.$emit('endCopy');
}, 350);
}, },
// CSS // CSS
async customStyle () { async customStyle () {
@ -207,26 +217,22 @@ export default {
}, },
// //
reset() { reset() {
this.$confirm('此操作将丢失本地缓存的文本和自定义样式,是否继续?', '提示', { this.showResetConfirm = true;
confirmButtonText: '确定', },
cancelButtonText: '取消', confirmReset() {
confirmButtonClass: 'el-button--success', localStorage.clear()
cancelButtonClass: 'el-button--success is-plain', this.clearEditorToDefault();
type: 'warning', this.editor.focus()
center: true this.citeStatus = false;
}).then(() => { this.statusChanged(false);
localStorage.clear() this.fontChanged(this.config.builtinFonts[0].value)
this.clearEditorToDefault(); this.colorChanged(this.config.colorOption[1].value)
this.editor.focus() this.sizeChanged(this.config.sizeOption[2].value)
this.citeStatus = false; this.$emit('cssChanged')
this.statusChanged(false); },
this.fontChanged(this.config.builtinFonts[0].value) cancelReset() {
this.colorChanged(this.config.colorOption[1].value) this.showResetConfirm = false;
this.sizeChanged(this.config.sizeOption[2].value) this.editor.focus()
this.$emit('cssChanged')
}).catch(() => {
this.editor.focus()
})
}, },
// //
downloadEditorContent () { downloadEditorContent () {

View File

@ -0,0 +1,43 @@
<template>
<el-dialog title="提示" class="reset__dialog" :visible="showResetConfirm" @close="$emit('close')">
<div class="text">
此操作将丢失本地缓存的文本和自定义样式是否继续?
</div>
<div slot="footer" class="dialog-footer">
<el-button :type="btnType" plain @click="$emit('close')"> </el-button>
<el-button :type="btnType" @click="$emit('confirm')" plain> </el-button>
</div>
</el-dialog>
</template>
<script>
import {mapState} from 'vuex';
export default {
props: {
showResetConfirm: {
type: Boolean,
default: false
}
},
computed: {
btnType() {
return !this.nightMode ? 'success' : 'default';
},
...mapState({
nightMode: state=> state.nightMode
})
}
}
</script>
<style lang="less" scoped>
.reset__dialog {
text-align: center;
}
.text {
text-align: center;
}
.dialog-footer {
text-align: center;
}
</style>

View File

@ -13,9 +13,9 @@ export function solveWeChatImage() {
image.style.height = height; image.style.height = height;
} }
} }
export function solveHtml() { export function solveHtml(nightMode = false) {
const element = document.getElementById("output-wrapper"); const element = document.getElementById("output-wrapper");
let html = element.innerHTML; let html = element.innerHTML
let res = ""; let res = "";
res = juice.inlineContent( res = juice.inlineContent(
html, html,
@ -25,4 +25,4 @@ export function solveHtml() {
} }
); );
return res; return res;
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="container" :class="{'container_night': nightMode}"> <div class="container" :class="{'container_night': nightMode}">
<el-container> <el-container>
<el-header class="editor__header is-dark"> <el-header class="editor__header">
<editor-header <editor-header
@refresh="onEditorRefresh" @refresh="onEditorRefresh"
@uploaded="uploaded" @uploaded="uploaded"
@ -9,6 +9,8 @@
@showBox="showBox = !showBox" @showBox="showBox = !showBox"
@showAboutDialog="aboutDialogVisible = true" @showAboutDialog="aboutDialogVisible = true"
@showDialogForm="dialogFormVisible = true" @showDialogForm="dialogFormVisible = true"
@startCopy="isCoping = true, backLight = true"
@endCopy="endCopy"
/> />
</el-header> </el-header>
<el-main class="main-body"> <el-main class="main-body">
@ -17,11 +19,15 @@
<textarea id="editor" type="textarea" placeholder="Your markdown text here." v-model="source"> <textarea id="editor" type="textarea" placeholder="Your markdown text here." v-model="source">
</textarea> </textarea>
</el-col> </el-col>
<el-col :span="12" class="preview-wrapper" id="preview"> <el-col :span="12" class="preview-wrapper" id="preview" :class="{'preview-wrapper_night': nightMode && isCoping}">
<section id="output-wrapper" > <section id="output-wrapper" :class="{'output_night': nightMode && !backLight}">
<div class="preview"> <div class="preview">
<section id="output" v-html="output"> <section id="output" v-html="output">
</section> </section>
<div class="loading-mask" v-if="nightMode && isCoping">
<div class="loading__img"></div>
<span>正在生成</span>
</div>
</div> </div>
</section> </section>
</el-col> </el-col>
@ -77,6 +83,8 @@ export default {
showBox: false, showBox: false,
aboutDialogVisible: false, aboutDialogVisible: false,
dialogFormVisible: false, dialogFormVisible: false,
isCoping: false,
backLight: false,
timeout: null, timeout: null,
changeTimer: null, changeTimer: null,
source: '' source: ''
@ -232,6 +240,12 @@ export default {
this.editorRefresh(); this.editorRefresh();
setTimeout(()=> PR.prettyPrint(), 0); setTimeout(()=> PR.prettyPrint(), 0);
}, },
endCopy() {
this.backLight = false;
setTimeout(()=> {
this.isCoping = false;
}, 800);
},
...mapMutations(['initEditorState', 'initEditorEntity', 'setWxRendererOptions', ...mapMutations(['initEditorState', 'initEditorEntity', 'setWxRendererOptions',
'editorRefresh', 'initCssEditorEntity']) 'editorRefresh', 'initCssEditorEntity'])
}, },
@ -258,4 +272,47 @@ export default {
.container { .container {
transition: all .3s; transition: all .3s;
} }
.preview {
transition: background 0s;
transition-delay: .2s;
}
.preview-wrapper_night {
overflow-y: inherit;
position: relative;
left: -3px;
.preview {
background-color: #fff;
}
}
#output-wrapper {
position: relative;
}
.loading-mask {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 376px;
height: 101%;
padding-top: 1px;
font-size: 15px;
color: gray;
background-color: #1e1e1e;
.loading__img {
position: absolute;
left: 50%;
top: 330px;
width: 50px;
height: 50px;
transform: translate(-50%, -50%);
background: url('../assets/images/favicon.png') no-repeat;
background-size: cover;
}
span {
position: absolute;
left: 50%;
top: 390px;
transform: translate(-50%, -50%);
}
}
</style> </style>