From a8630d71d571d4921af2cbf1b9de2823ffaf98f7 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Sat, 5 Jun 2021 11:48:14 +0900 Subject: [PATCH 01/91] Add mobile script --- mobile.html | 15 +++ package.json | 1 + src/mobile/components/App.tsx | 7 ++ src/mobile/index.tsx | 72 ++++++++++++ webpack.mobile.config.ts | 199 ++++++++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 mobile.html create mode 100644 src/mobile/components/App.tsx create mode 100644 src/mobile/index.tsx create mode 100644 webpack.mobile.config.ts diff --git a/mobile.html b/mobile.html new file mode 100644 index 0000000000..f986c38cbe --- /dev/null +++ b/mobile.html @@ -0,0 +1,15 @@ + + + + + + Boost Note + + + + + + +
+ + diff --git a/package.json b/package.json index 14e2a42101..29f54d93dc 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dev:cloud": "env-cmd cross-env NODE_ENV=development TARGET=electron TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack-dev-server --mode development --config webpack.cloud.config.ts", "dev:webpack": "env-cmd cross-env NODE_ENV=development TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack-dev-server --mode development", "dev:electron": "env-cmd cross-env NODE_ENV=development ts-node -P tsconfig-webpack.json scripts/dev-electron.ts", + "dev:mobile": "env-cmd cross-env NODE_ENV=development TS_NODE_PROJECT=\"tsconfig-webpack.json\" webpack-dev-server --mode development --config webpack.mobile.config.ts", "start": "electron electron/index.js", "lint": "eslint src/* --ext .ts,.tsx", "format": "prettier --write \"src/**/*\"", diff --git a/src/mobile/components/App.tsx b/src/mobile/components/App.tsx new file mode 100644 index 0000000000..ffc8724c08 --- /dev/null +++ b/src/mobile/components/App.tsx @@ -0,0 +1,7 @@ +import React from 'react' + +const App = () => { + return
Test
+} + +export default App diff --git a/src/mobile/index.tsx b/src/mobile/index.tsx new file mode 100644 index 0000000000..2b7b3e2b84 --- /dev/null +++ b/src/mobile/index.tsx @@ -0,0 +1,72 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import App from './components/App' +// import { V2ToastProvider } from './shared/lib/stores/toast' +// import { V2WindowProvider } from './shared/lib/stores/window' +// import { V2DialogProvider } from './shared/lib/stores/dialog' +// import { V2ModalProvider } from './shared/lib/stores/modal' +// import { V2ContextMenuProvider } from './shared/lib/stores/contextMenu' +// import { V2SidebarCollapseProvider } from './lib/v2/stores/sidebarCollapse' +// import { DbProvider } from './lib/db' +// import { RouterProvider } from './lib/router' +import { combineProviders } from '../lib/context' +// import { PreferencesProvider } from './lib/preferences' +// import { GeneralStatusProvider } from './lib/generalStatus' +// import { PreviewStyleProvider } from './lib/preview' +// import { AnalyticsProvider } from './lib/analytics' +// import { StorageRouterProvider } from './lib/storageRouter' +// import { SearchModalProvider } from './lib/searchModal' +// import { CheckedFeaturesProvider } from './lib/checkedFeatures' +// import { BoostHubStoreProvider } from './lib/boosthub' +// import { CreateWorkspaceModalProvider } from './lib/createWorkspaceModal' +// import { CloudIntroModalProvider } from './lib/cloudIntroModal' +// import { MigrationProvider } from './lib/migrate/store' +// import { DialogProvider } from './lib/dialog' + +// const V2CombinedProvider = combineProviders( +// V2ToastProvider, +// V2SidebarCollapseProvider, +// V2WindowProvider, +// V2ContextMenuProvider, +// V2ModalProvider, +// V2DialogProvider +// ) + +const CombinedProvider = combineProviders() +// V2CombinedProvider, +// BoostHubStoreProvider, +// SearchModalProvider, +// PreviewStyleProvider, +// MigrationProvider, +// GeneralStatusProvider, +// DialogProvider, +// DbProvider, +// AnalyticsProvider, +// PreferencesProvider, +// StorageRouterProvider, +// RouterProvider, +// CheckedFeaturesProvider, +// CreateWorkspaceModalProvider, +// CloudIntroModalProvider + +function render(Component: typeof App) { + let rootDiv = document.getElementById('root') + if (rootDiv == null) { + rootDiv = document.createElement('div', {}) + rootDiv.setAttribute('id', 'root') + document.body.appendChild(rootDiv) + } + ReactDOM.render( + + + , + document.getElementById('root') + ) +} + +if (module.hot != null) { + module.hot.accept('./components/App', () => { + render(App) + }) +} +render(App) diff --git a/webpack.mobile.config.ts b/webpack.mobile.config.ts new file mode 100644 index 0000000000..be80a05acb --- /dev/null +++ b/webpack.mobile.config.ts @@ -0,0 +1,199 @@ +import path from 'path' +import webpack from 'webpack' +import HtmlWebpackPlugin from 'html-webpack-plugin' +import express from 'express' +import ErrorOverlayPlugin from 'error-overlay-webpack-plugin' +import CopyPlugin from 'copy-webpack-plugin' +import packageJson from './package.json' + +module.exports = (env, argv) => { + const config: webpack.Configuration = { + entry: ['./src/mobile/index.tsx'], + + output: { + filename: '[name].[hash].js', + path: path.resolve(__dirname, 'compiled-mobile'), + }, + + devtool: 'inline-source-map', + + module: { + rules: [ + { + test: /\.css$/i, + use: ['style-loader', 'css-loader'], + }, + { + test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i, + loader: 'url-loader', + options: { + limit: 8192, + }, + }, + { + test: /\.tsx?$/, + use: [{ loader: 'ts-loader', options: { transpileOnly: true } }], + exclude: /node_modules/, + }, + { + test: /\.md$/, + use: [ + { + loader: 'raw-loader', + }, + ], + }, + ], + }, + + plugins: [ + new webpack.NamedModulesPlugin(), + // prints more readable module names in the browser console on HMR updates + + new webpack.NoEmitOnErrorsPlugin(), + // do not emit compiled assets that include errors + new HtmlWebpackPlugin({ + template: 'mobile.html', + }), + new ErrorOverlayPlugin(), + new webpack.DefinePlugin({ + 'process.env.VERSION': JSON.stringify(packageJson.version), + }), + new webpack.EnvironmentPlugin([ + 'NODE_ENV', + 'AMPLIFY_AUTH_IDENTITY_POOL_ID', + 'AMPLIFY_AUTH_REGION', + 'AMPLIFY_PINPOINT_APPID', + 'AMPLIFY_PINPOINT_REGION', + 'BOOST_NOTE_BASE_URL', + 'BOOST_HUB_BASE_URL', + 'SSE_URL', + 'REALTIME_URL', + 'GA_TRACKING_ID', + 'GITHUB_OAUTH_ID', + 'GOOGLE_CLIENT_ID', + 'INTERCOM_APP_ID', + 'STRIPE_PUBLISHABLE_KEY', + 'COUPONS_NEW_USER_STANDARD', + 'COUPONS_NEW_USER_PRO', + ]), + new CopyPlugin({ + patterns: [ + { + from: path.join(__dirname, 'node_modules/codemirror/theme'), + to: 'app/codemirror/theme', + }, + // { + // from: path.join(__dirname, 'mobile-static'), + // to: 'app/static', + // }, + { + from: path.join(__dirname, 'node_modules/katex/dist/katex.min.css'), + to: 'app/katex/katex.min.css', + }, + { + from: path.join( + __dirname, + 'node_modules/remark-admonitions/styles/classic.css' + ), + to: 'app/remark-admonitions/classic.css', + }, + ], + }), + ], + + devServer: { + host: 'localhost', + port: 3005, + + disableHostCheck: true, + + historyApiFallback: { + index: '/', + }, + // respond to 404s with index.html + + hot: true, + // enable HMR on the server + + before: function (app, server) { + app.use((req, res, next) => { + res.setHeader( + 'Access-Control-Allow-Origin', + process.env.BOOST_HUB_BASE_URL + ) + res.setHeader( + 'Access-Control-Allow-Methods', + 'OPTIONS, GET, POST, PUT, PATCH, DELETE' + ) + res.setHeader( + 'Access-Control-Allow-Headers', + 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization, Cookie, Set-Cookie' + ) + res.setHeader('Access-Control-Allow-Credentials', 'true') + next() + }) + + app.use( + '/app/codemirror/mode', + express.static(path.join(__dirname, 'node_modules/codemirror/mode')) + ) + app.use( + '/app/codemirror/addon', + express.static(path.join(__dirname, 'node_modules/codemirror/addon')) + ) + app.use( + '/app/codemirror/theme', + express.static(path.join(__dirname, 'node_modules/codemirror/theme')) + ) + app.use( + '/app/katex/katex.min.css', + express.static( + path.join(__dirname, 'node_modules/katex/dist/katex.min.css') + ) + ) + app.use( + '/app/remark-admonitions/classic.css', + express.static( + path.join( + __dirname, + 'node_modules/remark-admonitions/styles/classic.css' + ) + ) + ) + // app.use( + // '/static', + // express.static(path.join(__dirname, 'mobile-static')) + // ) + }, + }, + + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, + node: { + fs: 'empty', + }, + } + + if (argv.mode === 'development') { + config.plugins.unshift(new webpack.HotModuleReplacementPlugin()) + + config.entry = [ + 'react-hot-loader/patch', + 'webpack-dev-server/client?http://localhost:3005', + 'webpack/hot/only-dev-server', + ...(config.entry as string[]), + ] + config.output.publicPath = '/' + } + + if (argv.mode === 'production') { + config.optimization = { + minimize: true, + } + config.output.publicPath = '/' + } + + return config +} From 01439a5395471fc4eb40648657a79d846f666618 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Tue, 15 Jun 2021 15:41:26 +0900 Subject: [PATCH 02/91] Implement basic functionality --- .../atoms/buttons/login/GithubLoginButton.tsx | 3 +- src/cloud/lib/consts.ts | 2 + src/mobile/components/App.tsx | 65 +- src/mobile/components/Router.tsx | 394 +++++++ src/mobile/components/layouts/AppLayout.tsx | 140 +++ .../components/organisms/ContentManager.tsx | 602 ++++++++++ src/mobile/components/organisms/Navigator.tsx | 158 +++ .../components/pages/BookmarksListPage.tsx | 22 + src/mobile/components/pages/CooperatePage.tsx | 79 ++ .../components/pages/CreateTeamPage.tsx | 145 +++ src/mobile/components/pages/DocEditPage.tsx | 1016 +++++++++++++++++ src/mobile/components/pages/DocPage.tsx | 132 +++ .../components/pages/DocStatusShowPage.tsx | 104 ++ src/mobile/components/pages/DocViewPage.tsx | 283 +++++ src/mobile/components/pages/FolderPage.tsx | 124 ++ .../components/pages/OpenInvitePage.tsx | 135 +++ src/mobile/components/pages/ResourcesPage.tsx | 48 + src/mobile/components/pages/RootPage.tsx | 58 + .../components/pages/SharedDocsListPage.tsx | 44 + .../components/pages/SmartFolderPage.tsx | 281 +++++ src/mobile/components/pages/TagsShowPage.tsx | 79 ++ .../components/pages/TeamDeletePage.tsx | 192 ++++ src/mobile/components/pages/TeamIndex.tsx | 65 ++ src/mobile/components/pages/TimeLinePage.tsx | 167 +++ src/mobile/components/pages/UploadsPage.tsx | 220 ++++ src/mobile/index.tsx | 55 +- src/mobile/lib/href.ts | 36 + webpack.mobile.config.ts | 2 +- 28 files changed, 4594 insertions(+), 57 deletions(-) create mode 100644 src/mobile/components/Router.tsx create mode 100644 src/mobile/components/layouts/AppLayout.tsx create mode 100644 src/mobile/components/organisms/ContentManager.tsx create mode 100644 src/mobile/components/organisms/Navigator.tsx create mode 100644 src/mobile/components/pages/BookmarksListPage.tsx create mode 100644 src/mobile/components/pages/CooperatePage.tsx create mode 100644 src/mobile/components/pages/CreateTeamPage.tsx create mode 100644 src/mobile/components/pages/DocEditPage.tsx create mode 100644 src/mobile/components/pages/DocPage.tsx create mode 100644 src/mobile/components/pages/DocStatusShowPage.tsx create mode 100644 src/mobile/components/pages/DocViewPage.tsx create mode 100644 src/mobile/components/pages/FolderPage.tsx create mode 100644 src/mobile/components/pages/OpenInvitePage.tsx create mode 100644 src/mobile/components/pages/ResourcesPage.tsx create mode 100644 src/mobile/components/pages/RootPage.tsx create mode 100644 src/mobile/components/pages/SharedDocsListPage.tsx create mode 100644 src/mobile/components/pages/SmartFolderPage.tsx create mode 100644 src/mobile/components/pages/TagsShowPage.tsx create mode 100644 src/mobile/components/pages/TeamDeletePage.tsx create mode 100644 src/mobile/components/pages/TeamIndex.tsx create mode 100644 src/mobile/components/pages/TimeLinePage.tsx create mode 100644 src/mobile/components/pages/UploadsPage.tsx create mode 100644 src/mobile/lib/href.ts diff --git a/src/cloud/components/atoms/buttons/login/GithubLoginButton.tsx b/src/cloud/components/atoms/buttons/login/GithubLoginButton.tsx index a398973992..f295cad0d0 100644 --- a/src/cloud/components/atoms/buttons/login/GithubLoginButton.tsx +++ b/src/cloud/components/atoms/buttons/login/GithubLoginButton.tsx @@ -4,6 +4,7 @@ import styled from '../../../../lib/styled' import { stringify } from 'querystring' import IconMdi from '../../IconMdi' import { mdiGithub } from '@mdi/js' +import { boostHubBaseUrl } from '../../../../lib/consts' interface GithubLoginButtonProps { query?: any @@ -21,7 +22,7 @@ const GithubLoginButton = ({ setDisabled, }: GithubLoginButtonProps) => { const [sending, setSending] = useState(false) - const loginHref = `/api/oauth/github${ + const loginHref = `${boostHubBaseUrl}/api/oauth/github${ query != null ? `?${stringify(query)}` : '' }` diff --git a/src/cloud/lib/consts.ts b/src/cloud/lib/consts.ts index e7da49f3eb..ac1a27c926 100644 --- a/src/cloud/lib/consts.ts +++ b/src/cloud/lib/consts.ts @@ -13,3 +13,5 @@ export const googleClientId = process.env.GOOGLE_CLIENT_ID || 'elidid' export const newUserStandardCouponId = process.env.COUPONS_NEW_USER_STANDARD export const newUserProCouponId = process.env.COUPONS_NEW_USER_PRO export const newSpaceCouponId = process.env.COUPONS_NEW_SPACE +export const mobileBaseUrl = + process.env.MOBILE_BASE_URL || 'http://localhost:3005' diff --git a/src/mobile/components/App.tsx b/src/mobile/components/App.tsx index ffc8724c08..29b539e500 100644 --- a/src/mobile/components/App.tsx +++ b/src/mobile/components/App.tsx @@ -1,7 +1,68 @@ -import React from 'react' +import React, { useState } from 'react' +import Router from './Router' +import { RouterProvider } from '../../cloud/lib/router' +import { GlobalDataProvider } from '../../cloud/lib/stores/globalData' +// import { gaTrackingId, nodeEnv, boostHubBaseUrl } from '../../cloud/lib/consts' + +import { RealtimeConnProvider } from '../../cloud/lib/stores/realtimeConn' +import { V2ToastProvider } from '../../shared/lib/stores/toast' +import { useEffectOnce } from 'react-use' +import { initAccessToken } from '../../cloud/lib/stores/electron' +import { nodeEnv } from '../../cloud/lib/consts' const App = () => { - return
Test
+ const [accessTokenInitialized, setAccessTokenInitialized] = useState(false) + + useEffectOnce(() => { + ;(async () => { + if (nodeEnv !== 'production') { + await initAccessToken() + } + setAccessTokenInitialized(true) + })() + }) + if (!accessTokenInitialized) { + return
Fetching access token...
+ } + + return ( + <> + + + + + + + + + + + + + + {/*