scratch3.0 scratch-gui中集成自定义用户系统1(第四章)

scratch3.0系列章节列表

scratch3.0二次开发scratch3.0基本介绍(第一章)

scratch3.0二次开发运行scratch-gui项目并了解工程结构(第二章)

scratch3.0二次自定义品牌logo(第三章)

scratch3.0 scratch-gui中集成自定义用户系统1(第四章)

scratch3.0 scratch-gui中集成自定义用户系统2(第五章)

scratch3.0 scratch-gui中集成自定义用户系统3(第六章)

scratch3.0 scratch-gui中集成自定义用户系统4(第七章)

scratch3.0 scratch-gui中集成自定义用户系统5(第八章)

scratch3.0 scratch-gui中集成自定义用户系统6(第九章)

scratch3.0 scratch-gui中集成作品系统1(第九章)

scratch3.0 scratch-gui中集成作品系统2(第十章)

scratch3.0 scratch-gui中集成作品系统3(第十一章)

scratch3.0 scratch-gui加载自定义初始化角色(第十二章)

scratch3.0 scratch-gui打开自己平台云端作品(第十三章)

写在前面

该系列文章是为具有开发能力的朋友写作的,目的是帮助他们在刮擦3.0的基础上开发一套完整的集刮擦3.0编程工具,用户社区和作品云端存储及分享,品牌集成于一体的刮擦编程平台。如果您不是开发者,但想要拥有自己的教育平台和品牌,也欢迎学习交流和洽谈合作。

所以如果您是想学习scratch少儿编程课程,那请忽略该系列的文章。

 

前言

前面我们将scratch-gui工程成功建造运行起来,并且成功植入了我们的品牌徽标,这让我们对整个项目有了初步的认识。

现在我们已经有了scratch编程工具,但是我们还剩下两个主要的后台,用户社区后台和GUI的存储后台。目前Scratch3.0团队还没有发现社区替换和GUI的存储部分是否有开源计划,考虑到Scratch2.0的重新初始化开源,3.0社区初始化开源的可能也不大。

 

scratch-www项目提供了用户社区的功能,但是需要通过接口去分析它的后台的数据存储的结构,我觉得比较麻烦,不如我们自己来开发一个,集成到我们的编程工具scratch-gui中。

所以接下来我们的工作是自己来提供相关的两个前提平台,并与GUI集成到一起。

 

约会用户登录状态

我们先一步一步来,先做一个比较简单的用户系统,再一步一步迭代。

 

这一章,我们先来改造一下前面的scratch-gui,约会用户登录状态的检测。

在进入项目时,检测用户是否登录,如果用户未登录,则在右上角显示登录按钮,否则显示用户头像和姓名等基本信息。

 

先在减少器目录中创建user-state.js文件,用作记录用户的信息。

添加如下内容:

import keyMirror from 'keymirror';

const UserState = keyMirror({    NOT_LOGINED: null,    LOGINED: null});



const UserStates = Object.keys(UserState)

const initialState = {    error: null,    userData: null,    loginState: UserState.NOT_LOGINED};

const getIsLogined = loginState => (    loginState === UserState.LOGINED);

const reducer = function (state, action) {    if (typeof state === 'undefined') state = initialState;}

export {    reducer as default,    initialState as userStateInitialState,    UserState,    UserStates,    getIsLogined};

在减少器/gui.js中,作为项目的用户相关的初始化信息。

在reducer / gui.js中日期用户状态:

​​​

import userStateReducer, {userStateInitialState} from './user-state';```加入到initialState中:```const guiInitialState = {    alerts: alertsInitialState,    assetDrag: assetDragInitialState,    blockDrag: blockDragInitialState,    cards: cardsInitialState,    colorPicker: colorPickerInitialState,    connectionModal: connectionModalInitialState,    customProcedures: customProceduresInitialState,    editorTab: editorTabInitialState,    mode: modeInitialState,    hoveredTarget: hoveredTargetInitialState,    stageSize: stageSizeInitialState,    menus: menuInitialState,    micIndicator: micIndicatorInitialState,    modals: modalsInitialState,    monitors: monitorsInitialState,    monitorLayout: monitorLayoutInitialState,    projectChanged: projectChangedInitialState,    projectState: projectStateInitialState,    projectTitle: projectTitleInitialState,    fontsLoaded: fontsLoadedInitialState,    restoreDeletion: restoreDeletionInitialState,    targets: targetsInitialState,    timeout: timeoutInitialState,    toolbox: toolboxInitialState,    vm: vmInitialState,    vmStatus: vmStatusInitialState,    userState: userStateInitialState};```将reducer加入到guiReducer中:```const guiReducer = combineReducers({    alerts: alertsReducer,    assetDrag: assetDragReducer,    blockDrag: blockDragReducer,    cards: cardsReducer,    colorPicker: colorPickerReducer,    connectionModal: connectionModalReducer,    customProcedures: customProceduresReducer,    editorTab: editorTabReducer,    mode: modeReducer,    hoveredTarget: hoveredTargetReducer,    stageSize: stageSizeReducer,    menus: menuReducer,    micIndicator: micIndicatorReducer,    modals: modalReducer,    monitors: monitorReducer,    monitorLayout: monitorLayoutReducer,    projectChanged: projectChangedReducer,    projectState: projectStateReducer,    projectTitle: projectTitleReducer,    fontsLoaded: fontsLoadedReducer,    restoreDeletion: restoreDeletionReducer,    targets: targetReducer,    timeout: timeoutReducer,    toolbox: toolboxReducer,    vm: vmReducer,    vmStatus: vmStatusReducer,    userState: userStateReducer});

下面去container / gui.jsx中为里面定义的GUI Component添加loginState这个道具,使用标识用户是否登录:

GUI.propTypes = {    assetHost: PropTypes.string,    children: PropTypes.node,    cloudHost: PropTypes.string,    error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),    fetchingProject: PropTypes.bool,    intl: intlShape,    isError: PropTypes.bool,    isLoading: PropTypes.bool,    isScratchDesktop: PropTypes.bool,    isShowingProject: PropTypes.bool,    loadingStateVisible: PropTypes.bool,    onProjectLoaded: PropTypes.func,    onSeeCommunity: PropTypes.func,    onStorageInit: PropTypes.func,    onUpdateProjectId: PropTypes.func,    onUpdateProjectTitle: PropTypes.func,    onUpdateReduxProjectTitle: PropTypes.func,    onVmInit: PropTypes.func,    projectHost: PropTypes.string,    projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),    projectTitle: PropTypes.string,    telemetryModalVisible: PropTypes.bool,    vm: PropTypes.instanceOf(VM).isRequired,    loginState: PropTypes.bool};

这个`loginState`道具的状态值来自于user-state.js中getIsLogined中检测当前的loginState(指状态中的)是否等于UserState.LOGINED:

const mapStateToProps = state => {    const loadingState = state.scratchGui.projectState.loadingState;    const loginState = state.scratchGui.userState.loginState;    return {        activeTabIndex: state.scratchGui.editorTab.activeTabIndex,        alertsVisible: state.scratchGui.alerts.visible,        backdropLibraryVisible: state.scratchGui.modals.backdropLibrary,        blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX,        cardsVisible: state.scratchGui.cards.visible,        connectionModalVisible: state.scratchGui.modals.connectionModal,        costumeLibraryVisible: state.scratchGui.modals.costumeLibrary,        costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX,        error: state.scratchGui.projectState.error,        isError: getIsError(loadingState),        isFullScreen: state.scratchGui.mode.isFullScreen,        isPlayerOnly: state.scratchGui.mode.isPlayerOnly,        isRtl: state.locales.isRtl,        isShowingProject: getIsShowingProject(loadingState),        loadingStateVisible: state.scratchGui.modals.loadingProject,        projectId: state.scratchGui.projectState.projectId,        soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX,        targetIsStage: (            state.scratchGui.targets.stage &&            state.scratchGui.targets.stage.id === state.scratchGui.targets.editingTarget        ),        telemetryModalVisible: state.scratchGui.modals.telemetryModal,        tipsLibraryVisible: state.scratchGui.modals.tipsLibrary,        vm: state.scratchGui.vm,        loginState: getIsLogined(loginState)    };};

现在container / gui.jsx中定义的Component GUI具有登录状态属性了,我们要把它传到menu-bar中,因为我们要在menu-bar中去控制右上角的显示状态。

 

在这个GUI组件中使用了components / gui / gui.jsx定义的GUIComponent这个组件,GUIComponent定义了整个项目的基本样式结构中,可以找到对MenuBar的使用。

 

首先,在GUIComponent的定义中日期之前定义的`loginState`:

const GUIComponent = props => {    const {        accountNavOpen,        activeTabIndex,        alertsVisible,        authorId,        authorThumbnailUrl,        authorUsername,        basePath,        backdropLibraryVisible,        backpackHost,        backpackVisible,        blocksTabVisible,        cardsVisible,        canCreateNew,        canEditTitle,        canRemix,        canSave,        canCreateCopy,        canShare,        canUseCloud,        children,        connectionModalVisible,        costumeLibraryVisible,        costumesTabVisible,        enableCommunity,        intl,        isCreating,        isFullScreen,        isPlayerOnly,        isRtl,        isShared,        loading,        renderLogin,        onClickAccountNav,        onCloseAccountNav,        onLogOut,        onOpenRegistration,        onToggleLoginOpen,        onUpdateProjectTitle,        onActivateCostumesTab,        onActivateSoundsTab,        onActivateTab,        onClickLogo,        onExtensionButtonClick,        onProjectTelemetryEvent,        onRequestCloseBackdropLibrary,        onRequestCloseCostumeLibrary,        onRequestCloseTelemetryModal,        onSeeCommunity,        onShare,        onTelemetryModalCancel,        onTelemetryModalOptIn,        onTelemetryModalOptOut,        showComingSoon,        soundsTabVisible,        stageSizeMode,        targetIsStage,        telemetryModalVisible,        tipsLibraryVisible,        vm,        loginState,        ...componentProps    } = omit(props, 'dispatch');    ...

再在使用MenuBar的地方也为MenuBar定义`loginState`属性,它的值就是GUIComponent传进来的`loginState`的值:

<MenuBar                    accountNavOpen={accountNavOpen}                    authorId={authorId}                    authorThumbnailUrl={authorThumbnailUrl}                    authorUsername={authorUsername}                    canCreateCopy={canCreateCopy}                    canCreateNew={canCreateNew}                    canEditTitle={canEditTitle}                    canRemix={canRemix}                    canSave={canSave}                    canShare={canShare}                    className={styles.menuBarPosition}                    enableCommunity={enableCommunity}                    isShared={isShared}                    renderLogin={renderLogin}                    showComingSoon={showComingSoon}                    onClickAccountNav={onClickAccountNav}                    onClickLogo={onClickLogo}                    onCloseAccountNav={onCloseAccountNav}                    onLogOut={onLogOut}                    onOpenRegistration={onOpenRegistration}                    onProjectTelemetryEvent={onProjectTelemetryEvent}                    onSeeCommunity={onSeeCommunity}                    onShare={onShare}                    onToggleLoginOpen={onToggleLoginOpen}                    onUpdateProjectTitle={onUpdateProjectTitle}                    loginState={loginState}                />

最后修改components / menu-bar.jsx中的MenuBar组件的显示,将右上角替换成:

<React.Fragment>                            {this.props.loginState ? (                                <React.Fragment>                                    <MenuBarItemTooltip id="mystuff">                                        <div                                            className={classNames(                                                styles.menuBarItem,                                                styles.hoverable,                                                styles.mystuffButton                                            )}                                        >                                            <img                                                className={styles.mystuffIcon}                                                src={mystuffIcon}                                            />                                        </div>                                    </MenuBarItemTooltip>                                    <MenuBarItemTooltip                                        id="account-nav"                                        place={this.props.isRtl ? 'right' : 'left'}                                    >                                        <div                                            className={classNames(                                                styles.menuBarItem,                                                styles.hoverable,                                                styles.accountNavMenu                                            )}                                        >                                            <img                                                className={styles.profileIcon}                                                src={profileIcon}                                            />                                            <span>                                                {'scratch-cat'}                                            </span>                                            <img                                                className={styles.dropdownCaretIcon}                                                src={dropdownCaret}                                            />                                        </div>                                    </MenuBarItemTooltip>                                </React.Fragment>                            ) : <button >Login</button>}                        </React.Fragment>

如果用户已登录,就显示头像和姓名的样式(具体的用户信息需要跟后台打通,我们后面再实现):

否则显示登录按钮:

我们可以通过修改reducers / user-state.js中的loginState的初始值来查看效果:

loginState: UserState.NOT_LOGINED

loginState: UserState.LOGINED

这个值我们会在后面根据用户登录的token去获取。

 

为了与项目整体风格一致,我们修改这个登录按钮的样式,在菜单栏目录中添加login-button.css和login-button.jsx文件,内容分别如下:

​​

@import "../../css/colors.css";

.login-button {    background: $data-primary;}
import classNames from 'classnames';import {FormattedMessage} from 'react-intl';import PropTypes from 'prop-types';import React from 'react';import Button from '../button/button.jsx';

import styles from './login-button.css';

const LoginButton = ({    className,    onClick}) => (    <Button        className={classNames(            className,            styles.loginButton        )}        onClick={onClick}    >        <FormattedMessage            defaultMessage="Login"            description="Label for login"            id="gui.menuBar.login"        />

    </Button>);

LoginButton.propTypes = {    className: PropTypes.string,    onClick: PropTypes.func};

LoginButton.defaultProps = {    onClick: () => {}};

export default LoginButton;

然后在menu-bar.jsx中如下使用:

<LoginButton className={styles.menuBarButton} />

 这样看起来就好看多了:

好了,这里接收完成后,我们接下来就可以实现一个后台系统,然后对接后台系统登录和获取用户信息了。

上一章节链接:https://blog.csdn.net/tank_ft/article/details/104039006
下一章节链接:等待更新

有不懂的欢迎访问我的博客获取我的联系方式,手把手教哈,博客地址:http://www.liyblog.top/p/1.html

发布了9 篇原创文章 · 获赞 1 · 访问量 543

猜你喜欢

转载自blog.csdn.net/tank_ft/article/details/104094462