From 12b9cde507228d7fb67a98eda7f852aaff245153 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sat, 23 Feb 2019 16:25:22 +0100 Subject: [PATCH 01/17] Confirm modal now works for servers too --- .../ConfirmDeleteModal.js} | 29 ++++++++++--------- .../ConfirmDeleteModal.scss} | 0 app/components/DInstance/DInstance.js | 2 +- app/routes.js | 8 ++--- 4 files changed, 21 insertions(+), 18 deletions(-) rename app/components/{ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.js => ConfirmDeleteModal/ConfirmDeleteModal.js} (63%) rename app/components/{ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.scss => ConfirmDeleteModal/ConfirmDeleteModal.scss} (100%) diff --git a/app/components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.js b/app/components/ConfirmDeleteModal/ConfirmDeleteModal.js similarity index 63% rename from app/components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.js rename to app/components/ConfirmDeleteModal/ConfirmDeleteModal.js index edad39953..21441c568 100644 --- a/app/components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.js +++ b/app/components/ConfirmDeleteModal/ConfirmDeleteModal.js @@ -7,25 +7,30 @@ import { go } from 'connected-react-router'; import fs from 'fs'; import fsa from 'fs-extra'; import { promisify } from 'util'; -import styles from './ConfirmDeleteInstanceModal.scss'; +import styles from './ConfirmDeleteModal.scss'; import Modal from '../Common/Modal/Modal'; -import { PACKS_PATH } from '../../constants'; +import { PACKS_PATH, SERVERS_PATH } from '../../constants'; type Props = {}; export default props => { const [unMount, setUnMount] = useState(false); const [deleting, setDeleting] = useState(false); + const { name, type } = props.match.params; - const deleteInstance = async () => { - const { instance } = props.match.params; + const deleteType = async () => { + if (deleting === true) { + return; + } try { setDeleting(true); - await fsa.remove(path.join(PACKS_PATH, instance)); - message.success('Instance deleted'); + await fsa.remove( + path.join(type === 'instance' ? PACKS_PATH : SERVERS_PATH, name) + ); + message.success(`${type === 'instance' ? 'Instance' : 'Server'} deleted`); } catch (err) { setDeleting(false); - message.error('Error deleting instance'); + message.error(`Error deleting ${name}`); log.error(err); } finally { setUnMount(true); @@ -36,12 +41,12 @@ export default props => {
- Are you sure you want to delete the following instance?
-
{props.match.params.instance}
+ Are you sure you want to delete the following?
+
{props.match.params.name}
This cannot be undone and you will lose everything you've done
@@ -52,9 +57,7 @@ export default props => { > No, Abort - {}}> - Yes, Delete - + deleteType()}>Yes, Delete
); diff --git a/app/components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.scss b/app/components/ConfirmDeleteModal/ConfirmDeleteModal.scss similarity index 100% rename from app/components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal.scss rename to app/components/ConfirmDeleteModal/ConfirmDeleteModal.scss diff --git a/app/components/DInstance/DInstance.js b/app/components/DInstance/DInstance.js index 18a18cda6..0fabb9dab 100644 --- a/app/components/DInstance/DInstance.js +++ b/app/components/DInstance/DInstance.js @@ -325,7 +325,7 @@ export default class DInstance extends Component { data={{ foo: 'bar' }} onClick={() => history.push({ - pathname: `/confirmInstanceDelete/${name}`, + pathname: `/confirmInstanceDelete/instance/${name}`, state: { modal: true } }) } diff --git a/app/routes.js b/app/routes.js index 9de665cab..8a5ec74d7 100644 --- a/app/routes.js +++ b/app/routes.js @@ -42,8 +42,8 @@ const ImportPack = lazy(() => import('./components/ImportPack/ImportPack')); const ChangelogsModal = lazy(() => import('./components/ChangelogModal/ChangelogModal') ); -const ConfirmInstanceDelete = lazy(() => - import('./components/ConfirmDeleteInstanceModal/ConfirmDeleteInstanceModal') +const ConfirmDeleteModal = lazy(() => + import('./components/ConfirmDeleteModal/ConfirmDeleteModal') ); const JavaGlobalOptionsFixModal = lazy(() => import('./components/JavaGlobalOptionsFixModal/JavaGlobalOptionsFixModal') @@ -223,8 +223,8 @@ class RouteDef extends Component { ) : null} {isModal ? ( ) : null} {isModal ? ( From 19beeb356e38ebb990232201398efc4edbd13790 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sat, 23 Feb 2019 18:46:21 +0100 Subject: [PATCH 02/17] Fixed game sounds in versions < 1.6 --- app/actions/downloadManager.js | 6 +- app/utils/assets.js | 11 ++++ app/utils/getMCFilesList.js | 105 +++++++++++++++++++++------------ 3 files changed, 82 insertions(+), 40 deletions(-) diff --git a/app/actions/downloadManager.js b/app/actions/downloadManager.js index eac19f33d..0d24a8393 100644 --- a/app/actions/downloadManager.js +++ b/app/actions/downloadManager.js @@ -25,7 +25,7 @@ import { } from '../utils/getMCFilesList'; import { downloadMod, getModsList, createDoNotTouchFile } from '../utils/mods'; import { arraify } from '../utils/strings'; -import { copyAssetsToLegacy } from '../utils/assets'; +import { copyAssetsToLegacy, copyAssetsToResources } from '../utils/assets'; export const START_DOWNLOAD = 'START_DOWNLOAD'; export const CLEAR_QUEUE = 'CLEAR_QUEUE'; @@ -185,7 +185,7 @@ export function downloadPack(pack) { let forgeJSON = null; - const assets = await extractAssets(vnlJSON); + const assets = await extractAssets(vnlJSON, pack); const mainJar = await extractMainJar(vnlJSON); if (currPack.forgeVersion !== null) { @@ -392,6 +392,8 @@ export function downloadPack(pack) { if (vnlJSON.assets === 'legacy') { await copyAssetsToLegacy(assets); + } else if (vnlJSON.assets === 'pre-1.6') { + await copyAssetsToResources(assets); } await extractNatives(libraries.filter(lib => 'natives' in lib), pack); diff --git a/app/utils/assets.js b/app/utils/assets.js index 28eba8bfb..86bf017b6 100644 --- a/app/utils/assets.js +++ b/app/utils/assets.js @@ -14,3 +14,14 @@ export const copyAssetsToLegacy = async assets => { } }); }; + +export const copyAssetsToResources = async assets => { + await Promise.map(assets, async asset => { + try { + await promisify(fs.access)(asset.resourcesPath); + } catch { + await makeDir(path.dirname(asset.resourcesPath)); + await promisify(fs.copyFile)(asset.path, asset.resourcesPath); + } + }); +}; diff --git a/app/utils/getMCFilesList.js b/app/utils/getMCFilesList.js index be790fa30..511fc05f7 100644 --- a/app/utils/getMCFilesList.js +++ b/app/utils/getMCFilesList.js @@ -26,31 +26,40 @@ export const extractMainJar = async json => { export const extractVanillaLibs = async json => { const libs = []; await Promise.all( - json.libraries.filter(lib => !parseLibRules(lib.rules)).map(async lib => { - if ('artifact' in lib.downloads) { - libs.push({ - url: lib.downloads.artifact.url, - path: path.join(INSTANCES_PATH, 'libraries', lib.downloads.artifact.path) - }); - } - if ( - 'classifiers' in lib.downloads && - `natives-${convertOSToMCFormat(SysOS.type())}` in - lib.downloads.classifiers - ) { - libs.push({ - url: - lib.downloads.classifiers[ - `natives-${convertOSToMCFormat(SysOS.type())}` - ].url, - path: - path.join(INSTANCES_PATH, 'libraries', lib.downloads.classifiers[ - `natives-${convertOSToMCFormat(SysOS.type())}` - ].path), - natives: true - }); - } - }) + json.libraries + .filter(lib => !parseLibRules(lib.rules)) + .map(async lib => { + if ('artifact' in lib.downloads) { + libs.push({ + url: lib.downloads.artifact.url, + path: path.join( + INSTANCES_PATH, + 'libraries', + lib.downloads.artifact.path + ) + }); + } + if ( + 'classifiers' in lib.downloads && + `natives-${convertOSToMCFormat(SysOS.type())}` in + lib.downloads.classifiers + ) { + libs.push({ + url: + lib.downloads.classifiers[ + `natives-${convertOSToMCFormat(SysOS.type())}` + ].url, + path: path.join( + INSTANCES_PATH, + 'libraries', + lib.downloads.classifiers[ + `natives-${convertOSToMCFormat(SysOS.type())}` + ].path + ), + natives: true + }); + } + }) ); return libs; }; @@ -68,7 +77,7 @@ export const extractNatives = async (libs, packName) => { } }; -export const extractAssets = async json => { +export const extractAssets = async (json, instanceName) => { let res; const assets = []; const assetsFile = path.join( @@ -96,30 +105,50 @@ export const extractAssets = async json => { 0, 2 )}/${assetCont.hash}`, - path: path.join(INSTANCES_PATH, 'assets', 'objects', assetCont.hash.substring(0, 2), assetCont.hash), - legacyPath: path.join(INSTANCES_PATH, 'assets', 'virtual', 'legacy', asset) + path: path.join( + INSTANCES_PATH, + 'assets', + 'objects', + assetCont.hash.substring(0, 2), + assetCont.hash + ), + legacyPath: path.join( + INSTANCES_PATH, + 'assets', + 'virtual', + 'legacy', + asset + ), + resourcesPath: path.join(PACKS_PATH, instanceName, 'resources', asset) }); }); return assets; }; export const isVirtualAssets = async assetsName => { - const assetsJSON = await promisify(fs.readFile)(path.join( - INSTANCES_PATH, - 'assets', - 'indexes', - `${assetsName}.json` - )); + const assetsJSON = await promisify(fs.readFile)( + path.join(INSTANCES_PATH, 'assets', 'indexes', `${assetsName}.json`) + ); return _.has(assetsJSON, 'virtual') && assetsJSON.virtual === true; -} +}; + +export const isMapToResourcesAssets = async assetsName => { + const assetsJSON = await promisify(fs.readFile)( + path.join(INSTANCES_PATH, 'assets', 'indexes', `${assetsName}.json`) + ); + return ( + _.has(assetsJSON, 'map_to_resources') && + assetsJSON.map_to_resources === true + ); +}; export const getForgeLibraries = async forge => { const forgeLibCalculator = async library => { let completeUrl; if (_.has(library, 'url')) { - completeUrl = `${CURSEFORGE_MODLOADERS_API}/${arraify( - library.name - ).join('/')}`; + completeUrl = `${CURSEFORGE_MODLOADERS_API}/${arraify(library.name).join( + '/' + )}`; } else { completeUrl = `${MC_LIBRARIES_URL}/${arraify(library.name).join('/')}`; } From 64ba0b83343f71eb28e971221b0bf400536c3275 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sat, 23 Feb 2019 19:20:02 +0100 Subject: [PATCH 03/17] Implemented basic telemetry --- app/GAnalytics.js | 5 +++ .../JavaGlobalOptionsFixModal.js | 16 +++---- app/index.js | 4 +- app/routes.js | 43 +++++++++++++------ package.json | 1 + yarn.lock | 11 ++++- 6 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 app/GAnalytics.js diff --git a/app/GAnalytics.js b/app/GAnalytics.js new file mode 100644 index 000000000..61dcfed80 --- /dev/null +++ b/app/GAnalytics.js @@ -0,0 +1,5 @@ +import ua from 'universal-analytics'; + +const ga = uuid => ua('UA-135064026-2', uuid); + +export default ga; diff --git a/app/components/JavaGlobalOptionsFixModal/JavaGlobalOptionsFixModal.js b/app/components/JavaGlobalOptionsFixModal/JavaGlobalOptionsFixModal.js index bf8a81b00..7ec5c0b82 100644 --- a/app/components/JavaGlobalOptionsFixModal/JavaGlobalOptionsFixModal.js +++ b/app/components/JavaGlobalOptionsFixModal/JavaGlobalOptionsFixModal.js @@ -1,17 +1,12 @@ import React, { useState, useEffect } from 'react'; import { message, Button } from 'antd'; -import path from 'path'; import log from 'electron-log'; -import { Link } from 'react-router-dom'; -import { go } from 'connected-react-router'; -import fs from 'fs'; import { platform } from 'os'; import { remote } from 'electron'; -import fsa from 'fs-extra'; -import store from '../../localStore'; import { exec } from 'sudo-prompt'; -import child_process from 'child_process'; +import childProcess from 'child_process'; import { promisify } from 'util'; +import store from '../../localStore'; import styles from './JavaGlobalOptionsFixModal.scss'; import Modal from '../Common/Modal/Modal'; import { PACKS_PATH, WINDOWS } from '../../constants'; @@ -46,13 +41,12 @@ export default props => { setFixing(false); log.error(err); return; - } else { - log.error(err.message); } + log.error(err.message); } finally { try { // Removes the _JAVA_OPTIONS and sets it to empty in the user registry to apply it without rebooting - const { stdout, stderr } = await promisify(child_process.exec)( + const { stdout, stderr } = await promisify(childProcess.exec)( 'SETX _JAVA_OPTIONS "" & REG delete HKCU\\Environment /F /V _JAVA_OPTIONS' ); } catch {} @@ -60,7 +54,7 @@ export default props => { } else { try { // unset _JAVA_OPTIONS should be enough - const { stdout, stderr } = await promisify(child_process.exec)( + const { stdout, stderr } = await promisify(childProcess.exec)( 'unset _JAVA_OPTIONS' ); } catch {} diff --git a/app/index.js b/app/index.js index 0deddfd11..6a45d00f7 100644 --- a/app/index.js +++ b/app/index.js @@ -9,8 +9,8 @@ import './app.global.scss'; if (module.hot) setConfig({ ignoreSFC: true, // RHL will be __completely__ disabled for SFC - pureRender: true, // RHL will not change render method - }) + pureRender: true // RHL will not change render method + }); const store = configureStore(); log.info('Welcome to GDLauncher'); render( diff --git a/app/routes.js b/app/routes.js index 8a5ec74d7..496171d52 100644 --- a/app/routes.js +++ b/app/routes.js @@ -2,14 +2,16 @@ import React, { Component, lazy, Suspense } from 'react'; import { connect } from 'react-redux'; import { Switch, Route, Redirect } from 'react-router'; -import { history } from './store/configureStore'; import { Form, notification } from 'antd'; import { bindActionCreators } from 'redux'; +import { screen } from 'electron'; import * as AuthActions from './actions/auth'; import * as SettingsActions from './actions/settings'; import { JAVA_URL } from './constants'; +import ga from './GAnalytics'; import App from './containers/App'; import store from './localStore'; +import { history } from './store/configureStore'; import SideBar from './components/Common/SideBar/SideBar'; import Navigation from './containers/Navigation'; import SysNavBar from './components/Common/SystemNavBar/SystemNavBar'; @@ -61,6 +63,7 @@ class RouteDef extends Component { this.state = { globalJavaOptions: false }; + this.appVersion = require('../package.json').version; } componentDidMount = async () => { @@ -100,6 +103,19 @@ class RouteDef extends Component { } componentDidUpdate = (prevProps, prevState) => { + if (this.props.isAuthValid && process.env.NODE_ENV === 'development') { + ga(this.props.uuid).set('ds', 'app'); + ga(this.props.uuid).set( + 'sr', + `${screen.getPrimaryDisplay().bounds.width}x${ + screen.getPrimaryDisplay().bounds.height + }` + ); + ga(this.props.uuid).set('vp', `${window.innerWidth}x${window.innerHeight}`); + ga(this.props.uuid) + .screenview(this.props.location.pathname, 'GDLauncher', this.appVersion) + .send(); + } if ( this.state.globalJavaOptions && this.props.location.pathname === '/home' && @@ -110,6 +126,17 @@ class RouteDef extends Component { state: { modal: true } }); this.setState({ globalJavaOptions: false }); + return; + } + /* Show the changelogs after an update */ + if ( + this.props.location.pathname === '/home' && + store.get('showChangelogs') !== false + ) { + history.push({ + pathname: `/changelogs`, + state: { modal: true } + }); } }; @@ -169,17 +196,6 @@ class RouteDef extends Component { - {/* Show the changelogs after an update */} - {location.pathname === '/home' && - store.get('showChangelogs') !== false && ( - - )} {/* ALL MODALS */} {isModal ? : null} {isModal ? ( @@ -261,7 +277,8 @@ function WaitingComponent(MyComponent) { function mapStateToProps(state) { return { location: state.router.location, - isAuthValid: state.auth.isAuthValid + isAuthValid: state.auth.isAuthValid, + uuid: state.auth.uuid }; } diff --git a/package.json b/package.json index bfa814c33..650cdbc82 100644 --- a/package.json +++ b/package.json @@ -224,6 +224,7 @@ "request-promise-native": "^1.0.5", "source-map-support": "^0.5.10", "sudo-prompt": "^8.2.5", + "universal-analytics": "^0.4.20", "version-sort": "^0.1.1" }, "browserslist": "electron 1.6", diff --git a/yarn.lock b/yarn.lock index 9255ab203..68b7157fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13209,6 +13209,15 @@ unist-util-visit@^1.1.0: dependencies: unist-util-visit-parents "^2.0.0" +universal-analytics@^0.4.20: + version "0.4.20" + resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" + integrity sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw== + dependencies: + debug "^3.0.0" + request "^2.88.0" + uuid "^3.0.0" + universal-user-agent@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.0.3.tgz#9f6f09f9cc33de867bb720d84c08069b14937c6c" @@ -13376,7 +13385,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.0.1, uuid@^3.3.2: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== From 9bbcc6d230bdaa1def2490503677414d1583666d Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sat, 23 Feb 2019 20:28:44 +0100 Subject: [PATCH 04/17] Fixed context-menu icons --- app/app.global.scss | 21 ++++++---------- app/components/DInstance/DInstance.js | 35 +++++++++++++++++++++------ app/utils/assets.js | 4 +++ 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/app/app.global.scss b/app/app.global.scss index 0e2f72e4b..a0068b45f 100644 --- a/app/app.global.scss +++ b/app/app.global.scss @@ -127,9 +127,6 @@ textarea, box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition: transform 100ms !important; - span:first-child { - padding: 0 10px; - } } .react-contextmenu span { @@ -151,9 +148,14 @@ textarea, cursor: pointer; font-weight: 400; line-height: 1.5; - padding: 4px 10px; + padding: 2px 10px; text-align: left; white-space: nowrap; + span { + color: $text-main-color; + width: 25px; + + } } .react-contextmenu-item.react-contextmenu-item--active, @@ -188,13 +190,6 @@ textarea, padding: 0; } -.react-contextmenu-item.react-contextmenu-submenu - > .react-contextmenu-item::after { - content: '▶'; - display: inline-block; - position: absolute; - right: 7px; -} .example-multiple-targets::after { content: attr(data-count); @@ -226,10 +221,10 @@ textarea, .ant-btn-group { a:first-child .ant-btn { - border-radius: 4px 0 0 4px; + border-radius: 2px 0 0 2px; } a:last-child .ant-btn { - border-radius: 0 4px 4px 0; + border-radius: 0 2px 2px 0; } } diff --git a/app/components/DInstance/DInstance.js b/app/components/DInstance/DInstance.js index 0fabb9dab..1ab5be5b0 100644 --- a/app/components/DInstance/DInstance.js +++ b/app/components/DInstance/DInstance.js @@ -243,11 +243,17 @@ export default class DInstance extends Component { > {playing.find(el => el.name === name) ? (
- Kill + + + {' '} + Kill
) : (
- Launch + + + {' '} + Launch
)} @@ -261,10 +267,16 @@ export default class DInstance extends Component { }) } > - Manage + + + {' '} + Manage shell.openItem(path.join(PACKS_PATH, name))}> - Open Folder + + + {' '} + Open Folder { @@ -300,7 +312,10 @@ export default class DInstance extends Component { process.env.NODE_ENV === 'development' } > - Create Shortcut + + + {' '} + Create Shortcut {/* { } onClick={() => this.props.addToQueue(name, version, forgeVersion)} > - Repair + + + {' '} + Repair { }) } > - Delete + + + {' '} + Delete diff --git a/app/utils/assets.js b/app/utils/assets.js index 86bf017b6..07899bcc8 100644 --- a/app/utils/assets.js +++ b/app/utils/assets.js @@ -4,6 +4,8 @@ import fs from 'fs'; import makeDir from 'make-dir'; import { promisify } from 'util'; +// This copies all the required assets to the "virtual" folder inside the assets folder +// This is needed for "virtual" assets versions export const copyAssetsToLegacy = async assets => { await Promise.map(assets, async asset => { try { @@ -15,6 +17,8 @@ export const copyAssetsToLegacy = async assets => { }); }; +// This copies all the required assets to the "resources" folder inside the instance +// This is needed for "pre-1.6" assets versions export const copyAssetsToResources = async assets => { await Promise.map(assets, async asset => { try { From 54ccfac5a9f2e0fa882ebd395bfee700ef27fb70 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sat, 23 Feb 2019 20:29:17 +0100 Subject: [PATCH 05/17] v0.11.5-beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 650cdbc82..c12593507 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gdlauncher", - "version": "0.11.4", + "version": "0.11.5-beta", "description": "GDLauncher is simple, yet powerful Minecraft custom launcher with a strong focus on the user experience", "keywords": [ "boilerplate", From 3c559abfaf03255ff709fd75cc9a71e8688b18b5 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sun, 24 Feb 2019 14:44:39 +0100 Subject: [PATCH 06/17] Implemented better and completely anonymous telemetry --- app/actions/auth.js | 87 ++++++++++++++++++++++++++++++++++----------- app/routes.js | 12 +++++-- 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/app/actions/auth.js b/app/actions/auth.js index 828e42541..7dd24b6e3 100644 --- a/app/actions/auth.js +++ b/app/actions/auth.js @@ -9,7 +9,7 @@ import store from '../localStore'; import { LOGIN_API, ACCESS_TOKEN_VALIDATION_URL, - ACCESS_TOKEN_REFRESH_URL, + ACCESS_TOKEN_REFRESH_URL } from '../constants'; export const LOGOUT = 'LOGOUT'; @@ -28,15 +28,20 @@ export function login(username, password, remember) { type: START_AUTH_LOADING }); try { - const { data, status } = await axios.post(LOGIN_API, { - agent: { - name: "Minecraft", - version: 1 + const { data, status } = await axios.post( + LOGIN_API, + { + agent: { + name: 'Minecraft', + version: 1 + }, + username, + password, + requestUser: true, + ...(store.get('clientToken') && { clientToken: getClientToken() }) }, - username, - password, - requestUser: true - }, { headers: { 'Content-Type': 'application/json' }, }); + { headers: { 'Content-Type': 'application/json' } } + ); if ( status === 200 && data !== undefined && @@ -48,7 +53,6 @@ export function login(username, password, remember) { username: data.user.username, displayName: data.selectedProfile.name, accessToken: data.accessToken, - clientToken: data.clientToken, legacy: data.selectedProfile.legacyProfile, uuid: data.selectedProfile.id, userID: data.selectedProfile.userId @@ -58,12 +62,16 @@ export function login(username, password, remember) { user: { ...payload }, + clientToken: data.clientToken, lastUsername: data.user.username }); } dispatch({ type: AUTH_SUCCESS, - payload + payload: { + ...payload, + clientToken: data.clientToken + } }); const { newUser } = store.get('settings'); @@ -111,13 +119,18 @@ export function checkAccessToken() { try { const res = await axios.post( ACCESS_TOKEN_VALIDATION_URL, - { accessToken: userData.accessToken }, + { + accessToken: userData.accessToken + }, { 'Content-Type': 'application/json;charset=UTF-8' } ); if (res.status === 204) { dispatch({ type: AUTH_SUCCESS, - payload: userData + payload: { + ...userData, + clientToken: getClientToken() + } }); dispatch(push('/home')); } @@ -133,7 +146,10 @@ export function checkAccessToken() { message.info('You are offline. Logging in in offline-mode'); dispatch({ type: AUTH_SUCCESS, - payload: userData + payload: { + ...userData, + clientToken: getClientToken() + } }); dispatch(push('/home')); } @@ -142,6 +158,8 @@ export function checkAccessToken() { type: STOP_TOKEN_CHECK_LOADING }); } + } else { + dispatch(push('/')); } }; } @@ -169,7 +187,7 @@ export function tryNativeLauncherProfiles() { ACCESS_TOKEN_REFRESH_URL, { accessToken, - clientToken: vnlJson.clientToken, + clientToken: getClientToken(), requestUser: true }, { 'Content-Type': 'application/json' } @@ -186,25 +204,29 @@ export function tryNativeLauncherProfiles() { username: data.user.username, displayName: data.selectedProfile.name, accessToken: data.accessToken, - clientToken: data.clientToken, legacy: data.selectedProfile.legacyProfile, uuid: data.selectedProfile.id, userID: data.selectedProfile.userId }; // We need to update the accessToken in launcher_profiles.json - vnlJson.authenticationDatabase[data.selectedProfile.userId].accessToken = - data.accessToken; + vnlJson.authenticationDatabase[ + data.selectedProfile.userId + ].accessToken = data.accessToken; await fsa.writeJson( path.join(vanillaMCPath, 'launcher_profiles.json'), vnlJson ); store.set({ user: { ...payload }, + clientToken: data.clientToken, lastUsername: data.user.username }); dispatch({ type: AUTH_SUCCESS, - payload + payload: { + ...payload, + clientToken: data.clientToken, + } }); const { newUser } = store.get('settings'); @@ -216,7 +238,9 @@ export function tryNativeLauncherProfiles() { } } } catch (err) { - message.error('We could not log you in through Minecraft Launcher. Invalid data.'); + message.error( + 'We could not log you in through Minecraft Launcher. Invalid data.' + ); dispatch({ type: AUTH_FAILED }); @@ -226,3 +250,26 @@ export function tryNativeLauncherProfiles() { } }; } + +// Util functions + +const uuidv4 = () => { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + ( + c ^ + (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) + ).toString(16) + ); +}; + +const getClientToken = () => { + const clientToken = store.get('clientToken'); + if ( + clientToken && + clientToken !== undefined && + typeof clientToken === 'string' + ) { + return clientToken; + } + return uuidv4().replace('-', ''); +}; diff --git a/app/routes.js b/app/routes.js index 496171d52..a5d2fad0c 100644 --- a/app/routes.js +++ b/app/routes.js @@ -5,6 +5,7 @@ import { Switch, Route, Redirect } from 'react-router'; import { Form, notification } from 'antd'; import { bindActionCreators } from 'redux'; import { screen } from 'electron'; +import { release, arch } from 'os'; import * as AuthActions from './actions/auth'; import * as SettingsActions from './actions/settings'; import { JAVA_URL } from './constants'; @@ -103,15 +104,22 @@ class RouteDef extends Component { } componentDidUpdate = (prevProps, prevState) => { - if (this.props.isAuthValid && process.env.NODE_ENV === 'development') { + if (this.props.isAuthValid) { + console.log(this.props.uuid); + ga(this.props.uuid).set('uid', this.props.uuid); ga(this.props.uuid).set('ds', 'app'); + ga(this.props.uuid).set('ua', `${release()} ${arch()}`); + ga(this.props.uuid).set('cd1', `${release()} ${arch()}`); ga(this.props.uuid).set( 'sr', `${screen.getPrimaryDisplay().bounds.width}x${ screen.getPrimaryDisplay().bounds.height }` ); - ga(this.props.uuid).set('vp', `${window.innerWidth}x${window.innerHeight}`); + ga(this.props.uuid).set( + 'vp', + `${window.innerWidth}x${window.innerHeight}` + ); ga(this.props.uuid) .screenview(this.props.location.pathname, 'GDLauncher', this.appVersion) .send(); From 785b3c4c9d12896980d4ec9369fb82875ae1e7d0 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Sun, 24 Feb 2019 14:45:54 +0100 Subject: [PATCH 07/17] Hotfix for telemetry --- app/routes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes.js b/app/routes.js index a5d2fad0c..a8b3bac30 100644 --- a/app/routes.js +++ b/app/routes.js @@ -286,7 +286,7 @@ function mapStateToProps(state) { return { location: state.router.location, isAuthValid: state.auth.isAuthValid, - uuid: state.auth.uuid + uuid: state.auth.clientToken }; } From e0772b14ea64305c5e2ca81c703742ebf83194d9 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Mon, 25 Feb 2019 17:18:48 +0100 Subject: [PATCH 08/17] Updated some antd components --- antd/lib/checkbox/Checkbox.d.ts | 50 +++ antd/lib/checkbox/Checkbox.js | 162 ++++++++ antd/lib/checkbox/Group.d.ts | 64 ++++ antd/lib/checkbox/Group.js | 217 +++++++++++ antd/lib/checkbox/index.d.ts | 4 + antd/lib/checkbox/index.js | 16 + antd/lib/checkbox/style/css.js | 5 + antd/lib/checkbox/style/index.css | 229 ++++++++++++ antd/lib/checkbox/style/index.d.ts | 2 + antd/lib/checkbox/style/index.js | 5 + antd/lib/checkbox/style/index.less | 4 +- antd/lib/checkbox/style/mixin.less | 22 +- antd/lib/style/components.less | 89 ++--- antd/lib/tree/DirectoryTree.d.ts | 33 ++ antd/lib/tree/DirectoryTree.js | 294 +++++++++++++++ antd/lib/tree/Tree.d.ts | 161 ++++++++ antd/lib/tree/Tree.js | 153 ++++++++ antd/lib/tree/index.d.ts | 4 + antd/lib/tree/index.js | 13 + antd/lib/tree/style/css.js | 7 + antd/lib/tree/style/directory.less | 95 +++++ antd/lib/tree/style/index.css | 570 +++++++++++++++++++++++++++++ antd/lib/tree/style/index.d.ts | 3 + antd/lib/tree/style/index.js | 7 + antd/lib/tree/style/index.less | 239 ++++++++++++ antd/lib/tree/style/mixin.less | 28 ++ antd/lib/tree/util.d.ts | 4 + antd/lib/tree/util.js | 87 +++++ app/app.global.scss | 4 + 29 files changed, 2514 insertions(+), 57 deletions(-) create mode 100644 antd/lib/checkbox/Checkbox.d.ts create mode 100644 antd/lib/checkbox/Checkbox.js create mode 100644 antd/lib/checkbox/Group.d.ts create mode 100644 antd/lib/checkbox/Group.js create mode 100644 antd/lib/checkbox/index.d.ts create mode 100644 antd/lib/checkbox/index.js create mode 100644 antd/lib/checkbox/style/css.js create mode 100644 antd/lib/checkbox/style/index.css create mode 100644 antd/lib/checkbox/style/index.d.ts create mode 100644 antd/lib/checkbox/style/index.js create mode 100644 antd/lib/tree/DirectoryTree.d.ts create mode 100644 antd/lib/tree/DirectoryTree.js create mode 100644 antd/lib/tree/Tree.d.ts create mode 100644 antd/lib/tree/Tree.js create mode 100644 antd/lib/tree/index.d.ts create mode 100644 antd/lib/tree/index.js create mode 100644 antd/lib/tree/style/css.js create mode 100644 antd/lib/tree/style/directory.less create mode 100644 antd/lib/tree/style/index.css create mode 100644 antd/lib/tree/style/index.d.ts create mode 100644 antd/lib/tree/style/index.js create mode 100644 antd/lib/tree/style/index.less create mode 100644 antd/lib/tree/style/mixin.less create mode 100644 antd/lib/tree/util.d.ts create mode 100644 antd/lib/tree/util.js diff --git a/antd/lib/checkbox/Checkbox.d.ts b/antd/lib/checkbox/Checkbox.d.ts new file mode 100644 index 000000000..035039028 --- /dev/null +++ b/antd/lib/checkbox/Checkbox.d.ts @@ -0,0 +1,50 @@ +import * as React from 'react'; +import * as PropTypes from 'prop-types'; +import CheckboxGroup, { CheckboxGroupContext } from './Group'; +import { ConfigConsumerProps } from '../config-provider'; +export interface AbstractCheckboxProps { + prefixCls?: string; + className?: string; + defaultChecked?: boolean; + checked?: boolean; + style?: React.CSSProperties; + disabled?: boolean; + onChange?: (e: T) => void; + onMouseEnter?: React.MouseEventHandler; + onMouseLeave?: React.MouseEventHandler; + onKeyPress?: React.KeyboardEventHandler; + onKeyDown?: React.KeyboardEventHandler; + value?: any; + tabIndex?: number; + name?: string; + children?: React.ReactNode; +} +export interface CheckboxProps extends AbstractCheckboxProps { + indeterminate?: boolean; +} +export interface CheckboxChangeEventTarget extends CheckboxProps { + checked: boolean; +} +export interface CheckboxChangeEvent { + target: CheckboxChangeEventTarget; + stopPropagation: () => void; + preventDefault: () => void; + nativeEvent: MouseEvent; +} +export default class Checkbox extends React.Component { + static Group: typeof CheckboxGroup; + static defaultProps: { + indeterminate: boolean; + }; + static contextTypes: { + checkboxGroup: PropTypes.Requireable; + }; + context: any; + private rcCheckbox; + shouldComponentUpdate(nextProps: CheckboxProps, nextState: {}, nextContext: CheckboxGroupContext): boolean; + focus(): void; + blur(): void; + saveCheckbox: (node: any) => void; + renderCheckbox: ({ getPrefixCls }: ConfigConsumerProps) => JSX.Element; + render(): JSX.Element; +} diff --git a/antd/lib/checkbox/Checkbox.js b/antd/lib/checkbox/Checkbox.js new file mode 100644 index 000000000..a8eccae11 --- /dev/null +++ b/antd/lib/checkbox/Checkbox.js @@ -0,0 +1,162 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var React = _interopRequireWildcard(require("react")); + +var PropTypes = _interopRequireWildcard(require("prop-types")); + +var _classnames = _interopRequireDefault(require("classnames")); + +var _rcCheckbox = _interopRequireDefault(require("rc-checkbox")); + +var _shallowequal = _interopRequireDefault(require("shallowequal")); + +var _configProvider = require("../config-provider"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +var __rest = void 0 && (void 0).__rest || function (s, e) { + var t = {}; + + for (var p in s) { + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + } + + if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; + } + return t; +}; + +var Checkbox = +/*#__PURE__*/ +function (_React$Component) { + _inherits(Checkbox, _React$Component); + + function Checkbox() { + var _this; + + _classCallCheck(this, Checkbox); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Checkbox).apply(this, arguments)); + + _this.saveCheckbox = function (node) { + _this.rcCheckbox = node; + }; + + _this.renderCheckbox = function (_ref) { + var _classNames; + + var getPrefixCls = _ref.getPrefixCls; + + var _assertThisInitialize = _assertThisInitialized(_assertThisInitialized(_this)), + props = _assertThisInitialize.props, + context = _assertThisInitialize.context; + + var customizePrefixCls = props.prefixCls, + className = props.className, + children = props.children, + indeterminate = props.indeterminate, + style = props.style, + onMouseEnter = props.onMouseEnter, + onMouseLeave = props.onMouseLeave, + restProps = __rest(props, ["prefixCls", "className", "children", "indeterminate", "style", "onMouseEnter", "onMouseLeave"]); + + var checkboxGroup = context.checkboxGroup; + var prefixCls = getPrefixCls('checkbox', customizePrefixCls); + + var checkboxProps = _extends({}, restProps); + + if (checkboxGroup) { + checkboxProps.onChange = function () { + if (restProps.onChange) { + restProps.onChange.apply(restProps, arguments); + } + + checkboxGroup.toggleOption({ + label: children, + value: props.value + }); + }; + + checkboxProps.checked = checkboxGroup.value.indexOf(props.value) !== -1; + checkboxProps.disabled = props.disabled || checkboxGroup.disabled; + } + + var classString = (0, _classnames["default"])(className, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-wrapper"), true), _defineProperty(_classNames, "".concat(prefixCls, "-wrapper-checked"), checkboxProps.checked), _defineProperty(_classNames, "".concat(prefixCls, "-wrapper-disabled"), checkboxProps.disabled), _classNames)); + var checkboxClass = (0, _classnames["default"])(_defineProperty({}, "".concat(prefixCls, "-indeterminate"), indeterminate)); + return React.createElement("label", { + className: classString, + style: style, + onMouseEnter: onMouseEnter, + onMouseLeave: onMouseLeave + }, React.createElement(_rcCheckbox["default"], _extends({}, checkboxProps, { + prefixCls: prefixCls, + className: checkboxClass, + ref: _this.saveCheckbox + })), children !== undefined && React.createElement("span", null, children)); + }; + + return _this; + } + + _createClass(Checkbox, [{ + key: "shouldComponentUpdate", + value: function shouldComponentUpdate(nextProps, nextState, nextContext) { + return !(0, _shallowequal["default"])(this.props, nextProps) || !(0, _shallowequal["default"])(this.state, nextState) || !(0, _shallowequal["default"])(this.context.checkboxGroup, nextContext.checkboxGroup); + } + }, { + key: "focus", + value: function focus() { + this.rcCheckbox.focus(); + } + }, { + key: "blur", + value: function blur() { + this.rcCheckbox.blur(); + } + }, { + key: "render", + value: function render() { + return React.createElement(_configProvider.ConfigConsumer, null, this.renderCheckbox); + } + }]); + + return Checkbox; +}(React.Component); + +exports["default"] = Checkbox; +Checkbox.defaultProps = { + indeterminate: false +}; +Checkbox.contextTypes = { + checkboxGroup: PropTypes.any +}; \ No newline at end of file diff --git a/antd/lib/checkbox/Group.d.ts b/antd/lib/checkbox/Group.d.ts new file mode 100644 index 000000000..41e27b20a --- /dev/null +++ b/antd/lib/checkbox/Group.d.ts @@ -0,0 +1,64 @@ +import * as React from 'react'; +import * as PropTypes from 'prop-types'; +import { CheckboxChangeEvent } from './Checkbox'; +import { ConfigConsumerProps } from '../config-provider'; +export declare type CheckboxValueType = string | number | boolean; +export interface CheckboxOptionType { + label: React.ReactNode; + value: CheckboxValueType; + disabled?: boolean; + onChange?: (e: CheckboxChangeEvent) => void; +} +export interface AbstractCheckboxGroupProps { + prefixCls?: string; + className?: string; + options?: Array; + disabled?: boolean; + style?: React.CSSProperties; +} +export interface CheckboxGroupProps extends AbstractCheckboxGroupProps { + defaultValue?: Array; + value?: Array; + onChange?: (checkedValue: Array) => void; +} +export interface CheckboxGroupState { + value: any; +} +export interface CheckboxGroupContext { + checkboxGroup: { + toggleOption: (option: CheckboxOptionType) => void; + value: any; + disabled: boolean; + }; +} +declare class CheckboxGroup extends React.Component { + static defaultProps: { + options: never[]; + }; + static propTypes: { + defaultValue: PropTypes.Requireable; + value: PropTypes.Requireable; + options: PropTypes.Validator; + onChange: PropTypes.Requireable<(...args: any[]) => any>; + }; + static childContextTypes: { + checkboxGroup: PropTypes.Requireable; + }; + static getDerivedStateFromProps(nextProps: CheckboxGroupProps): { + value: CheckboxValueType[]; + } | null; + constructor(props: CheckboxGroupProps); + getChildContext(): { + checkboxGroup: { + toggleOption: (option: CheckboxOptionType) => void; + value: any; + disabled: boolean | undefined; + }; + }; + shouldComponentUpdate(nextProps: CheckboxGroupProps, nextState: CheckboxGroupState): boolean; + getOptions(): CheckboxOptionType[]; + toggleOption: (option: CheckboxOptionType) => void; + renderGroup: ({ getPrefixCls }: ConfigConsumerProps) => JSX.Element; + render(): JSX.Element; +} +export default CheckboxGroup; diff --git a/antd/lib/checkbox/Group.js b/antd/lib/checkbox/Group.js new file mode 100644 index 000000000..3a14b6af7 --- /dev/null +++ b/antd/lib/checkbox/Group.js @@ -0,0 +1,217 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var React = _interopRequireWildcard(require("react")); + +var PropTypes = _interopRequireWildcard(require("prop-types")); + +var _reactLifecyclesCompat = require("react-lifecycles-compat"); + +var _classnames = _interopRequireDefault(require("classnames")); + +var _shallowequal = _interopRequireDefault(require("shallowequal")); + +var _omit = _interopRequireDefault(require("omit.js")); + +var _Checkbox = _interopRequireDefault(require("./Checkbox")); + +var _configProvider = require("../config-provider"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +var __rest = void 0 && (void 0).__rest || function (s, e) { + var t = {}; + + for (var p in s) { + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + } + + if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; + } + return t; +}; + +var CheckboxGroup = +/*#__PURE__*/ +function (_React$Component) { + _inherits(CheckboxGroup, _React$Component); + + function CheckboxGroup(props) { + var _this; + + _classCallCheck(this, CheckboxGroup); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(CheckboxGroup).call(this, props)); + + _this.toggleOption = function (option) { + var optionIndex = _this.state.value.indexOf(option.value); + + var value = _toConsumableArray(_this.state.value); + + if (optionIndex === -1) { + value.push(option.value); + } else { + value.splice(optionIndex, 1); + } + + if (!('value' in _this.props)) { + _this.setState({ + value: value + }); + } + + var onChange = _this.props.onChange; + + if (onChange) { + onChange(value); + } + }; + + _this.renderGroup = function (_ref) { + var getPrefixCls = _ref.getPrefixCls; + + var _assertThisInitialize = _assertThisInitialized(_assertThisInitialized(_this)), + props = _assertThisInitialize.props, + state = _assertThisInitialize.state; + + var customizePrefixCls = props.prefixCls, + className = props.className, + style = props.style, + options = props.options, + restProps = __rest(props, ["prefixCls", "className", "style", "options"]); + + var prefixCls = getPrefixCls('checkbox', customizePrefixCls); + var groupPrefixCls = "".concat(prefixCls, "-group"); + var domProps = (0, _omit["default"])(restProps, ['children', 'defaultValue', 'value', 'onChange', 'disabled']); + var children = props.children; + + if (options && options.length > 0) { + children = _this.getOptions().map(function (option) { + return React.createElement(_Checkbox["default"], { + prefixCls: prefixCls, + key: option.value.toString(), + disabled: 'disabled' in option ? option.disabled : props.disabled, + value: option.value, + checked: state.value.indexOf(option.value) !== -1, + onChange: option.onChange, + className: "".concat(groupPrefixCls, "-item") + }, option.label); + }); + } + + var classString = (0, _classnames["default"])(groupPrefixCls, className); + return React.createElement("div", _extends({ + className: classString, + style: style + }, domProps), children); + }; + + _this.state = { + value: props.value || props.defaultValue || [] + }; + return _this; + } + + _createClass(CheckboxGroup, [{ + key: "getChildContext", + value: function getChildContext() { + return { + checkboxGroup: { + toggleOption: this.toggleOption, + value: this.state.value, + disabled: this.props.disabled + } + }; + } + }, { + key: "shouldComponentUpdate", + value: function shouldComponentUpdate(nextProps, nextState) { + return !(0, _shallowequal["default"])(this.props, nextProps) || !(0, _shallowequal["default"])(this.state, nextState); + } + }, { + key: "getOptions", + value: function getOptions() { + var options = this.props.options; // https://github.com/Microsoft/TypeScript/issues/7960 + + return options.map(function (option) { + if (typeof option === 'string') { + return { + label: option, + value: option + }; + } + + return option; + }); + } + }, { + key: "render", + value: function render() { + return React.createElement(_configProvider.ConfigConsumer, null, this.renderGroup); + } + }], [{ + key: "getDerivedStateFromProps", + value: function getDerivedStateFromProps(nextProps) { + if ('value' in nextProps) { + return { + value: nextProps.value || [] + }; + } + + return null; + } + }]); + + return CheckboxGroup; +}(React.Component); + +CheckboxGroup.defaultProps = { + options: [] +}; +CheckboxGroup.propTypes = { + defaultValue: PropTypes.array, + value: PropTypes.array, + options: PropTypes.array.isRequired, + onChange: PropTypes.func +}; +CheckboxGroup.childContextTypes = { + checkboxGroup: PropTypes.any +}; +(0, _reactLifecyclesCompat.polyfill)(CheckboxGroup); +var _default = CheckboxGroup; +exports["default"] = _default; \ No newline at end of file diff --git a/antd/lib/checkbox/index.d.ts b/antd/lib/checkbox/index.d.ts new file mode 100644 index 000000000..f04d33f2d --- /dev/null +++ b/antd/lib/checkbox/index.d.ts @@ -0,0 +1,4 @@ +import Checkbox from './Checkbox'; +export { CheckboxProps, CheckboxChangeEvent } from './Checkbox'; +export { CheckboxGroupProps, CheckboxOptionType } from './Group'; +export default Checkbox; diff --git a/antd/lib/checkbox/index.js b/antd/lib/checkbox/index.js new file mode 100644 index 000000000..929d5468b --- /dev/null +++ b/antd/lib/checkbox/index.js @@ -0,0 +1,16 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var _Checkbox = _interopRequireDefault(require("./Checkbox")); + +var _Group = _interopRequireDefault(require("./Group")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +_Checkbox["default"].Group = _Group["default"]; +var _default = _Checkbox["default"]; +exports["default"] = _default; \ No newline at end of file diff --git a/antd/lib/checkbox/style/css.js b/antd/lib/checkbox/style/css.js new file mode 100644 index 000000000..39466542c --- /dev/null +++ b/antd/lib/checkbox/style/css.js @@ -0,0 +1,5 @@ +"use strict"; + +require("../../style/index.css"); + +require("./index.css"); \ No newline at end of file diff --git a/antd/lib/checkbox/style/index.css b/antd/lib/checkbox/style/index.css new file mode 100644 index 000000000..50a5e7bad --- /dev/null +++ b/antd/lib/checkbox/style/index.css @@ -0,0 +1,229 @@ +/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */ +/* stylelint-disable no-duplicate-selectors */ +/* stylelint-disable */ +/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */ +@-webkit-keyframes antCheckboxEffect { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1.6); + transform: scale(1.6); + opacity: 0; + } +} +@keyframes antCheckboxEffect { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1.6); + transform: scale(1.6); + opacity: 0; + } +} +.ant-checkbox { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + white-space: nowrap; + cursor: pointer; + outline: none; + display: inline-block; + line-height: 1; + position: relative; + vertical-align: middle; + top: -0.09em; +} +.ant-checkbox-wrapper:hover .ant-checkbox-inner, +.ant-checkbox:hover .ant-checkbox-inner, +.ant-checkbox-input:focus + .ant-checkbox-inner { + border-color: #1890ff; +} +.ant-checkbox-checked:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 2px; + border: 1px solid #1890ff; + content: ''; + -webkit-animation: antCheckboxEffect 0.36s ease-in-out; + animation: antCheckboxEffect 0.36s ease-in-out; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + visibility: hidden; +} +.ant-checkbox:hover:after, +.ant-checkbox-wrapper:hover .ant-checkbox:after { + visibility: visible; +} +.ant-checkbox-inner { + position: relative; + top: 0; + left: 0; + display: block; + width: 16px; + height: 16px; + border: 1px solid #d9d9d9; + border-radius: 2px; + background-color: #fff; + -webkit-transition: all 0.3s; + transition: all 0.3s; + border-collapse: separate; +} +.ant-checkbox-inner:after { + -webkit-transform: rotate(45deg) scale(0) translate(-50%, -50%); + -ms-transform: rotate(45deg) scale(0) translate(-50%, -50%); + transform: rotate(45deg) scale(0) translate(-50%, -50%); + position: absolute; + top: 50%; + left: 21%; + display: table; + width: 5.71428571px; + height: 9.14285714px; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + -webkit-transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s; + transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s; + opacity: 0; +} +.ant-checkbox-input { + position: absolute; + left: 0; + z-index: 1; + cursor: pointer; + opacity: 0; + top: 0; + bottom: 0; + right: 0; + width: 100%; + height: 100%; +} +.ant-checkbox-checked .ant-checkbox-inner:after { + -webkit-transform: rotate(45deg) scale(1) translate(-50%, -50%); + -ms-transform: rotate(45deg) scale(1) translate(-50%, -50%); + transform: rotate(45deg) scale(1) translate(-50%, -50%); + position: absolute; + display: table; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + -webkit-transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s; + transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s; + opacity: 1; +} +.ant-checkbox-checked .ant-checkbox-inner { + background-color: #1890ff; + border-color: #1890ff; +} +.ant-checkbox-disabled { + cursor: not-allowed; +} +.ant-checkbox-disabled.ant-checkbox-checked .ant-checkbox-inner:after { + -webkit-animation-name: none; + animation-name: none; + border-color: rgba(0, 0, 0, 0.25); +} +.ant-checkbox-disabled .ant-checkbox-input { + cursor: not-allowed; +} +.ant-checkbox-disabled .ant-checkbox-inner { + border-color: #d9d9d9 !important; + background-color: #f5f5f5; +} +.ant-checkbox-disabled .ant-checkbox-inner:after { + -webkit-animation-name: none; + animation-name: none; + border-color: #f5f5f5; + border-collapse: separate; +} +.ant-checkbox-disabled + span { + color: rgba(0, 0, 0, 0.25); + cursor: not-allowed; +} +.ant-checkbox-wrapper { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + line-height: unset; + cursor: pointer; + display: inline-block; +} +.ant-checkbox-wrapper + .ant-checkbox-wrapper { + margin-left: 8px; +} +.ant-checkbox-wrapper + span, +.ant-checkbox + span { + padding-left: 8px; + padding-right: 8px; +} +.ant-checkbox-group { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + display: inline-block; +} +.ant-checkbox-group-item { + display: inline-block; + margin-right: 8px; +} +.ant-checkbox-group-item:last-child { + margin-right: 0; +} +.ant-checkbox-group-item + .ant-checkbox-group-item { + margin-left: 0; +} +.ant-checkbox-indeterminate .ant-checkbox-inner { + background-color: #fff; + border-color: #d9d9d9; +} +.ant-checkbox-indeterminate .ant-checkbox-inner:after { + content: ' '; + -webkit-transform: translate(-50%, -50%) scale(1); + -ms-transform: translate(-50%, -50%) scale(1); + transform: translate(-50%, -50%) scale(1); + border: 0; + left: 50%; + top: 50%; + width: 8px; + height: 8px; + background-color: #1890ff; + opacity: 1; +} +.ant-checkbox-indeterminate.ant-checkbox-disabled .ant-checkbox-inner:after { + border-color: rgba(0, 0, 0, 0.25); + background-color: rgba(0, 0, 0, 0.25); +} diff --git a/antd/lib/checkbox/style/index.d.ts b/antd/lib/checkbox/style/index.d.ts new file mode 100644 index 000000000..3a3ab0de5 --- /dev/null +++ b/antd/lib/checkbox/style/index.d.ts @@ -0,0 +1,2 @@ +import '../../style/index.less'; +import './index.less'; diff --git a/antd/lib/checkbox/style/index.js b/antd/lib/checkbox/style/index.js new file mode 100644 index 000000000..4e06645e9 --- /dev/null +++ b/antd/lib/checkbox/style/index.js @@ -0,0 +1,5 @@ +"use strict"; + +require("../../style/index.less"); + +require("./index.less"); \ No newline at end of file diff --git a/antd/lib/checkbox/style/index.less b/antd/lib/checkbox/style/index.less index fa88d365a..2d669f4f7 100644 --- a/antd/lib/checkbox/style/index.less +++ b/antd/lib/checkbox/style/index.less @@ -1,4 +1,4 @@ -@import "../../style/themes/default"; -@import "./mixin"; +@import '../../style/themes/default'; +@import './mixin'; .antCheckboxFn(); diff --git a/antd/lib/checkbox/style/mixin.less b/antd/lib/checkbox/style/mixin.less index 81fc57010..50d962785 100644 --- a/antd/lib/checkbox/style/mixin.less +++ b/antd/lib/checkbox/style/mixin.less @@ -1,7 +1,7 @@ -@import "../../style/mixins/index"; +@import '../../style/mixins/index'; -.antCheckboxFn(@checkbox-prefix-cls: ~"@{ant-prefix}-checkbox") { - @checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner"; +.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-checkbox') { + @checkbox-inner-prefix-cls: ~'@{checkbox-prefix-cls}-inner'; // 一般状态 .@{checkbox-prefix-cls} { .reset-component; @@ -28,7 +28,7 @@ height: 100%; border-radius: @border-radius-sm; border: 1px solid @checkbox-color; - content: ""; + content: ''; animation: antCheckboxEffect 0.36s ease-in-out; animation-fill-mode: both; visibility: hidden; @@ -49,7 +49,7 @@ border: @checkbox-border-width @border-style-base @border-color-base; border-radius: @border-radius-sm; background-color: @checkbox-check-color; - transition: all .3s; + transition: all 0.3s; // Fix IE checked style // https://github.com/ant-design/ant-design/issues/12597 border-collapse: separate; @@ -57,10 +57,10 @@ &:after { @check-width: (@checkbox-size / 14) * 5px; @check-height: (@checkbox-size / 14) * 8px; - transform: rotate(45deg) scale(0); + transform: rotate(45deg) scale(0) translate(-50%, -50%); position: absolute; - left: (@checkbox-size - @check-width) / 2 - 0.5px * (@checkbox-size / 14); - top: (@checkbox-size - @check-height) / 2 - 2px * (@checkbox-size / 14); + top: 50%; + left: 21%; display: table; width: @check-width; height: @check-height; @@ -68,7 +68,7 @@ border-top: 0; border-left: 0; content: ' '; - transition: all .1s @ease-in-back, opacity .1s; + transition: all 0.1s @ease-in-back, opacity 0.1s; opacity: 0; } } @@ -89,14 +89,14 @@ // 选中状态 .@{checkbox-prefix-cls}-checked .@{checkbox-inner-prefix-cls}:after { - transform: rotate(45deg) scale(1); + transform: rotate(45deg) scale(1) translate(-50%, -50%); position: absolute; display: table; border: 2px solid @checkbox-check-color; border-top: 0; border-left: 0; content: ' '; - transition: all .2s @ease-out-back .1s; + transition: all 0.2s @ease-out-back 0.1s; opacity: 1; } diff --git a/antd/lib/style/components.less b/antd/lib/style/components.less index 52411bdfa..293274e73 100644 --- a/antd/lib/style/components.less +++ b/antd/lib/style/components.less @@ -1,44 +1,45 @@ -@import "../affix/style/index.less"; -@import "../alert/style/index.less"; -@import "../anchor/style/index.less"; -@import "../auto-complete/style/index.less"; -@import "../avatar/style/index.less"; -@import "../back-top/style/index.less"; -@import "../badge/style/index.less"; -@import "../breadcrumb/style/index.less"; -@import "../button/style/index.less"; -@import "../calendar/style/index.less"; -@import "../card/style/index.less"; -@import "../carousel/style/index.less"; -@import "../cascader/style/index.less"; -@import "../checkbox/style/index.less"; -@import "../collapse/style/index.less"; -@import "../comment/style/index.less"; -@import "../config-provider/style/index.less"; -@import "../divider/style/index.less"; -@import "../drawer/style/index.less"; -@import "../dropdown/style/index.less"; -@import "../form/style/index.less"; -@import "../grid/style/index.less"; -@import "../icon/style/index.less"; -@import "../input/style/index.less"; -@import "../input-number/style/index.less"; -@import "../layout/style/index.less"; -@import "../list/style/index.less"; -@import "../locale-provider/style/index.less"; -@import "../menu/style/index.less"; -@import "../message/style/index.less"; -@import "../modal/style/index.less"; -@import "../notification/style/index.less"; -@import "../pagination/style/index.less"; -@import "../popover/style/index.less"; -@import "../progress/style/index.less"; -@import "../radio/style/index.less"; -@import "../select/style/index.less"; -@import "../skeleton/style/index.less"; -@import "../slider/style/index.less"; -@import "../spin/style/index.less"; -@import "../switch/style/index.less"; -@import "../table/style/index.less"; -@import "../tabs/style/index.less"; -@import "../tooltip/style/index.less"; +@import '../affix/style/index.less'; +@import '../alert/style/index.less'; +@import '../anchor/style/index.less'; +@import '../auto-complete/style/index.less'; +@import '../avatar/style/index.less'; +@import '../back-top/style/index.less'; +@import '../badge/style/index.less'; +@import '../breadcrumb/style/index.less'; +@import '../button/style/index.less'; +@import '../calendar/style/index.less'; +@import '../card/style/index.less'; +@import '../carousel/style/index.less'; +@import '../cascader/style/index.less'; +@import '../checkbox/style/index.less'; +@import '../collapse/style/index.less'; +@import '../comment/style/index.less'; +@import '../config-provider/style/index.less'; +@import '../divider/style/index.less'; +@import '../drawer/style/index.less'; +@import '../dropdown/style/index.less'; +@import '../form/style/index.less'; +@import '../grid/style/index.less'; +@import '../icon/style/index.less'; +@import '../input/style/index.less'; +@import '../input-number/style/index.less'; +@import '../layout/style/index.less'; +@import '../list/style/index.less'; +@import '../locale-provider/style/index.less'; +@import '../menu/style/index.less'; +@import '../message/style/index.less'; +@import '../modal/style/index.less'; +@import '../notification/style/index.less'; +@import '../pagination/style/index.less'; +@import '../popover/style/index.less'; +@import '../progress/style/index.less'; +@import '../radio/style/index.less'; +@import '../select/style/index.less'; +@import '../skeleton/style/index.less'; +@import '../slider/style/index.less'; +@import '../spin/style/index.less'; +@import '../switch/style/index.less'; +@import '../table/style/index.less'; +@import '../tabs/style/index.less'; +@import '../tree/style/index.less'; +@import '../tooltip/style/index.less'; diff --git a/antd/lib/tree/DirectoryTree.d.ts b/antd/lib/tree/DirectoryTree.d.ts new file mode 100644 index 000000000..a19fcfe02 --- /dev/null +++ b/antd/lib/tree/DirectoryTree.d.ts @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { ConfigConsumerProps } from '../config-provider'; +import Tree, { TreeProps, AntTreeNodeExpandedEvent, AntTreeNodeSelectedEvent, AntTreeNode } from './Tree'; +export declare type ExpandAction = false | 'click' | 'doubleClick'; +export interface DirectoryTreeProps extends TreeProps { + expandAction?: ExpandAction; +} +export interface DirectoryTreeState { + expandedKeys?: string[]; + selectedKeys?: string[]; +} +export default class DirectoryTree extends React.Component { + static defaultProps: { + showIcon: boolean; + expandAction: string; + }; + state: DirectoryTreeState; + tree: Tree; + onDebounceExpand: (event: React.MouseEvent, node: AntTreeNode) => void; + lastSelectedKey?: string; + cachedSelectedKeys?: string[]; + constructor(props: DirectoryTreeProps); + componentWillReceiveProps(nextProps: DirectoryTreeProps): void; + onExpand: (expandedKeys: string[], info: AntTreeNodeExpandedEvent) => void | PromiseLike; + onClick: (event: React.MouseEvent, node: AntTreeNode) => void; + onDoubleClick: (event: React.MouseEvent, node: AntTreeNode) => void; + onSelect: (keys: string[], event: AntTreeNodeSelectedEvent) => void; + setTreeRef: (node: Tree) => void; + expandFolderNode: (event: React.MouseEvent, node: AntTreeNode) => void; + setUncontrolledState: (state: DirectoryTreeState) => void; + renderDirectoryTree: ({ getPrefixCls }: ConfigConsumerProps) => JSX.Element; + render(): JSX.Element; +} diff --git a/antd/lib/tree/DirectoryTree.js b/antd/lib/tree/DirectoryTree.js new file mode 100644 index 000000000..4b3805c1f --- /dev/null +++ b/antd/lib/tree/DirectoryTree.js @@ -0,0 +1,294 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var React = _interopRequireWildcard(require("react")); + +var _classnames = _interopRequireDefault(require("classnames")); + +var _omit = _interopRequireDefault(require("omit.js")); + +var _debounce = _interopRequireDefault(require("lodash/debounce")); + +var _util = require("rc-tree/lib/util"); + +var _configProvider = require("../config-provider"); + +var _Tree = _interopRequireDefault(require("./Tree")); + +var _util2 = require("./util"); + +var _icon = _interopRequireDefault(require("../icon")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +var __rest = void 0 && (void 0).__rest || function (s, e) { + var t = {}; + + for (var p in s) { + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + } + + if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; + } + return t; +}; + +function getIcon(props) { + var isLeaf = props.isLeaf, + expanded = props.expanded; + + if (isLeaf) { + return React.createElement(_icon["default"], { + type: "file" + }); + } + + return React.createElement(_icon["default"], { + type: expanded ? 'folder-open' : 'folder' + }); +} + +var DirectoryTree = +/*#__PURE__*/ +function (_React$Component) { + _inherits(DirectoryTree, _React$Component); + + function DirectoryTree(props) { + var _this; + + _classCallCheck(this, DirectoryTree); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(DirectoryTree).call(this, props)); + + _this.onExpand = function (expandedKeys, info) { + var onExpand = _this.props.onExpand; + + _this.setUncontrolledState({ + expandedKeys: expandedKeys + }); // Call origin function + + + if (onExpand) { + return onExpand(expandedKeys, info); + } + + return undefined; + }; + + _this.onClick = function (event, node) { + var _this$props = _this.props, + onClick = _this$props.onClick, + expandAction = _this$props.expandAction; // Expand the tree + + if (expandAction === 'click') { + _this.onDebounceExpand(event, node); + } + + if (onClick) { + onClick(event, node); + } + }; + + _this.onDoubleClick = function (event, node) { + var _this$props2 = _this.props, + onDoubleClick = _this$props2.onDoubleClick, + expandAction = _this$props2.expandAction; // Expand the tree + + if (expandAction === 'doubleClick') { + _this.onDebounceExpand(event, node); + } + + if (onDoubleClick) { + onDoubleClick(event, node); + } + }; + + _this.onSelect = function (keys, event) { + var _this$props3 = _this.props, + onSelect = _this$props3.onSelect, + multiple = _this$props3.multiple, + children = _this$props3.children; + var _this$state$expandedK = _this.state.expandedKeys, + expandedKeys = _this$state$expandedK === void 0 ? [] : _this$state$expandedK; + var node = event.node, + nativeEvent = event.nativeEvent; + var _node$props$eventKey = node.props.eventKey, + eventKey = _node$props$eventKey === void 0 ? '' : _node$props$eventKey; + var newState = {}; // Windows / Mac single pick + + var ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey; + var shiftPick = nativeEvent.shiftKey; // Generate new selected keys + + var newSelectedKeys; + + if (multiple && ctrlPick) { + // Control click + newSelectedKeys = keys; + _this.lastSelectedKey = eventKey; + _this.cachedSelectedKeys = newSelectedKeys; + } else if (multiple && shiftPick) { + // Shift click + newSelectedKeys = Array.from(new Set([].concat(_toConsumableArray(_this.cachedSelectedKeys || []), _toConsumableArray((0, _util2.calcRangeKeys)(children, expandedKeys, eventKey, _this.lastSelectedKey))))); + } else { + // Single click + newSelectedKeys = [eventKey]; + _this.lastSelectedKey = eventKey; + _this.cachedSelectedKeys = newSelectedKeys; + } + + newState.selectedKeys = newSelectedKeys; + + if (onSelect) { + onSelect(newSelectedKeys, event); + } + + _this.setUncontrolledState(newState); + }; + + _this.setTreeRef = function (node) { + _this.tree = node; + }; + + _this.expandFolderNode = function (event, node) { + var isLeaf = node.props.isLeaf; + + if (isLeaf || event.shiftKey || event.metaKey || event.ctrlKey) { + return; + } // Get internal rc-tree + + + var internalTree = _this.tree.tree; // Call internal rc-tree expand function + // https://github.com/ant-design/ant-design/issues/12567 + + internalTree.onNodeExpand(event, node); + }; + + _this.setUncontrolledState = function (state) { + var newState = (0, _omit["default"])(state, Object.keys(_this.props)); + + if (Object.keys(newState).length) { + _this.setState(newState); + } + }; + + _this.renderDirectoryTree = function (_ref) { + var getPrefixCls = _ref.getPrefixCls; + + var _a = _this.props, + customizePrefixCls = _a.prefixCls, + className = _a.className, + props = __rest(_a, ["prefixCls", "className"]); + + var _this$state = _this.state, + expandedKeys = _this$state.expandedKeys, + selectedKeys = _this$state.selectedKeys; + var prefixCls = getPrefixCls('tree', customizePrefixCls); + var connectClassName = (0, _classnames["default"])("".concat(prefixCls, "-directory"), className); + return React.createElement(_Tree["default"], _extends({ + icon: getIcon, + ref: _this.setTreeRef + }, props, { + prefixCls: prefixCls, + className: connectClassName, + expandedKeys: expandedKeys, + selectedKeys: selectedKeys, + onSelect: _this.onSelect, + onClick: _this.onClick, + onDoubleClick: _this.onDoubleClick, + onExpand: _this.onExpand + })); + }; + + var defaultExpandAll = props.defaultExpandAll, + defaultExpandParent = props.defaultExpandParent, + expandedKeys = props.expandedKeys, + defaultExpandedKeys = props.defaultExpandedKeys, + children = props.children; + + var _convertTreeToEntitie = (0, _util.convertTreeToEntities)(children), + keyEntities = _convertTreeToEntitie.keyEntities; // Selected keys + + + _this.state = { + selectedKeys: props.selectedKeys || props.defaultSelectedKeys || [] + }; // Expanded keys + + if (defaultExpandAll) { + _this.state.expandedKeys = (0, _util2.getFullKeyList)(props.children); + } else if (defaultExpandParent) { + _this.state.expandedKeys = (0, _util.conductExpandParent)(expandedKeys || defaultExpandedKeys, keyEntities); + } else { + _this.state.expandedKeys = expandedKeys || defaultExpandedKeys; + } + + _this.onDebounceExpand = (0, _debounce["default"])(_this.expandFolderNode, 200, { + leading: true + }); + return _this; + } + + _createClass(DirectoryTree, [{ + key: "componentWillReceiveProps", + value: function componentWillReceiveProps(nextProps) { + if ('expandedKeys' in nextProps) { + this.setState({ + expandedKeys: nextProps.expandedKeys + }); + } + + if ('selectedKeys' in nextProps) { + this.setState({ + selectedKeys: nextProps.selectedKeys + }); + } + } + }, { + key: "render", + value: function render() { + return React.createElement(_configProvider.ConfigConsumer, null, this.renderDirectoryTree); + } + }]); + + return DirectoryTree; +}(React.Component); + +exports["default"] = DirectoryTree; +DirectoryTree.defaultProps = { + showIcon: true, + expandAction: 'click' +}; \ No newline at end of file diff --git a/antd/lib/tree/Tree.d.ts b/antd/lib/tree/Tree.d.ts new file mode 100644 index 000000000..c3caeae07 --- /dev/null +++ b/antd/lib/tree/Tree.d.ts @@ -0,0 +1,161 @@ +import * as React from 'react'; +import DirectoryTree from './DirectoryTree'; +import { ConfigConsumerProps } from '../config-provider'; +export interface AntdTreeNodeAttribute { + eventKey: string; + prefixCls: string; + className: string; + expanded: boolean; + selected: boolean; + checked: boolean; + halfChecked: boolean; + children: React.ReactNode; + title: React.ReactNode; + pos: string; + dragOver: boolean; + dragOverGapTop: boolean; + dragOverGapBottom: boolean; + isLeaf: boolean; + selectable: boolean; + disabled: boolean; + disableCheckbox: boolean; +} +export interface AntTreeNodeProps { + className?: string; + disabled?: boolean; + disableCheckbox?: boolean; + title?: string | React.ReactNode; + key?: string; + eventKey?: string; + isLeaf?: boolean; + checked?: boolean; + expanded?: boolean; + loading?: boolean; + selected?: boolean; + selectable?: boolean; + icon?: ((treeNode: AntdTreeNodeAttribute) => React.ReactNode) | React.ReactNode; + children?: React.ReactNode; + [customProp: string]: any; +} +export interface AntTreeNode extends React.Component { +} +export interface AntTreeNodeBaseEvent { + node: AntTreeNode; + nativeEvent: MouseEvent; +} +export interface AntTreeNodeCheckedEvent extends AntTreeNodeBaseEvent { + event: 'check'; + checked?: boolean; + checkedNodes?: AntTreeNode[]; +} +export interface AntTreeNodeSelectedEvent extends AntTreeNodeBaseEvent { + event: 'select'; + selected?: boolean; + selectedNodes?: AntTreeNode[]; +} +export interface AntTreeNodeExpandedEvent extends AntTreeNodeBaseEvent { + expanded?: boolean; +} +export interface AntTreeNodeMouseEvent { + node: AntTreeNode; + event: React.MouseEventHandler; +} +export interface AntTreeNodeDropEvent { + node: AntTreeNode; + dragNode: AntTreeNode; + dragNodesKeys: string[]; + dropPosition: number; + dropToGap?: boolean; + event: React.MouseEventHandler; +} +export interface TreeProps { + showLine?: boolean; + className?: string; + /** 是否支持多选 */ + multiple?: boolean; + /** 是否自动展开父节点 */ + autoExpandParent?: boolean; + /** checkable状态下节点选择完全受控(父子节点选中状态不再关联)*/ + checkStrictly?: boolean; + /** 是否支持选中 */ + checkable?: boolean; + /** 是否禁用树 */ + disabled?: boolean; + /** 默认展开所有树节点 */ + defaultExpandAll?: boolean; + /** 默认展开对应树节点 */ + defaultExpandParent?: boolean; + /** 默认展开指定的树节点 */ + defaultExpandedKeys?: string[]; + /** (受控)展开指定的树节点 */ + expandedKeys?: string[]; + /** (受控)选中复选框的树节点 */ + checkedKeys?: string[] | { + checked: string[]; + halfChecked: string[]; + }; + /** 默认选中复选框的树节点 */ + defaultCheckedKeys?: string[]; + /** (受控)设置选中的树节点 */ + selectedKeys?: string[]; + /** 默认选中的树节点 */ + defaultSelectedKeys?: string[]; + selectable?: boolean; + /** 展开/收起节点时触发 */ + onExpand?: (expandedKeys: string[], info: AntTreeNodeExpandedEvent) => void | PromiseLike; + /** 点击复选框触发 */ + onCheck?: (checkedKeys: string[] | { + checked: string[]; + halfChecked: string[]; + }, e: AntTreeNodeCheckedEvent) => void; + /** 点击树节点触发 */ + onSelect?: (selectedKeys: string[], e: AntTreeNodeSelectedEvent) => void; + /** 单击树节点触发 */ + onClick?: (e: React.MouseEvent, node: AntTreeNode) => void; + /** 双击树节点触发 */ + onDoubleClick?: (e: React.MouseEvent, node: AntTreeNode) => void; + /** filter some AntTreeNodes as you need. it should return true */ + filterAntTreeNode?: (node: AntTreeNode) => boolean; + /** 异步加载数据 */ + loadData?: (node: AntTreeNode) => PromiseLike; + loadedKeys?: string[]; + onLoaded?: (loadedKeys: string[], info: { + event: 'load'; + node: AntTreeNode; + }) => void; + /** 响应右键点击 */ + onRightClick?: (options: AntTreeNodeMouseEvent) => void; + /** 设置节点可拖拽(IE>8)*/ + draggable?: boolean; + onDragStart?: (options: AntTreeNodeMouseEvent) => void; + onDragEnter?: (options: AntTreeNodeMouseEvent) => void; + onDragOver?: (options: AntTreeNodeMouseEvent) => void; + onDragLeave?: (options: AntTreeNodeMouseEvent) => void; + onDragEnd?: (options: AntTreeNodeMouseEvent) => void; + onDrop?: (options: AntTreeNodeDropEvent) => void; + style?: React.CSSProperties; + showIcon?: boolean; + icon?: (nodeProps: AntdTreeNodeAttribute) => React.ReactNode | React.ReactNode; + switcherIcon?: React.ReactElement; + prefixCls?: string; + filterTreeNode?: (node: AntTreeNode) => boolean; + children?: React.ReactNode | React.ReactNode[]; +} +export default class Tree extends React.Component { + static TreeNode: React.ComponentClass; + static DirectoryTree: typeof DirectoryTree; + static defaultProps: { + checkable: boolean; + showIcon: boolean; + openAnimation: { + appear: null; + enter(node: HTMLElement, done: () => void): any; + leave(node: HTMLElement, done: () => void): any; + }; + }; + tree: any; + renderSwitcherIcon: (prefixCls: string, switcherIcon: React.ReactElement React.ReactElement React.Component)> | null) | (new (props: any) => React.Component)> | undefined, { isLeaf, expanded, loading }: AntTreeNodeProps) => JSX.Element | null; + setTreeRef: (node: any) => void; + renderTree: ({ getPrefixCls }: ConfigConsumerProps) => JSX.Element; + render(): JSX.Element; +} diff --git a/antd/lib/tree/Tree.js b/antd/lib/tree/Tree.js new file mode 100644 index 000000000..be5a4ae52 --- /dev/null +++ b/antd/lib/tree/Tree.js @@ -0,0 +1,153 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var React = _interopRequireWildcard(require("react")); + +var _rcTree = _interopRequireWildcard(require("rc-tree")); + +var _DirectoryTree = _interopRequireDefault(require("./DirectoryTree")); + +var _classnames = _interopRequireDefault(require("classnames")); + +var _icon = _interopRequireDefault(require("../icon")); + +var _configProvider = require("../config-provider"); + +var _openAnimation = _interopRequireDefault(require("../_util/openAnimation")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +var Tree = +/*#__PURE__*/ +function (_React$Component) { + _inherits(Tree, _React$Component); + + function Tree() { + var _this; + + _classCallCheck(this, Tree); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Tree).apply(this, arguments)); + + _this.renderSwitcherIcon = function (prefixCls, switcherIcon, _ref) { + var isLeaf = _ref.isLeaf, + expanded = _ref.expanded, + loading = _ref.loading; + var showLine = _this.props.showLine; + + if (loading) { + return React.createElement(_icon["default"], { + type: "loading", + className: "".concat(prefixCls, "-switcher-loading-icon") + }); + } + + if (showLine) { + if (isLeaf) { + return React.createElement(_icon["default"], { + type: "file", + className: "".concat(prefixCls, "-switcher-line-icon") + }); + } + + return React.createElement(_icon["default"], { + type: expanded ? 'minus-square' : 'plus-square', + className: "".concat(prefixCls, "-switcher-line-icon"), + theme: "outlined" + }); + } else { + var switcherCls = "".concat(prefixCls, "-switcher-icon"); + + if (isLeaf) { + return null; + } else if (switcherIcon) { + var switcherOriginCls = switcherIcon.props.className || ''; + return React.cloneElement(switcherIcon, { + className: [switcherOriginCls, switcherCls] + }); + } else { + return React.createElement(_icon["default"], { + type: "caret-down", + className: switcherCls, + theme: "filled" + }); + } + } + }; + + _this.setTreeRef = function (node) { + _this.tree = node; + }; + + _this.renderTree = function (_ref2) { + var getPrefixCls = _ref2.getPrefixCls; + var props = _this.props; + var customizePrefixCls = props.prefixCls, + className = props.className, + showIcon = props.showIcon, + _switcherIcon = props.switcherIcon; + var checkable = props.checkable; + var prefixCls = getPrefixCls('tree', customizePrefixCls); + return React.createElement(_rcTree["default"], _extends({ + ref: _this.setTreeRef + }, props, { + prefixCls: prefixCls, + className: (0, _classnames["default"])(!showIcon && "".concat(prefixCls, "-icon-hide"), className), + checkable: checkable ? React.createElement("span", { + className: "".concat(prefixCls, "-checkbox-inner") + }) : checkable, + switcherIcon: function switcherIcon(nodeProps) { + return _this.renderSwitcherIcon(prefixCls, _switcherIcon, nodeProps); + } + }), _this.props.children); + }; + + return _this; + } + + _createClass(Tree, [{ + key: "render", + value: function render() { + return React.createElement(_configProvider.ConfigConsumer, null, this.renderTree); + } + }]); + + return Tree; +}(React.Component); + +exports["default"] = Tree; +Tree.TreeNode = _rcTree.TreeNode; +Tree.DirectoryTree = _DirectoryTree["default"]; +Tree.defaultProps = { + checkable: false, + showIcon: false, + openAnimation: _extends({}, _openAnimation["default"], { + appear: null + }) +}; \ No newline at end of file diff --git a/antd/lib/tree/index.d.ts b/antd/lib/tree/index.d.ts new file mode 100644 index 000000000..5a2a83510 --- /dev/null +++ b/antd/lib/tree/index.d.ts @@ -0,0 +1,4 @@ +import Tree from './Tree'; +export { TreeProps, AntTreeNode, AntTreeNodeMouseEvent, AntTreeNodeExpandedEvent, AntTreeNodeCheckedEvent, AntTreeNodeSelectedEvent, AntdTreeNodeAttribute, AntTreeNodeProps, } from './Tree'; +export { ExpandAction as DirectoryTreeExpandAction, DirectoryTreeProps } from './DirectoryTree'; +export default Tree; diff --git a/antd/lib/tree/index.js b/antd/lib/tree/index.js new file mode 100644 index 000000000..9fff8153f --- /dev/null +++ b/antd/lib/tree/index.js @@ -0,0 +1,13 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = void 0; + +var _Tree = _interopRequireDefault(require("./Tree")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +var _default = _Tree["default"]; +exports["default"] = _default; \ No newline at end of file diff --git a/antd/lib/tree/style/css.js b/antd/lib/tree/style/css.js new file mode 100644 index 000000000..a57935191 --- /dev/null +++ b/antd/lib/tree/style/css.js @@ -0,0 +1,7 @@ +"use strict"; + +require("../../style/index.css"); + +require("./index.css"); + +require("../../checkbox/style/css"); \ No newline at end of file diff --git a/antd/lib/tree/style/directory.less b/antd/lib/tree/style/directory.less new file mode 100644 index 000000000..7718db4cd --- /dev/null +++ b/antd/lib/tree/style/directory.less @@ -0,0 +1,95 @@ +@import '../../style/themes/default'; + +@tree-prefix-cls: ~'@{ant-prefix}-tree'; + +.@{tree-prefix-cls} { + &.@{tree-prefix-cls}-directory { + position: relative; + + // Stretch selector width + > li, + .@{tree-prefix-cls}-child-tree > li { + span { + &.@{tree-prefix-cls}-switcher { + position: relative; + z-index: 1; + + &.@{tree-prefix-cls}-switcher-noop { + pointer-events: none; + } + } + + &.@{tree-prefix-cls}-checkbox { + position: relative; + z-index: 1; + } + + &.@{tree-prefix-cls}-node-content-wrapper { + user-select: none; + border-radius: 0; + + &:hover { + background: transparent; + + &:before { + background: @item-hover-bg; + } + } + + &.@{tree-prefix-cls}-node-selected { + color: @tree-directory-selected-color; + background: transparent; + } + + &:before { + content: ''; + position: absolute; + left: 0; + right: 0; + height: @tree-title-height; + transition: all 0.3s; + } + + > span { + position: relative; + z-index: 1; + } + } + } + + &.@{tree-prefix-cls}-treenode-selected { + > span { + &.@{tree-prefix-cls}-switcher { + color: @tree-directory-selected-color; + } + + &.@{tree-prefix-cls}-checkbox { + .@{tree-prefix-cls}-checkbox-inner { + border-color: @primary-color; + } + + &.@{tree-prefix-cls}-checkbox-checked { + &:after { + border-color: @checkbox-check-color; + } + + .@{tree-prefix-cls}-checkbox-inner { + background: @checkbox-check-color; + + &:after { + border-color: @primary-color; + } + } + } + } + + &.@{tree-prefix-cls}-node-content-wrapper { + &:before { + background: @tree-directory-selected-bg; + } + } + } + } + } + } +} diff --git a/antd/lib/tree/style/index.css b/antd/lib/tree/style/index.css new file mode 100644 index 000000000..3d1899893 --- /dev/null +++ b/antd/lib/tree/style/index.css @@ -0,0 +1,570 @@ +/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */ +/* stylelint-disable no-duplicate-selectors */ +/* stylelint-disable */ +/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */ +@-webkit-keyframes antCheckboxEffect { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1.6); + transform: scale(1.6); + opacity: 0; + } +} +@keyframes antCheckboxEffect { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1.6); + transform: scale(1.6); + opacity: 0; + } +} +.ant-tree.ant-tree-directory { + position: relative; +} +.ant-tree.ant-tree-directory > li span.ant-tree-switcher, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-switcher { + position: relative; + z-index: 1; +} +.ant-tree.ant-tree-directory > li span.ant-tree-switcher.ant-tree-switcher-noop, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-switcher.ant-tree-switcher-noop { + pointer-events: none; +} +.ant-tree.ant-tree-directory > li span.ant-tree-checkbox, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-checkbox { + position: relative; + z-index: 1; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 0; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper:hover, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper:hover { + background: transparent; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper:hover:before, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper:hover:before { + background: #e6f7ff; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper.ant-tree-node-selected, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper.ant-tree-node-selected { + color: #fff; + background: transparent; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper:before, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper:before { + content: ''; + position: absolute; + left: 0; + right: 0; + height: 24px; + -webkit-transition: all 0.3s; + transition: all 0.3s; +} +.ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper > span, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li span.ant-tree-node-content-wrapper > span { + position: relative; + z-index: 1; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-switcher, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-switcher { + color: #fff; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-checkbox .ant-tree-checkbox-inner, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-checkbox .ant-tree-checkbox-inner { + border-color: #1890ff; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked:after, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked:after { + border-color: #fff; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner { + background: #fff; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-checkbox.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after { + border-color: #1890ff; +} +.ant-tree.ant-tree-directory > li.ant-tree-treenode-selected > span.ant-tree-node-content-wrapper:before, +.ant-tree.ant-tree-directory .ant-tree-child-tree > li.ant-tree-treenode-selected > span.ant-tree-node-content-wrapper:before { + background: #1890ff; +} +.ant-tree-checkbox { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + white-space: nowrap; + cursor: pointer; + outline: none; + display: inline-block; + line-height: 1; + position: relative; + vertical-align: middle; + top: -0.09em; +} +.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-inner, +.ant-tree-checkbox:hover .ant-tree-checkbox-inner, +.ant-tree-checkbox-input:focus + .ant-tree-checkbox-inner { + border-color: #1890ff; +} +.ant-tree-checkbox-checked:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 2px; + border: 1px solid #1890ff; + content: ''; + -webkit-animation: antCheckboxEffect 0.36s ease-in-out; + animation: antCheckboxEffect 0.36s ease-in-out; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + visibility: hidden; +} +.ant-tree-checkbox:hover:after, +.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox:after { + visibility: visible; +} +.ant-tree-checkbox-inner { + position: relative; + top: 0; + left: 0; + display: block; + width: 16px; + height: 16px; + border: 1px solid #d9d9d9; + border-radius: 2px; + background-color: #fff; + -webkit-transition: all 0.3s; + transition: all 0.3s; + border-collapse: separate; +} +.ant-tree-checkbox-inner:after { + -webkit-transform: rotate(45deg) scale(0) translate(-50%, -50%); + -ms-transform: rotate(45deg) scale(0) translate(-50%, -50%); + transform: rotate(45deg) scale(0) translate(-50%, -50%); + position: absolute; + top: 50%; + left: 21%; + display: table; + width: 5.71428571px; + height: 9.14285714px; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + -webkit-transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s; + transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s; + opacity: 0; +} +.ant-tree-checkbox-input { + position: absolute; + left: 0; + z-index: 1; + cursor: pointer; + opacity: 0; + top: 0; + bottom: 0; + right: 0; + width: 100%; + height: 100%; +} +.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after { + -webkit-transform: rotate(45deg) scale(1) translate(-50%, -50%); + -ms-transform: rotate(45deg) scale(1) translate(-50%, -50%); + transform: rotate(45deg) scale(1) translate(-50%, -50%); + position: absolute; + display: table; + border: 2px solid #fff; + border-top: 0; + border-left: 0; + content: ' '; + -webkit-transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s; + transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s; + opacity: 1; +} +.ant-tree-checkbox-checked .ant-tree-checkbox-inner { + background-color: #1890ff; + border-color: #1890ff; +} +.ant-tree-checkbox-disabled { + cursor: not-allowed; +} +.ant-tree-checkbox-disabled.ant-tree-checkbox-checked .ant-tree-checkbox-inner:after { + -webkit-animation-name: none; + animation-name: none; + border-color: rgba(0, 0, 0, 0.25); +} +.ant-tree-checkbox-disabled .ant-tree-checkbox-input { + cursor: not-allowed; +} +.ant-tree-checkbox-disabled .ant-tree-checkbox-inner { + border-color: #d9d9d9 !important; + background-color: #f5f5f5; +} +.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after { + -webkit-animation-name: none; + animation-name: none; + border-color: #f5f5f5; + border-collapse: separate; +} +.ant-tree-checkbox-disabled + span { + color: rgba(0, 0, 0, 0.25); + cursor: not-allowed; +} +.ant-tree-checkbox-wrapper { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + line-height: unset; + cursor: pointer; + display: inline-block; +} +.ant-tree-checkbox-wrapper + .ant-tree-checkbox-wrapper { + margin-left: 8px; +} +.ant-tree-checkbox-wrapper + span, +.ant-tree-checkbox + span { + padding-left: 8px; + padding-right: 8px; +} +.ant-tree-checkbox-group { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + list-style: none; + display: inline-block; +} +.ant-tree-checkbox-group-item { + display: inline-block; + margin-right: 8px; +} +.ant-tree-checkbox-group-item:last-child { + margin-right: 0; +} +.ant-tree-checkbox-group-item + .ant-tree-checkbox-group-item { + margin-left: 0; +} +.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner { + background-color: #fff; + border-color: #d9d9d9; +} +.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner:after { + content: ' '; + -webkit-transform: translate(-50%, -50%) scale(1); + -ms-transform: translate(-50%, -50%) scale(1); + transform: translate(-50%, -50%) scale(1); + border: 0; + left: 50%; + top: 50%; + width: 8px; + height: 8px; + background-color: #1890ff; + opacity: 1; +} +.ant-tree-checkbox-indeterminate.ant-tree-checkbox-disabled .ant-tree-checkbox-inner:after { + border-color: rgba(0, 0, 0, 0.25); + background-color: rgba(0, 0, 0, 0.25); +} +.ant-tree { + font-size: 14px; + font-variant: tabular-nums; + -webkit-font-feature-settings: 'tnum'; + font-feature-settings: 'tnum'; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + -webkit-box-sizing: border-box; + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0; +} +.ant-tree ol, +.ant-tree ul { + list-style: none; + margin: 0; + padding: 0; +} +.ant-tree li { + padding: 4px 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; +} +.ant-tree li span[draggable], +.ant-tree li span[draggable='true'] { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-top: 2px transparent solid; + border-bottom: 2px transparent solid; + /* Required to make elements draggable in old WebKit */ + -khtml-user-drag: element; + -webkit-user-drag: element; + line-height: 20px; +} +.ant-tree li.drag-over > span[draggable] { + background-color: #1890ff; + color: white; + opacity: 0.8; +} +.ant-tree li.drag-over-gap-top > span[draggable] { + border-top-color: #1890ff; +} +.ant-tree li.drag-over-gap-bottom > span[draggable] { + border-bottom-color: #1890ff; +} +.ant-tree li.filter-node > span { + color: #f5222d !important; + font-weight: 500 !important; +} +.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-loading-icon, +.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-loading-icon { + display: inline-block; + position: absolute; + left: 0; + width: 24px; + height: 24px; + color: #1890ff; + -webkit-transform: none; + -ms-transform: none; + transform: none; + font-size: 14px; +} +.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-loading-icon svg, +.ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-loading-icon svg { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; +} +:root .ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_open:after, +:root .ant-tree li.ant-tree-treenode-loading span.ant-tree-switcher.ant-tree-switcher_close:after { + opacity: 0; +} +.ant-tree li ul { + margin: 0; + padding: 0 0 0 18px; +} +.ant-tree li .ant-tree-node-content-wrapper { + display: inline-block; + padding: 0 5px; + border-radius: 2px; + margin: 0; + cursor: pointer; + text-decoration: none; + vertical-align: top; + color: rgba(0, 0, 0, 0.65); + -webkit-transition: all 0.3s; + transition: all 0.3s; + height: 24px; + line-height: 24px; +} +.ant-tree li .ant-tree-node-content-wrapper:hover { + background-color: #e6f7ff; +} +.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected { + background-color: #bae7ff; +} +.ant-tree li span.ant-tree-checkbox { + margin: 4px 4px 0 2px; +} +.ant-tree li span.ant-tree-switcher, +.ant-tree li span.ant-tree-iconEle { + margin: 0; + width: 24px; + height: 24px; + line-height: 24px; + display: inline-block; + vertical-align: top; + border: 0 none; + cursor: pointer; + outline: none; + text-align: center; +} +.ant-tree li span.ant-tree-switcher { + position: relative; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher-noop { + cursor: default; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon, +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon { + font-size: 12px; + font-size: 10px \9; + -webkit-transform: scale(0.83333333) rotate(0deg); + -ms-transform: scale(0.83333333) rotate(0deg); + transform: scale(0.83333333) rotate(0deg); + display: inline-block; + font-weight: bold; +} +:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon, +:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon { + font-size: 12px; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon svg, +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon svg { + -webkit-transition: -webkit-transform 0.3s; + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon, +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon { + font-size: 12px; + font-size: 10px \9; + -webkit-transform: scale(0.83333333) rotate(0deg); + -ms-transform: scale(0.83333333) rotate(0deg); + transform: scale(0.83333333) rotate(0deg); + display: inline-block; + font-weight: bold; +} +:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon, +:root .ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon { + font-size: 12px; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg, +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon svg { + -webkit-transition: -webkit-transform 0.3s; + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} +.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg { + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); +} +.ant-tree li:last-child > span.ant-tree-switcher:before, +.ant-tree li:last-child > span.ant-tree-iconEle:before { + display: none; +} +.ant-tree > li:first-child { + padding-top: 7px; +} +.ant-tree > li:last-child { + padding-bottom: 7px; +} +.ant-tree-child-tree { + display: none; +} +.ant-tree-child-tree-open { + display: block; +} +li.ant-tree-treenode-disabled > span:not(.ant-tree-switcher), +li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper, +li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper span { + color: rgba(0, 0, 0, 0.25); + cursor: not-allowed; +} +li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper:hover { + background: transparent; +} +.ant-tree-icon__open { + margin-right: 2px; + vertical-align: top; +} +.ant-tree-icon__close { + margin-right: 2px; + vertical-align: top; +} +.ant-tree.ant-tree-show-line li { + position: relative; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher { + background: #fff; + color: rgba(0, 0, 0, 0.45); +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-tree-switcher-icon, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-select-switcher-icon { + font-size: 12px; + display: inline-block; + font-weight: normal; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-tree-switcher-icon svg, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher-noop .ant-select-switcher-icon svg { + -webkit-transition: -webkit-transform 0.3s; + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon { + font-size: 12px; + display: inline-block; + font-weight: normal; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-tree-switcher-icon svg, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_open .ant-select-switcher-icon svg { + -webkit-transition: -webkit-transform 0.3s; + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon { + font-size: 12px; + display: inline-block; + font-weight: normal; +} +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon svg, +.ant-tree.ant-tree-show-line li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon svg { + -webkit-transition: -webkit-transform 0.3s; + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} +.ant-tree.ant-tree-show-line li:not(:last-child):before { + content: ' '; + width: 1px; + border-left: 1px solid #d9d9d9; + height: 100%; + position: absolute; + left: 12px; + margin: 22px 0; +} +.ant-tree.ant-tree-icon-hide .ant-tree-treenode-loading .ant-tree-iconEle { + display: none; +} diff --git a/antd/lib/tree/style/index.d.ts b/antd/lib/tree/style/index.d.ts new file mode 100644 index 000000000..af4fc3c93 --- /dev/null +++ b/antd/lib/tree/style/index.d.ts @@ -0,0 +1,3 @@ +import '../../style/index.less'; +import './index.less'; +import '../../checkbox/style'; diff --git a/antd/lib/tree/style/index.js b/antd/lib/tree/style/index.js new file mode 100644 index 000000000..ddcbe8d90 --- /dev/null +++ b/antd/lib/tree/style/index.js @@ -0,0 +1,7 @@ +"use strict"; + +require("../../style/index.less"); + +require("./index.less"); + +require("../../checkbox/style"); \ No newline at end of file diff --git a/antd/lib/tree/style/index.less b/antd/lib/tree/style/index.less new file mode 100644 index 000000000..102afcda8 --- /dev/null +++ b/antd/lib/tree/style/index.less @@ -0,0 +1,239 @@ +@import '../../style/themes/default'; +@import '../../style/mixins/index'; +@import '../../checkbox/style/mixin'; +@import './mixin'; +@import './directory'; + +@tree-prefix-cls: ~'@{ant-prefix}-tree'; +@tree-showline-icon-color: @text-color-secondary; + +.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-tree-checkbox'); + +.@{tree-prefix-cls} { + .reset-component; + margin: 0; + padding: 0; + + ol, + ul { + list-style: none; + margin: 0; + padding: 0; + } + + li { + padding: 4px 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; + span[draggable], + span[draggable='true'] { + user-select: none; + border-top: 2px transparent solid; + border-bottom: 2px transparent solid; + /* Required to make elements draggable in old WebKit */ + -khtml-user-drag: element; + -webkit-user-drag: element; + + line-height: @tree-title-height - 4px; + } + &.drag-over { + > span[draggable] { + background-color: @primary-color; + color: white; + opacity: 0.8; + } + } + &.drag-over-gap-top { + > span[draggable] { + border-top-color: @primary-color; + } + } + &.drag-over-gap-bottom { + > span[draggable] { + border-bottom-color: @primary-color; + } + } + &.filter-node { + > span { + color: @highlight-color !important; + font-weight: 500 !important; + } + } + + // When node is loading + &.@{tree-prefix-cls}-treenode-loading { + span { + &.@{tree-prefix-cls}-switcher { + &.@{tree-prefix-cls}-switcher_open, + &.@{tree-prefix-cls}-switcher_close { + .@{tree-prefix-cls}-switcher-loading-icon { + display: inline-block; + position: absolute; + left: 0; + width: 24px; + height: 24px; + color: @primary-color; + transform: none; + font-size: 14px; + svg { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + } + } + + :root &:after { + opacity: 0; + } + } + } + } + } + + ul { + margin: 0; + padding: 0 0 0 @tree-child-padding; + } + .@{tree-prefix-cls}-node-content-wrapper { + display: inline-block; + padding: 0 5px; + border-radius: @border-radius-sm; + margin: 0; + cursor: pointer; + text-decoration: none; + vertical-align: top; + color: @text-color; + transition: all 0.3s; + height: @tree-title-height; + line-height: @tree-title-height; + &:hover { + background-color: @item-hover-bg; + } + &.@{tree-prefix-cls}-node-selected { + background-color: @primary-2; + } + } + span { + &.@{tree-prefix-cls}-checkbox { + margin: 4px 4px 0 2px; + } + &.@{tree-prefix-cls}-switcher, + &.@{tree-prefix-cls}-iconEle { + margin: 0; + width: 24px; + height: 24px; + line-height: @tree-title-height; + display: inline-block; + vertical-align: top; + border: 0 none; + cursor: pointer; + outline: none; + text-align: center; + } + + &.@{tree-prefix-cls}-switcher { + position: relative; + + &.@{tree-prefix-cls}-switcher-noop { + cursor: default; + } + &.@{tree-prefix-cls}-switcher_open { + .antTreeSwitcherIcon(); + } + &.@{tree-prefix-cls}-switcher_close { + .antTreeSwitcherIcon(); + .@{tree-prefix-cls}-switcher-icon { + svg { + transform: rotate(-90deg); + } + } + } + } + } + &:last-child > span { + &.@{tree-prefix-cls}-switcher, + &.@{tree-prefix-cls}-iconEle { + &:before { + display: none; + } + } + } + } + + > li { + &:first-child { + padding-top: 7px; + } + &:last-child { + padding-bottom: 7px; + } + } + &-child-tree { + display: none; + &-open { + display: block; + } + } + li&-treenode-disabled { + > span:not(.@{tree-prefix-cls}-switcher), + > .@{tree-prefix-cls}-node-content-wrapper, + > .@{tree-prefix-cls}-node-content-wrapper span { + color: @disabled-color; + cursor: not-allowed; + } + > .@{tree-prefix-cls}-node-content-wrapper:hover { + background: transparent; + } + } + &-icon__open { + margin-right: 2px; + vertical-align: top; + } + &-icon__close { + margin-right: 2px; + vertical-align: top; + } + // Tree with line + &&-show-line { + li { + position: relative; + span { + &.@{tree-prefix-cls}-switcher { + background: @component-background; + color: @tree-showline-icon-color; + &.@{tree-prefix-cls}-switcher-noop { + .antTreeShowLineIcon('tree-doc-icon'); + } + &.@{tree-prefix-cls}-switcher_open { + .antTreeShowLineIcon('tree-showline-open-icon'); + } + &.@{tree-prefix-cls}-switcher_close { + .antTreeShowLineIcon('tree-showline-close-icon'); + } + } + } + } + li:not(:last-child):before { + content: ' '; + width: 1px; + border-left: 1px solid @border-color-base; + height: 100%; + position: absolute; + left: 12px; + margin: 22px 0; + } + } + + &.@{tree-prefix-cls}-icon-hide { + .@{tree-prefix-cls}-treenode-loading { + .@{tree-prefix-cls}-iconEle { + display: none; + } + } + } +} diff --git a/antd/lib/tree/style/mixin.less b/antd/lib/tree/style/mixin.less new file mode 100644 index 000000000..360990533 --- /dev/null +++ b/antd/lib/tree/style/mixin.less @@ -0,0 +1,28 @@ +@import '../../style/mixins/index'; + +@tree-prefix-cls: ~'@{ant-prefix}-tree'; +@tree-select-prefix-cls: ~'@{ant-prefix}-select'; + +.antTreeSwitcherIcon(@type: 'tree-default-open-icon') { + .@{tree-prefix-cls}-switcher-icon, + .@{tree-select-prefix-cls}-switcher-icon { + .iconfont-size-under-12px(10px); + display: inline-block; + font-weight: bold; + svg { + transition: transform 0.3s; + } + } +} + +.antTreeShowLineIcon(@type) { + .@{tree-prefix-cls}-switcher-icon, + .@{tree-select-prefix-cls}-switcher-icon { + font-size: 12px; + display: inline-block; + font-weight: normal; + svg { + transition: transform 0.3s; + } + } +} diff --git a/antd/lib/tree/util.d.ts b/antd/lib/tree/util.d.ts new file mode 100644 index 000000000..887a0d786 --- /dev/null +++ b/antd/lib/tree/util.d.ts @@ -0,0 +1,4 @@ +import * as React from 'react'; +export declare function getFullKeyList(children: React.ReactNode | React.ReactNode[]): string[]; +/** 计算选中范围,只考虑expanded情况以优化性能 */ +export declare function calcRangeKeys(rootChildren: React.ReactNode | React.ReactNode[], expandedKeys: string[], startKey?: string, endKey?: string): string[]; diff --git a/antd/lib/tree/util.js b/antd/lib/tree/util.js new file mode 100644 index 000000000..01de20f17 --- /dev/null +++ b/antd/lib/tree/util.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFullKeyList = getFullKeyList; +exports.calcRangeKeys = calcRangeKeys; + +var _util = require("rc-tree/lib/util"); + +var Record; + +(function (Record) { + Record[Record["None"] = 0] = "None"; + Record[Record["Start"] = 1] = "Start"; + Record[Record["End"] = 2] = "End"; +})(Record || (Record = {})); // TODO: Move this logic into `rc-tree` + + +function traverseNodesKey(rootChildren, callback) { + var nodeList = (0, _util.getNodeChildren)(rootChildren) || []; + + function processNode(node) { + var key = node.key, + children = node.props.children; + + if (callback(key) !== false) { + traverseNodesKey(children, callback); + } + } + + nodeList.forEach(processNode); +} + +function getFullKeyList(children) { + var _convertTreeToEntitie = (0, _util.convertTreeToEntities)(children), + keyEntities = _convertTreeToEntitie.keyEntities; + + return Object.keys(keyEntities); +} +/** 计算选中范围,只考虑expanded情况以优化性能 */ + + +function calcRangeKeys(rootChildren, expandedKeys, startKey, endKey) { + var keys = []; + var record = Record.None; + + if (startKey && startKey === endKey) { + return [startKey]; + } + + if (!startKey || !endKey) { + return []; + } + + function matchKey(key) { + return key === startKey || key === endKey; + } + + traverseNodesKey(rootChildren, function (key) { + if (record === Record.End) { + return false; + } + + if (matchKey(key)) { + // Match test + keys.push(key); + + if (record === Record.None) { + record = Record.Start; + } else if (record === Record.Start) { + record = Record.End; + return false; + } + } else if (record === Record.Start) { + // Append selection + keys.push(key); + } + + if (expandedKeys.indexOf(key) === -1) { + return false; + } + + return true; + }); + return keys; +} \ No newline at end of file diff --git a/app/app.global.scss b/app/app.global.scss index a0068b45f..08269f9d5 100644 --- a/app/app.global.scss +++ b/app/app.global.scss @@ -452,6 +452,10 @@ textarea, background-color: var(--primary); } +.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected { + background-color: var(--primary); +} + .container { max-width: 24rem; margin: 1rem auto; From a028c6aede73723c0c860756cf8e602c46947470 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Wed, 27 Feb 2019 20:06:58 +0100 Subject: [PATCH 09/17] Fixed eslint config --- .eslintrc | 66 +--------------------------------------------------- package.json | 7 +++++- yarn.lock | 36 +++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 67 deletions(-) diff --git a/.eslintrc b/.eslintrc index ec57d3717..e9c05a80c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,69 +1,5 @@ { - "parser": "babel-eslint", - "parserOptions": { - "sourceType": "module", - "allowImportExportEverywhere": true - }, - "extends": ["airbnb", "prettier", "prettier/flowtype", "prettier/react"], - "env": { - "browser": true, - "node": true - }, - "rules": { - "arrow-parens": ["off"], - "compat/compat": "error", - "consistent-return": "off", - "comma-dangle": "off", - "flowtype/boolean-style": ["error", "boolean"], - "flowtype/define-flow-type": "warn", - "flowtype/delimiter-dangle": ["error", "never"], - "flowtype/generic-spacing": ["error", "never"], - "flowtype/no-primitive-constructor-types": "error", - "flowtype/no-weak-types": "warn", - "flowtype/object-type-delimiter": ["error", "comma"], - "flowtype/require-parameter-type": "off", - "flowtype/require-return-type": "off", - "flowtype/require-valid-file-annotation": "off", - "flowtype/semi": ["error", "always"], - "flowtype/space-after-type-colon": ["error", "always"], - "flowtype/space-before-generic-bracket": ["error", "never"], - "flowtype/space-before-type-colon": ["error", "never"], - "flowtype/union-intersection-spacing": ["error", "always"], - "flowtype/use-flow-type": "error", - "flowtype/valid-syntax": "error", - "generator-star-spacing": "off", - "import/no-unresolved": "error", - "import/no-extraneous-dependencies": "off", - "jsx-a11y/anchor-is-valid": "off", - "no-console": "off", - "no-use-before-define": "off", - "no-multi-assign": "off", - "promise/param-names": "error", - "promise/always-return": "error", - "promise/catch-or-return": "error", - "promise/no-native": "off", - "react/sort-comp": [ - "error", - { - "order": [ - "type-annotations", - "static-methods", - "lifecycle", - "everything-else", - "render" - ] - } - ], - "react/jsx-no-bind": "off", - "react/jsx-filename-extension": [ - "error", - { - "extensions": [".js", ".jsx"] - } - ], - "react/prefer-stateless-function": "off" - }, - "plugins": ["flowtype", "import", "promise", "compat", "react"], + "extends": "erb", "settings": { "import/resolver": { "webpack": { diff --git a/package.json b/package.json index c12593507..fa6c6613b 100644 --- a/package.json +++ b/package.json @@ -138,8 +138,10 @@ "eslint-plugin-import": "^2.16.0", "eslint-plugin-jest": "^22.2.2", "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-prettier": "^3.0.1", "eslint-plugin-promise": "^4.0.1", "eslint-plugin-react": "^7.12.4", + "eslint-plugin-testcafe": "^0.2.1", "fbjs-scripts": "^1.0.1", "file-loader": "^3.0.1", "flow-bin": "^0.92.1", @@ -189,9 +191,11 @@ "connected-react-router": "^6.3.1", "css-vars": "^2.2.0", "devtron": "^1.4.0", + "directory-tree": "^2.2.1", "electron-debug": "^2.1.0", "electron-log": "^3.0.1", "electron-store": "^2.0.0", + "eslint-config-erb": "^0.0.2", "extract-zip": "^1.6.7", "fs-extra": "^7.0.1", "history": "^4.7.2", @@ -225,7 +229,8 @@ "source-map-support": "^0.5.10", "sudo-prompt": "^8.2.5", "universal-analytics": "^0.4.20", - "version-sort": "^0.1.1" + "version-sort": "^0.1.1", + "yazl": "^2.5.1" }, "browserslist": "electron 1.6", "build": { diff --git a/yarn.lock b/yarn.lock index 68b7157fa..2a37c8f77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3940,6 +3940,11 @@ dir-glob@^2.2.1: dependencies: path-type "^3.0.0" +directory-tree@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/directory-tree/-/directory-tree-2.2.1.tgz#3d56ce8a82a6c9612ac0879c6b4ed9ea54e89bde" + integrity sha512-AWgnCDEKC2/oSAA/0Ae3RhXnMkvOZtNAVQu7wF2/qXF5Xm8LhjWnEXLV4Yza45SmWkNPvNlo4zWPhZjcVd4T5w== + discontinuous-range@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" @@ -4572,6 +4577,11 @@ eslint-config-airbnb@^17.1.0: object.assign "^4.1.0" object.entries "^1.0.4" +eslint-config-erb@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/eslint-config-erb/-/eslint-config-erb-0.0.2.tgz#0970873e44bdebb88a9c4b1201664cbc5a1604c4" + integrity sha512-l1yOp4wefwpZOrjwYJjSah/OU77b+GuaFrhx6WW92hWxxmOvgBPPoKSo8TeLEc/LNdK/lvw864GQQUti48V2zQ== + eslint-config-prettier@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.0.0.tgz#16cedeea0a56e74de60dcbbe3be0ab2c645405b9" @@ -4676,6 +4686,13 @@ eslint-plugin-jsx-a11y@6.2.1: has "^1.0.3" jsx-ast-utils "^2.0.1" +eslint-plugin-prettier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz#19d521e3981f69dd6d14f64aec8c6a6ac6eb0b0d" + integrity sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-promise@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" @@ -4694,6 +4711,11 @@ eslint-plugin-react@^7.12.4: prop-types "^15.6.2" resolve "^1.9.0" +eslint-plugin-testcafe@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-testcafe/-/eslint-plugin-testcafe-0.2.1.tgz#4089f646dadb69b1376a01d7e608184907e6036b" + integrity sha1-QIn2RtrbabE3agHX5ggYSQfmA2s= + eslint-restricted-globals@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" @@ -5103,6 +5125,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" @@ -10007,6 +10034,13 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@^1.14.3: version "1.16.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.0.tgz#104dd25f5ee3d0c9d0a6ce4bb40ced8481d51219" @@ -14113,7 +14147,7 @@ yauzl@^2.7.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yazl@^2.4.2: +yazl@^2.4.2, yazl@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== From 77b97fcfa3d3dc6fbe86d372b1b01f38afb262a5 Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Thu, 28 Feb 2019 01:18:08 +0100 Subject: [PATCH 10/17] Merged all instance's configs into one --- app/actions/downloadManager.js | 53 +++++++++---------- .../ModsManager/LocalMods/LocalMods.js | 13 ++--- .../ModsManager/ModsBrowser/ModPage.js | 17 +++--- .../ModsManager/ModsBrowser/ModsList.js | 4 +- .../ModsBrowser/ModsListWrapper.js | 2 +- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/app/actions/downloadManager.js b/app/actions/downloadManager.js index 0d24a8393..45b0ac63f 100644 --- a/app/actions/downloadManager.js +++ b/app/actions/downloadManager.js @@ -265,23 +265,15 @@ export function downloadPack(pack) { // This is the main config file for the instance await makeDir(path.join(PACKS_PATH, pack)); - const thumbnailURL = currPack.addonID - ? (await axios.get( - `${CURSEMETA_API_URL}/direct/addon/${currPack.addonID}` - )).data.attachments[0].thumbnailUrl - : null; + let thumbnailURL = null; - await promisify(fs.writeFile)( - path.join(PACKS_PATH, pack, 'config.json'), - JSON.stringify({ - version: currPack.version, - forgeVersion: - currPack.forgeVersion === null - ? null - : `forge-${currPack.forgeVersion}`, - timePlayed: 0 - }) - ); + if (currPack.addonID) { + const addonRequest = await axios.get( + `${CURSEMETA_API_URL}/direct/addon/${currPack.addonID}` + ); + + thumbnailURL = addonRequest.data.attachments[0].thumbnailUrl; + } // We download the legacy java fixer if needed const legacyJavaFixer = @@ -295,6 +287,7 @@ export function downloadPack(pack) { // Here we work on the mods await createDoNotTouchFile(pack); + let modsManifest = []; try { const manifest = JSON.parse( await promisify(fs.readFile)( @@ -313,14 +306,10 @@ export function downloadPack(pack) { ); }) ); - await fse.move( - path.join(INSTANCES_PATH, 'temp', pack, 'manifest.json'), - path.join(PACKS_PATH, pack, 'manifest.json') - ); - // await fse.remove(path.join(INSTANCES_PATH, 'temp', pack)); + + await fse.remove(path.join(INSTANCES_PATH, 'temp')); let modsDownloaded = 0; - let modsManifest = []; await Promise.map( manifest.files, async mod => { @@ -345,16 +334,24 @@ export function downloadPack(pack) { }, { concurrency: 4 } ); - - // Write the mods list to a file - await promisify(fs.writeFile)( - path.join(PACKS_PATH, pack, 'mods.json'), - JSON.stringify(modsManifest) - ); } catch (err) { log.error(err); } + await promisify(fs.writeFile)( + path.join(PACKS_PATH, pack, 'config.json'), + JSON.stringify({ + version: currPack.version, + forgeVersion: + currPack.forgeVersion === null + ? null + : `forge-${currPack.forgeVersion}`, + ...(currPack.addonID && { projectID: currPack.addonID }), + timePlayed: 0, + mods: modsManifest + }) + ); + const totalFiles = libraries.length + assets.length + mainJar.length; dispatch({ diff --git a/app/components/InstanceManagerModal/ModsManager/LocalMods/LocalMods.js b/app/components/InstanceManagerModal/ModsManager/LocalMods/LocalMods.js index 9ba86b536..2dc6b7487 100644 --- a/app/components/InstanceManagerModal/ModsManager/LocalMods/LocalMods.js +++ b/app/components/InstanceManagerModal/ModsManager/LocalMods/LocalMods.js @@ -110,16 +110,17 @@ const LocalMods = props => { // Remove the actual file await promisify(fss.unlink)(path.join(modsFolder, filteredMods[i].name)); // Remove the reference in the mods file json - const oldMods = JSON.parse( + const config = JSON.parse( await promisify(fss.readFile)( - path.join(PACKS_PATH, props.match.params.instance, 'mods.json') + path.join(PACKS_PATH, props.match.params.instance, 'config.json') ) ); await promisify(fss.writeFile)( - path.join(PACKS_PATH, props.match.params.instance, 'mods.json'), - JSON.stringify( - oldMods.filter(v => v.fileNameOnDisk !== filteredMods[i].name) - ) + path.join(PACKS_PATH, props.match.params.instance, 'config.json'), + JSON.stringify({ + ...config, + mods: config.mods.filter(v => v.fileNameOnDisk !== filteredMods[i].name) + }) ); }; diff --git a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModPage.js b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModPage.js index 22092d3d2..58c26a5f6 100644 --- a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModPage.js +++ b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModPage.js @@ -40,20 +40,21 @@ function ModPage(props) { projectFileId, props.instance ); - let modsFile = []; try { - modsFile = JSON.parse( + const config = JSON.parse( await promisify(fs.readFile)( - path.join(PACKS_PATH, props.instance, 'mods.json') + path.join(PACKS_PATH, props.instance, 'config.json') ) ); + await promisify(fs.writeFile)( + path.join(PACKS_PATH, props.instance, 'config.json'), + JSON.stringify({ + ...config, + mods: [...config.mods, newMod, ...dependancies] + }) + ); } catch {} - await promisify(fs.writeFile)( - path.join(PACKS_PATH, props.instance, 'mods.json'), - JSON.stringify([...modsFile, newMod, ...dependancies]) - ); - setModsInstalling({ ...modsInstalling, [filename]: { installing: false, completed: true } diff --git a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsList.js b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsList.js index 27d515129..df799e4b1 100644 --- a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsList.js +++ b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsList.js @@ -42,9 +42,9 @@ const ModsList = props => { const loadInstalledMods = async () => { const Imods = await promisify(fs.readFile)( - path.join(PACKS_PATH, props.match.params.instance, 'mods.json') + path.join(PACKS_PATH, props.match.params.instance, 'config.json') ); - setInstalledMods(JSON.parse(Imods)); + setInstalledMods(JSON.parse(Imods).mods); }; // The "e" param is just used for invoking this function without params in events handlers diff --git a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsListWrapper.js b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsListWrapper.js index be9b231cb..a9a4f2d9f 100644 --- a/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsListWrapper.js +++ b/app/components/InstanceManagerModal/ModsManager/ModsBrowser/ModsListWrapper.js @@ -100,7 +100,7 @@ export default function ModsListWrapper({ > {mod && mod.name} - {mod && installedMods.find(v => v.id === mod.id) && ( + {mod && installedMods.find(v => v.projectID === mod.id) && (
INSTALLED
)} From 7892fdf0a8c6ed0c39715dfb3897f0a7705969aa Mon Sep 17 00:00:00 2001 From: Davide Ceschia Date: Thu, 28 Feb 2019 01:20:14 +0100 Subject: [PATCH 11/17] Adapted mods downloader to new config format --- app/utils/mods.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/utils/mods.js b/app/utils/mods.js index 534aec39c..424a496cc 100644 --- a/app/utils/mods.js +++ b/app/utils/mods.js @@ -34,7 +34,8 @@ export const downloadMod = async ( () => {} ); return { - id: modId, + projectID: modId, + fileID: projectFileId, packageFingerprint: data.packageFingerprint, fileNameOnDisk: sanitizedFileName }; @@ -64,9 +65,9 @@ export const downloadDependancies = async ( // See if the mod already exists in this instance const installedMods = JSON.parse( await promisify(fs.readFile)( - path.join(PACKS_PATH, instanceName, 'mods.json') + path.join(PACKS_PATH, instanceName, 'config.json') ) - ); + ).mods; if (installedMods.find(v => v.id === dep.addonId)) toDownload = false; } catch { @@ -76,9 +77,9 @@ export const downloadDependancies = async ( const depData = await axios.get( `${CURSEMETA_API_URL}/direct/addon/${dep.addonId}/files` ); - const { id, fileNameOnDisk } = depData.data.reverse().find( - n => n.gameVersion[0] === gameVersion - ); + const { id, fileNameOnDisk } = depData.data + .reverse() + .find(n => n.gameVersion[0] === gameVersion); const downloadedDep = await downloadMod( dep.addonId, id, @@ -133,7 +134,7 @@ export const getModMurmurHash2 = async modPath => { export const createDoNotTouchFile = async instance => { await makeDir(path.join(PACKS_PATH, instance, 'mods')); await promisify(fs.writeFile)( - path.join(PACKS_PATH, instance, 'mods', '_DO_NOT_TOUCH_THIS_FOLDER.txt'), + path.join(PACKS_PATH, instance, 'mods', '_README_I_AM_VERY_IMPORTANT.txt'), 'Do not directly edit the files in this folder, if you want to delete a file or add one, use GDLauncher. \r DO NOT RENAME ANYTHING' ); }; From f1dbc84447ce7f4a06f0edaba865946011e2cd87 Mon Sep 17 00:00:00 2001 From: Gianmarco Date: Thu, 28 Feb 2019 17:24:07 +0100 Subject: [PATCH 12/17] Updated setting's and modpack's explorer close button --- .../CurseModpackExplorerModal.js | 15 +++++++------- .../CurseModpackExplorerModal.scss | 13 ++++++++++++ app/components/Settings/Settings.js | 6 +++++- app/components/Settings/Settings.scss | 20 ++++++++++++++++++- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/app/components/CurseModpackExplorerModal/CurseModpackExplorerModal.js b/app/components/CurseModpackExplorerModal/CurseModpackExplorerModal.js index aa9eaf678..36cdb96ca 100644 --- a/app/components/CurseModpackExplorerModal/CurseModpackExplorerModal.js +++ b/app/components/CurseModpackExplorerModal/CurseModpackExplorerModal.js @@ -5,6 +5,7 @@ import { Button } from 'antd'; import log from 'electron-log'; import ReactHtmlParser from 'react-html-parser'; import ProgressiveImage from 'react-progressive-image'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Modal from '../Common/Modal/Modal'; import { numberToRoundedWord } from '../../utils/numbers'; import { CURSEMETA_API_URL } from '../../constants'; @@ -51,12 +52,10 @@ export default props => { header="false" title="Modpack Explorer" backBtn={ - + ); +}; diff --git a/app/components/ExportPackModal/ContinueButton.js b/app/components/ExportPackModal/ContinueButton.js new file mode 100644 index 000000000..282c7788f --- /dev/null +++ b/app/components/ExportPackModal/ContinueButton.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { Button } from 'antd'; +import styles from './ExportPackModal.scss'; + +export default props => { + if (props.filePath === null) return null; + return ( + + ); +}; diff --git a/app/components/ExportPackModal/ExportPackModal.js b/app/components/ExportPackModal/ExportPackModal.js new file mode 100644 index 000000000..f9ddfb887 --- /dev/null +++ b/app/components/ExportPackModal/ExportPackModal.js @@ -0,0 +1,95 @@ +import { Button } from 'antd'; +import { remote } from 'electron'; +import path from 'path'; +import React, { useState } from 'react'; +import { connect } from 'react-redux'; +import Modal from '../Common/Modal/Modal'; +import FirstStep from './FirstStep'; +import SecondStep from './SecondStep'; +import BackButton from './BackButton'; +import ContinueButton from './ContinueButton'; +import styles from './ExportPackModal.scss'; +import ThirdStep from './ThirdStep'; +type Props = {}; + +const ExportPack = props => { + const [unMount, setUnMount] = useState(false); + // const [loading, setLoading] = useState(false); + const [filePath, setFilePath] = useState(null); + const [selectedFiles, setSelectedFiles] = useState([]); + const [actualStep, setActualStep] = useState(0); + // const [packType, setPackType] = useState('Twitch'); + + // const handleSubmit = e => { + // e.preventDefault(); + // form.validateFields(async (err, values) => { + // if (!err) { + // if (filePath === null) { + // message.warning('Please select a zip file.'); + // } + + // try { + // await promisify(fs.access)(path.join(PACKS_PATH, values.packName)); + // message.warning('An instance with this name already exists.'); + // } catch (error) { + // setLoading(true); + // await props.importTwitchProfile(values.packName, filePath); + // setUnMount(true); + // } + // } + // }); + // }; + + const showFileDialog = () => { + remote.dialog.showOpenDialog( + { + properties: ['openDirectory'] + }, + paths => { + setFilePath(paths[0]); + } + ); + }; + + return ( + + {actualStep === 0 && ( + + )} + {actualStep === 1 && ( + + )} + {actualStep === 2 && ( + + )} + + ); +}; + +const mapDispatchToProps = {}; + +export default connect( + null, + mapDispatchToProps +)(ExportPack); diff --git a/app/components/ExportPackModal/ExportPackModal.scss b/app/components/ExportPackModal/ExportPackModal.scss new file mode 100644 index 000000000..92d90977b --- /dev/null +++ b/app/components/ExportPackModal/ExportPackModal.scss @@ -0,0 +1,33 @@ +.container { + height: 85%; + width: 100%; + font-family: 'GlacialIndifferenceRegular'; + padding: 20px; + overflow-y: auto; +} + +.selectFolderBtn { + margin-top: 80px; + min-width: 130px; +} + +.continueBtn { + position: absolute; + bottom: 10px; + right: 10px; +} + +.backBtn { + position: absolute; + bottom: 10px; + left: 10px; +} + +.centeredDiv { + display: flex; + justify-content: center; + width: 100%; + height: 100%; + align-items: center; + text-align: center; +} diff --git a/app/components/ExportPackModal/FirstStep.js b/app/components/ExportPackModal/FirstStep.js new file mode 100644 index 000000000..c68d898dc --- /dev/null +++ b/app/components/ExportPackModal/FirstStep.js @@ -0,0 +1,33 @@ +import React from 'react'; +import path from 'path'; +import { Button, Checkbox } from 'antd'; +import ContinueButton from './ContinueButton'; + +import styles from './ExportPackModal.scss'; + +export default function FirstStep(props) { + return ( +
+
+
+

Where do you want to save the exported zip pack?

+ +
+
+ +
+ ); +} diff --git a/app/components/ExportPackModal/SecondStep.js b/app/components/ExportPackModal/SecondStep.js new file mode 100644 index 000000000..890123fce --- /dev/null +++ b/app/components/ExportPackModal/SecondStep.js @@ -0,0 +1,98 @@ +import React, { useEffect, useState } from 'react'; +import dirTree from 'directory-tree'; +import { Tree } from 'antd'; +import path from 'path'; +import { PACKS_PATH } from '../../constants'; +import BackButton from './BackButton'; +import ContinueButton from './ContinueButton'; +import styles from './ExportPackModal.scss'; + +export default function SecondStep(props) { + const [treeData, setTreeData] = useState([]); + const [expandedKeys, setExpandedKeys] = useState([]); + const [checkedKeys, setCheckedKeys] = useState([]); + const [selectedKeys, setSelectedKeys] = useState([]); + const [autoExpandParent, setAutoExpandParent] = useState(true); + + const filesToDisable = [ + path.join(PACKS_PATH, props.instanceName, 'config.json'), + path.join(PACKS_PATH, props.instanceName, 'natives'), + path.join(PACKS_PATH, props.instanceName, 'thumbnail.png'), + path.join(PACKS_PATH, props.instanceName, 'usercache.json'), + path.join(PACKS_PATH, props.instanceName, 'usernamecache.json') + ]; + + useEffect(() => getTreeData(), []); + + const getTreeData = () => { + const arr = dirTree(path.join(PACKS_PATH, props.instanceName)); + + const mapArr = children => { + if (children === undefined || children.length === 0) return []; + return children.map(child => ({ + title: child.name, + key: child.path, + children: mapArr(child.children) + })); + }; + + setTreeData(mapArr(arr.children)); + setCheckedKeys(props.selectedFiles); + }; + + const onExpand = LexpandedKeys => { + // if not set autoExpandParent to false, if children expanded, parent can not collapse. + // or, you can remove all expanded children keys. + setExpandedKeys(LexpandedKeys); + setAutoExpandParent(false); + }; + + const onCheck = LcheckedKeys => { + setCheckedKeys(LcheckedKeys); + props.setSelectedFiles(LcheckedKeys); + }; + + const onSelect = (LselectedKeys, info) => { + setSelectedKeys(LselectedKeys); + }; + + const renderTreeNodes = data => + data.map(item => { + if (item.children) { + return ( + item.key === f)} + title={item.title} + key={item.key} + dataRef={item} + > + {renderTreeNodes(item.children)} + + ); + } + return ; + }); + + return ( +
+

What files/folders would you like to export?

+ + {renderTreeNodes(treeData)} + + + +
+ ); +} diff --git a/app/components/ExportPackModal/ThirdStep.js b/app/components/ExportPackModal/ThirdStep.js new file mode 100644 index 000000000..1bcf857bb --- /dev/null +++ b/app/components/ExportPackModal/ThirdStep.js @@ -0,0 +1,127 @@ +import React, { useEffect, useState } from 'react'; +import yazl from 'yazl'; +import fs from 'fs'; +import { Icon, Button } from 'antd'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; +import path from 'path'; +import axios from 'axios'; +import { promisify } from 'util'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Promise from 'bluebird'; +import BackButton from './BackButton'; +import styles from './ExportPackModal.scss'; +import { PACKS_PATH, CURSEMETA_API_URL } from '../../constants'; + +const ThirdStep = props => { + const [isCompleted, setIsCompleted] = useState(false); + const { filePath, instanceName } = props; + useEffect(() => { + workOnFiles(); + }, []); + const workOnFiles = async () => { + const installedMods = JSON.parse( + await promisify(fs.readFile)( + path.join(PACKS_PATH, instanceName, 'config.json') + ) + ).mods; + const filteredFiles = props.selectedFiles.filter( + file => + !installedMods.find( + installedMod => installedMod.fileNameOnDisk === path.basename(file) + ) + ); + const zipFile = new yazl.ZipFile(); + zipFile.outputStream + .pipe(fs.createWriteStream(path.join(filePath, `${instanceName}.zip`))) + .on('close', () => { + setIsCompleted(true); + }); + + await Promise.map( + filteredFiles, + async file => { + const stats = await promisify(fs.stat)(file); + if (stats.isFile()) + zipFile.addFile( + file, + path.join( + 'overrides', + path.relative(path.join(PACKS_PATH, instanceName), file) + ) + ); + }, + { concurrency: 30 } + ); + const manifest = await createManifest(); + zipFile.addBuffer(Buffer.from(manifest, 'utf8'), 'manifest.json'); + zipFile.end(); + }; + + const createManifest = async () => { + const config = JSON.parse( + await promisify(fs.readFile)( + path.join(PACKS_PATH, instanceName, 'config.json') + ) + ); + let data = null; + + if (config.projectID) { + data = await axios.get( + `${CURSEMETA_API_URL}/direct/addon/${config.projectID}` + ); + } + + return JSON.stringify({ + minecraft: { + version: config.version, + modLoaders: [ + { + id: config.forgeVersion, + primary: true + } + ] + }, + manifestType: 'minecraftModpack', + manifestVersion: 1, + version: config.modpackVersion, + author: config.projectID ? data.primaryAuthorName : props.username, + projectID: config.projectID, + name: instanceName, + files: config.mods.map(mod => ({ + projectID: mod.projectID, + fileID: mod.fileID, + required: true + })) + }); + }; + return ( +
+
+ {isCompleted ? ( +
+

+ All Done!{' '} + +

+ +
+ ) : ( +

+ We're doing some magical stuff +

+ )} +
+
+ ); +}; + +function mapStateToProps(state) { + return { + username: state.auth.displayName + }; +} + +export default connect(mapStateToProps)(ThirdStep); diff --git a/app/routes.js b/app/routes.js index 6e0b06125..baca77088 100644 --- a/app/routes.js +++ b/app/routes.js @@ -42,6 +42,9 @@ const CurseModpackExplorerModal = lazy(() => import('./components/CurseModpackExplorerModal/CurseModpackExplorerModal') ); const ImportPack = lazy(() => import('./components/ImportPack/ImportPack')); +const ExportPackModal = lazy(() => + import('./components/ExportPackModal/ExportPackModal') +); const ChangelogsModal = lazy(() => import('./components/ChangelogModal/ChangelogModal') ); @@ -105,7 +108,6 @@ class RouteDef extends Component { componentDidUpdate = (prevProps, prevState) => { if (this.props.isAuthValid && process.env.NODE_ENV !== 'development') { - console.log(this.props.uuid); ga(this.props.uuid).set('uid', this.props.uuid); ga(this.props.uuid).set('ds', 'app'); ga(this.props.uuid).set('ua', `${release()} ${arch()}`); @@ -233,6 +235,12 @@ class RouteDef extends Component { {isModal ? ( ) : null} + {isModal ? ( + + ) : null} {isModal ? ( Date: Thu, 28 Feb 2019 23:47:11 +0100 Subject: [PATCH 17/17] v0.11.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9159bca55..04d6f88f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gdlauncher", - "version": "0.11.5-beta", + "version": "0.11.6", "description": "GDLauncher is simple, yet powerful Minecraft custom launcher with a strong focus on the user experience", "keywords": [ "boilerplate",