Merge branch 'dev' into feature/messenger

This commit is contained in:
MyNameIsBatman 2021-09-16 20:49:13 -03:00
commit 749aed141d
33 changed files with 255 additions and 204 deletions

11
.browserslistrc Normal file
View File

@ -0,0 +1,11 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 1 Edge major versions
last 2 Safari major versions
last 2 iOS major versions

86
.eslintrc.js Normal file
View File

@ -0,0 +1,86 @@
module.exports = {
'extends': [
'react-app',
'react-app/jest'
],
'rules': {
'linebreak-style': [
'off'
],
'quotes': [
'error',
'single'
],
'brace-style': [
'error',
'allman',
{
'allowSingleLine': true
}
],
'object-curly-spacing': [
'error',
'always'
],
'keyword-spacing': [
'error',
{
'overrides': {
'if': {
'after': false
},
'for': {
'after': false
},
'while': {
'after': false
},
'switch': {
'after': false
}
}
}
],
'@typescript-eslint/no-explicit-any': [
'off'
],
'@typescript-eslint/ban-ts-comment': [
'off'
],
'@typescript-eslint/no-empty-function': [
'error',
{
'allow': [
'functions',
'arrowFunctions',
'generatorFunctions',
'methods',
'generatorMethods',
'constructors'
]
}
],
'@typescript-eslint/no-unused-vars': [
'off'
],
'@typescript-eslint/ban-types': [
'error',
{
'types': {
'String': true,
'Boolean': true,
'Number': true,
'Symbol': true,
'{}': false,
'Object': false,
'object': false,
'Function': false
},
'extendDefaults': true
}
],
'no-switch-case-fall-through': [
'off'
]
}
}

32
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Deploy Bundle@dev
on:
push:
branches: [ dev ]
jobs:
build:
runs-on: self-hosted
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Install & Build
run: |
npm run build:prod
- name: Archive Artifacts
uses: actions/upload-artifact@v2
with:
path: |
build
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
host: ${{ secrets.HOST }}
port: ${{ secrets.PORT }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSHKEY }}
path: |
build
target: "/var/www/nitrots.co/domains/prod.nitrots.co/html"

5
craco.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
eslint: {
enabled: false
}
}

View File

@ -2,6 +2,13 @@
"name": "nitro-react",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "react-scripts start",
"build": "react-scripts --max_old_space_size=8048 build",
"build:prod": "npm uninstall @nitrots/nitro-renderer && npm i git+https://git@git.krews.org/nitro/nitro-renderer#dev && npm i && npm run build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"dependencies": {
"@nitrots/nitro-renderer": "file:../nitro-renderer",
"animate.css": "^4.1.1",
@ -17,112 +24,6 @@
"typescript": "^4.3.5",
"web-vitals": "^1.1.2"
},
"scripts": {
"postinstall": "node ./webpack-patcher.js",
"start": "react-scripts start",
"build": "react-scripts build",
"build:prod": "npm i git+https://git@git.krews.org/nitro/nitro-renderer#dev && npm i && npm run build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"rules": {
"linebreak-style": [
"off"
],
"quotes": [
"error",
"single"
],
"brace-style": [
"error",
"allman",
{
"allowSingleLine": true
}
],
"object-curly-spacing": [
"error",
"always"
],
"keyword-spacing": [
"error",
{
"overrides": {
"if": {
"after": false
},
"for": {
"after": false
},
"while": {
"after": false
},
"switch": {
"after": false
}
}
}
],
"@typescript-eslint/no-explicit-any": [
"off"
],
"@typescript-eslint/ban-ts-comment": [
"off"
],
"@typescript-eslint/no-empty-function": [
"error",
{
"allow": [
"functions",
"arrowFunctions",
"generatorFunctions",
"methods",
"generatorMethods",
"constructors"
]
}
],
"@typescript-eslint/no-unused-vars": [
"off"
],
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"String": true,
"Boolean": true,
"Number": true,
"Symbol": true,
"{}": false,
"Object": false,
"object": false,
"Function": false
},
"extendDefaults": true
}
],
"no-switch-case-fall-through": [
"off"
]
}
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",

View File

@ -6,7 +6,7 @@
"images.url": "${asset.url}/images",
"gamedata.url": "${asset.url}/gamedata",
"sounds.url": "${asset.url}/sounds",
"external.texts.url": "${gamedata.url}/ExternalTexts.json",
"external.texts.url": [ "${gamedata.url}/ExternalTexts.json", "${gamedata.url}/UITexts.json" ],
"external.samples.url": "${hof.furni.url}/mp3/sound_machine_sample_%sample%.mp3",
"furnidata.url": "${gamedata.url}/FurnitureData.json",
"productdata.url": "${gamedata.url}/ProductData.json",

View File

@ -45,6 +45,7 @@
5,
101
],
"currency.display.number.short": false,
"currency.asset.icon.url": "${images.url}/wallet/%type%.png",
"catalog.asset.url": "${image.library.url}catalogue",
"catalog.asset.image.url": "${catalog.asset.url}/%name%.gif",

View File

@ -0,0 +1,6 @@
export function LocalizeFormattedNumber(number: number): string
{
if(!number || isNaN(number)) return '0';
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
};

View File

@ -1,6 +1,7 @@
export * from './ColorUtils';
export * from './LocalizeBadgeDescription';
export * from './LocalizeBageName';
export * from './LocalizeFormattedNumber';
export * from './LocalizeShortNumber';
export * from './LocalizeText';
export * from './Randomizer';

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

View File

@ -125,6 +125,12 @@
height: 15px;
}
&.icon-help {
background: url('../images/icons/help.png');
width: 13px;
height: 23px;
}
&.icon-joinroom {
background-image: url('../images/toolbar/icons/joinroom.png');
width: 21px;

View File

@ -1,14 +1,11 @@
.nitro-notification-bubble {
pointer-events: all;
background-color: $gable-green;
border: 2px solid rgba($white, 0.5);
padding: 6px 5px;
background-color: rgba($dark,.95);
box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4);
font-size: $font-size-sm;
margin-bottom: 5px;
&.club-gift {
}
.bubble-image {
width: 30px;
height: 30px;

View File

@ -21,7 +21,7 @@ export const NotificationBubbleView: FC<NotificationBubbleViewProps> = props =>
}, [ fadesOut, close ]);
return (
<div className={ ('nitro-notification-bubble p-1 rounded ' + (className || '')) } { ...rest } onClick={ close }>
<div className={ ('nitro-notification-bubble rounded ' + (className || '')) } { ...rest } onClick={ close }>
{ children }
</div>
)

View File

@ -69,8 +69,8 @@
}
.creator-tab {
height: 230px;
min-height: 230px;
max-height: 230px;
height: 260px;
min-height: 260px;
max-height: 260px;
}
}

View File

@ -2,8 +2,8 @@
width: 385px;
.manager-tab {
height: 230px;
min-height: 230px;
max-height: 230px;
height: 260px;
min-height: 260px;
max-height: 260px;
}
}

View File

@ -1,8 +1,8 @@
.nitro-group-room-information {
pointer-events: all;
padding: 2px;
background-color: $gable-green;
border: 2px solid rgba($white, 0.5);
padding: 6px 5px;
background-color: rgba($dark,.95);
box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4);
font-size: $font-size-sm;
margin-bottom: 5px;

View File

@ -104,7 +104,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
if(!groupInformation) return null;
return (
<div className="nitro-group-room-information rounded py-1 px-2">
<div className="nitro-group-room-information rounded">
<div className="d-flex justify-content-between align-items-center cursor-pointer" onClick={ () => setIsExpended(value => !value) }>
<div>{ LocalizeText('group.homeroominfo.title') }</div>
<i className={ 'fas fa-chevron-' + (isExpended ? 'up' : 'down') } />
@ -119,7 +119,7 @@ export const GroupRoomInformationView: FC<{}> = props =>
</div>
</div>
{ (groupInformation.type !== GroupType.PRIVATE || isRealOwner()) &&
<button className="btn btn-sm btn-primary w-100 mt-1" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING } onClick={ handleButtonClick }>
<button className="btn btn-sm btn-success w-100 mt-1" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING } onClick={ handleButtonClick }>
{ LocalizeText(getButtonText()) }
</button>
}

View File

@ -3,11 +3,14 @@
position: relative;
border-radius: $border-radius;
width: 16px;
height: 12px;
height: 16px;
background: $white;
border: 2px solid $white;
box-shadow: inset 3px 3px rgba(0, 0, 0, .1);
&.active {
background: $primary;
box-shadow: none;
}
}
@ -15,7 +18,13 @@
position: relative;
border-radius: $border-radius;
width: 16px;
height: 12px;
height: 16px;
border: 2px solid $white;
box-shadow: inset 3px 3px rgba(0, 0, 0, .1);
&.active {
box-shadow: none;
}
}
.selection-list {

View File

@ -113,7 +113,7 @@ export const GroupSharedTabBadgeView: FC<GroupSharedTabBadgeViewProps> = props =
<div className="row row-cols-8 g-0 gap-1 w-100 h-100 overflow-auto">
{ badgePartColors && badgePartColors.map((item, index) =>
{
return <div key={ index } className="color-swatch cursor-pointer" style={{ backgroundColor: '#' + item.color }} onClick={ () => selectPartProperty('color', item.id) }></div>
return <div key={ index } className={ 'color-swatch cursor-pointer' + classNames({ ' active': item.id === getCurrentPart('color') }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectPartProperty('color', item.id) }></div>
}) }
</div>
</div>

View File

@ -4,6 +4,12 @@
position: relative;
border-radius: $border-radius;
width: 15px;
height: 12px;
height: 15px;
border: 2px solid $white;
box-shadow: inset 2px 2px rgba(0, 0, 0, .2);
&.active {
box-shadow: none;
}
}
}

View File

@ -1,3 +1,4 @@
import classNames from 'classnames';
import { FC, useCallback, useEffect, useState } from 'react';
import { LocalizeText } from '../../../../../api';
import { useGroupsContext } from '../../../context/GroupsContext';
@ -64,7 +65,7 @@ export const GroupSharedTabColorsView: FC<{}> = props =>
<div className="row row-cols-18 g-0 gap-1 w-100 h-100 overflow-auto">
{ groupColorsA && groupColorsA.map((item, index) =>
{
return <div key={ index } className="color-swatch cursor-pointer" style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(item.id) }></div>
return <div key={ index } className={ 'color-swatch cursor-pointer' + classNames({ ' active': groupColors[selectingColorIndex] === item.id }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(item.id) }></div>
}) }
</div>
<div><i className="fas fa-chevron-right h2 m-0 text-primary cursor-pointer" onClick={ () => setSelectingColorIndex(1) } /></div>
@ -77,7 +78,7 @@ export const GroupSharedTabColorsView: FC<{}> = props =>
<div className="row row-cols-18 g-0 gap-1 w-100 h-100 overflow-auto">
{ groupColorsB && groupColorsB.map((item, index) =>
{
return <div key={ index } className="color-swatch cursor-pointer" style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(item.id) }></div>
return <div key={ index } className={ 'color-swatch cursor-pointer' + classNames({ ' active': groupColors[selectingColorIndex] === item.id }) } style={{ backgroundColor: '#' + item.color }} onClick={ () => selectColor(item.id) }></div>
}) }
</div>
</div>

View File

@ -11,13 +11,13 @@ export const NotificationClubGiftBubbleView: FC<NotificationBubbleLayoutViewProp
return (
<NotificationBubbleView className="flex-column club-gift" close={ close } { ...rest }>
<div className="d-flex mb-1">
<CurrencyIcon type="hc" />
<div className="d-flex align-items-center gap-2 mb-2">
<CurrencyIcon type="hc" className="flex-shrink-0" />
<span className="ms-1">{ LocalizeText('notifications.text.club_gift') }</span>
</div>
<div className="d-flex align-items-center justify-content-end">
<span className="fw-bold me-1" onClick={ close }>{ LocalizeText('notifications.button.later') }</span>
<button type="button" className="btn btn-primary btn-sm" onClick={ () => NotificationUtilities.openUrl(item.linkUrl) }>{ LocalizeText('notifications.button.show_gift_list') }</button>
<div className="d-flex align-items-center justify-content-end gap-2">
<button type="button" className="btn btn-success w-100 btn-sm" onClick={ () => NotificationUtilities.openUrl(item.linkUrl) }>{ LocalizeText('notifications.button.show_gift_list') }</button>
<span className="text-decoration-underline cursor-pointer text-nowrap" onClick={ close }>{ LocalizeText('notifications.button.later') }</span>
</div>
</NotificationBubbleView>
);

View File

@ -1,12 +1,10 @@
.nitro-purse {
padding: 2px;
background-color: $gable-green;
border: 2px solid rgba($white, 0.5);
border-top: 0;
background-color: rgba($dark,.95);
font-size: $font-size-sm;
pointer-events: all;
margin-bottom:5px;
margin-bottom: 5px;
padding: 6px 5px;
box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4);
.notification-button {
color:lighten($dark,20);
@ -17,19 +15,21 @@
}
.nitro-purse-hc {
background-color: $william;
margin:0 2px;
background-color: rgba($light,.1);
margin: 0 5px;
}
.nitro-purse-button {
background: $bg-mirage-split-background;
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
padding: 2px 3px;
border-radius: $border-radius;
&:not(:first-child) {
margin-top:2px;
&:last-child {
border-bottom: none;
}
&:hover {
background: $bg-cello-split-background;
background-color: rgba($light,.1);
}
}
}

View File

@ -29,6 +29,11 @@ export const PurseView: FC<{}> = props =>
return GetConfiguration<number[]>('system.currency.types', []);
}, []);
const currencyDisplayNumberShort = useMemo(() =>
{
return GetConfiguration<boolean>('currency.display.number.short', false);
}, []);
const getCurrencyElements = useCallback((offset: number, limit: number = -1, seasonal: boolean = false) =>
{
if(!purse.activityPoints.size) return null;
@ -53,13 +58,13 @@ export const PurseView: FC<{}> = props =>
if((limit > -1) && (count === limit)) break;
if(seasonal) elements.push(<SeasonalView key={ type } type={ type } amount={ purse.activityPoints.get(type) } />);
else elements.push(<CurrencyView key={ type } type={ type } amount={ purse.activityPoints.get(type) } />);
else elements.push(<CurrencyView key={ type } type={ type } amount={ purse.activityPoints.get(type) } short={ currencyDisplayNumberShort } />);
count++;
}
return elements;
}, [ purse, displayedCurrencies ]);
}, [ purse, displayedCurrencies, currencyDisplayNumberShort ]);
const getClubText = useCallback(() =>
{
@ -123,19 +128,19 @@ export const PurseView: FC<{}> = props =>
<div className="row mx-0 w-100">
<div className="col-6 px-0">
<div className="d-flex flex-column nitro-currencies">
<CurrencyView type={ -1 } amount={ purse.credits } />
<CurrencyView type={ -1 } amount={ purse.credits } short={ currencyDisplayNumberShort } />
{ getCurrencyElements(0, 2) }
</div>
</div>
<div className="col-4 px-0">
<div className="nitro-purse-hc p-1 d-flex flex-column justify-content-center align-items-center h-100">
<div className="nitro-purse-hc rounded mx-1 p-1 d-flex flex-column justify-content-center align-items-center h-100">
<CurrencyIcon className="flex-shrink-0" type="hc" />
<span>{ getClubText() }</span>
</div>
</div>
<div className="col-2 px-0">
<div className="d-flex flex-column nitro-purse-buttons h-100 justify-content-center">
<div className="nitro-purse-button text-white h-100 text-center d-flex align-items-center justify-content-center cursor-pointer"><i className="fas fa-life-ring"/></div>
<div className="nitro-purse-button text-white h-100 text-center d-flex align-items-center justify-content-center cursor-pointer"><i className="icon icon-help"/></div>
<div className="nitro-purse-button text-white h-100 text-center d-flex align-items-center justify-content-center cursor-pointer" onClick={ handleUserSettingsClick } ><i className="fas fa-cogs"/></div>
</div>
</div>

View File

@ -1,9 +1,4 @@
.nitro-currency {
pointer-events: all;
background: $bg-mirage-split-background;
position: relative;
&:not(:first-of-type) {
margin-top:2px;
}
}

View File

@ -1,25 +1,32 @@
import { FC } from 'react';
import { FC, useMemo } from 'react';
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
import { LocalizeShortNumber } from '../../../../api';
import { LocalizeFormattedNumber, LocalizeShortNumber } from '../../../../api';
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
import { CurrencyViewProps } from './CurrencyView.types';
export const CurrencyView: FC<CurrencyViewProps> = props =>
{
const { type = -1, amount = -1 } = props;
const { type = -1, amount = -1, short = false } = props;
const element = useMemo(() =>
{
return (<div className="nitro-currency d-flex justify-content-end nitro-purse-button">
<div className="px-1 text-end text-truncate nitro-currency-text align-self-center">{ short ? LocalizeShortNumber(amount) : LocalizeFormattedNumber(amount) }</div>
<CurrencyIcon className="flex-shrink-0" type={ type } />
</div>);
}, [ amount, short, type ]);
if(!short) return element;
return (
<OverlayTrigger
placement="left"
overlay={
<Tooltip id={`tooltip-${ type }`}>
{ amount }
{ LocalizeFormattedNumber(amount) }
</Tooltip>
}>
<div className="nitro-currency d-flex justify-content-end nitro-purse-button">
<div className="px-1 text-end text-truncate nitro-currency-text align-self-center">{LocalizeShortNumber(amount)}</div>
<CurrencyIcon className="flex-shrink-0" type={ type } />
</div>
{ element }
</OverlayTrigger>
);
}

View File

@ -2,4 +2,5 @@ export interface CurrencyViewProps
{
type: number;
amount: number;
short: boolean;
}

View File

@ -1,16 +1,12 @@
.nitro-seasonal-currency {
pointer-events: all;
padding: 2px;
background-color: $gable-green;
border: 2px solid rgba($white, 0.5);
padding: 6px 5px;
background-color: rgba($dark,.95);
box-shadow: inset 0px 5px lighten(rgba($dark,.6),2.5), inset 0 -4px darken(rgba($dark,.6),4);
font-size: $font-size-sm;
margin-bottom: 5px;
.nitro-currency-text {
background: $bg-mirage-split-background;
}
.nitro-seasonal-icon {
background-color: $william;
.seasonal-text {
color: rgba($light,.5);
}
}

View File

@ -1,5 +1,5 @@
import { FC } from 'react';
import { LocalizeShortNumber, LocalizeText } from '../../../../api';
import { LocalizeFormattedNumber, LocalizeText } from '../../../../api';
import { CurrencyIcon } from '../../../shared/currency-icon/CurrencyIcon';
import { SeasonalViewProps } from './SeasonalView.types';
@ -10,11 +10,11 @@ export const SeasonalView: FC<SeasonalViewProps> = props =>
return (
<div className="nitro-seasonal-currency rounded d-flex justify-content-end">
<div className="nitro-currency-text w-100 px-1 d-flex justify-content-between">
<span>{ LocalizeText(`purse.seasonal.currency.${ type }`) }</span>
<span>{ LocalizeShortNumber(amount) }</span>
<span className="seasonal-text">{ LocalizeText(`purse.seasonal.currency.${ type }`) }</span>
<span>{ LocalizeFormattedNumber(amount) }</span>
</div>
<div className="nitro-seasonal-icon">
<CurrencyIcon type={ type } />
<div>
<CurrencyIcon type={ type } />
</div>
</div>
);

View File

@ -9,5 +9,11 @@
.color-swatch {
height: 30px;
border: 2px solid $white;
box-shadow: inset 3px 3px rgba(0, 0, 0, .2);
&.active {
box-shadow: none;
}
}
}

View File

@ -1,4 +1,5 @@
import { NitroEvent } from '@nitrots/nitro-renderer';
import classNames from 'classnames';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import ReactSlider from 'react-slider';
import { ColorUtils, GetConfiguration, LocalizeText, RoomWidgetDimmerChangeStateMessage, RoomWidgetDimmerPreviewMessage, RoomWidgetDimmerSavePresetMessage, RoomWidgetUpdateDimmerEvent, RoomWidgetUpdateDimmerStateEvent } from '../../../../../api';
@ -175,7 +176,7 @@ export const FurnitureDimmerView: FC<{}> = props =>
<div className="d-flex gap-2">
{ AVAILABLE_COLORS.map((color, index) =>
{
return <div key={ index } className="rounded w-100 color-swatch cursor-pointer" onClick={ () => setSelectedColor(color) } style={{ backgroundColor: HTML_COLORS[index] }}></div>;
return <div key={ index } className={ 'color-swatch rounded w-100 cursor-pointer' + classNames({ ' active': color === selectedColor }) } onClick={ () => setSelectedColor(color) } style={{ backgroundColor: HTML_COLORS[index] }}></div>;
}) }
</div> }
</div>

View File

@ -24,6 +24,6 @@
},
"include": [
"src",
"node_modules/@nitrots/nitro-renderer/src/**/*.ts",
"node_modules/@nitrots/nitro-renderer/**/*.ts",
]
}

View File

@ -1,22 +0,0 @@
const fs = require('fs');
function deleteLineFromFile(props)
{
const data = fs.readFileSync(props.path, 'utf-8');
const array = data.split('\n');
const value = array[props.lineToRemove.index - 1].trim();
if (value === props.lineToRemove.value)
{
array.splice(props.lineToRemove.index - 1, 1);
const newData = array.join('\n');
fs.writeFileSync(props.path, newData, 'utf-8');
}
}
deleteLineFromFile({
path: 'node_modules/react-scripts/config/webpack.config.js',
lineToRemove: { index: 406, value: 'include: paths.appSrc,' },
});