mirror of https://github.com/msgbyte/tailchat
feat: 增加intro插件用于新人引导
parent
e697527caf
commit
fcaa941e9a
@ -0,0 +1,9 @@
|
||||
{
|
||||
"label": "初始引导插件",
|
||||
"name": "com.msgbyte.intro",
|
||||
"url": "/plugins/com.msgbyte.intro/index.js",
|
||||
"version": "0.0.0",
|
||||
"author": "msgbyte",
|
||||
"description": "为应用首次打开介绍应用的能力",
|
||||
"requireRestart": true
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@plugins/com.msgbyte.intro",
|
||||
"main": "src/index.ts",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"shepherd.js": "^8.3.1"
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 异步加载
|
||||
*/
|
||||
import('./tour');
|
@ -0,0 +1,77 @@
|
||||
import Shepherd from 'shepherd.js';
|
||||
|
||||
function buildWatchDom(selector: string) {
|
||||
return () => {
|
||||
return new Promise<void>((resolve) => {
|
||||
const findDom = () => {
|
||||
if (document.querySelector(selector)) {
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
findDom();
|
||||
}, 200);
|
||||
}
|
||||
};
|
||||
|
||||
findDom();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function buildStepOption(options: {
|
||||
id: string;
|
||||
text: string;
|
||||
selector: string;
|
||||
position?: Shepherd.Step.StepOptions['attachTo']['on'];
|
||||
canClickTarget?: boolean;
|
||||
}): Shepherd.Step.StepOptions {
|
||||
return {
|
||||
id: options.id,
|
||||
text: options.text,
|
||||
attachTo: {
|
||||
element: options.selector,
|
||||
on: options.position ?? 'auto',
|
||||
},
|
||||
canClickTarget: false,
|
||||
beforeShowPromise: buildWatchDom(options.selector),
|
||||
};
|
||||
}
|
||||
|
||||
export const steps: Shepherd.Step.StepOptions[] = [
|
||||
buildStepOption({
|
||||
id: 'navbar',
|
||||
text: '这是导航栏, 在这里可以切换tailchat的各个主要页面',
|
||||
selector: '[data-tc-role=navbar]',
|
||||
position: 'right',
|
||||
}),
|
||||
buildStepOption({
|
||||
id: 'personal',
|
||||
text: '这是个人信息,在这里可以管理您的好友、插件、以及私信',
|
||||
selector: '[data-tc-role=navbar-personal]',
|
||||
position: 'right',
|
||||
}),
|
||||
buildStepOption({
|
||||
id: 'groups',
|
||||
text: '这是群组列表, 会显示所有已加入的群组,您可以通过点击切换切换群组,也可以点击 + 号按钮来创建群组',
|
||||
selector: '[data-tc-role=navbar-groups]',
|
||||
position: 'right',
|
||||
}),
|
||||
buildStepOption({
|
||||
id: 'settings',
|
||||
text: '这是设置按钮,可以通过此按钮来进行个人信息的变更、系统设置的变更、软件信息等内容',
|
||||
selector: '[data-tc-role=navbar-settings]',
|
||||
position: 'right',
|
||||
}),
|
||||
buildStepOption({
|
||||
id: 'sidebar',
|
||||
text: '这是侧边栏,用于切换内容',
|
||||
selector: '[data-tc-role^=sidebar-]',
|
||||
position: 'right',
|
||||
}),
|
||||
buildStepOption({
|
||||
id: 'content',
|
||||
text: '这是内容区,用于显示主要内容',
|
||||
selector: '[data-tc-role^=content-]',
|
||||
position: 'right',
|
||||
}),
|
||||
];
|
@ -0,0 +1,176 @@
|
||||
.shepherd-button {
|
||||
background: #3288e6;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
color: hsla(0, 0%, 100%, 0.75);
|
||||
cursor: pointer;
|
||||
margin-right: 0.5rem;
|
||||
padding: 0.5rem 1.5rem;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.shepherd-button:not(:disabled):hover {
|
||||
background: #196fcc;
|
||||
color: hsla(0, 0%, 100%, 0.75);
|
||||
}
|
||||
.shepherd-button.shepherd-button-secondary {
|
||||
background: #f1f2f3;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.shepherd-button.shepherd-button-secondary:not(:disabled):hover {
|
||||
background: #d6d9db;
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.shepherd-button:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.shepherd-footer {
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0 0.75rem 0.75rem;
|
||||
}
|
||||
.shepherd-footer .shepherd-button:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.shepherd-cancel-icon {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: hsla(0, 0%, 50.2%, 0.75);
|
||||
font-size: 2em;
|
||||
cursor: pointer;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
transition: color 0.5s ease;
|
||||
}
|
||||
.shepherd-cancel-icon:hover {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.shepherd-has-title .shepherd-content .shepherd-cancel-icon {
|
||||
color: hsla(0, 0%, 50.2%, 0.75);
|
||||
}
|
||||
.shepherd-has-title .shepherd-content .shepherd-cancel-icon:hover {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.shepherd-title {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
display: flex;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
flex: 1 0 auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.shepherd-header {
|
||||
align-items: center;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
line-height: 2em;
|
||||
padding: 0.75rem 0.75rem 0;
|
||||
}
|
||||
.shepherd-has-title .shepherd-content .shepherd-header {
|
||||
background: #e6e6e6;
|
||||
padding: 1em;
|
||||
}
|
||||
.shepherd-text {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
font-size: 1rem;
|
||||
line-height: 1.3em;
|
||||
padding: 0.75em;
|
||||
}
|
||||
.shepherd-text p {
|
||||
margin-top: 0;
|
||||
}
|
||||
.shepherd-text p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.shepherd-content {
|
||||
border-radius: 5px;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
.shepherd-element {
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
|
||||
max-width: 400px;
|
||||
opacity: 0;
|
||||
outline: none;
|
||||
transition: opacity 0.3s, visibility 0.3s;
|
||||
visibility: hidden;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
.shepherd-enabled.shepherd-element {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
.shepherd-element[data-popper-reference-hidden]:not(.shepherd-centered) {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
.shepherd-element,
|
||||
.shepherd-element *,
|
||||
.shepherd-element :after,
|
||||
.shepherd-element :before {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.shepherd-arrow,
|
||||
.shepherd-arrow:before {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
z-index: -1;
|
||||
}
|
||||
.shepherd-arrow:before {
|
||||
content: '';
|
||||
transform: rotate(45deg);
|
||||
background: #fff;
|
||||
}
|
||||
.shepherd-element[data-popper-placement^='top'] > .shepherd-arrow {
|
||||
bottom: -8px;
|
||||
}
|
||||
.shepherd-element[data-popper-placement^='bottom'] > .shepherd-arrow {
|
||||
top: -8px;
|
||||
}
|
||||
.shepherd-element[data-popper-placement^='left'] > .shepherd-arrow {
|
||||
right: -8px;
|
||||
}
|
||||
.shepherd-element[data-popper-placement^='right'] > .shepherd-arrow {
|
||||
left: -8px;
|
||||
}
|
||||
.shepherd-element.shepherd-centered > .shepherd-arrow {
|
||||
opacity: 0;
|
||||
}
|
||||
.shepherd-element.shepherd-has-title[data-popper-placement^='bottom']
|
||||
> .shepherd-arrow:before {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.shepherd-target-click-disabled.shepherd-enabled.shepherd-target,
|
||||
.shepherd-target-click-disabled.shepherd-enabled.shepherd-target * {
|
||||
pointer-events: none;
|
||||
}
|
||||
.shepherd-modal-overlay-container {
|
||||
height: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
transition: all 0.3s ease-out, height 0ms 0.3s, opacity 0.3s 0ms;
|
||||
width: 100vw;
|
||||
z-index: 9997;
|
||||
}
|
||||
.shepherd-modal-overlay-container.shepherd-modal-is-visible {
|
||||
height: 100vh;
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s ease-out, height 0s 0s, opacity 0.3s 0s;
|
||||
}
|
||||
.shepherd-modal-overlay-container.shepherd-modal-is-visible path {
|
||||
pointer-events: all;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import Shepherd from 'shepherd.js';
|
||||
import { steps } from './steps';
|
||||
import './style.less';
|
||||
|
||||
const KEY = 'com.msgbyte.intro/hasRun';
|
||||
|
||||
if (!window.localStorage.getItem(KEY)) {
|
||||
const tour = new Shepherd.Tour({
|
||||
useModalOverlay: true,
|
||||
defaultStepOptions: {
|
||||
classes: 'shadow-md',
|
||||
scrollTo: true,
|
||||
arrow: false,
|
||||
modalOverlayOpeningRadius: 4,
|
||||
modalOverlayOpeningPadding: 4,
|
||||
buttons: [
|
||||
{
|
||||
text: '跳过引导',
|
||||
secondary: true,
|
||||
action() {
|
||||
this.complete();
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '下一步',
|
||||
action() {
|
||||
this.next();
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
tour.on('complete', () => {
|
||||
window.localStorage.setItem(KEY, 'true');
|
||||
});
|
||||
|
||||
tour.addSteps(steps);
|
||||
|
||||
tour.start();
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"baseUrl": "./src",
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"paths": {
|
||||
"@capital/*": ["../../../src/plugin/*"],
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@popperjs/core@^2.9.2":
|
||||
version "2.10.1"
|
||||
resolved "https://registry.nlark.com/@popperjs/core/download/@popperjs/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be"
|
||||
integrity sha1-co7NlasgequKmk5CHwQi2zKSMr4=
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha1-RNLqNnm49NT/ujPwPYZfwee/SVU=
|
||||
|
||||
shepherd.js@^8.3.1:
|
||||
version "8.3.1"
|
||||
resolved "https://registry.nlark.com/shepherd.js/download/shepherd.js-8.3.1.tgz#131eeefc5eb2bc44c9e23d0da139db46b2b55339"
|
||||
integrity sha1-Ex7u/F6yvETJ4j0NoTnbRrK1Uzk=
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.2"
|
||||
deepmerge "^4.2.2"
|
||||
smoothscroll-polyfill "^0.4.4"
|
||||
|
||||
smoothscroll-polyfill@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.nlark.com/smoothscroll-polyfill/download/smoothscroll-polyfill-0.4.4.tgz#3a259131dc6930e6ca80003e1cb03b603b69abf8"
|
||||
integrity sha1-OiWRMdxpMObKgAA+HLA7YDtpq/g=
|
Loading…
Reference in New Issue