Skip to content

Commit

Permalink
Revert "Cloud/desktop mode switcher (#6308)" (#6444)
Browse files Browse the repository at this point in the history
  • Loading branch information
wdanilo authored Apr 26, 2023
1 parent a00efb2 commit d0e1dd5
Show file tree
Hide file tree
Showing 30 changed files with 724 additions and 1,210 deletions.
4 changes: 0 additions & 4 deletions app/ide-desktop/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,6 @@ const RESTRICTED_SYNTAXES = [
'TSAsExpression:has(TSUnknownKeyword, TSNeverKeyword, TSAnyKeyword) > TSAsExpression',
message: 'Use type assertions to specific types instead of `unknown`, `any` or `never`',
},
{
selector: 'IfStatement > ExpressionStatement',
message: 'Wrap `if` branches in `{}`',
},
]

/* eslint-disable @typescript-eslint/naming-convention */
Expand Down
9 changes: 7 additions & 2 deletions app/ide-desktop/lib/content/esbuild-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export function bundlerOptions(args: Arguments) {
entryPoints: [
pathModule.resolve(THIS_PATH, 'src', 'index.ts'),
pathModule.resolve(THIS_PATH, 'src', 'index.html'),
pathModule.resolve(THIS_PATH, 'src', 'run.js'),
pathModule.resolve(THIS_PATH, 'src', 'style.css'),
pathModule.resolve(THIS_PATH, 'src', 'docsStyle.css'),
...wasmArtifacts.split(pathModule.delimiter),
Expand All @@ -107,9 +108,13 @@ export function bundlerOptions(args: Arguments) {
outbase: 'src',
plugins: [
{
// This is a workaround that is needed
// because esbuild panics when using `loader: { '.js': 'copy' }`.
// See https://github.com/evanw/esbuild/issues/3041.
// Setting `loader: 'copy'` prevents this file from being converted to ESM
// because of the `"type": "module"` in the `package.json`.
// This file MUST be in CommonJS format because it is loaded using `Function()`
// in `ensogl/pack/js/src/runner/index.ts`.
// All other files are ESM because of `"type": "module"` in `package.json`.
// in `ensogl/pack/js/src/runner/index.ts`
name: 'pkg-js-is-cjs',
setup: build => {
build.onLoad({ filter: /[/\\]pkg.js$/ }, async ({ path }) => ({
Expand Down
1 change: 1 addition & 0 deletions app/ide-desktop/lib/content/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<link rel="stylesheet" href="/docsStyle.css" />
<link rel="stylesheet" href="/tailwind.css" />
<script type="module" src="/index.js" defer></script>
<script type="module" src="/run.js" defer></script>
</head>
<body>
<div id="enso-dashboard" class="enso-dashboard"></div>
Expand Down
208 changes: 90 additions & 118 deletions app/ide-desktop/lib/content/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import * as authentication from 'enso-authentication'
import * as contentConfig from 'enso-content-config'

import * as app from '../../../../../target/ensogl-pack/linked-dist/index'
import * as projectManager from './project_manager'
import GLOBAL_CONFIG from '../../../../gui/config.yaml' assert { type: 'yaml' }

const logger = app.log.logger

Expand All @@ -23,8 +25,6 @@ const ESBUILD_EVENT_NAME = 'change'
const SECOND = 1000
/** Time in seconds after which a `fetchTimeout` ends. */
const FETCH_TIMEOUT = 300
/** The `id` attribute of the element that the IDE will be rendered into. */
const IDE_ELEMENT_ID = 'root'

// ===================
// === Live reload ===
Expand Down Expand Up @@ -119,132 +119,104 @@ function displayDeprecatedVersionDialog() {
}

// ========================
// === Main entry point ===
// === Main Entry Point ===
// ========================

interface StringConfig {
[key: string]: StringConfig | string
}

// Hack to mutate `configOptions.OPTIONS`
let currentAppInstance: app.App | null = new app.App({
config: {
loader: {
wasmUrl: 'pkg-opt.wasm',
jsUrl: 'pkg.js',
assetsUrl: 'dynamic-assets',
},
},
configOptions: contentConfig.OPTIONS,
packageInfo: {
version: BUILD_INFO.version,
engineVersion: BUILD_INFO.engineVersion,
},
})

function tryStopProject() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
currentAppInstance?.wasm?.drop?.()
}

async function runProject(inputConfig?: StringConfig) {
tryStopProject()
const rootElement = document.getElementById(IDE_ELEMENT_ID)
if (!rootElement) {
logger.error(`The root element (the element with ID '${IDE_ELEMENT_ID}') was not found.`)
} else {
while (rootElement.firstChild) {
rootElement.removeChild(rootElement.firstChild)
}
}

const config = Object.assign(
{
loader: {
wasmUrl: 'pkg-opt.wasm',
jsUrl: 'pkg.js',
assetsUrl: 'dynamic-assets',
class Main {
async main(inputConfig: StringConfig) {
const config = Object.assign(
{
loader: {
wasmUrl: 'pkg-opt.wasm',
jsUrl: 'pkg.js',
assetsUrl: 'dynamic-assets',
},
},
},
inputConfig
)

currentAppInstance = new app.App({
config,
configOptions: contentConfig.OPTIONS,
packageInfo: {
version: BUILD_INFO.version,
engineVersion: BUILD_INFO.engineVersion,
},
})
console.log('bruh', currentAppInstance)
inputConfig
)

const appInstance = new app.App({
config,
configOptions: contentConfig.OPTIONS,
packageInfo: {
version: BUILD_INFO.version,
engineVersion: BUILD_INFO.engineVersion,
},
})

if (!currentAppInstance.initialized) {
console.error('Failed to initialize the application.')
} else {
if (contentConfig.OPTIONS.options.dataCollection.value) {
// TODO: Add remote-logging here.
}
if (!(await checkMinSupportedVersion(contentConfig.OPTIONS))) {
displayDeprecatedVersionDialog()
} else {
const email = contentConfig.OPTIONS.groups.authentication.options.email.value
// The default value is `""`, so a truthiness check is most appropriate here.
if (email) {
logger.log(`User identified as '${email}'.`)
if (appInstance.initialized) {
if (contentConfig.OPTIONS.options.dataCollection.value) {
// TODO: Add remote-logging here.
}
void currentAppInstance.run()
}
}
}

if (
(contentConfig.OPTIONS.options.authentication.value ||
contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value) &&
contentConfig.OPTIONS.groups.startup.options.entry.value ===
contentConfig.OPTIONS.groups.startup.options.entry.default
) {
window.tryStopProject = tryStopProject
window.runProject = runProject
const hideAuth = () => {
const auth = document.getElementById('dashboard')
const ide = document.getElementById('root')
if (auth) {
auth.style.display = 'none'
}
if (ide) {
ide.hidden = false
}
}
/** This package is an Electron desktop app (i.e., not in the Cloud), so
* we're running on the desktop. */
/** TODO [NP]: https://github.com/enso-org/cloud-v2/issues/345
* `content` and `dashboard` packages **MUST BE MERGED INTO ONE**. The IDE
* should only have one entry point. Right now, we have two. One for the cloud
* and one for the desktop. Once these are merged, we can't hardcode the
* platform here, and need to detect it from the environment. */
const platform = authentication.Platform.desktop
/** FIXME [PB]: https://github.com/enso-org/cloud-v2/issues/366
* React hooks rerender themselves multiple times. It is resulting in multiple
* Enso main scene being initialized. As a temporary workaround we check whether
* appInstance was already ran. Target solution should move running appInstance
* where it will be called only once. */
let appInstanceRan = false
const onAuthenticated = () => {
if (!contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value) {
hideAuth()
if (!appInstanceRan) {
appInstanceRan = true
void runProject()
if (!(await checkMinSupportedVersion(contentConfig.OPTIONS))) {
displayDeprecatedVersionDialog()
} else {
if (
(contentConfig.OPTIONS.options.authentication.value ||
contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value) &&
contentConfig.OPTIONS.groups.startup.options.entry.value ===
contentConfig.OPTIONS.groups.startup.options.entry.default
) {
const hideAuth = () => {
const auth = document.getElementById('dashboard')
const ide = document.getElementById('root')
if (auth) auth.style.display = 'none'
if (ide) ide.style.display = ''
}
/** This package is an Electron desktop app (i.e., not in the Cloud), so
* we're running on the desktop. */
/** TODO [NP]: https://github.com/enso-org/cloud-v2/issues/345
* `content` and `dashboard` packages **MUST BE MERGED INTO ONE**. The IDE
* should only have one entry point. Right now, we have two. One for the cloud
* and one for the desktop. Once these are merged, we can't hardcode the
* platform here, and need to detect it from the environment. */
const platform = authentication.Platform.desktop
/** FIXME [PB]: https://github.com/enso-org/cloud-v2/issues/366
* React hooks rerender themselves multiple times. It is resulting in multiple
* Enso main scene being initialized. As a temporary workaround we check whether
* appInstance was already ran. Target solution should move running appInstance
* where it will be called only once. */
let appInstanceRan = false
const onAuthenticated = () => {
if (
!contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value
) {
hideAuth()
if (!appInstanceRan) {
appInstanceRan = true
void appInstance.run()
}
}
}
authentication.run({
logger,
platform,
projectManager: projectManager.ProjectManager.default(),
showDashboard:
contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value,
onAuthenticated,
})
} else {
void appInstance.run()
}
const email = contentConfig.OPTIONS.groups.authentication.options.email.value
// The default value is `""`, so a truthiness check is most appropriate here.
if (email) {
logger.log(`User identified as '${email}'.`)
}
}
} else {
console.error('Failed to initialize the application.')
}
}
authentication.run({
logger,
platform,
showDashboard: contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value,
onAuthenticated,
})
} else {
void runProject()
}

const API = new Main()

// @ts-expect-error `globalConfig.windowAppScopeName` is not known at typecheck time.
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
window[GLOBAL_CONFIG.windowAppScopeName] = API
39 changes: 39 additions & 0 deletions app/ide-desktop/lib/content/src/newtype.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/** @file TypeScript's closest equivalent of `newtype`s. */

interface NewtypeVariant<TypeName extends string> {
// eslint-disable-next-line @typescript-eslint/naming-convention
_$type: TypeName
}

/** Used to create a "branded type",
* which contains a property that only exists at compile time.
*
* `Newtype<string, 'A'>` and `Newtype<string, 'B'>` are not compatible with each other,
* however both are regular `string`s at runtime.
*
* This is useful in parameters that require values from a certain source,
* for example IDs for a specific object type.
*
* It is similar to a `newtype` in other languages.
* Note however because TypeScript is structurally typed,
* a branded type is assignable to its base type:
* `a: string = asNewtype<Newtype<string, 'Name'>>(b)` successfully typechecks. */
export type Newtype<T, TypeName extends string> = NewtypeVariant<TypeName> & T

interface NotNewtype {
// eslint-disable-next-line @typescript-eslint/naming-convention
_$type?: never
}

export function asNewtype<T extends Newtype<unknown, string>>(
s: NotNewtype & Omit<T, '_$type'>
): T {
// This cast is unsafe.
// `T` has an extra property `_$type` which is used purely for typechecking
// and does not exist at runtime.
//
// The property name is specifically chosen to trigger eslint's `naming-convention` lint,
// so it should not be possible to accidentally create a value with such a type.
// eslint-disable-next-line no-restricted-syntax
return s as unknown as T
}
Loading

0 comments on commit d0e1dd5

Please sign in to comment.