remane some files, continue with popups
This commit is contained in:
parent
bed2ae48e2
commit
8b361a2965
|
@ -111,6 +111,11 @@ msgstr ""
|
||||||
msgid "Loading..."
|
msgid "Loading..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/ssr/Win.jsx:55
|
||||||
|
#: src/ssr/Win.jsx:56
|
||||||
|
msgid "PixelPlanet.Fun PopUp"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/ssr/Main.jsx:54
|
#: src/ssr/Main.jsx:54
|
||||||
msgid "PixelPlanet.Fun"
|
msgid "PixelPlanet.Fun"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -119,14 +124,6 @@ msgstr ""
|
||||||
msgid "Place color pixels on an map styled canvas with other players online"
|
msgid "Place color pixels on an map styled canvas with other players online"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/ssr/Win.jsx:31
|
|
||||||
msgid "PixelPlanet.Fun Window"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/ssr/Win.jsx:32
|
|
||||||
msgid "PixelPlanet.Fun Windows"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/core/mail.js:71
|
#: src/core/mail.js:71
|
||||||
#, javascript-format
|
#, javascript-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
@ -350,26 +347,6 @@ msgid ""
|
||||||
"request a new one."
|
"request a new one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/routes/api/auth/register.js:26
|
|
||||||
msgid "No Captcha given"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/routes/api/auth/register.js:29
|
|
||||||
msgid "E-Mail already in use."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/routes/api/auth/register.js:31
|
|
||||||
msgid "Username already in use."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/routes/api/auth/register.js:84
|
|
||||||
msgid "Failed to create new user :("
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/routes/api/auth/register.js:100
|
|
||||||
msgid "Failed to establish session after register :("
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/routes/api/auth/logout.js:11
|
#: src/routes/api/auth/logout.js:11
|
||||||
msgid "You are not even logged in."
|
msgid "You are not even logged in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -391,6 +368,26 @@ msgstr ""
|
||||||
msgid "Incorrect password!"
|
msgid "Incorrect password!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/routes/api/auth/register.js:26
|
||||||
|
msgid "No Captcha given"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/routes/api/auth/register.js:29
|
||||||
|
msgid "E-Mail already in use."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/routes/api/auth/register.js:31
|
||||||
|
msgid "Username already in use."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/routes/api/auth/register.js:84
|
||||||
|
msgid "Failed to create new user :("
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/routes/api/auth/register.js:100
|
||||||
|
msgid "Failed to establish session after register :("
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/ssr/RedirectionPage.jsx:19
|
#: src/ssr/RedirectionPage.jsx:19
|
||||||
msgid "PixelPlanet.fun Accounts"
|
msgid "PixelPlanet.fun Accounts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -203,22 +203,6 @@ msgstr ""
|
||||||
msgid "Server answered with gibberish :("
|
msgid "Server answered with gibberish :("
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/store/actions/windows.js:98
|
|
||||||
msgid "Register New Account"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/store/actions/windows.js:105
|
|
||||||
msgid "Restore my Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/store/actions/windows.js:112
|
|
||||||
msgid "Welcome to PixelPlanet.fun"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/store/actions/windows.js:118
|
|
||||||
msgid "Look at past Canvases"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/store/middleware/notifications.js:33
|
#: src/store/middleware/notifications.js:33
|
||||||
msgid "Your next pixels are ready"
|
msgid "Your next pixels are ready"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -237,7 +221,7 @@ msgstr ""
|
||||||
|
|
||||||
#: src/components/Converter.jsx:561
|
#: src/components/Converter.jsx:561
|
||||||
#: src/components/CoordinatesBox.jsx:31
|
#: src/components/CoordinatesBox.jsx:31
|
||||||
#: src/components/ModWatchtools.jsx:364
|
#: src/components/ModWatchtools.jsx:360
|
||||||
msgid "Copy to Clipboard"
|
msgid "Copy to Clipboard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -253,11 +237,6 @@ msgstr ""
|
||||||
msgid "Pixels placed"
|
msgid "Pixels placed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/buttons/CanvasSwitchButton.jsx:22
|
|
||||||
#: src/components/windows/index.js:19
|
|
||||||
msgid "Canvas Selection"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/buttons/ChatButton.jsx:88
|
#: src/components/buttons/ChatButton.jsx:88
|
||||||
msgid "Close Chat"
|
msgid "Close Chat"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -274,33 +253,25 @@ msgstr ""
|
||||||
msgid "Open Menu"
|
msgid "Open Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Admintools.jsx:101
|
#: src/components/buttons/CanvasSwitchButton.jsx:22
|
||||||
#: src/components/ModCanvastools.jsx:232
|
#: src/components/windows/index.js:19
|
||||||
#: src/components/ModWatchtools.jsx:113
|
msgid "Canvas Selection"
|
||||||
#: src/components/Window.jsx:141
|
|
||||||
#: src/components/Window.jsx:210
|
|
||||||
#: src/components/contextmenus/ChannelContextMenu.jsx:68
|
|
||||||
msgid "Close"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Window.jsx:151
|
#: src/store/actions/windows.js:98
|
||||||
msgid "Restore"
|
msgid "Register New Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Window.jsx:186
|
#: src/store/actions/windows.js:105
|
||||||
msgid "Clone"
|
msgid "Restore my Password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Window.jsx:194
|
#: src/store/actions/windows.js:112
|
||||||
msgid "Move"
|
msgid "Welcome to PixelPlanet.fun"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Window.jsx:202
|
#: src/store/actions/windows.js:118
|
||||||
msgid "Maximize"
|
msgid "Look at past Canvases"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Window.jsx:218
|
|
||||||
msgid "Resize"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/HistorySelect.jsx:144
|
#: src/components/HistorySelect.jsx:144
|
||||||
|
@ -311,6 +282,39 @@ msgstr ""
|
||||||
msgid "Select Date above"
|
msgid "Select Date above"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Admintools.jsx:101
|
||||||
|
#: src/components/ModCanvastools.jsx:221
|
||||||
|
#: src/components/ModWatchtools.jsx:110
|
||||||
|
#: src/components/Window.jsx:153
|
||||||
|
#: src/components/Window.jsx:254
|
||||||
|
#: src/components/contextmenus/ChannelContextMenu.jsx:59
|
||||||
|
msgid "Close"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:169
|
||||||
|
msgid "PopUp"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:180
|
||||||
|
msgid "Restore"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:215
|
||||||
|
msgid "Clone"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:223
|
||||||
|
msgid "Move"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:246
|
||||||
|
msgid "Maximize"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Window.jsx:262
|
||||||
|
msgid "Resize"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/BanInfo.jsx:76
|
#: src/components/BanInfo.jsx:76
|
||||||
#: src/components/buttons/HelpButton.jsx:22
|
#: src/components/buttons/HelpButton.jsx:22
|
||||||
#: src/components/windows/index.js:13
|
#: src/components/windows/index.js:13
|
||||||
|
@ -343,8 +347,32 @@ msgstr ""
|
||||||
msgid "Open Palette"
|
msgid "Open Palette"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/index.js:16
|
||||||
|
msgid "Registration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/index.js:17
|
||||||
|
msgid "Forgot Password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/index.js:18
|
||||||
|
msgid "Chat"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/index.js:20
|
||||||
|
msgid "Canvas Archive"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/BanInfo.jsx:67
|
||||||
|
msgid "You are banned. You think it is unjustifed? Check out the "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/BanInfo.jsx:77
|
||||||
|
msgid " on how to appeal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/BanInfo.jsx:81
|
#: src/components/BanInfo.jsx:81
|
||||||
#: src/components/Captcha.jsx:77
|
#: src/components/Captcha.jsx:76
|
||||||
#: src/components/ChangeMail.jsx:72
|
#: src/components/ChangeMail.jsx:72
|
||||||
#: src/components/ChangeName.jsx:58
|
#: src/components/ChangeName.jsx:58
|
||||||
#: src/components/ChangePassword.jsx:79
|
#: src/components/ChangePassword.jsx:79
|
||||||
|
@ -356,28 +384,6 @@ msgstr ""
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ChangeMail.jsx:93
|
|
||||||
#: src/components/ChangeName.jsx:70
|
|
||||||
#: src/components/ChangePassword.jsx:115
|
|
||||||
#: src/components/DeleteAccount.jsx:68
|
|
||||||
#: src/components/GlobalCaptcha.jsx:47
|
|
||||||
#: src/components/windows/ForgotPassword.jsx:88
|
|
||||||
#: src/components/windows/Register.jsx:131
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/GlobalCaptcha.jsx:53
|
|
||||||
msgid "Send"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/BanInfo.jsx:67
|
|
||||||
msgid "You are banned. You think it is unjustifed? Check out the "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/BanInfo.jsx:77
|
|
||||||
msgid " on how to appeal."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/BanInfo.jsx:86
|
#: src/components/BanInfo.jsx:86
|
||||||
#: src/components/ModIIDtools.jsx:72
|
#: src/components/ModIIDtools.jsx:72
|
||||||
msgid "Reason"
|
msgid "Reason"
|
||||||
|
@ -412,69 +418,18 @@ msgstr ""
|
||||||
msgid "Why?"
|
msgid "Why?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/index.js:16
|
#: src/components/ChangeMail.jsx:93
|
||||||
msgid "Registration"
|
#: src/components/ChangeName.jsx:70
|
||||||
|
#: src/components/ChangePassword.jsx:115
|
||||||
|
#: src/components/DeleteAccount.jsx:68
|
||||||
|
#: src/components/GlobalCaptcha.jsx:47
|
||||||
|
#: src/components/windows/ForgotPassword.jsx:88
|
||||||
|
#: src/components/windows/Register.jsx:131
|
||||||
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/index.js:17
|
#: src/components/GlobalCaptcha.jsx:53
|
||||||
msgid "Forgot Password"
|
msgid "Send"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/windows/index.js:18
|
|
||||||
msgid "Chat"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/windows/index.js:20
|
|
||||||
msgid "Canvas Archive"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/contextmenus/UserContextMenu.jsx:60
|
|
||||||
msgid "Ping"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/contextmenus/UserContextMenu.jsx:87
|
|
||||||
msgid "DM"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/contextmenus/UserContextMenu.jsx:97
|
|
||||||
msgid "Block"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/contextmenus/ChannelContextMenu.jsx:56
|
|
||||||
msgid "Mute"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:50
|
|
||||||
#: src/components/Captcha.jsx:105
|
|
||||||
msgid "Could not load captcha"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:68
|
|
||||||
msgid "Type the characters from the following image:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:71
|
|
||||||
msgid "Tip: Not case-sensitive; I and l are the same"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:114
|
|
||||||
msgid "Load Captcha"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:119
|
|
||||||
msgid "Click to Load Captcha"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:124
|
|
||||||
msgid "Can't read? Reload:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:128
|
|
||||||
msgid "Reload"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Captcha.jsx:138
|
|
||||||
msgid "Enter Characters"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Help.jsx:42
|
#: src/components/windows/Help.jsx:42
|
||||||
|
@ -777,27 +732,16 @@ msgstr ""
|
||||||
|
|
||||||
#: src/components/Admintools.jsx:152
|
#: src/components/Admintools.jsx:152
|
||||||
#: src/components/Admintools.jsx:236
|
#: src/components/Admintools.jsx:236
|
||||||
#: src/components/ModCanvastools.jsx:314
|
#: src/components/ModCanvastools.jsx:301
|
||||||
#: src/components/ModCanvastools.jsx:396
|
#: src/components/ModCanvastools.jsx:381
|
||||||
#: src/components/ModCanvastools.jsx:471
|
#: src/components/ModCanvastools.jsx:454
|
||||||
#: src/components/ModCanvastools.jsx:564
|
#: src/components/ModCanvastools.jsx:545
|
||||||
#: src/components/ModIIDtools.jsx:134
|
#: src/components/ModIIDtools.jsx:134
|
||||||
#: src/components/windows/ForgotPassword.jsx:86
|
#: src/components/windows/ForgotPassword.jsx:86
|
||||||
#: src/components/windows/Register.jsx:125
|
#: src/components/windows/Register.jsx:125
|
||||||
msgid "Submit"
|
msgid "Submit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/CanvasSelect.jsx:27
|
|
||||||
msgid ""
|
|
||||||
"Select the canvas you want to use. Every canvas is unique and has "
|
|
||||||
"different palettes, cooldown and requirements. Archive of closed canvases "
|
|
||||||
"can be accessed here:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/windows/CanvasSelect.jsx:35
|
|
||||||
msgid "Archive"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/windows/UserArea.jsx:31
|
#: src/components/windows/UserArea.jsx:31
|
||||||
#: src/components/windows/UserArea.jsx:50
|
#: src/components/windows/UserArea.jsx:50
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
|
@ -823,6 +767,17 @@ msgstr ""
|
||||||
msgid "Consider joining us on Guilded:"
|
msgid "Consider joining us on Guilded:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/CanvasSelect.jsx:27
|
||||||
|
msgid ""
|
||||||
|
"Select the canvas you want to use. Every canvas is unique and has "
|
||||||
|
"different palettes, cooldown and requirements. Archive of closed canvases "
|
||||||
|
"can be accessed here:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/windows/CanvasSelect.jsx:35
|
||||||
|
msgid "Archive"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Archive.jsx:16
|
#: src/components/windows/Archive.jsx:16
|
||||||
msgid ""
|
msgid ""
|
||||||
"While we tend to not delete canvases, some canvases are started for fun or "
|
"While we tend to not delete canvases, some canvases are started for fun or "
|
||||||
|
@ -856,19 +811,19 @@ msgid ""
|
||||||
"how the canvas was at that time."
|
"how the canvas was at that time."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Chat.jsx:143
|
#: src/components/windows/Chat.jsx:176
|
||||||
msgid "Start chatting here"
|
msgid "Start chatting here"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Chat.jsx:183
|
#: src/components/windows/Chat.jsx:213
|
||||||
msgid "Chat here"
|
msgid "Chat here"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Chat.jsx:205
|
#: src/components/windows/Chat.jsx:239
|
||||||
msgid "You must be logged in to chat"
|
msgid "You must be logged in to chat"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Chat.jsx:233
|
#: src/components/windows/Chat.jsx:268
|
||||||
msgid "Channel settings"
|
msgid "Channel settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -880,6 +835,39 @@ msgstr ""
|
||||||
msgid "Enter your mail address and we will send you a new password:"
|
msgid "Enter your mail address and we will send you a new password:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:50
|
||||||
|
#: src/components/Captcha.jsx:104
|
||||||
|
msgid "Could not load captcha"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:68
|
||||||
|
msgid "Type the characters from the following image:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:71
|
||||||
|
msgid "Tip: Not case-sensitive; I and l are the same"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:113
|
||||||
|
msgid "Load Captcha"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:118
|
||||||
|
msgid "Click to Load Captcha"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:123
|
||||||
|
msgid "Can't read? Reload:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:127
|
||||||
|
msgid "Reload"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/Captcha.jsx:137
|
||||||
|
msgid "Enter Characters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/utils/validation.js:17
|
#: src/utils/validation.js:17
|
||||||
msgid "Email can't be empty."
|
msgid "Email can't be empty."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -943,51 +931,6 @@ msgstr ""
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:29
|
|
||||||
msgid "Online Users"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:34
|
|
||||||
msgid "Cooldown"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:40
|
|
||||||
msgid "Stacking till"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:42
|
|
||||||
msgid "Ranked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:44
|
|
||||||
msgid "Yes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:44
|
|
||||||
msgid "No"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:50
|
|
||||||
msgid "Requirements"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:53
|
|
||||||
msgid "User Account"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:55
|
|
||||||
#, javascript-format
|
|
||||||
msgid "and ${ canvas.req } Pixels set"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:58
|
|
||||||
msgid "Top 10 Daily Ranking"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/CanvasItem.jsx:64
|
|
||||||
msgid "Dimensions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/LogInArea.jsx:20
|
#: src/components/LogInArea.jsx:20
|
||||||
msgid "Login to access more features and stats."
|
msgid "Login to access more features and stats."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1070,7 +1013,7 @@ msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/Converter.jsx:190
|
#: src/components/Converter.jsx:190
|
||||||
#: src/components/ModCanvastools.jsx:236
|
#: src/components/ModCanvastools.jsx:225
|
||||||
msgid "Choose Canvas"
|
msgid "Choose Canvas"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1148,6 +1091,51 @@ msgstr ""
|
||||||
msgid "Download Template"
|
msgid "Download Template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:29
|
||||||
|
msgid "Online Users"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:34
|
||||||
|
msgid "Cooldown"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:40
|
||||||
|
msgid "Stacking till"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:42
|
||||||
|
msgid "Ranked"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:44
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:44
|
||||||
|
msgid "No"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:50
|
||||||
|
msgid "Requirements"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:53
|
||||||
|
msgid "User Account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:55
|
||||||
|
#, javascript-format
|
||||||
|
msgid "and ${ canvas.req } Pixels set"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:58
|
||||||
|
msgid "Top 10 Daily Ranking"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/CanvasItem.jsx:64
|
||||||
|
msgid "Dimensions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/LogInForm.jsx:77
|
#: src/components/LogInForm.jsx:77
|
||||||
msgid "Name or Email"
|
msgid "Name or Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1156,20 +1144,6 @@ msgstr ""
|
||||||
msgid "LogIn"
|
msgid "LogIn"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/UserMessages.jsx:28
|
|
||||||
msgid ""
|
|
||||||
"Please verify your mail address or your account could get deleted after a "
|
|
||||||
"few days."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/UserMessages.jsx:49
|
|
||||||
msgid "A new verification mail is getting sent to you."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/UserMessages.jsx:53
|
|
||||||
msgid "Click here to request a new verification mail."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ChangePassword.jsx:21
|
#: src/components/ChangePassword.jsx:21
|
||||||
msgid "Passwords do not match."
|
msgid "Passwords do not match."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1204,6 +1178,20 @@ msgstr ""
|
||||||
msgid "New Mail"
|
msgid "New Mail"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/UserMessages.jsx:28
|
||||||
|
msgid ""
|
||||||
|
"Please verify your mail address or your account could get deleted after a "
|
||||||
|
"few days."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/UserMessages.jsx:49
|
||||||
|
msgid "A new verification mail is getting sent to you."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/UserMessages.jsx:53
|
||||||
|
msgid "Click here to request a new verification mail."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/DeleteAccount.jsx:66
|
#: src/components/DeleteAccount.jsx:66
|
||||||
msgid "Yes, Delete My Account!"
|
msgid "Yes, Delete My Account!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1220,127 +1208,99 @@ msgstr ""
|
||||||
msgid "You have no users blocked"
|
msgid "You have no users blocked"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:174
|
#: src/components/ModCanvastools.jsx:167
|
||||||
msgid "Build image on canvas."
|
msgid "Build image on canvas."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:177
|
#: src/components/ModCanvastools.jsx:170
|
||||||
msgid "Build image and set it to protected."
|
msgid "Build image and set it to protected."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:180
|
#: src/components/ModCanvastools.jsx:173
|
||||||
msgid "Build image, but reset cooldown to unset-pixel cd."
|
msgid "Build image, but reset cooldown to unset-pixel cd."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:190
|
#: src/components/ModCanvastools.jsx:183
|
||||||
msgid "Clean spare pixels that are surrounded by unset pixels"
|
msgid "Clean spare pixels that are surrounded by unset pixels"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:194
|
#: src/components/ModCanvastools.jsx:187
|
||||||
msgid ""
|
msgid ""
|
||||||
"Clean spare pixels that are surrounded by unset pixels and up to 1 other "
|
"Clean spare pixels that are surrounded by unset pixels and up to 1 other "
|
||||||
"set pixels"
|
"set pixels"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:198
|
#: src/components/ModCanvastools.jsx:191
|
||||||
msgid ""
|
msgid ""
|
||||||
"Clean spare pixels that are surrounded by a single other color or unset "
|
"Clean spare pixels that are surrounded by a single other color or unset "
|
||||||
"pixels (VERY AGGRESSIVE ON CANVASES THAT ALLOW UNSET PIXELS (where there "
|
"pixels (VERY AGGRESSIVE ON CANVASES THAT ALLOW UNSET PIXELS (where there "
|
||||||
"are two cooldowns)!)"
|
"are two cooldowns)!)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:213
|
#: src/components/ModCanvastools.jsx:202
|
||||||
msgid "Status: Not running"
|
msgid "Status: Not running"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:255
|
#: src/components/ModCanvastools.jsx:244
|
||||||
msgid "Image Upload"
|
msgid "Image Upload"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:256
|
#: src/components/ModCanvastools.jsx:245
|
||||||
msgid "Upload images to canvas"
|
msgid "Upload images to canvas"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:258
|
#: src/components/ModCanvastools.jsx:247
|
||||||
msgid "File"
|
msgid "File"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:279
|
#: src/components/ModCanvastools.jsx:268
|
||||||
msgid "Coordinates in X_Y format:"
|
msgid "Coordinates in X_Y format:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:319
|
#: src/components/ModCanvastools.jsx:306
|
||||||
msgid "Pixel Protection"
|
msgid "Pixel Protection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:321
|
#: src/components/ModCanvastools.jsx:308
|
||||||
msgid ""
|
msgid ""
|
||||||
"Set protection of areas (if you need finer grained control, "
|
"Set protection of areas (if you need finer grained control, "
|
||||||
"use protect with image upload and alpha layers)"
|
"use protect with image upload and alpha layers)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:342
|
#: src/components/ModCanvastools.jsx:329
|
||||||
#: src/components/ModCanvastools.jsx:417
|
#: src/components/ModCanvastools.jsx:402
|
||||||
#: src/components/ModCanvastools.jsx:502
|
#: src/components/ModCanvastools.jsx:485
|
||||||
#: src/components/ModWatchtools.jsx:169
|
#: src/components/ModWatchtools.jsx:166
|
||||||
msgid "Top-left corner"
|
msgid "Top-left corner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:360
|
#: src/components/ModCanvastools.jsx:346
|
||||||
#: src/components/ModCanvastools.jsx:435
|
#: src/components/ModCanvastools.jsx:419
|
||||||
#: src/components/ModCanvastools.jsx:520
|
#: src/components/ModCanvastools.jsx:502
|
||||||
#: src/components/ModWatchtools.jsx:187
|
#: src/components/ModWatchtools.jsx:183
|
||||||
msgid "Bottom-right corner"
|
msgid "Bottom-right corner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:402
|
#: src/components/ModCanvastools.jsx:387
|
||||||
msgid "Rollback to Date"
|
msgid "Rollback to Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:404
|
#: src/components/ModCanvastools.jsx:389
|
||||||
msgid "Rollback an area of the canvas to a set date (00:00 UTC)"
|
msgid "Rollback an area of the canvas to a set date (00:00 UTC)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:477
|
#: src/components/ModCanvastools.jsx:460
|
||||||
msgid "Canvas Cleaner"
|
msgid "Canvas Cleaner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:479
|
#: src/components/ModCanvastools.jsx:462
|
||||||
msgid "Apply a filter to clean trash in large canvas areas."
|
msgid "Apply a filter to clean trash in large canvas areas."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModCanvastools.jsx:582
|
#: src/components/ModCanvastools.jsx:563
|
||||||
msgid "Stop Cleaner"
|
msgid "Stop Cleaner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:45
|
|
||||||
msgid "Interval is invalid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:117
|
|
||||||
msgid "Check who placed in an area"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:118
|
|
||||||
msgid "Canvas"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:135
|
|
||||||
msgid "Interval"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:151
|
|
||||||
msgid "IID (optional)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:233
|
|
||||||
msgid "Get Pixels"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/ModWatchtools.jsx:264
|
|
||||||
msgid "Get Users"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/components/Admintools.jsx:107
|
#: src/components/Admintools.jsx:107
|
||||||
msgid "IP Actions"
|
msgid "IP Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1373,6 +1333,34 @@ msgstr ""
|
||||||
msgid "User Name"
|
msgid "User Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:45
|
||||||
|
msgid "Interval is invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:114
|
||||||
|
msgid "Check who placed in an area"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:115
|
||||||
|
msgid "Canvas"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:134
|
||||||
|
msgid "Interval"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:149
|
||||||
|
msgid "IID (optional)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:228
|
||||||
|
msgid "Get Pixels"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/ModWatchtools.jsx:259
|
||||||
|
msgid "Get Users"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/ModIIDtools.jsx:19
|
#: src/components/ModIIDtools.jsx:19
|
||||||
msgid "You must enter a duration"
|
msgid "You must enter a duration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1393,6 +1381,22 @@ msgstr ""
|
||||||
msgid "(0 = infinite)"
|
msgid "(0 = infinite)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/contextmenus/ChannelContextMenu.jsx:46
|
||||||
|
msgid "Mute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/contextmenus/UserContextMenu.jsx:49
|
||||||
|
msgid "Ping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/contextmenus/UserContextMenu.jsx:75
|
||||||
|
msgid "DM"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/contextmenus/UserContextMenu.jsx:86
|
||||||
|
msgid "Block"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/windows/Help.jsx:15
|
#: src/components/windows/Help.jsx:15
|
||||||
#: src/components/windows/Settings.jsx:87
|
#: src/components/windows/Settings.jsx:87
|
||||||
msgctxt "keybinds"
|
msgctxt "keybinds"
|
||||||
|
|
|
@ -8,26 +8,26 @@ import { createRoot } from 'react-dom/client';
|
||||||
import { IconContext } from 'react-icons';
|
import { IconContext } from 'react-icons';
|
||||||
|
|
||||||
import Style from './Style';
|
import Style from './Style';
|
||||||
import UIWin from './UIWin';
|
import UIPopUp from './UIPopUp';
|
||||||
|
|
||||||
const iconContextValue = { style: { verticalAlign: 'middle' } };
|
const iconContextValue = { style: { verticalAlign: 'middle' } };
|
||||||
|
|
||||||
const AppWin = () => (
|
const AppPopUp = () => (
|
||||||
<>
|
<>
|
||||||
<Style />
|
<Style />
|
||||||
<IconContext.Provider value={iconContextValue}>
|
<IconContext.Provider value={iconContextValue}>
|
||||||
<UIWin />
|
<UIPopUp />
|
||||||
</IconContext.Provider>
|
</IconContext.Provider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
function renderAppWin(domParent, store) {
|
function renderAppPopUp(domParent, store) {
|
||||||
const root = createRoot(domParent);
|
const root = createRoot(domParent);
|
||||||
root.render(
|
root.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<AppWin />
|
<AppPopUp />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default renderAppWin;
|
export default renderAppPopUp;
|
43
src/components/UIPopUp.jsx
Normal file
43
src/components/UIPopUp.jsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* UI for single-window popUp
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
import { selectWindowType, selectWIndowArgs } from '../store/selectors/popup';
|
||||||
|
import { setWindowArgs, setWindowTitle } from '../store/actions/popup';
|
||||||
|
import COMPONENTS from './windows';
|
||||||
|
|
||||||
|
const UIPopUp = () => {
|
||||||
|
const windowType = useSelector(selectWindowType);
|
||||||
|
const args = useSelector(selectWIndowArgs);
|
||||||
|
|
||||||
|
const [Content] = COMPONENTS[windowType];
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const setArgs = useCallback(
|
||||||
|
(newArgs) => dispatch(setWindowArgs(newArgs),
|
||||||
|
), [dispatch]);
|
||||||
|
const setTitle = useCallback(
|
||||||
|
(title) => dispatch(setWindowTitle(title),
|
||||||
|
), [dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="window show"
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
overflow: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(windowType)
|
||||||
|
? <Content args={args} setArgs={setArgs} setTitle={setTitle} />
|
||||||
|
: <h1>Loading</h1>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(UIPopUp);
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import { selectWindowType } from '../store/selectors/win';
|
|
||||||
import COMPONENTS from './windows';
|
|
||||||
|
|
||||||
const UIWin = () => {
|
|
||||||
const windowType = useSelector(selectWindowType);
|
|
||||||
|
|
||||||
const [Content, name] = COMPONENTS[windowType];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="window show"
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
overflow: 'auto',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{(windowType)
|
|
||||||
? <Content />
|
|
||||||
: <h1>Loading</h1>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(UIWin);
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
} from '../store/selectors/windows';
|
} from '../store/selectors/windows';
|
||||||
import useDrag from './hooks/drag';
|
import useDrag from './hooks/drag';
|
||||||
import COMPONENTS from './windows';
|
import COMPONENTS from './windows';
|
||||||
|
import popUpTypes, { buildPopUpUrl } from './windows/popUpAvailable';
|
||||||
|
|
||||||
const Window = ({ id }) => {
|
const Window = ({ id }) => {
|
||||||
const [render, setRender] = useState(false);
|
const [render, setRender] = useState(false);
|
||||||
|
@ -81,11 +82,6 @@ const Window = ({ id }) => {
|
||||||
width, height,
|
width, height,
|
||||||
} = position;
|
} = position;
|
||||||
|
|
||||||
const popUp = useCallback((evt) => {
|
|
||||||
openPopUp(xPos, yPos, width, height);
|
|
||||||
close(evt);
|
|
||||||
}, [xPos, yPos, width, height]);
|
|
||||||
|
|
||||||
useDrag(
|
useDrag(
|
||||||
titleBarRef,
|
titleBarRef,
|
||||||
focus,
|
focus,
|
||||||
|
@ -157,15 +153,23 @@ const Window = ({ id }) => {
|
||||||
title={t`Close`}
|
title={t`Close`}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
>✕</div>
|
>✕</div>
|
||||||
<div
|
{(popUpTypes[windowType]) && (
|
||||||
onClick={popUp}
|
<div
|
||||||
className="modal-topbtn pop"
|
onClick={(evt) => {
|
||||||
role="button"
|
openPopUp(
|
||||||
label="close"
|
buildPopUpUrl(windowType, args),
|
||||||
key="popbtn"
|
xPos, yPos, width, height,
|
||||||
title={t`PopUp`}
|
);
|
||||||
tabIndex={-1}
|
close(evt);
|
||||||
>G</div>
|
}}
|
||||||
|
className="modal-topbtn pop"
|
||||||
|
role="button"
|
||||||
|
label="close"
|
||||||
|
key="popbtn"
|
||||||
|
title={t`PopUp`}
|
||||||
|
tabIndex={-1}
|
||||||
|
>G</div>
|
||||||
|
)}
|
||||||
{(showWindows) && (
|
{(showWindows) && (
|
||||||
<div
|
<div
|
||||||
onClick={toggleMaximize}
|
onClick={toggleMaximize}
|
||||||
|
@ -220,13 +224,21 @@ const Window = ({ id }) => {
|
||||||
>
|
>
|
||||||
{windowTitle}
|
{windowTitle}
|
||||||
</span>
|
</span>
|
||||||
<span
|
{(popUpTypes[windowType]) && (
|
||||||
className="win-topbtn"
|
<span
|
||||||
key="pobtn"
|
className="win-topbtn"
|
||||||
onClick={popUp}
|
key="pobtnm"
|
||||||
>
|
onClick={(evt) => {
|
||||||
G
|
openPopUp(
|
||||||
</span>
|
buildPopUpUrl(windowType, args),
|
||||||
|
xPos, yPos, width, height,
|
||||||
|
);
|
||||||
|
close(evt);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
G
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
className="win-topbtn"
|
className="win-topbtn"
|
||||||
key="maxbtn"
|
key="maxbtn"
|
||||||
|
|
|
@ -20,3 +20,9 @@ export default {
|
||||||
ARCHIVE: [Archive, t`Canvas Archive`],
|
ARCHIVE: [Archive, t`Canvas Archive`],
|
||||||
/* other windows */
|
/* other windows */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE:
|
||||||
|
* set windows that should be accessable via popup / url
|
||||||
|
* also in ./popUpAvailable.js
|
||||||
|
*/
|
||||||
|
|
40
src/components/windows/popUpAvailable.js
Normal file
40
src/components/windows/popUpAvailable.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* windows that can be opened as pop-up
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const argsTypes = {
|
||||||
|
USERAREA: ['activeTab'],
|
||||||
|
CHAT: ['chatChannel'],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function buildPopUpUrl(windowType, args) {
|
||||||
|
let path = `/${windowType.toLowerCase()}`;
|
||||||
|
const typeArr = argsTypes[windowType];
|
||||||
|
for (let i = 0; i < typeArr.length; i += 1) {
|
||||||
|
const key = typeArr[i];
|
||||||
|
if (args[key]) {
|
||||||
|
path += `/${args[key]}`;
|
||||||
|
delete args[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let searchParams = new URLSearchParams();
|
||||||
|
const keys = Object.keys(args);
|
||||||
|
for (let i = 0; i < keys.length; i += 1) {
|
||||||
|
const key = keys[i];
|
||||||
|
searchParams.append(key, args[key]);
|
||||||
|
}
|
||||||
|
searchParams = searchParams.toString();
|
||||||
|
if (searchParams) {
|
||||||
|
path += `?${searchParams}`;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default [
|
||||||
|
'HELP',
|
||||||
|
'SETTINGS',
|
||||||
|
'USERAREA',
|
||||||
|
'CHAT',
|
||||||
|
'CANVAS_SELECTION',
|
||||||
|
'ARCHIVE',
|
||||||
|
];
|
|
@ -52,7 +52,7 @@ class PopUps {
|
||||||
|
|
||||||
const popUps = new PopUps();
|
const popUps = new PopUps();
|
||||||
|
|
||||||
export function openPopUp(xPos, yPos, width, height) {
|
export function openPopUp(url, xPos, yPos, width, height) {
|
||||||
let left;
|
let left;
|
||||||
let top;
|
let top;
|
||||||
try {
|
try {
|
||||||
|
@ -74,8 +74,9 @@ export function openPopUp(xPos, yPos, width, height) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return window.open(
|
return window.open(
|
||||||
'./win',
|
url,
|
||||||
'lol',
|
url,
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
`popup=yes,width=${width},height=${height},left=${left},top=${top},toolbar=no,status=no,directories=no,menubar=no`,
|
`popup=yes,width=${width},height=${height},left=${left},top=${top},toolbar=no,status=no,directories=no,menubar=no`,
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
|
|
23
src/popup.js
Normal file
23
src/popup.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Main Script for windows (pop-ups and stuff)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import store from './store/storePopUp';
|
||||||
|
import {
|
||||||
|
urlChange,
|
||||||
|
} from './store/actions';
|
||||||
|
|
||||||
|
import renderAppPopUp from './components/AppPopUp';
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
window.addEventListener('popstate', () => {
|
||||||
|
store.dispatch(urlChange());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('hello');
|
||||||
|
renderAppPopUp(document.getElementById('app'), store);
|
||||||
|
});
|
|
@ -19,9 +19,10 @@ import api from './api';
|
||||||
import { assets } from '../core/assets';
|
import { assets } from '../core/assets';
|
||||||
import { expressTTag } from '../core/ttag';
|
import { expressTTag } from '../core/ttag';
|
||||||
import generateGlobePage from '../ssr/Globe';
|
import generateGlobePage from '../ssr/Globe';
|
||||||
import generateWinPage from '../ssr/Win';
|
import generatePopUpPage from '../ssr/PopUp';
|
||||||
import generateMainPage from '../ssr/Main';
|
import generateMainPage from '../ssr/Main';
|
||||||
|
|
||||||
|
import AVAILABLE_POPUPS from '../components/windows/popUpAvailable';
|
||||||
import { MONTH } from '../core/constants';
|
import { MONTH } from '../core/constants';
|
||||||
import { GUILDED_INVITE } from '../core/config';
|
import { GUILDED_INVITE } from '../core/config';
|
||||||
|
|
||||||
|
@ -122,26 +123,30 @@ router.get('/globe', (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// Windows (like chat pop-up etc.)
|
// PopUps
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const winEtag = etag(
|
const winEtag = etag(
|
||||||
assets.win.js,
|
assets.popup.js,
|
||||||
{ weak: true },
|
{ weak: true },
|
||||||
);
|
);
|
||||||
router.get('/win', async (req, res) => {
|
|
||||||
res.set({
|
|
||||||
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
|
||||||
'Content-Type': 'text/html; charset=utf-8',
|
|
||||||
ETag: globeEtag,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (req.headers['if-none-match'] === winEtag) {
|
router.get(
|
||||||
res.status(304).end();
|
`/:t(${AVAILABLE_POPUPS.map((p) => p.toLowerCase()).join('|')})`,
|
||||||
return;
|
async (req, res) => {
|
||||||
}
|
res.set({
|
||||||
|
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
||||||
|
'Content-Type': 'text/html; charset=utf-8',
|
||||||
|
ETag: winEtag,
|
||||||
|
});
|
||||||
|
|
||||||
res.status(200).send(generateWinPage(req.lang));
|
if (req.headers['if-none-match'] === winEtag) {
|
||||||
});
|
res.status(304).end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send(generatePopUpPage(req.lang));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Main Page (react generated)
|
// Main Page (react generated)
|
||||||
|
|
|
@ -18,22 +18,6 @@ import logger from '../core/logger';
|
||||||
import { APISOCKET_KEY } from '../core/config';
|
import { APISOCKET_KEY } from '../core/config';
|
||||||
|
|
||||||
|
|
||||||
async function verifyClient(info, done) {
|
|
||||||
const { req } = info;
|
|
||||||
const { headers } = req;
|
|
||||||
const ip = getIPFromRequest(req);
|
|
||||||
|
|
||||||
if (!headers.authorization
|
|
||||||
|| !APISOCKET_KEY
|
|
||||||
|| headers.authorization !== `Bearer ${APISOCKET_KEY}`) {
|
|
||||||
logger.warn(`API ws request from ${ip} authenticated`);
|
|
||||||
return done(false);
|
|
||||||
}
|
|
||||||
logger.warn(`API ws request from ${ip} successfully authenticated`);
|
|
||||||
return done(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class APISocketServer {
|
class APISocketServer {
|
||||||
wss; // WebSocket.Server
|
wss; // WebSocket.Server
|
||||||
|
|
||||||
|
@ -47,7 +31,6 @@ class APISocketServer {
|
||||||
// path: "/mcws",
|
// path: "/mcws",
|
||||||
// server,
|
// server,
|
||||||
noServer: true,
|
noServer: true,
|
||||||
verifyClient,
|
|
||||||
});
|
});
|
||||||
this.wss = wss;
|
this.wss = wss;
|
||||||
|
|
||||||
|
@ -86,6 +69,24 @@ class APISocketServer {
|
||||||
setInterval(this.ping, 45 * 1000);
|
setInterval(this.ping, 45 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleUpgrade(request, socket, head) {
|
||||||
|
const { headers } = request;
|
||||||
|
const ip = getIPFromRequest(request);
|
||||||
|
|
||||||
|
if (!headers.authorization
|
||||||
|
|| !APISOCKET_KEY
|
||||||
|
|| headers.authorization !== `Bearer ${APISOCKET_KEY}`) {
|
||||||
|
logger.warn(`API ws request from ${ip} not authenticated`);
|
||||||
|
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
logger.warn(`API ws request from ${ip} successfully authenticated`);
|
||||||
|
|
||||||
|
this.wss.handleUpgrade(request, socket, head, (ws) => {
|
||||||
|
this.wss.emit('connection', ws, request);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
broadcastChatMessage(
|
broadcastChatMessage(
|
||||||
name,
|
name,
|
||||||
msg,
|
msg,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* create html for Window page
|
* create html for popup page
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -36,14 +36,14 @@ if (BACKUP_URL) {
|
||||||
* @param lang language code
|
* @param lang language code
|
||||||
* @return html of mainpage
|
* @return html of mainpage
|
||||||
*/
|
*/
|
||||||
function generateWinPage(lang) {
|
function generatePopUpPage(lang) {
|
||||||
const ssvR = {
|
const ssvR = {
|
||||||
...ssv,
|
...ssv,
|
||||||
lang: lang === 'default' ? 'en' : lang,
|
lang: lang === 'default' ? 'en' : lang,
|
||||||
};
|
};
|
||||||
const script = (assets[`win-${lang}`])
|
const script = (assets[`popup-${lang}`])
|
||||||
? assets[`win-${lang}`].js
|
? assets[`popup-${lang}`].js
|
||||||
: assets.win.js;
|
: assets.popup.js;
|
||||||
|
|
||||||
const { t } = getTTag(lang);
|
const { t } = getTTag(lang);
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ function generateWinPage(lang) {
|
||||||
<html lang="${lang}">
|
<html lang="${lang}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>${t`PixelPlanet.Fun Window`}</title>
|
<title>${t`PixelPlanet.Fun PopUp`}</title>
|
||||||
<meta name="description" content="${t`PixelPlanet.Fun Windows`}" />
|
<meta name="description" content="${t`PixelPlanet.Fun PopUp`}" />
|
||||||
<meta name="google" content="nopagereadaloud" />
|
<meta name="google" content="nopagereadaloud" />
|
||||||
<meta name="theme-color" content="#cae3ff" />
|
<meta name="theme-color" content="#cae3ff" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
|
@ -75,4 +75,4 @@ function generateWinPage(lang) {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateWinPage;
|
export default generatePopUpPage;
|
|
@ -468,12 +468,6 @@ export function unmuteChatChannel(cid) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reloadUrl() {
|
|
||||||
return {
|
|
||||||
type: 'RELOAD_URL',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function onViewFinishChange() {
|
export function onViewFinishChange() {
|
||||||
return {
|
return {
|
||||||
type: 'ON_VIEW_FINISH_CHANGE',
|
type: 'ON_VIEW_FINISH_CHANGE',
|
||||||
|
@ -489,7 +483,9 @@ export function selectHistoricalTime(date, time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function urlChange() {
|
export function urlChange() {
|
||||||
return reloadUrl();
|
return {
|
||||||
|
type: 'RELOAD_URL',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unload() {
|
export function unload() {
|
||||||
|
|
17
src/store/actions/popup.js
Normal file
17
src/store/actions/popup.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Actions taht are used only within popup
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function setWindowArgs(args) {
|
||||||
|
return {
|
||||||
|
type: 'SET_WIN_ARGS',
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setWindowTitle(title) {
|
||||||
|
return {
|
||||||
|
type: 'SET_WIN_TITLE',
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
}
|
33
src/store/middleware/titlePopUp.js
Normal file
33
src/store/middleware/titlePopUp.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* set URL and querys in pupup window
|
||||||
|
*/
|
||||||
|
import { buildPopUpUrl } from '../../components/windows/popUpAvailable';
|
||||||
|
|
||||||
|
export default (store) => (next) => (action) => {
|
||||||
|
const ret = next(action);
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
case 'SET_WIN_TITLE': {
|
||||||
|
const { windowType } = store.getState().popup;
|
||||||
|
const { title } = action;
|
||||||
|
const name = windowType[0] + windowType.substring(1).toLowerCase();
|
||||||
|
document.title = (title) ? `${name} - ${title}` : name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'SET_WIN_ARGS': {
|
||||||
|
const {
|
||||||
|
args,
|
||||||
|
windowType,
|
||||||
|
} = store.getState().popup;
|
||||||
|
const url = buildPopUpUrl(windowType, args);
|
||||||
|
window.history.pushState({}, undefined, url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
73
src/store/reducers/popup.js
Normal file
73
src/store/reducers/popup.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* state for single-window page (popup)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { argsTypes } from '../../components/windows/popUpAvailable';
|
||||||
|
|
||||||
|
function getWinDataFromURL() {
|
||||||
|
const path = window.location.pathname.split('/').slice(1);
|
||||||
|
/*
|
||||||
|
* first part of path is windowType
|
||||||
|
*/
|
||||||
|
const windowType = path[0].toUpperCase();
|
||||||
|
/*
|
||||||
|
* get args from path
|
||||||
|
*/
|
||||||
|
const argsArr = path.slice(1);
|
||||||
|
const args = {};
|
||||||
|
const typeArr = argsTypes[windowType];
|
||||||
|
if (typeArr) {
|
||||||
|
let i = Math.min(typeArr.length, argsArr.length);
|
||||||
|
while (i > 0) {
|
||||||
|
i -= 1;
|
||||||
|
args[typeArr[i]] = argsArr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* get args from query
|
||||||
|
*/
|
||||||
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||||
|
const params = Object.fromEntries(urlSearchParams.entries());
|
||||||
|
|
||||||
|
return {
|
||||||
|
windowType,
|
||||||
|
args: {
|
||||||
|
...args,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
windowType: 'SETTINGS',
|
||||||
|
title: '',
|
||||||
|
args: {},
|
||||||
|
isPopup: window.opener && !window.opener.closed,
|
||||||
|
...getWinDataFromURL(),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function popup(
|
||||||
|
state = initialState,
|
||||||
|
action,
|
||||||
|
) {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'RELOAD_URL': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...getWinDataFromURL(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'SET_WIN_ARGS': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
args: {
|
||||||
|
...action.args,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* state for single-window page (popup)
|
|
||||||
*/
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
// windowType: null,
|
|
||||||
windowType: 'SETTINGS',
|
|
||||||
title: '',
|
|
||||||
args: {},
|
|
||||||
isPopup: window.opener && !window.opener.closed,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function win(
|
|
||||||
state = initialState,
|
|
||||||
action,
|
|
||||||
) {
|
|
||||||
switch (action.type) {
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,3 +3,5 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const selectWindowType = (state) => state.win.windowType;
|
export const selectWindowType = (state) => state.win.windowType;
|
||||||
|
|
||||||
|
export const selectWIndowArgs = (state) => state.win.args;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* redux store for windows / popups
|
* redux store for popups
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
@ -15,7 +15,7 @@ import { persistStore } from 'redux-persist';
|
||||||
*/
|
*/
|
||||||
import sharedReducers from './sharedReducers';
|
import sharedReducers from './sharedReducers';
|
||||||
import canvas from './reducers/canvas';
|
import canvas from './reducers/canvas';
|
||||||
import win from './reducers/win';
|
import popup from './reducers/popup';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* middleware
|
* middleware
|
||||||
|
@ -25,7 +25,7 @@ import parent from './middleware/parent';
|
||||||
const reducers = combineReducers({
|
const reducers = combineReducers({
|
||||||
...sharedReducers,
|
...sharedReducers,
|
||||||
canvas,
|
canvas,
|
||||||
win,
|
popup,
|
||||||
});
|
});
|
||||||
|
|
||||||
const store = createStore(
|
const store = createStore(
|
24
src/win.js
24
src/win.js
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Main Script for windows (pop-ups and stuff)
|
|
||||||
*/
|
|
||||||
|
|
||||||
import store from './store/storeWin';
|
|
||||||
|
|
||||||
import renderAppWin from './components/AppWin';
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
// window.addEventListener('message', store.dispatch);
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('hello');
|
|
||||||
renderAppWin(document.getElementById('app'), store);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check if popup or independent window
|
|
||||||
*/
|
|
||||||
if (!window.opener || window.opener.closed) {
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -68,8 +68,8 @@ function buildWebpackClientConfig(
|
||||||
[path.resolve('src', 'client.js')],
|
[path.resolve('src', 'client.js')],
|
||||||
[(locale !== 'default') ? `globe-${locale}` : 'globe']:
|
[(locale !== 'default') ? `globe-${locale}` : 'globe']:
|
||||||
[path.resolve('src', 'globe.js')],
|
[path.resolve('src', 'globe.js')],
|
||||||
[(locale !== 'default') ? `win-${locale}` : 'win']:
|
[(locale !== 'default') ? `popup-${locale}` : 'popup']:
|
||||||
[path.resolve('src', 'win.js')],
|
[path.resolve('src', 'popup.js')],
|
||||||
},
|
},
|
||||||
|
|
||||||
output: {
|
output: {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user