Skip to content

Commit

Permalink
Cloud/desktop mode switcher (#6448)
Browse files Browse the repository at this point in the history
This is a re-creation of #6308.
Creates buttons to switch between cloud and local backends for listing directories, opening projects etc.

# Important Notes
The desktop backend currently uses a hardcoded list of templates, mostly because they look better because they have background images. However, it can easily be changed to use `listSamples` endpoint and switched to the default grey background.
  • Loading branch information
somebody1234 authored May 2, 2023
1 parent 42cc42c commit a1d48e7
Show file tree
Hide file tree
Showing 39 changed files with 2,309 additions and 1,648 deletions.
4 changes: 4 additions & 0 deletions app/gui/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ windowAppScopeConfigName: "config"
# utilities and allowing for runtime theme modification.
windowAppScopeThemeName: "theme"

# The URL to the JSON-RPC endpoint to the Project Manager.
# This MUST be kept in sync with the corresponding value in `app/gui/src/constants.rs`.
projectManagerEndpoint: "ws://127.0.0.1:30535"

# TODO [ao] add description here.
minimumSupportedVersion": "2.0.0-alpha.6"

Expand Down
4 changes: 4 additions & 0 deletions app/ide-desktop/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ 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
8 changes: 2 additions & 6 deletions app/ide-desktop/lib/content/esbuild-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,9 @@ 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`
// in `ensogl/pack/js/src/runner/index.ts`.
// All other files are ESM because of `"type": "module"` in `package.json`.
name: 'pkg-js-is-cjs',
setup: build => {
build.onLoad({ filter: /[/\\]pkg.js$/ }, async ({ path }) => ({
Expand Down
2 changes: 1 addition & 1 deletion app/ide-desktop/lib/content/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
user-scalable = no"
/>
<title>Enso</title>
<link rel="stylesheet" href="/tailwind.css" />
<link rel="stylesheet" href="/style.css" />
<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>
Expand Down
135 changes: 77 additions & 58 deletions app/ide-desktop/lib/content/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ 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 Down Expand Up @@ -119,15 +118,26 @@ function displayDeprecatedVersionDialog() {
}

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

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

class Main {
async main(inputConfig: StringConfig) {
class Main implements AppRunner {
app: app.App | null = null

stopApp() {
this.app?.stop()
}

async runApp(inputConfig?: StringConfig) {
this.stopApp()

/** FIXME: https://github.com/enso-org/enso/issues/6475
* Default values names are out of sync with values used in code.
* Rather than setting fixed values here we need to fix default values in config. */
const config = Object.assign(
{
loader: {
Expand All @@ -139,7 +149,7 @@ class Main {
inputConfig
)

const appInstance = new app.App({
this.app = new app.App({
config,
configOptions: contentConfig.OPTIONS,
packageInfo: {
Expand All @@ -148,75 +158,84 @@ class Main {
},
})

if (appInstance.initialized) {
if (!this.app.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 {
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}'.`)
}
void this.app.run()
}
}
}

main(inputConfig?: StringConfig) {
contentConfig.OPTIONS.loadAll([app.urlParams()])
const isUsingAuthentication = contentConfig.OPTIONS.options.authentication.value
const isUsingNewDashboard =
contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value
const isOpeningMainEntryPoint =
contentConfig.OPTIONS.groups.startup.options.entry.value ===
contentConfig.OPTIONS.groups.startup.options.entry.default
if ((isUsingAuthentication || isUsingNewDashboard) && isOpeningMainEntryPoint) {
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. */
const currentPlatform = contentConfig.OPTIONS.groups.startup.options.platform.value
let platform = authentication.Platform.desktop
if (currentPlatform === 'web') {
platform = authentication.Platform.cloud
}
/** 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 this.runApp(inputConfig)
}
}
}
authentication.run({
appRunner: this,
logger,
platform,
showDashboard:
contentConfig.OPTIONS.groups.featurePreview.options.newDashboard.value,
onAuthenticated,
})
} else {
console.error('Failed to initialize the application.')
void this.runApp(inputConfig)
}
}
}

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
window[GLOBAL_CONFIG.windowAppScopeName] = new Main()
39 changes: 0 additions & 39 deletions app/ide-desktop/lib/content/src/newtype.ts

This file was deleted.

Loading

0 comments on commit a1d48e7

Please sign in to comment.