docs: add new website homepage

pull/90/head
moonrailgun 2 years ago
parent ba16ff6cb1
commit 1a4ac522c7

@ -1418,6 +1418,7 @@ importers:
glob: ^7.2.3
less: ^4.1.3
less-loader: ^10.2.0
medium-zoom: ^1.0.8
prism-react-renderer: ^1.3.5
react: ^17.0.2
react-dom: ^17.0.2
@ -1434,6 +1435,7 @@ importers:
docusaurus-plugin-image-zoom: 0.1.1
docusaurus-plugin-less: 2.0.2_cry5vv7wixxq3wqbwkikkfe4le
file-loader: 6.2.0
medium-zoom: 1.0.8
prism-react-renderer: 1.3.5_react@17.0.2
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
@ -7426,7 +7428,7 @@ packages:
peerDependencies:
react: '*'
dependencies:
'@types/react': 18.0.26
'@types/react': 17.0.53
prop-types: 15.8.1
react: 17.0.2
@ -15671,6 +15673,7 @@ packages:
dependencies:
webpack: 5.75.0_webpack-cli@4.10.0
webpack-cli: 4.10.0_hdfrwtmlewz4o7kkfxfrhnzu24
dev: true
/@webpack-cli/info/1.5.0_webpack-cli@4.10.0:
resolution: {integrity: sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==}
@ -15679,6 +15682,7 @@ packages:
dependencies:
envinfo: 7.8.1
webpack-cli: 4.10.0_hdfrwtmlewz4o7kkfxfrhnzu24
dev: true
/@webpack-cli/serve/1.7.0_ud4agclah7rahur6ntojouq57y:
resolution: {integrity: sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==}
@ -15691,6 +15695,7 @@ packages:
dependencies:
webpack-cli: 4.10.0_hdfrwtmlewz4o7kkfxfrhnzu24
webpack-dev-server: 4.11.1_pda42hcaj7d62cr262fr632kue
dev: true
/@xobotyi/scrollbar-width/1.9.5:
resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==}
@ -19226,7 +19231,7 @@ packages:
normalize-path: 3.0.0
schema-utils: 4.0.0
serialize-javascript: 6.0.1
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/core-js-compat/3.28.0:
resolution: {integrity: sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==}
@ -21070,6 +21075,7 @@ packages:
resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==}
engines: {node: '>=4'}
hasBin: true
dev: true
/eol/0.9.1:
resolution: {integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==}
@ -22238,6 +22244,7 @@ packages:
/fastest-levenshtein/1.0.16:
resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==}
engines: {node: '>= 4.9.1'}
dev: true
/fastest-stable-stringify/2.0.2:
resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==}
@ -22391,7 +22398,7 @@ packages:
dependencies:
loader-utils: 2.0.4
schema-utils: 3.1.1
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/file-selector/0.5.0:
resolution: {integrity: sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA==}
@ -24099,7 +24106,7 @@ packages:
lodash: 4.17.21
pretty-error: 4.0.0
tapable: 2.2.1
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/htmlparser2/6.1.0:
resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
@ -24466,6 +24473,7 @@ packages:
dependencies:
pkg-dir: 4.2.0
resolve-cwd: 3.0.0
dev: true
/imurmurhash/0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
@ -28120,7 +28128,7 @@ packages:
webpack: ^5.0.0
dependencies:
schema-utils: 4.0.0
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/mini-star/1.3.1:
resolution: {integrity: sha512-u9Rw8mPZibaAkEVXBsOQJ1irAURTgjqdKoITFd24+KxIGVXCDK+RYR8KjKRF99VLaCbK6TwTqiJ6iNsqq0G+wA==}
@ -34085,6 +34093,7 @@ packages:
engines: {node: '>= 0.10'}
dependencies:
resolve: 1.22.1
dev: true
/rechoir/0.8.0:
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
@ -34651,6 +34660,7 @@ packages:
engines: {node: '>=8'}
dependencies:
resolve-from: 5.0.0
dev: true
/resolve-dir/1.0.1:
resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==}
@ -34671,6 +34681,7 @@ packages:
/resolve-from/5.0.0:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
dev: true
/resolve-global/1.0.0:
resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==}
@ -37178,7 +37189,7 @@ packages:
schema-utils: 3.1.1
serialize-javascript: 6.0.1
terser: 5.16.5
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/terser/4.8.1:
resolution: {integrity: sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==}
@ -38893,7 +38904,7 @@ packages:
loader-utils: 2.0.4
mime-types: 2.1.35
schema-utils: 3.1.1
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/url-parse-lax/3.0.0:
resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==}
@ -39528,6 +39539,7 @@ packages:
webpack-bundle-analyzer: 4.8.0
webpack-dev-server: 4.11.1_pda42hcaj7d62cr262fr632kue
webpack-merge: 5.8.0
dev: true
/webpack-dev-middleware/3.7.3_webpack@4.46.0:
resolution: {integrity: sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==}
@ -39603,6 +39615,7 @@ packages:
- debug
- supports-color
- utf-8-validate
dev: true
/webpack-dev-server/4.11.1_webpack@5.75.0:
resolution: {integrity: sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==}
@ -39883,6 +39896,7 @@ packages:
- '@swc/core'
- esbuild
- uglify-js
dev: true
/webpackbar/5.0.2_webpack@5.75.0:
resolution: {integrity: sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==}
@ -39894,7 +39908,7 @@ packages:
consola: 2.15.3
pretty-time: 1.1.0
std-env: 3.3.2
webpack: 5.75.0_webpack-cli@4.10.0
webpack: 5.75.0
/websocket-driver/0.7.4:
resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}

@ -56,7 +56,7 @@ const [allowSendMessage] = useHasGroupPermission(groupId, [
The way of using arrays is convenient for some business logics that need to have multiple permission points.
### backend
### Backend
The permission statement of the backend is maintained in `server/packages/sdk/src/services/lib/role.ts`, and the usage method is very simple. as follows:
```ts

@ -26,6 +26,7 @@
"docusaurus-plugin-image-zoom": "^0.1.1",
"docusaurus-plugin-less": "^2.0.2",
"file-loader": "^6.2.0",
"medium-zoom": "^1.0.8",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",

@ -0,0 +1,160 @@
.feature-sections {
padding: 2rem 1rem;
@media (min-width: 997px) {
padding: 5rem 1rem;
}
.main {
margin: auto;
max-width: 80rem;
.title {
display: flex;
position: sticky;
top: var(--ifm-navbar-height);
background-color: var(--ifm-background-color);
z-index: 20;
margin-top: -1rem;
gap: 1.5rem;
padding-bottom: 1.5rem;
padding-top: 1.5rem;
align-items: center;
flex-direction: column;
@media (min-width: 997px) {
height: 5rem;
flex-direction: row;
justify-content: space-between;
padding-bottom: 0;
padding-top: 0;
}
.left {
text-align: center;
margin-bottom: 0;
margin-top: 0;
line-height: 1.5;
@media (min-width: 997px) {
font-size: 2.5rem;
}
}
.right {
margin: auto;
align-self: flex-start;
flex: 1;
justify-content: center;
align-items: center;
display: flex;
max-width: 100%;
@media (min-width: 997px) {
width: auto;
justify-content: flex-end;
}
.right-body {
display: inline-flex;
align-items: center;
border-radius: 0.5rem;
padding: 0.5rem;
font-size: .875rem;
line-height: 1.25rem;
border-radius: 0.5rem;
background-color: var(--ifm-color-emphasis-200);
overflow: auto;
@media (min-width: 997px) {
font-size: 1rem;
line-height: 1.5rem;
}
.pill {
flex: 1;
cursor: pointer;
padding: 0.5rem;
padding: 0.5rem 1.5rem;
text-align: center;
font-size: .875rem;
line-height: 1.25rem;
border-radius: .375rem;
&.active {
background-color: var(--ifm-color-primary);
color: var(--ifm-color-white);
}
}
}
}
}
.body {
display: flex;
flex-direction: column;
gap: 2rem;
.item {
display: flex;
background-color: var(--ifm-color-gray-900);
border-radius: 1.5rem;
overflow: hidden;
flex-direction: column;
[data-theme="light"] & {
background-color: var(--ifm-color-gray-100);
}
@media (min-width: 997px) {
flex-direction: row;
&.reverse {
flex-direction: row-reverse;
}
}
.left {
flex: 1;
padding: 1.5rem;
@media (min-width: 997px) {
flex-direction: row;
padding: 1.5rem 1.5rem 1.5rem 4rem;
}
h3 {
font-size: 2.25rem;
font-weight: 700;
}
}
.right {
flex: 1;
background-color: var(--ifm-color-gray-800);
border-radius: 1.5rem;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
[data-theme="light"] & {
background-color: var(--ifm-color-gray-200);
}
img {
display: block;
}
}
.btns {
display: flex;
flex-direction: row;
gap: 0.5rem;
overflow: auto;
}
}
}
}
}

@ -0,0 +1,202 @@
import { useColorMode } from '@docusaurus/theme-common';
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import Head from '@docusaurus/Head';
import Link from '@docusaurus/Link';
import { nightlyUrl } from '../utils/consts';
import './FeatureSection.less';
export const FeatureSection: React.FC = React.memo(() => {
const { colorMode } = useColorMode();
const [visibleSection, setVisibleSection] = useState('messenger');
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
const section = entry.target.id;
if (entry.isIntersecting) {
entry.target.classList.add('intersected');
setVisibleSection(section);
}
}
},
{ rootMargin: '-50% 0% -50% 0%' }
);
const elements = document.querySelectorAll(
'.feature-sections .body > .item'
);
elements.forEach((el) => {
observer.observe(el);
});
return () => {
observer.disconnect();
};
}, []);
function Pill({ section }) {
return (
<div
className={clsx(
'pill',
'flex-1 cursor-pointer rounded-md py-2 px-6 text-center font-jakarta text-sm font-semibold',
{ active: visibleSection === section }
)}
onClick={() => {
document
.getElementById(section)
?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}}
>
{`${section[0].toUpperCase()}${section.substring(1)}`}
</div>
);
}
return (
<section className="feature-sections">
<Head>
<link rel="prefetch" href="/img/hero-light.png" as="image" />
<link rel="prefetch" href="/img/hero-dark.png" as="image" />
<link rel="preload" href="/img/intro/hello.png" as="image" />
<link rel="preload" href="/img/intro/plugins.png" as="image" />
<link rel="preload" href="/img/intro/roles.png" as="image" />
<link rel="preload" href="/img/intro/github-bot.png" as="image" />
</Head>
<div className="main">
<div className="title">
<h2 className="left">Feature Overview</h2>
<div className="right">
<div className="right-body">
<Pill section="messenger" />
<Pill section="plugin" />
<Pill section="roles" />
<Pill section="bot" />
<Pill section="platform" />
</div>
</div>
</div>
<div className="body">
<div className="item" id="messenger">
<div className="left">
<h3>Messenger</h3>
<p>
Basic message support, multi message type like
text/link/mention/image/file etc. and support append reaction
for anything you want with messages.
</p>
<p>
You can join multiple groups, and discuss different topics,
perhaps information and notifications, through multiple panels
in the group. Not just a simple chat.
</p>
<p>
In the inbox, you can receive anything you need to know, such as
mention or plugin notification. Or you can push anything on
yourself.
</p>
</div>
<div className="right">
<img data-zoomable src="/img/intro/hello.png" />
</div>
</div>
<div className="item reverse" id="plugin">
<div className="left">
<h3>Plugin Center</h3>
<p>
Tailchat has a complete plugin system. With plugins, you can
integrate your apps and projects into your chat app in any form
you want. Unlike VSCode, Tailchat has fewer restrictions on the
form of expression. I think Tailchat is not only a chat app, but
also a platform for integrating different applications. You can
start a video conference, listen to music, use online tools and
more in Tailchat.
</p>
<p>
At the same time, through plugins, you can further improve the
chat experience, such as topic panel, end-to-end encryption,
rich text, message notification, online drawing, receiving push
from third-party applications, etc.
</p>
</div>
<div className="right">
<img data-zoomable src="/img/intro/plugins.png" />
</div>
</div>
<div className="item" id="roles">
<div className="left">
<h3>Group Roles</h3>
<p>
Tailchat has a builtin RBAC permission management system. Based
on the combination of role assignment and permission points,
various permission combinations can be matched. At the same
time, permission points can be easily integrated by plugins,
which are a very flexible design.
</p>
<Link
className="button button--link"
to="/docs/contribution/dev/role"
>
Learn More
</Link>
</div>
<div className="right">
<img data-zoomable src="/img/intro/roles.png" />
</div>
</div>
<div className="item reverse" id="bot">
<div className="left">
<h3>Bot</h3>
<p>
Tailchat has a very simple way to integrate third-party
applications with bot like most applications. A simple url
request or add openapi app or even create a backend plugin. You
can use anyway to connect anything, its free!
</p>
</div>
<div className="right">
<img data-zoomable src="/img/intro/github-bot.png" />
</div>
</div>
<div className="item" id="platform">
<div className="left">
<h3>Multi-platform Support</h3>
<p>
Tailchat design on HTML, and fit any platform or os, but its
still some native support cannot provide in web. So Tailchat
also has client to provide os support like mobile notification ,
desktop screenshot and etc.
</p>
<div className="btns">
<Link className="button button--primary" to={nightlyUrl}>
Web
</Link>
<Link className="button button--secondary disabled">
Mobile (in Alpha Test)
</Link>
<Link className="button button--secondary disabled">
Desktop (in Alpha Test)
</Link>
</div>
</div>
<div className="right">
<img data-zoomable src={`/img/hero-${colorMode}.png`} />
</div>
</div>
</div>
</div>
</section>
);
});
FeatureSection.displayName = 'FeatureSection';

@ -1,7 +1,11 @@
.homepage-header {
padding: 4rem 1rem 0;
padding: 1rem 1rem 0;
text-align: center;
@media (min-width: 997px) {
padding: 4rem 1rem 0;
}
.header {
flex: 1;
text-align: center;

@ -4,6 +4,7 @@ import Head from '@docusaurus/Head';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Translate from '@docusaurus/Translate';
import { useColorMode } from '@docusaurus/theme-common';
import { inviteLink, nightlyUrl } from '../utils/consts';
import './HomepageHeader.less';
export const HomepageHeader: React.FC = React.memo(() => {
@ -26,10 +27,7 @@ export const HomepageHeader: React.FC = React.memo(() => {
<p className="desc">Tailchat: {siteConfig.tagline}</p>
<div className="btns">
<Link
className="button button--primary button--lg"
to="https://nightly.paw.msgbyte.com/invite/8Jfm1dWb"
>
<Link className="button button--primary button--lg" to={inviteLink}>
<Translate>Join our Group</Translate>
</Link>
@ -42,7 +40,7 @@ export const HomepageHeader: React.FC = React.memo(() => {
</div>
<div className="link">
<Link to="https://nightly.paw.msgbyte.com/">
<Link to={nightlyUrl}>
<Translate>Or direct visit Tailchat nightly version</Translate>
</Link>
</div>

@ -0,0 +1,13 @@
.join-community {
text-align: center;
padding: 5rem 0;
h3 {
font-weight: 700;
font-size: 1.875rem;
}
p {
color: var(--ifm-color-emphasis-600);
}
}

@ -0,0 +1,20 @@
import React from 'react';
import { inviteLink } from '../utils/consts';
import Link from '@docusaurus/Link';
import './JoinCommunity.less';
export const JoinCommunity: React.FC = React.memo(() => {
return (
<div className="join-community">
<h3>Join the community</h3>
<p>
Engage with our ever-growing community to get the latest updates,
product support, and more.
</p>
<Link className="button button--primary button--lg" href={inviteLink}>
Join Our Group
</Link>
</div>
);
});
JoinCommunity.displayName = 'JoinCommunity';

@ -21,6 +21,10 @@
--ifm-heading-font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
}
[data-theme="light"] {
--ifm-background-color: white;
}
.docusaurus-highlight-code-line {
background-color: rgba(0, 0, 0, 0.1);

@ -6,31 +6,35 @@ import HomepageFeatures from '../components/HomepageFeatures';
import { HomepageHeader } from '../components/HomepageHeader';
// @ts-ignore
import { ColorModeProvider } from '@docusaurus/theme-common/internal';
import { FeatureSection } from '../components/FeatureSection';
import { useMediumZoom } from '../utils/useMediumZoom';
import { JoinCommunity } from '../components/JoinCommunity';
function HomepageVideo() {
return (
<div className={styles.videoContainer}>
<iframe
className={styles.videoIframe}
src="//player.bilibili.com/player.html?aid=340398093&bvid=BV1394y1Z76n&cid=568332564&page=1"
scrolling="no"
border="0"
frameBorder="no"
framespacing="0"
allowFullScreen="true"
>
{' '}
</iframe>
</div>
);
}
// function HomepageVideo() {
// return (
// <div className={styles.videoContainer}>
// <iframe
// className={styles.videoIframe}
// src="//player.bilibili.com/player.html?aid=340398093&bvid=BV1394y1Z76n&cid=568332564&page=1"
// scrolling="no"
// border="0"
// frameBorder="no"
// frameSpacing="0"
// allowFullScreen="true"
// >
// {' '}
// </iframe>
// </div>
// );
// }
export default function Home() {
const { siteConfig } = useDocusaurusContext();
useMediumZoom();
return (
<Layout
title={`${siteConfig.title} | ${siteConfig.tagline}`}
title={`${siteConfig.title} - ${siteConfig.tagline}`}
description={`${siteConfig.tagline}`}
>
<ColorModeProvider>
@ -40,7 +44,11 @@ export default function Home() {
{/* TODO: Global Support */}
{/* <HomepageVideo /> */}
<HomepageFeatures />
<FeatureSection />
{/* <HomepageFeatures /> */}
<JoinCommunity />
</main>
</ColorModeProvider>
</Layout>

@ -0,0 +1,3 @@
export const nightlyUrl = 'https://nightly.paw.msgbyte.com/';
export const inviteLink = 'https://nightly.paw.msgbyte.com/invite/8Jfm1dWb';

@ -0,0 +1,8 @@
import { useEffect } from 'react';
import mediumZoom from 'medium-zoom';
export function useMediumZoom() {
useEffect(() => {
mediumZoom('[data-zoomable]');
}, []);
}
Loading…
Cancel
Save