Skip to content

Commit

Permalink
Merge branch 'welcome-screen-improvements' into experiment-private-fork
Browse files Browse the repository at this point in the history
  • Loading branch information
afarago committed Oct 14, 2024
2 parents 14ee7b8 + 4020cba commit c1f61dd
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 23 deletions.
2 changes: 2 additions & 0 deletions src/app/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,5 @@ export const googleApiKey = 'AIzaSyDkJMU1OqsnEULcV6kCwja2OJef6Ge_NxQ'; // proces
/** Google OAuth 2.0 Client ID */
export const googleClientId =
'688983308610-sst0jc72ti5p196srnkst442a9iadkqs.apps.googleusercontent.com'; // process.env.GOOGLE_CLIENT_ID
/** maximum number of recent file displayed */
export const recentFileCount = 3;
51 changes: 40 additions & 11 deletions src/editor/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
// welcome screen that is shown when no editor is open.

import { Button, Colors } from '@blueprintjs/core';
import { Document, Plus } from '@blueprintjs/icons';
import { DocumentOpen, Plus } from '@blueprintjs/icons';
import React, { useCallback, useEffect, useRef } from 'react';
import { useDispatch } from 'react-redux';
import Two from 'two.js';
import { useTernaryDarkMode } from 'usehooks-ts';
import { Activity, useActivitiesSelectedActivity } from '../activities/hooks';
import { recentFileCount } from '../app/constants';
import { explorerCreateNewFile } from '../explorer/actions';
import { UUID } from '../fileStorage';
import { useSelector } from '../reducers';
import { editorActivateFile } from './actions';
import { useI18n } from './i18n';
import logoSvg from './logo.svg';
import { RecentFileMetadata } from '.';

const defaultRotation = -Math.PI / 9; // radians
const rotationSpeedIncrement = 0.1; // radians per second
Expand Down Expand Up @@ -100,6 +105,7 @@ const Welcome: React.FunctionComponent<WelcomeProps> = ({ isVisible }) => {

const logo = two.load(logoSvg, (g) => {
g.center();

two.add(logo);
two.play();
});
Expand All @@ -111,7 +117,7 @@ const Welcome: React.FunctionComponent<WelcomeProps> = ({ isVisible }) => {
});

logo.fill = fillColorRef.current;
logo.scale = Math.min(two.width, two.height) / 90;
logo.scale = Math.min(two.width, two.height) / 80;
logo.rotation = stateRef.current.rotation;

two.scene.position.x = two.width / 2;
Expand Down Expand Up @@ -169,9 +175,37 @@ const Welcome: React.FunctionComponent<WelcomeProps> = ({ isVisible }) => {
dispatch(explorerCreateNewFile());
}, [dispatch, setSelectedActivity]);

const handleOpenExplorer = useCallback(() => {
setSelectedActivity(Activity.Explorer);
}, [setSelectedActivity]);
const handleOpenExplorer = useCallback(
(uuid: UUID) => {
setSelectedActivity(Activity.Explorer);
dispatch(editorActivateFile(uuid));
},
[dispatch, setSelectedActivity],
);

const recentFiles: readonly RecentFileMetadata[] = useSelector(
(s) => s.editor.recentFiles,
);

const getRecentFileShortCuts = () => (
<>
{recentFiles.slice(0, recentFileCount).map((fitem: RecentFileMetadata) => (
<dl key={fitem.uuid}>
<dt>
{i18n.translate('welcome.openProject', {
fileName: fitem.path,
})}
</dt>
<dd>
<Button
icon={<DocumentOpen />}
onClick={() => handleOpenExplorer(fitem.uuid)}
/>
</dd>
</dl>
))}
</>
);

return (
<div
Expand All @@ -183,12 +217,7 @@ const Welcome: React.FunctionComponent<WelcomeProps> = ({ isVisible }) => {
>
<div className="logo" ref={elementRef}></div>
<div className="shortcuts">
<dl>
<dt>{i18n.translate('welcome.openProject')}</dt>
<dd>
<Button icon={<Document />} onClick={handleOpenExplorer} />
</dd>
</dl>
{getRecentFileShortCuts()}
<dl>
<dt>{i18n.translate('welcome.newProject')}</dt>
<dd>
Expand Down
12 changes: 11 additions & 1 deletion src/editor/actions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022-2023 The Pybricks Authors
// Copyright (c) 2022-2024 The Pybricks Authors

import { createAction } from '../actions';
import { UUID } from '../fileStorage';
import { RecentFileMetadata } from '.';
export {
didFailToInit as editorCompletionDidFailToInit,
didInit as editorCompletionDidInit,
Expand Down Expand Up @@ -132,3 +133,12 @@ export const editorReplaceFile = createAction((uuid: UUID, value: string) => ({
uuid,
value,
}));

/**
* Requests to replace the value a file in the editor.
* @param files The recent files.
*/
export const editorRecentFiles = createAction((files: RecentFileMetadata[]) => ({
type: 'editor.action.recentFiles',
files,
}));
18 changes: 10 additions & 8 deletions src/editor/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,26 @@
justify-content: center;
align-items: center;

// display: block;
width: 100%;
height: 100%;
// max-width: 290px;

.logo {
flex: 1;
display: flex;
min-height: 0;
width: 100%;
height: 100%;
position: absolute;
top: -2%;

svg {
overflow: visible !important;
width: 100%;
height: 100%;
object-fit: contain;
min-height: 10;
flex: 1;
}
}
.shortcuts {
position: relative;
top: +6%;
padding: 20px;
text-align: center;

border-collapse: separate;
border-spacing: 11px 17px;
Expand Down
14 changes: 14 additions & 0 deletions src/editor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2024 The Pybricks Authors

import { UUID } from '../fileStorage';

/**
* LocalStorage recent files data type.
*/
export type RecentFileMetadata = Readonly<{
/** A globally unique identifier that serves a a file handle. */
uuid: UUID;
/** The path of the file in storage. */
path: string;
}>;
21 changes: 20 additions & 1 deletion src/editor/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2024 The Pybricks Authors

import { Reducer, combineReducers } from 'redux';
import { UUID } from '../fileStorage';
Expand All @@ -8,8 +8,10 @@ import {
editorDidCloseFile,
editorDidCreate,
editorDidOpenFile,
editorRecentFiles,
} from './actions';
import codeCompletion from './redux/codeCompletion';
import { RecentFileMetadata } from '.';

/** Indicates that the code editor is ready for use. */
const isReady: Reducer<boolean> = (state = false, action) => {
Expand Down Expand Up @@ -46,9 +48,26 @@ const openFileUuids: Reducer<readonly UUID[]> = (state = [], action) => {
return state;
};

/** A list of recent files in the order they should be displayed to the user. */
const initialStateRecentFiles = JSON.parse(
localStorage.getItem('editor.recentFiles') || '[]',
) as readonly RecentFileMetadata[];
const recentFiles: Reducer<readonly RecentFileMetadata[]> = (
state = initialStateRecentFiles,
action,
) => {
if (editorRecentFiles.matches(action)) {
return action.files;
//return { ...state, recentFiles: action.files };
}

return state;
};

export default combineReducers({
codeCompletion,
isReady,
activeFileUuid,
openFileUuids,
recentFiles,
});
32 changes: 31 additions & 1 deletion src/editor/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022-2023 The Pybricks Authors
// Copyright (c) 2022-2024 The Pybricks Authors

import type { DatabaseChangeType, IDatabaseChange } from 'dexie-observable/api';
import * as monaco from 'monaco-editor';
Expand All @@ -17,6 +17,7 @@ import {
takeEvery,
} from 'typed-redux-saga/macro';
import { alertsShowAlert } from '../alerts/actions';
import { recentFileCount } from '../app/constants';
import { FileStorageDb, UUID } from '../fileStorage';
import {
fileStorageDidFailToLoadTextFile,
Expand Down Expand Up @@ -62,11 +63,13 @@ import {
editorGetValueResponse,
editorGoto,
editorOpenFile,
editorRecentFiles,
editorReplaceFile,
} from './actions';
import { EditorError } from './error';
import { ActiveFileHistoryManager, OpenFileManager } from './lib';
import { pybricksMicroPythonId } from './pybricksMicroPython';
import { RecentFileMetadata } from '.';

function* handleEditorGetValueRequest(
editor: monaco.editor.ICodeEditor,
Expand Down Expand Up @@ -273,6 +276,33 @@ function* handleEditorActivateFile(

editor.focus();

// store the activated uuid in the recent files queue
let recentFiles = (() => {
try {
return JSON.parse(
localStorage.getItem('editor.recentFiles') ?? '',
) as RecentFileMetadata[];
} catch {
return [];
}
})();

// Check if the file already exists
const fileIndex = recentFiles.findIndex((fitem: RecentFileMetadata) => {
return fitem.uuid === action.uuid;
});
if (fileIndex !== -1) {
recentFiles.splice(fileIndex, 1);
}

const db = yield* getContext<FileStorageDb>('fileStorage');
const metadata = yield* call(() => db.metadata.get(action.uuid));
recentFiles.unshift({ uuid: action.uuid, path: metadata?.path ?? '' }); // Add new (or existing) file to the beginning
recentFiles = [...recentFiles.slice(0, recentFileCount)]; // Keep only the first 10 items
localStorage.setItem('editor.recentFiles', JSON.stringify(recentFiles));
yield* put(editorRecentFiles(recentFiles));

// signal activation done
yield* put(editorDidActivateFile(action.uuid));
} catch (err) {
yield* put(editorDidFailToActivateFile(action.uuid, ensureError(err)));
Expand Down
2 changes: 1 addition & 1 deletion src/editor/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"welcome": {
"label": "Welcome",
"openProject": "Open existing project",
"openProject": "Open {fileName}",
"newProject": "Open a new project"
}
}

0 comments on commit c1f61dd

Please sign in to comment.