diff --git a/backend/tabby/app/urls.py b/backend/tabby/app/urls.py index a0f79b7..847f493 100644 --- a/backend/tabby/app/urls.py +++ b/backend/tabby/app/urls.py @@ -12,6 +12,7 @@ urlpatterns = [ path('app-dist//', views.AppDistView.as_view()), path('terminal', views.TerminalView.as_view()), + path('demo', views.DemoView.as_view()), path('', include(api.urlpatterns)), ] diff --git a/backend/tabby/app/views.py b/backend/tabby/app/views.py index bd32f15..c1e4d3a 100644 --- a/backend/tabby/app/views.py +++ b/backend/tabby/app/views.py @@ -22,6 +22,13 @@ class TerminalView(APIView): return response +class DemoView(APIView): + def get(self, request, format=None): + response = static.serve(request, 'demo.html', document_root=str(settings.STATIC_ROOT)) + response['X-Frame-Options'] = 'ALLOW-FROM https://tabby.sh' + return response + + class AppDistView(APIView): def get(self, request, version=None, path=None, format=None): fs = fsspec.filesystem(urlparse(settings.APP_DIST_STORAGE).scheme) diff --git a/frontend/src/demo.html b/frontend/src/demo.html new file mode 100644 index 0000000..b82d162 --- /dev/null +++ b/frontend/src/demo.html @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/frontend/src/demo.ts b/frontend/src/demo.ts new file mode 100644 index 0000000..7ec4eaa --- /dev/null +++ b/frontend/src/demo.ts @@ -0,0 +1,85 @@ +import * as semverCompare from 'semver/functions/compare-loose' +import { Subject } from 'rxjs' +import { Version } from './api' + +class DemoConnector { + constructor ( + window: Window, + private version: Version, + ) { + window['tabbyWebDemoDataPath'] = `${this.getDistURL()}/${version.version}/tabby-web-demo/data` + } + + async loadConfig (): Promise { + return `{ + recoverTabs: false, + web: { + preventAccidentalTabClosure: false, + }, + terminal: { + fontSize: 11, + }, + }` + } + + // eslint-disable-next-line @typescript-eslint/no-empty-function + async saveConfig (_content: string): Promise { } + + getAppVersion (): string { + return this.version.version + } + + getDistURL (): string { + return 'https://api.tabby.sh/app-dist' + } + + getPluginsToLoad (): string[] { + return [ + 'tabby-core', + 'tabby-settings', + 'tabby-terminal', + 'tabby-community-color-schemes', + 'tabby-ssh', + 'tabby-telnet', + 'tabby-web', + 'tabby-web-demo', + ] + } + + createSocket () { + return new DemoSocketProxy() + } +} + +export class DemoSocketProxy { + connect$ = new Subject() + data$ = new Subject() + error$ = new Subject() + close$ = new Subject() + + async connect () { + this.error$.next(new Error('This web demo can\'t actually access Internet, but feel free to download the release and try it out!')) + } +} + +// eslint-disable-next-line @typescript-eslint/init-declarations +let iframe: HTMLIFrameElement +// eslint-disable-next-line @typescript-eslint/init-declarations +let version: Version + +const connectorRequestHandler = event => { + if (event.data === 'request-connector') { + iframe.contentWindow!['__connector__'] = new DemoConnector(iframe.contentWindow!, version) + iframe.contentWindow!.postMessage('connector-ready', '*') + } +} + +window.addEventListener('message', connectorRequestHandler) + +document.addEventListener('DOMContentLoaded', async () => { + iframe = document.querySelector('iframe')! + const versions = (await fetch('https://api.tabby.sh/api/1/versions').then(x => x.json())) as Version[] + versions.sort((a, b) => -semverCompare(a.version, b.version)) + version = versions[0]! + iframe.src = '/terminal' +}) diff --git a/frontend/src/server.ts b/frontend/src/server.ts index a03ff38..7c17b0a 100644 --- a/frontend/src/server.ts +++ b/frontend/src/server.ts @@ -67,6 +67,10 @@ function start () { res.sendFile(join(DIST_FOLDER, 'terminal.html')) }) + app.get(['/demo'], (req, res) => { + res.sendFile(join(DIST_FOLDER, 'demo.html')) + }) + for (const [key, value] of Object.entries(hardlinks)) { app.get(`/go/${key}`, (req, res) => res.redirect(value)) } diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index dc1bc5d..73f5221 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -19,6 +19,7 @@ module.exports = { entry: { index: path.resolve(__dirname, 'src/index.ts'), terminal: path.resolve(__dirname, 'src/terminal.ts'), + demo: path.resolve(__dirname, 'src/demo.ts'), }, plugins: [ ...baseConfig.plugins, @@ -39,7 +40,13 @@ module.exports = { chunks: ['terminal'], ...htmlPluginOptions, }), - ], + new HtmlWebpackPlugin({ + template: './src/demo.html', + filename: 'demo.html', + chunks: ['demo'], + ...htmlPluginOptions, + }), + ], output: { path: outputPath, pathinfo: true,