From 515a4add86e013ec31bbfb10d552305aaee8b976 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Wed, 28 Dec 2022 15:46:31 +0100 Subject: [PATCH 01/49] editor video icon --- .../components/editor-toolbar/index.tsx | 14 +++++++++++-- .../video-upload-threespeak/index.scss | 20 +++++++++++++++++++ .../video-upload-threespeak/index.tsx | 17 ++++++++++++++++ src/common/img/svg.tsx | 12 +++++++++++ src/style/_components.scss | 1 + 5 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/common/components/video-upload-threespeak/index.scss create mode 100644 src/common/components/video-upload-threespeak/index.tsx diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index cf649d458d2..c4a47eb5acc 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -42,7 +42,8 @@ import { gridSvg, emoticonHappyOutlineSvg, textShortSvg, - gifIcon + gifIcon, + videoSvg } from "../../img/svg"; interface Props { @@ -367,7 +368,7 @@ export class EditorToolbar extends Component { } else { error(_t("editor-toolbar.image-error-cache")); } - } catch (e) { + } catch (e: any) { if (e.response?.status === 413) { error(_t("editor-toolbar.image-error-size")); } else { @@ -553,6 +554,15 @@ export class EditorToolbar extends Component { )} + + +
+
+ {videoSvg} +
+
+
+ { + + const [selectedFile, setSelectedFile]: any = useState(""); + + const onVideoUpload = () => { + console.log(selectedFile); + }; + + return ( +
+
{ videoSvg }
+
+ ) +} diff --git a/src/common/img/svg.tsx b/src/common/img/svg.tsx index 655d638a237..d9f21088283 100644 --- a/src/common/img/svg.tsx +++ b/src/common/img/svg.tsx @@ -1725,3 +1725,15 @@ export const downCarouselSvg = ( ); + +export const videoSvg = ( + + + +); diff --git a/src/style/_components.scss b/src/style/_components.scss index 62d2989a1af..3887752ba39 100644 --- a/src/style/_components.scss +++ b/src/style/_components.scss @@ -55,6 +55,7 @@ @import "../common/components/login"; @import "../common/components/comment"; @import "../common/components/comment-engagement"; +@import "../common/components/video-upload-threespeak"; @import "../common/components/transfer"; @import "../common/components/or-divider"; @import "../common/components/notifications"; From 31558eb6407e67c4f8897e6e4461f453a6593b02 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Wed, 15 Mar 2023 20:46:06 +0100 Subject: [PATCH 02/49] test input --- src/common/components/editor-toolbar/index.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index c4a47eb5acc..abc0421b32d 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -45,6 +45,7 @@ import { gifIcon, videoSvg } from "../../img/svg"; +import { VideoUpload } from "../video-upload-threespeak"; interface Props { global: Global; @@ -556,10 +557,14 @@ export class EditorToolbar extends Component { )} -
-
- {videoSvg} -
+
) => { + e.stopPropagation(); + const el = this.fileInput.current; + if (el) el.click(); + }}> +
From 64e7e3506a1dc90ee9f9d1234850fa212aa3362f Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Fri, 17 Mar 2023 09:46:32 +0100 Subject: [PATCH 03/49] test file --- src/common/components/editor-toolbar/index.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index abc0421b32d..23fd8bf4d72 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -82,6 +82,7 @@ export class EditorToolbar extends Component { holder = React.createRef(); fileInput = React.createRef(); + videoInput = React.createRef(); shouldComponentUpdate(nextProps: Readonly, nextState: Readonly): boolean { return ( @@ -343,6 +344,12 @@ export class EditorToolbar extends Component { // reset input e.target.value = ""; }; + + videoInputChanged = (e: any | React.ChangeEvent): void => { + console.log(e.target.files) + console.log(e.target.files[0]) + + }; upload = async (file: File) => { const { activeUser, global } = this.props; @@ -561,7 +568,7 @@ export class EditorToolbar extends Component { // Test onClick={(e: React.MouseEvent) => { e.stopPropagation(); - const el = this.fileInput.current; + const el = this.videoInput.current; if (el) el.click(); }}> @@ -578,6 +585,15 @@ export class EditorToolbar extends Component { multiple={true} style={{ display: "none" }} /> + {gallery && activeUser && ( Date: Fri, 17 Mar 2023 15:18:55 +0100 Subject: [PATCH 04/49] uploads handlers --- package.json | 3 + src/common/api/threespeak.ts | 205 ++++++++++++++++++ .../components/editor-toolbar/index.tsx | 16 +- yarn.lock | 125 ++++++++++- 4 files changed, 342 insertions(+), 7 deletions(-) create mode 100644 src/common/api/threespeak.ts diff --git a/package.json b/package.json index 70a3fc2bb62..bd50bcf011d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@types/webscopeio__react-textarea-autocomplete": "^4.7.2", "@webscopeio/react-textarea-autocomplete": "^4.8.1", "axios": "^0.21.2", + "axios-cookiejar-support": "^4.0.6", "bs58": "^4.0.1", "connected-react-router": "^6.8.0", "cookie-parser": "^1.4.5", @@ -79,6 +80,8 @@ "serialize-javascript": "^3.1.0", "sortablejs": "^1.13.0", "speakingurl": "^14.0.1", + "tough-cookie": "^4.1.2", + "tus-js-client": "^3.1.0", "use-async-effect": "^2.2.6", "xss": "^1.0.8" }, diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts new file mode 100644 index 00000000000..2c71a130cba --- /dev/null +++ b/src/common/api/threespeak.ts @@ -0,0 +1,205 @@ +const hive = require("@hiveio/dhive"); +const tus = require("tus-js-client"); + +const axios = require("axios").default; +const { CookieJar } = require("tough-cookie"); +const { wrapper } = require("axios-cookiejar-support"); + +const jar = new CookieJar(); +const client = wrapper(axios.create({ jar })); + +// Generate Memo from Username +const getMemo = async (username: string, studioEndPoint: string) => { + try { + let response = await client.get(`${studioEndPoint}/mobile/login?username=${username}`, { + withCredentials: true, + headers: { + "Content-Type": "application/json" + } + }); + return response.data.memo; + } catch (err) { + console.log(err, "error"); + throw err; + } +} + +// Get Cookie frow Memo (JWT) +const getCookies = async (username: string, studioEndPoint: string, jwt: string) => { + try { + let response = await client.get( + `${studioEndPoint}/mobile/login?username=${username}&access_token=${jwt}`, + { + withCredentials: true, + headers: { + "Content-Type": "application/json" + } + } + ); + return response.headers["set-cookie"]; + } catch (err) { + console.log(err); + throw err; + } +} + +const startUpload = (fileName: string, tusEndPoint: string | undefined, file: any) => { + return new Promise(function (resolve, reject) { + var upload = new tus.Upload(file, { + endpoint: tusEndPoint, + metadata: { + filename: fileName + }, + onError: function (error: string) { + console.log("Failed because: " + error); + return reject(error); + }, + onProgress: function (bytesUploaded: number, bytesTotal: number) { + var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + console.log(bytesUploaded, bytesTotal, percentage + "%"); + }, + onSuccess: function () { + return resolve(upload.url); + } + }); + upload.start(); + }); +} + +const updateVideoInfo = async ( + studioEndPoint: string, + oFilename: string, + videoUrl: any, + thumbnailUrl: any, + username: string +) => { + try { + const { data } = await client.post( + `${studioEndPoint}/mobile/api/upload_info`, + { + filename: videoUrl, + oFilename: oFilename, + size: 2221284, // NOTE: please change this constant value. This is POC app. It has to be in bytes. + duration: 44, // NOTE: please change this constant value. This is POC app. it has to be in seconds. + thumbnail: thumbnailUrl, + owner: username, + isReel: true // if video is a reel/short (Three Shorts) send this as true + }, + { + withCredentials: true, + headers: { + "Content-Type": "application/json" + } + } + ); + return data; + } catch (e) { + console.error(e); + throw e; + } +} + +const updateVideoMetadata = async( + studioEndPoint: string, + videoID: any, + title: string, + description: string, + isNsfwContent: boolean, + tags: string +) => { + try { + const info = { + videoId: videoID, + title: title, + description: description, + isNsfwContent: isNsfwContent, + tags: tags + }; + const { data } = await client.post(`${studioEndPoint}/mobile/api/update_info`, info, { + withCredentials: true, + headers: { + "Content-Type": "application/json" + } + }); + return data; + } catch (e) { + console.error(e); + throw e; + } +} + +const getAllVideoStatuses = async (studioEndPoint: string) => { + try { + let response = await client.get(`${studioEndPoint}/mobile/api/my-videos`, { + withCredentials: true, + headers: { + "Content-Type": "application/json" + } + }); + return response.data; + } catch (err) { + console.log(err); + throw err; + } +} + + +// Main Function that calls every other one in the file +export const uploadToThreeSpeak = async (username: string | any, file: string, thumbnail: string) => { + const studioEndPoint = "https://studio.3speak.tv"; + const tusEndPoint = "https://uploads.3speak.tv/files/"; + const postingKey = ""; + + // Step 1. Get JWT Encrypted Memo + const memo = await getMemo(username, studioEndPoint); + // Decoded Memo using dhive Memo.decode class + let decrypted = hive.Memo.decode(postingKey, memo); + decrypted = decrypted.replace("#", ""); + console.log(`Decrypted ${decrypted}\n\n`); + + // Step 2. Get Cookie using decrypted JWT + const cookies = await getCookies(username, studioEndPoint, decrypted); + // we are logging the cookies here just to make sure that we got those. + console.log(`Cookies are ${cookies}\n\n`); + + // Step 3. Upload video + const videoUpload: any = await startUpload("test-demo-video.mp4", tusEndPoint, file); + const videoUploadFileUrl = videoUpload.replace(`${tusEndPoint}`, ""); + console.log(`Video File Url ${videoUploadFileUrl}\n\n`); + + // Step 4. Upload Thumb + const thumbUpload: any = await startUpload("test-demo-video.mp4", tusEndPoint, thumbnail); + const thumbUploadFileUrl: string = thumbUpload.replace(`${tusEndPoint}`, ""); + console.log(`Thumb File ID ${thumbUploadFileUrl}\n\n`); + + // Step 5. Update Video upload information + const data = await updateVideoInfo( + studioEndPoint, + "test-demo-video.mp4", + videoUploadFileUrl, + thumbUploadFileUrl, + username + ); + console.log(`Video upload response: ${JSON.stringify(data)}`); + + // Step 6. Get all Videos data + const myAllVideosWithStatusInfo = await getAllVideoStatuses(studioEndPoint); + console.log(`All Videos Info response: ${JSON.stringify(myAllVideosWithStatusInfo)}`); + + const videoID = myAllVideosWithStatusInfo[0]._id; + console.log(videoID); + + // Step 7. Update MetaData of a specific video + const updatedVideoMetadata = await updateVideoMetadata( + studioEndPoint, + videoID, + "ActiFit & Ecency integrating #3Speak videos", // video title + "Lots of love for #Hive ♦️ and #3Speak ▶️", // video description - post content + false, // is NSFW + "threespeak,mobile,ios,test" // comma separated tags - no spaces + ); + console.log("uploading...") + console.log(`Video Info response: ${JSON.stringify(updatedVideoMetadata)}`); +} + +export default uploadToThreeSpeak; \ No newline at end of file diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 23fd8bf4d72..b43b75e6c11 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -46,6 +46,7 @@ import { videoSvg } from "../../img/svg"; import { VideoUpload } from "../video-upload-threespeak"; +import uploadToThreeSpeak from "../../api/threespeak"; interface Props { global: Global; @@ -345,10 +346,17 @@ export class EditorToolbar extends Component { e.target.value = ""; }; - videoInputChanged = (e: any | React.ChangeEvent): void => { - console.log(e.target.files) - console.log(e.target.files[0]) - + videoInputChanged = async (e: any | React.ChangeEvent): Promise => { + const { activeUser, global } = this.props; + console.log(activeUser?.username) + // console.log(e.target.files); + console.log(e.target.files[0]); + const upload = await uploadToThreeSpeak( + activeUser?.username, + e.target.files[0], + "https://1164326579-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fcryptowatch-guides%2F-MGtBBISJf5x2Uk-ldVl%2F-MGtLa7ILcJT6oJemFX3%2F0.gif?generation=1599763801987719&alt=media" + ); + console.log( upload ); }; upload = async (file: File) => { diff --git a/yarn.lock b/yarn.lock index f5e028b5751..d76ab6327d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2515,7 +2515,7 @@ adjust-sourcemap-loader@3.0.0: loader-utils "^2.0.0" regex-parser "^2.2.11" -agent-base@6: +agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== @@ -2846,6 +2846,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios-cookiejar-support@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/axios-cookiejar-support/-/axios-cookiejar-support-4.0.6.tgz#f57f75b1ae9bec929063130adc264eeabe81f5cc" + integrity sha512-lWDhgM6bc2xYAsHkXEhceLpTu9ytAeIz1VSuL5FoUgGx2lqcMNbNxTD9Hm4x5c8JF5Me0HfNrb06fhEGMC30mQ== + dependencies: + http-cookie-agent "^5.0.2" + axios@^0.21.2: version "0.21.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.2.tgz#21297d5084b2aeeb422f5d38e7be4fbb82239017" @@ -3293,7 +3300,7 @@ buffer-from@1.x: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer-from@^1.0.0: +buffer-from@^1.0.0, buffer-from@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -3856,6 +3863,14 @@ colors@1.4.0: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +combine-errors@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86" + integrity sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q== + dependencies: + custom-error-instance "2.1.1" + lodash.uniqby "4.5.0" + combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -4457,6 +4472,11 @@ currency-symbol-map@^4.0.4: resolved "https://registry.yarnpkg.com/currency-symbol-map/-/currency-symbol-map-4.0.4.tgz#3cfba625974dd3f86822d327ecbd10248695e95e" integrity sha512-hkSCCopJXVsvIZIiumJc6FoNXR5LQ646c3ufzF0yfv3155PYygysHw24JuzPSg4j86EFpvtgeX+vEhzRtcJ5Ag== +custom-error-instance@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a" + integrity sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg== + custom-event@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" @@ -6257,6 +6277,13 @@ htmlparser2@^8.0.1: domutils "^3.0.1" entities "^4.3.0" +http-cookie-agent@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/http-cookie-agent/-/http-cookie-agent-5.0.2.tgz#ec4d31ceebf64b1757225f5a68df635a61d44a79" + integrity sha512-BiBmZyIMGl5mLKmY7KH2uCVlcNUl1jexjdtWXFCUF4DFOrNZg1c5iPPTzWDzU7Ngfb6fB03DPpJQ80KQWmycsg== + dependencies: + agent-base "^6.0.2" + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -7430,6 +7457,11 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== +js-base64@^3.7.2: + version "3.7.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + js-cookie@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" @@ -7733,11 +7765,48 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash._baseiteratee@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102" + integrity sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ== + dependencies: + lodash._stringtopath "~4.8.0" + +lodash._basetostring@~4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df" + integrity sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw== + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A== + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash._stringtopath@~4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824" + integrity sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ== + dependencies: + lodash._basetostring "~4.12.0" + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -7773,11 +7842,24 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= +lodash.uniqby@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21" + integrity sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ== + dependencies: + lodash._baseiteratee "~4.7.0" + lodash._baseuniq "~4.6.0" + lodash@4.x, lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -9678,6 +9760,15 @@ prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + proxy-addr@~2.0.5: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -11983,6 +12074,16 @@ tough-cookie@^4.0.0: punycode "^2.1.1" universalify "^0.1.2" +tough-cookie@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -12119,6 +12220,19 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tus-js-client@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-3.1.0.tgz#20af57d06c23823fbe108ccb3a3dcb7503968cb4" + integrity sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw== + dependencies: + buffer-from "^1.1.2" + combine-errors "^3.0.3" + is-stream "^2.0.0" + js-base64 "^3.7.2" + lodash.throttle "^4.1.1" + proper-lockfile "^4.1.2" + url-parse "^1.5.7" + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -12273,6 +12387,11 @@ universalify@^0.1.2: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -12331,7 +12450,7 @@ url-loader@^4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@^1.5.3, url-parse@^1.5.7: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== From c9da6979e25bb705e2f92d39b8b56ac89cb55181 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 20 Mar 2023 20:09:04 +0100 Subject: [PATCH 05/49] fixed bug --- src/common/api/threespeak.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 2c71a130cba..6ea446627b7 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -3,7 +3,7 @@ const tus = require("tus-js-client"); const axios = require("axios").default; const { CookieJar } = require("tough-cookie"); -const { wrapper } = require("axios-cookiejar-support"); +const { wrapper } = require("axios-cookiejar-support"); const jar = new CookieJar(); const client = wrapper(axios.create({ jar })); From c75a409915a649aaf432c248ff6d3fd5fb862217 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Tue, 21 Mar 2023 15:02:26 +0100 Subject: [PATCH 06/49] fixed style --- src/common/components/video-upload-threespeak/index.scss | 5 +++++ src/common/components/video-upload-threespeak/index.tsx | 1 + 2 files changed, 6 insertions(+) diff --git a/src/common/components/video-upload-threespeak/index.scss b/src/common/components/video-upload-threespeak/index.scss index 53a1ead19e1..86130b4fefc 100644 --- a/src/common/components/video-upload-threespeak/index.scss +++ b/src/common/components/video-upload-threespeak/index.scss @@ -1,3 +1,8 @@ +@import "src/style/colors"; +@import "src/style/variables"; +@import "src/style/bootstrap_vars"; +@import "src/style/mixins"; + .new-feature{ position: relative; padding: 6px 22px; diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 6e2c7d3d5c1..bb2ffa8ecb3 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react' import { videoSvg } from '../../img/svg' +import "./index.scss"; export const VideoUpload = () => { From 324691135216730c51af9c63010e281418a1fa2f Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Sat, 25 Mar 2023 15:05:46 +0100 Subject: [PATCH 07/49] insert video text --- src/common/api/threespeak.ts | 13 +++++++------ src/common/components/editor-toolbar/index.tsx | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 6ea446627b7..25ef81da95c 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -4,6 +4,7 @@ const tus = require("tus-js-client"); const axios = require("axios").default; const { CookieJar } = require("tough-cookie"); const { wrapper } = require("axios-cookiejar-support"); +import { getPostingKey } from "../helper/user-token"; const jar = new CookieJar(); const client = wrapper(axios.create({ jar })); @@ -12,12 +13,12 @@ const client = wrapper(axios.create({ jar })); const getMemo = async (username: string, studioEndPoint: string) => { try { let response = await client.get(`${studioEndPoint}/mobile/login?username=${username}`, { - withCredentials: true, + withCredentials: false, // true headers: { "Content-Type": "application/json" } }); - return response.data.memo; + return response.data.memo; } catch (err) { console.log(err, "error"); throw err; @@ -30,7 +31,7 @@ const getCookies = async (username: string, studioEndPoint: string, jwt: string) let response = await client.get( `${studioEndPoint}/mobile/login?username=${username}&access_token=${jwt}`, { - withCredentials: true, + withCredentials: false, //true headers: { "Content-Type": "application/json" } @@ -148,8 +149,8 @@ const getAllVideoStatuses = async (studioEndPoint: string) => { export const uploadToThreeSpeak = async (username: string | any, file: string, thumbnail: string) => { const studioEndPoint = "https://studio.3speak.tv"; const tusEndPoint = "https://uploads.3speak.tv/files/"; - const postingKey = ""; - + const postingKey = getPostingKey(username) + console.log(postingKey) // Step 1. Get JWT Encrypted Memo const memo = await getMemo(username, studioEndPoint); // Decoded Memo using dhive Memo.decode class @@ -159,6 +160,7 @@ export const uploadToThreeSpeak = async (username: string | any, file: string, t // Step 2. Get Cookie using decrypted JWT const cookies = await getCookies(username, studioEndPoint, decrypted); + // we are logging the cookies here just to make sure that we got those. console.log(`Cookies are ${cookies}\n\n`); @@ -198,7 +200,6 @@ export const uploadToThreeSpeak = async (username: string | any, file: string, t false, // is NSFW "threespeak,mobile,ios,test" // comma separated tags - no spaces ); - console.log("uploading...") console.log(`Video Info response: ${JSON.stringify(updatedVideoMetadata)}`); } diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 5673798e88f..6450323b849 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -351,7 +351,8 @@ export class EditorToolbar extends Component { videoInputChanged = async (e: any | React.ChangeEvent): Promise => { const { activeUser, global } = this.props; console.log(activeUser?.username) - // console.log(e.target.files); + const tempVideoTag = `![Uploading ${e.target.files[0].name} #${Math.floor(Math.random() * 99)}]()\n\n`; + this.insertText(tempVideoTag); console.log(e.target.files[0]); const upload = await uploadToThreeSpeak( activeUser?.username, From e4a6b4ba13d307d4ed471168f3a9229aada4cf55 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 27 Mar 2023 19:57:01 +0100 Subject: [PATCH 08/49] logic fixes --- src/common/api/threespeak.ts | 157 ++++++++++-------- .../components/editor-toolbar/index.tsx | 17 +- 2 files changed, 97 insertions(+), 77 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 25ef81da95c..547dab614c0 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -1,10 +1,9 @@ const hive = require("@hiveio/dhive"); const tus = require("tus-js-client"); - +const Cookies = require("js-cookie"); const axios = require("axios").default; const { CookieJar } = require("tough-cookie"); -const { wrapper } = require("axios-cookiejar-support"); -import { getPostingKey } from "../helper/user-token"; +const { wrapper } = require("axios-cookiejar-support"); const jar = new CookieJar(); const client = wrapper(axios.create({ jar })); @@ -26,12 +25,13 @@ const getMemo = async (username: string, studioEndPoint: string) => { } // Get Cookie frow Memo (JWT) -const getCookies = async (username: string, studioEndPoint: string, jwt: string) => { +async function getCookies(username: string, studioEndPoint: string, jwt: string ) { try { let response = await client.get( `${studioEndPoint}/mobile/login?username=${username}&access_token=${jwt}`, { - withCredentials: false, //true + // withCredentials: true, + credentials: "include", headers: { "Content-Type": "application/json" } @@ -72,7 +72,8 @@ const updateVideoInfo = async ( oFilename: string, videoUrl: any, thumbnailUrl: any, - username: string + username: string, cookies: string, + size: number ) => { try { const { data } = await client.post( @@ -80,19 +81,21 @@ const updateVideoInfo = async ( { filename: videoUrl, oFilename: oFilename, - size: 2221284, // NOTE: please change this constant value. This is POC app. It has to be in bytes. - duration: 44, // NOTE: please change this constant value. This is POC app. it has to be in seconds. + size, // NOTE: please change this constant value. This is POC app. It has to be in bytes. + duration: 56, // NOTE: please change this constant value. This is POC app. it has to be in seconds. thumbnail: thumbnailUrl, owner: username, isReel: true // if video is a reel/short (Three Shorts) send this as true }, { - withCredentials: true, + withCredentials: false, headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", + Authorization: `Bearer ${cookies}` } } ); + console.log({data}) return data; } catch (e) { console.error(e); @@ -106,7 +109,8 @@ const updateVideoMetadata = async( title: string, description: string, isNsfwContent: boolean, - tags: string + tags: string, + cookies: string ) => { try { const info = { @@ -117,9 +121,10 @@ const updateVideoMetadata = async( tags: tags }; const { data } = await client.post(`${studioEndPoint}/mobile/api/update_info`, info, { - withCredentials: true, + withCredentials: false, headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", + Authorization: `Bearer ${cookies}` } }); return data; @@ -129,12 +134,13 @@ const updateVideoMetadata = async( } } -const getAllVideoStatuses = async (studioEndPoint: string) => { +const getAllVideoStatuses = async (studioEndPoint: string, cookies: string) => { try { let response = await client.get(`${studioEndPoint}/mobile/api/my-videos`, { - withCredentials: true, + withCredentials: false, headers: { - "Content-Type": "application/json" + "Content-Type": "application/json", + Authorization: `Bearer ${cookies}` } }); return response.data; @@ -146,61 +152,74 @@ const getAllVideoStatuses = async (studioEndPoint: string) => { // Main Function that calls every other one in the file -export const uploadToThreeSpeak = async (username: string | any, file: string, thumbnail: string) => { +export const uploadToThreeSpeak = async (username: string | any, file: any, thumbnail: any) => { const studioEndPoint = "https://studio.3speak.tv"; const tusEndPoint = "https://uploads.3speak.tv/files/"; - const postingKey = getPostingKey(username) - console.log(postingKey) - // Step 1. Get JWT Encrypted Memo - const memo = await getMemo(username, studioEndPoint); - // Decoded Memo using dhive Memo.decode class - let decrypted = hive.Memo.decode(postingKey, memo); - decrypted = decrypted.replace("#", ""); - console.log(`Decrypted ${decrypted}\n\n`); - - // Step 2. Get Cookie using decrypted JWT - const cookies = await getCookies(username, studioEndPoint, decrypted); - - // we are logging the cookies here just to make sure that we got those. - console.log(`Cookies are ${cookies}\n\n`); - - // Step 3. Upload video - const videoUpload: any = await startUpload("test-demo-video.mp4", tusEndPoint, file); - const videoUploadFileUrl = videoUpload.replace(`${tusEndPoint}`, ""); - console.log(`Video File Url ${videoUploadFileUrl}\n\n`); - - // Step 4. Upload Thumb - const thumbUpload: any = await startUpload("test-demo-video.mp4", tusEndPoint, thumbnail); - const thumbUploadFileUrl: string = thumbUpload.replace(`${tusEndPoint}`, ""); - console.log(`Thumb File ID ${thumbUploadFileUrl}\n\n`); - - // Step 5. Update Video upload information - const data = await updateVideoInfo( - studioEndPoint, - "test-demo-video.mp4", - videoUploadFileUrl, - thumbUploadFileUrl, - username - ); - console.log(`Video upload response: ${JSON.stringify(data)}`); - - // Step 6. Get all Videos data - const myAllVideosWithStatusInfo = await getAllVideoStatuses(studioEndPoint); - console.log(`All Videos Info response: ${JSON.stringify(myAllVideosWithStatusInfo)}`); - - const videoID = myAllVideosWithStatusInfo[0]._id; - console.log(videoID); - - // Step 7. Update MetaData of a specific video - const updatedVideoMetadata = await updateVideoMetadata( - studioEndPoint, - videoID, - "ActiFit & Ecency integrating #3Speak videos", // video title - "Lots of love for #Hive ♦️ and #3Speak ▶️", // video description - post content - false, // is NSFW - "threespeak,mobile,ios,test" // comma separated tags - no spaces - ); - console.log(`Video Info response: ${JSON.stringify(updatedVideoMetadata)}`); + // const postingKey = getPostingKey(username) + + try { + // Step 1. Get JWT Encrypted Memo + const memo = await getMemo(username, studioEndPoint); + + // Decoded Memo using dhive Memo.decode class + let decrypted = await hive.Memo.decode( + 'postingKey', + memo + ); + decrypted = decrypted.replace("#", ""); + console.log(`Decrypted Memo is ${decrypted}\n\n`); + + + // Step 2. Get Cookie using decrypted JWT + const cookies = await getCookies(username, studioEndPoint, decrypted); + + // we are logging the cookies here just to make sure that we got those. + console.log(`Cookies are ${cookies}\n\n`); + + // // Step 3. Upload video + const videoUpload: any = await startUpload("test-demo-video.mp4", tusEndPoint, file); + const videoUploadFileUrl = videoUpload.replace(`${tusEndPoint}`, ""); + console.log(`Video File Url ${videoUploadFileUrl}\n\n`); + + // // Step 4. Upload Thumb + const thumbUpload: any = await startUpload("test-demo-video.png", tusEndPoint, thumbnail); + const thumbUploadFileUrl: string = thumbUpload.replace(`${tusEndPoint}`, ""); + console.log(`Thumb File ID ${thumbUploadFileUrl}\n\n`); + + // Step 5. Update Video upload information + const data = await updateVideoInfo( + studioEndPoint, + file.name, + videoUploadFileUrl, + thumbUploadFileUrl, + username, + cookies, + file.size + ); + console.log(`Video upload response: ${JSON.stringify(data)}`); + + + // Step 6. Get all Videos data + const myAllVideosWithStatusInfo = await getAllVideoStatuses(studioEndPoint, cookies); + console.log(`All Videos Info response: ${JSON.stringify(myAllVideosWithStatusInfo)}`); + + const videoID = myAllVideosWithStatusInfo[0]._id; + console.log(videoID); + + // Step 7. Update MetaData of a specific video + const updatedVideoMetadata = await updateVideoMetadata( + studioEndPoint, + videoID, + "ActiFit & Ecency integrating #3Speak videos", // video title + "Lots of love for #Hive ♦️ and #3Speak ▶️", // video description - post content + false, // is NSFW + "threespeak,mobile,ios,test", // comma separated tags - no spaces + cookies + ); + console.log(`Video Info response: ${JSON.stringify(updatedVideoMetadata)}`); + } catch (err: any) { + console.error(err) + } } export default uploadToThreeSpeak; \ No newline at end of file diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 6450323b849..821a3069497 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -260,11 +260,11 @@ export class EditorToolbar extends Component { }; bold = () => { - this.insertText("**", "**"); + this.insertText("*", "*"); }; italic = () => { - this.insertText("*", "*"); + this.insertText("", ""); }; header = (w: number) => { @@ -350,16 +350,17 @@ export class EditorToolbar extends Component { videoInputChanged = async (e: any | React.ChangeEvent): Promise => { const { activeUser, global } = this.props; - console.log(activeUser?.username) + console.log(activeUser) const tempVideoTag = `![Uploading ${e.target.files[0].name} #${Math.floor(Math.random() * 99)}]()\n\n`; this.insertText(tempVideoTag); - console.log(e.target.files[0]); + console.log(e.target.files[0], e.target.files[1]); + const upload = await uploadToThreeSpeak( activeUser?.username, e.target.files[0], - "https://1164326579-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fcryptowatch-guides%2F-MGtBBISJf5x2Uk-ldVl%2F-MGtLa7ILcJT6oJemFX3%2F0.gif?generation=1599763801987719&alt=media" + e.target.files[1], ); - console.log( upload ); + console.log(upload); }; upload = async (file: File) => { @@ -602,7 +603,7 @@ export class EditorToolbar extends Component { className="file-input" ref={this.videoInput} type="file" - accept="video/*" + accept="any" multiple={true} style={{ display: "none" }} /> @@ -679,4 +680,4 @@ export default (props: Props) => { showGif: props.showGif }; return ; -}; +}; \ No newline at end of file From af6a7c8198e28391fe4dc67251a61ba2e74f2302 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 3 Apr 2023 16:21:10 +0100 Subject: [PATCH 09/49] change upload logic --- src/common/api/threespeak.ts | 33 +- .../components/editor-toolbar/index.tsx | 361 +++++++++++++++++- .../video-upload-threespeak/index.scss | 4 +- 3 files changed, 364 insertions(+), 34 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 547dab614c0..e454ae99ce0 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -8,11 +8,14 @@ const { wrapper } = require("axios-cookiejar-support"); const jar = new CookieJar(); const client = wrapper(axios.create({ jar })); +const studioEndPoint = "https://studio.3speak.tv"; +const tusEndPoint = "https://uploads.3speak.tv/files/"; + // Generate Memo from Username const getMemo = async (username: string, studioEndPoint: string) => { try { let response = await client.get(`${studioEndPoint}/mobile/login?username=${username}`, { - withCredentials: false, // true + withCredentials: false, headers: { "Content-Type": "application/json" } @@ -30,14 +33,15 @@ async function getCookies(username: string, studioEndPoint: string, jwt: string let response = await client.get( `${studioEndPoint}/mobile/login?username=${username}&access_token=${jwt}`, { - // withCredentials: true, - credentials: "include", + withCredentials: false, + // credentials: "include", headers: { "Content-Type": "application/json" } } ); - return response.headers["set-cookie"]; + console.log(response.data); + return response.data; } catch (err) { console.log(err); throw err; @@ -56,6 +60,7 @@ const startUpload = (fileName: string, tusEndPoint: string | undefined, file: an return reject(error); }, onProgress: function (bytesUploaded: number, bytesTotal: number) { + console.log(bytesUploaded) var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); console.log(bytesUploaded, bytesTotal, percentage + "%"); }, @@ -68,12 +73,13 @@ const startUpload = (fileName: string, tusEndPoint: string | undefined, file: an } const updateVideoInfo = async ( - studioEndPoint: string, + // studioEndPoint: string, oFilename: string, videoUrl: any, thumbnailUrl: any, - username: string, cookies: string, - size: number + username: string, + cookies: string, + // size: number ) => { try { const { data } = await client.post( @@ -81,7 +87,7 @@ const updateVideoInfo = async ( { filename: videoUrl, oFilename: oFilename, - size, // NOTE: please change this constant value. This is POC app. It has to be in bytes. + size: 9609313, // NOTE: please change this constant value. This is POC app. It has to be in bytes. duration: 56, // NOTE: please change this constant value. This is POC app. it has to be in seconds. thumbnail: thumbnailUrl, owner: username, @@ -153,8 +159,7 @@ const getAllVideoStatuses = async (studioEndPoint: string, cookies: string) => { // Main Function that calls every other one in the file export const uploadToThreeSpeak = async (username: string | any, file: any, thumbnail: any) => { - const studioEndPoint = "https://studio.3speak.tv"; - const tusEndPoint = "https://uploads.3speak.tv/files/"; + // const postingKey = getPostingKey(username) try { @@ -163,7 +168,7 @@ export const uploadToThreeSpeak = async (username: string | any, file: any, thum // Decoded Memo using dhive Memo.decode class let decrypted = await hive.Memo.decode( - 'postingKey', + '5KkEJ5JMKvEvH3BUzYwCGEJb8WSTSBW1nehZAc1hdyS5Bj3jdUx', memo ); decrypted = decrypted.replace("#", ""); @@ -188,13 +193,13 @@ export const uploadToThreeSpeak = async (username: string | any, file: any, thum // Step 5. Update Video upload information const data = await updateVideoInfo( - studioEndPoint, + // studioEndPoint, file.name, videoUploadFileUrl, thumbUploadFileUrl, username, - cookies, - file.size + decrypted, + // file.size ); console.log(`Video upload response: ${JSON.stringify(data)}`); diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 821a3069497..6c857c50771 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -41,6 +41,11 @@ import { } from "../../img/svg"; import { VideoUpload } from "../video-upload-threespeak"; import uploadToThreeSpeak from "../../api/threespeak"; +// import axios from "axios"; +import * as tus from "tus-js-client"; +import hive from "@hiveio/dhive"; +import { Button, Form, Modal, ModalBody } from "react-bootstrap"; +import ModalHeader from "react-bootstrap/esm/ModalHeader"; interface Props { global: Global; @@ -58,6 +63,15 @@ interface State { link: boolean; mobileImage: boolean; shGif: boolean; + // 3speak states + username: string; + postingKey: string; + accessToken: string; + videoUrl: string; + thumbUrl: string; + percent: string; + showUploadModal: boolean; + hideUploadModal: boolean; } export const detectEvent = (eventType: string) => { @@ -77,12 +91,24 @@ export class EditorToolbar extends Component { image: false, link: false, mobileImage: false, - shGif: false + shGif: false, + // 3speak states + username: "", + postingKey: "5KkEJ5JMKvEvH3BUzYwCGEJb8WSTSBW1nehZAc1hdyS5Bj3jdUx", + accessToken: "", + videoUrl: "", + thumbUrl: "", + percent: "", + showUploadModal: false, + hideUploadModal: false }; holder = React.createRef(); fileInput = React.createRef(); videoInput = React.createRef(); + studioEndPoint = "https://studio.3speak.tv"; + tusEndPoint = "https://uploads.3speak.tv/files/"; + client = axios.create({}); shouldComponentUpdate(nextProps: Readonly, nextState: Readonly): boolean { return ( @@ -348,20 +374,20 @@ export class EditorToolbar extends Component { e.target.value = ""; }; - videoInputChanged = async (e: any | React.ChangeEvent): Promise => { - const { activeUser, global } = this.props; - console.log(activeUser) - const tempVideoTag = `![Uploading ${e.target.files[0].name} #${Math.floor(Math.random() * 99)}]()\n\n`; - this.insertText(tempVideoTag); - console.log(e.target.files[0], e.target.files[1]); + // videoInputChanged = async (e: any | React.ChangeEvent): Promise => { + // const { activeUser, global } = this.props; + // console.log(activeUser) + // const tempVideoTag = `![Uploading ${e.target.files[0].name} #${Math.floor(Math.random() * 99)}]()\n\n`; + // this.insertText(tempVideoTag); + // console.log(e.target.files[0], e.target.files[1]); - const upload = await uploadToThreeSpeak( - activeUser?.username, - e.target.files[0], - e.target.files[1], - ); - console.log(upload); - }; + // const upload = await uploadToThreeSpeak( + // activeUser?.username, + // e.target.files[0], + // e.target.files[1], + // ); + // console.log(upload); + // }; upload = async (file: File) => { const { activeUser, global } = this.props; @@ -404,6 +430,219 @@ export class EditorToolbar extends Component { return ["jpg", "jpeg", "gif", "png"].some((el) => filenameLow.endsWith(el)); }; + logMe = async () => { + try { + let response = await this.client.get( + `${this.studioEndPoint}/mobile/login?username=${this.state.username}`, + { + withCredentials: false, + headers: { + "Content-Type": "application/json", + }, + } + ); + console.log(`Response: ${JSON.stringify(response)}`); + const memo = response.data.memo; + console.log(`Memo - ${response.data.memo}`); + let access_token = hive?.Memo.decode(this.state.postingKey, memo); + access_token = access_token.replace("#", ""); + console.log(`Decrypted ${access_token}\n\n`); + const user = await this.getTokenValidated(access_token); + // setAccessToken(access_token); + this.setState({ accessToken: access_token }) + console.log(`User is ${JSON.stringify(user)}`); + const allVideos = await this.getAllVideoStatuses(access_token); + console.log(`videos are is ${JSON.stringify(allVideos)})}`); + + // Step 3. Upload video + // const videoUpload = await startUpload("test-demo-video.mp4", tusEndPoint); + // const videoUploadFileUrl = videoUpload.replace(`${tusEndPoint}`, ""); + // console.log(`Video File Url ${videoUploadFileUrl}\n\n`); + + // // Step 4. Upload Thumb + // const thumbUpload = await startUpload("test-demo-thumb.png", tusEndPoint); + // const thumbUploadFileUrl = thumbUpload.replace(`${tusEndPoint}`, ""); + // console.log(`Thumb File ID ${thumbUploadFileUrl}\n\n`); + + // Step 5. Update Video upload information + // const data = await updateVideoInfo( + // "test-demo-video.mp4", + // 'bf7e91fc6ac176750a7e9ecd5e7d9413', + // ); + // console.log(`Video upload response: ${JSON.stringify(data)}`); + } catch (err) { + console.log(err); + throw err; + } + } + + uploadInfo = async () => { + const data = await this.updateVideoInfo("test-demo-video.mp4",this.state.videoUrl, this.state.thumbUrl); + console.log(`Video upload response: ${JSON.stringify(data)}`); + } + + getAllVideoStatuses = async (access_token: string) => { + try { + let response = await this.client.get( + `${this.studioEndPoint}/mobile/api/my-videos`, + { + withCredentials: false, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${access_token}`, + }, + } + ); + return response.data; + } catch (err) { + console.log(err); + throw err; + } + } + + // function to get cookies + getTokenValidated = async (jwt: string) => { + try { + let response = await this.client.get( + `${this.studioEndPoint}/mobile/login?username=${this.state.username}&access_token=${jwt}`, + { + withCredentials: false, + headers: { + "Content-Type": "application/json", + }, + } + ); + console.log(response.headers); + // setAccessToken(jwt); + this.setState({ accessToken: jwt}) + return response.data; //cookies + } catch (err) { + console.log(err); + throw err; + } + } + + updateVideoInfo = async ( + oFilename: string, + videoUrl: string, + thumbnailUrl: string, + ) => { + try { + const { data } = await axios.post( + `${this.studioEndPoint}/mobile/api/upload_info`, + { + filename: videoUrl, + oFilename: oFilename, + size: 9609313, // NOTE: please change this constant value. This is POC app. It has to be in bytes. + duration: 40, // NOTE: please change this constant value. This is POC app. it has to be in seconds. + thumbnail: thumbnailUrl, // NOTE: please change this constant value. This is POC app. It + owner: this.state.username, + isReel: false, // if video is a reel/short (Three Shorts) send this as true + }, + { + withCredentials: false, + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${this.state.accessToken}`, + }, + } + ); + return data; + } catch (e) { + console.error(e); + throw e; + } + } + + // onChange = (event: any) => { + // var file = event.target.files[0]; + // console.log(file); + + // if (file.type === "image/png"){ + // this.setState({ thumbUrl: file.name}) + // } else if ( file.type === "video/mp4") { + // this.setState({ videoUrl: file.name}) + // } + // var upload = new tus.Upload(file, { + // // Endpoint is the upload creation URL from your tus server + // endpoint: this.tusEndPoint, + // // Retry delays will enable tus-js-client to automatically retry on errors + // retryDelays: [0, 3000, 5000, 10000, 20000], + // // Attach additional meta data about the file for the server + // metadata: { + // filename: file.name, + // filetype: file.type, + // }, + // // Callback for errors which cannot be fixed using retries + // onError: function (error) { + // console.log("Failed because: " + error); + // }, + // // Callback for reporting upload progress + // onProgress: function (bytesUploaded, bytesTotal) { + // var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + // console.log(bytesUploaded, bytesTotal, percentage + "%"); + // // setPercent(percentage) + // // this.setState({percentage}) + // }, + // // Callback for once the upload is completed + // onSuccess: function () { + // console.log("File %s", upload.file?.name); + // console.log("URL %s", upload.url?.replace(this.tusEndPoint, "")); + // }, + // }); + // upload.start(); + // } + onChange = (event: { target: { files: any[]; }; }) => { + var file = event.target.files[0]; + console.log(file); + var upload: any = new tus.Upload(file, { + // Endpoint is the upload creation URL from your tus server + endpoint: this.tusEndPoint, + // Retry delays will enable tus-js-client to automatically retry on errors + retryDelays: [0, 3000, 5000, 10000, 20000], + // Attach additional meta data about the file for the server + metadata: { + filename: file.name, + filetype: file.type, + }, + // Callback for errors which cannot be fixed using retries + onError: function (error) { + console.log("Failed because: " + error); + }, + // Callback for reporting upload progress + onProgress: function (bytesUploaded, bytesTotal) { + var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + console.log(bytesUploaded, bytesTotal, percentage + "%"); + // setPercent(percentage) + }, + // Callback for once the upload is completed + onSuccess: function () { + console.log("File %s", upload.file?.name); + console.log("URL %s", upload?.url.replace(this.tusEndPoint, "")); + }, + }); + upload.start(); + } + + handleVideoUrlChange = (event: { target: { value: any; }; }) => { + // setVideoUrl(event.target.value); + console.log(event.target.value) + this.setState({ videoUrl: event.target.value}) + } + + handleThumbUrlChange = (event: { target: { value: any; }; }) => { + // setThumbUrl(event.target.value); + console.log(event.target.value) + this.setState({ thumbUrl: event.target.value}) + }; + + hideModal = () => { + this.setState({ showUploadModal: false }) + } + showModal = () => { + this.setState({ showUploadModal: true }) + } + render() { const { gallery, fragments, image, link, mobileImage } = this.state; const { global, sm, activeUser, showEmoji = true, showGif } = this.props; @@ -580,14 +819,98 @@ export class EditorToolbar extends Component {
) => { - e.stopPropagation(); - const el = this.videoInput.current; - if (el) el.click(); + this.showModal(); + // e.stopPropagation(); + // const el = this.videoInput.current; + // if (el) el.click(); }}>
+ + + Add File + + +
+
{ + // e.preventDefault(); + // e.stopPropagation(); + + // if (!this.form.current?.checkValidity()) { + // return; + // } + + // const { text, link } = this.state; + // const { onSubmit } = this.props; + // onSubmit(text, link); + // }} + > + + {/* */} + + handleInvalid(e, "add-image.", "validation-text")} + // onInput={handleOnInput} + /> + + + handleInvalid(e, "add-image.", "validation-image")} + // onInput={handleOnInput} + /> + +
+ +
+
+
+ {/*
+ +
+ + +
+
+ + +
+ +
*/} +
+
+
{ multiple={true} style={{ display: "none" }} /> - { accept="any" multiple={true} style={{ display: "none" }} - /> + /> */} {gallery && activeUser && ( Date: Tue, 4 Apr 2023 06:02:46 +0100 Subject: [PATCH 10/49] sec changes --- src/common/api/threespeak.ts | 6 ++++-- src/common/components/editor-toolbar/index.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index e454ae99ce0..cd55f416de3 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -1,3 +1,5 @@ +import { getPostingKey } from "../helper/user-token"; + const hive = require("@hiveio/dhive"); const tus = require("tus-js-client"); const Cookies = require("js-cookie"); @@ -160,7 +162,7 @@ const getAllVideoStatuses = async (studioEndPoint: string, cookies: string) => { // Main Function that calls every other one in the file export const uploadToThreeSpeak = async (username: string | any, file: any, thumbnail: any) => { - // const postingKey = getPostingKey(username) + const postingKey = getPostingKey(username) try { // Step 1. Get JWT Encrypted Memo @@ -168,7 +170,7 @@ export const uploadToThreeSpeak = async (username: string | any, file: any, thum // Decoded Memo using dhive Memo.decode class let decrypted = await hive.Memo.decode( - '5KkEJ5JMKvEvH3BUzYwCGEJb8WSTSBW1nehZAc1hdyS5Bj3jdUx', + postingKey, memo ); decrypted = decrypted.replace("#", ""); diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 6c857c50771..52a48866f25 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -94,7 +94,7 @@ export class EditorToolbar extends Component { shGif: false, // 3speak states username: "", - postingKey: "5KkEJ5JMKvEvH3BUzYwCGEJb8WSTSBW1nehZAc1hdyS5Bj3jdUx", + postingKey: "", accessToken: "", videoUrl: "", thumbUrl: "", From cfec5a2fa097fa7b01758d735a1da3f7fc41f608 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Tue, 4 Apr 2023 12:09:18 +0100 Subject: [PATCH 11/49] logic fixes --- .../components/editor-toolbar/index.tsx | 379 +++++++----------- 1 file changed, 151 insertions(+), 228 deletions(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 52a48866f25..b2306086a5e 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { Component, ChangeEvent } from "react"; import isEqual from "react-fast-compare"; import axios from "axios"; @@ -43,7 +43,7 @@ import { VideoUpload } from "../video-upload-threespeak"; import uploadToThreeSpeak from "../../api/threespeak"; // import axios from "axios"; import * as tus from "tus-js-client"; -import hive from "@hiveio/dhive"; +import { Memo } from "@hiveio/dhive"; import { Button, Form, Modal, ModalBody } from "react-bootstrap"; import ModalHeader from "react-bootstrap/esm/ModalHeader"; @@ -64,7 +64,6 @@ interface State { mobileImage: boolean; shGif: boolean; // 3speak states - username: string; postingKey: string; accessToken: string; videoUrl: string; @@ -93,7 +92,6 @@ export class EditorToolbar extends Component { mobileImage: false, shGif: false, // 3speak states - username: "", postingKey: "", accessToken: "", videoUrl: "", @@ -373,21 +371,6 @@ export class EditorToolbar extends Component { // reset input e.target.value = ""; }; - - // videoInputChanged = async (e: any | React.ChangeEvent): Promise => { - // const { activeUser, global } = this.props; - // console.log(activeUser) - // const tempVideoTag = `![Uploading ${e.target.files[0].name} #${Math.floor(Math.random() * 99)}]()\n\n`; - // this.insertText(tempVideoTag); - // console.log(e.target.files[0], e.target.files[1]); - - // const upload = await uploadToThreeSpeak( - // activeUser?.username, - // e.target.files[0], - // e.target.files[1], - // ); - // console.log(upload); - // }; upload = async (file: File) => { const { activeUser, global } = this.props; @@ -414,7 +397,6 @@ export class EditorToolbar extends Component { } else { error(_t("editor-toolbar.image-error-cache")); } - } catch (e) { if (axios.isAxiosError(e) && e.response?.status === 413) { error(_t("editor-toolbar.image-error-size")); @@ -430,121 +412,109 @@ export class EditorToolbar extends Component { return ["jpg", "jpeg", "gif", "png"].some((el) => filenameLow.endsWith(el)); }; - logMe = async () => { + logMe = async () => { try { + const { activeUser } = this.props; let response = await this.client.get( - `${this.studioEndPoint}/mobile/login?username=${this.state.username}`, + `${this.studioEndPoint}/mobile/login?username=${activeUser?.username}`, { withCredentials: false, headers: { - "Content-Type": "application/json", - }, + "Content-Type": "application/json" + } } ); console.log(`Response: ${JSON.stringify(response)}`); - const memo = response.data.memo; + const memo_string = response.data.memo; console.log(`Memo - ${response.data.memo}`); - let access_token = hive?.Memo.decode(this.state.postingKey, memo); + let access_token = Memo?.decode(this.state.postingKey, memo_string); + console.log({ access_token }); access_token = access_token.replace("#", ""); console.log(`Decrypted ${access_token}\n\n`); const user = await this.getTokenValidated(access_token); - // setAccessToken(access_token); - this.setState({ accessToken: access_token }) + + this.setState({ accessToken: access_token }); console.log(`User is ${JSON.stringify(user)}`); const allVideos = await this.getAllVideoStatuses(access_token); console.log(`videos are is ${JSON.stringify(allVideos)})}`); - // Step 3. Upload video - // const videoUpload = await startUpload("test-demo-video.mp4", tusEndPoint); - // const videoUploadFileUrl = videoUpload.replace(`${tusEndPoint}`, ""); - // console.log(`Video File Url ${videoUploadFileUrl}\n\n`); - - // // Step 4. Upload Thumb - // const thumbUpload = await startUpload("test-demo-thumb.png", tusEndPoint); - // const thumbUploadFileUrl = thumbUpload.replace(`${tusEndPoint}`, ""); - // console.log(`Thumb File ID ${thumbUploadFileUrl}\n\n`); - - // Step 5. Update Video upload information - // const data = await updateVideoInfo( - // "test-demo-video.mp4", - // 'bf7e91fc6ac176750a7e9ecd5e7d9413', - // ); - // console.log(`Video upload response: ${JSON.stringify(data)}`); } catch (err) { console.log(err); throw err; } - } + }; + + handlePostingKey = (e: any) => { + this.setState({ postingKey: e.target.value }); + }; - uploadInfo = async () => { - const data = await this.updateVideoInfo("test-demo-video.mp4",this.state.videoUrl, this.state.thumbUrl); + uploadInfo = async () => { + const data = await this.updateVideoInfo( + "test-demo-video.mp4", + this.state.videoUrl, + this.state.thumbUrl + ); console.log(`Video upload response: ${JSON.stringify(data)}`); - } + }; getAllVideoStatuses = async (access_token: string) => { try { - let response = await this.client.get( - `${this.studioEndPoint}/mobile/api/my-videos`, - { - withCredentials: false, - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${access_token}`, - }, + let response = await this.client.get(`${this.studioEndPoint}/mobile/api/my-videos`, { + withCredentials: false, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${access_token}` } - ); + }); return response.data; } catch (err) { console.log(err); throw err; } - } + }; // function to get cookies getTokenValidated = async (jwt: string) => { try { + const { activeUser } = this.props; let response = await this.client.get( - `${this.studioEndPoint}/mobile/login?username=${this.state.username}&access_token=${jwt}`, + `${this.studioEndPoint}/mobile/login?username=${activeUser?.username}&access_token=${jwt}`, { withCredentials: false, headers: { - "Content-Type": "application/json", - }, + "Content-Type": "application/json" + } } ); - console.log(response.headers); + console.log('Cookies', response.headers); // setAccessToken(jwt); - this.setState({ accessToken: jwt}) + this.setState({ accessToken: jwt }); return response.data; //cookies } catch (err) { console.log(err); throw err; } - } + }; - updateVideoInfo = async ( - oFilename: string, - videoUrl: string, - thumbnailUrl: string, - ) => { + updateVideoInfo = async (oFilename: string, videoUrl: string, thumbnailUrl: string) => { try { + const { activeUser } = this.props; const { data } = await axios.post( `${this.studioEndPoint}/mobile/api/upload_info`, { filename: videoUrl, oFilename: oFilename, - size: 9609313, // NOTE: please change this constant value. This is POC app. It has to be in bytes. - duration: 40, // NOTE: please change this constant value. This is POC app. it has to be in seconds. - thumbnail: thumbnailUrl, // NOTE: please change this constant value. This is POC app. It - owner: this.state.username, - isReel: false, // if video is a reel/short (Three Shorts) send this as true + size: 9609313, + duration: 40, + thumbnail: thumbnailUrl, + isReel: false }, { withCredentials: false, headers: { "Content-Type": "application/json", - "Authorization": `Bearer ${this.state.accessToken}`, - }, + Authorization: `Bearer ${this.state.accessToken}` + } } ); return data; @@ -552,49 +522,13 @@ export class EditorToolbar extends Component { console.error(e); throw e; } - } + }; - // onChange = (event: any) => { - // var file = event.target.files[0]; - // console.log(file); - - // if (file.type === "image/png"){ - // this.setState({ thumbUrl: file.name}) - // } else if ( file.type === "video/mp4") { - // this.setState({ videoUrl: file.name}) - // } - // var upload = new tus.Upload(file, { - // // Endpoint is the upload creation URL from your tus server - // endpoint: this.tusEndPoint, - // // Retry delays will enable tus-js-client to automatically retry on errors - // retryDelays: [0, 3000, 5000, 10000, 20000], - // // Attach additional meta data about the file for the server - // metadata: { - // filename: file.name, - // filetype: file.type, - // }, - // // Callback for errors which cannot be fixed using retries - // onError: function (error) { - // console.log("Failed because: " + error); - // }, - // // Callback for reporting upload progress - // onProgress: function (bytesUploaded, bytesTotal) { - // var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); - // console.log(bytesUploaded, bytesTotal, percentage + "%"); - // // setPercent(percentage) - // // this.setState({percentage}) - // }, - // // Callback for once the upload is completed - // onSuccess: function () { - // console.log("File %s", upload.file?.name); - // console.log("URL %s", upload.url?.replace(this.tusEndPoint, "")); - // }, - // }); - // upload.start(); - // } - onChange = (event: { target: { files: any[]; }; }) => { + onChange: any = (event: { target: { files: any[] } }, type: string) => { + // Set global this to self + var self = this; var file = event.target.files[0]; - console.log(file); + var upload: any = new tus.Upload(file, { // Endpoint is the upload creation URL from your tus server endpoint: this.tusEndPoint, @@ -603,7 +537,7 @@ export class EditorToolbar extends Component { // Attach additional meta data about the file for the server metadata: { filename: file.name, - filetype: file.type, + filetype: file.type }, // Callback for errors which cannot be fixed using retries onError: function (error) { @@ -613,35 +547,42 @@ export class EditorToolbar extends Component { onProgress: function (bytesUploaded, bytesTotal) { var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); console.log(bytesUploaded, bytesTotal, percentage + "%"); - // setPercent(percentage) }, // Callback for once the upload is completed onSuccess: function () { console.log("File %s", upload.file?.name); - console.log("URL %s", upload?.url.replace(this.tusEndPoint, "")); - }, + console.log("URL %s", upload?.url.replace("https://uploads.3speak.tv/files/", "")); + let file = upload?.url.replace(this.endpoint, ""); + if (type === "video") { + self.setState({ + videoUrl: file + }); + } else { + self.setState({ + thumbUrl: file + }); + } + } }); upload.start(); - } + }; - handleVideoUrlChange = (event: { target: { value: any; }; }) => { - // setVideoUrl(event.target.value); - console.log(event.target.value) - this.setState({ videoUrl: event.target.value}) - } + handleVideoUrlChange = (event: { target: { value: any } }) => { + console.log(event.target.value); + this.setState({ videoUrl: event.target.value }); + }; - handleThumbUrlChange = (event: { target: { value: any; }; }) => { - // setThumbUrl(event.target.value); - console.log(event.target.value) - this.setState({ thumbUrl: event.target.value}) + handleThumbUrlChange = (event: { target: { value: any } }) => { + console.log(event.target.value); + this.setState({ thumbUrl: event.target.value }); }; hideModal = () => { - this.setState({ showUploadModal: false }) - } + this.setState({ showUploadModal: false }); + }; showModal = () => { - this.setState({ showUploadModal: true }) - } + this.setState({ showUploadModal: true }); + }; render() { const { gallery, fragments, image, link, mobileImage } = this.state; @@ -816,101 +757,92 @@ export class EditorToolbar extends Component { )} -
) => { - this.showModal(); - // e.stopPropagation(); - // const el = this.videoInput.current; - // if (el) el.click(); - }}> - +
) => { + this.showModal(); + // e.stopPropagation(); + // const el = this.videoInput.current; + // if (el) el.click(); + }} + > +
Add File -
-
{ - // e.preventDefault(); - // e.stopPropagation(); - - // if (!this.form.current?.checkValidity()) { - // return; - // } - - // const { text, link } = this.state; - // const { onSubmit } = this.props; - // onSubmit(text, link); - // }} - > - - {/* */} - - handleInvalid(e, "add-image.", "validation-text")} - // onInput={handleOnInput} - /> - - - handleInvalid(e, "add-image.", "validation-image")} - // onInput={handleOnInput} - /> - -
- -
-
-
- {/*
- -
- - -
-
- - -
- -
*/} +
+
+ + ) => this.onChange(e, "video")} + /> + ) => this.onChange(e, "thumbnail")} + /> + + + + + + + + + +
+ +
+
+
-
{ multiple={true} style={{ display: "none" }} /> - {/* */} {gallery && activeUser && ( Date: Thu, 1 Jun 2023 12:25:17 +0100 Subject: [PATCH 12/49] move modal to video component --- .../components/editor-toolbar/index.tsx | 111 +++--------------- .../video-upload-threespeak/index.tsx | 111 ++++++++++++++++-- 2 files changed, 118 insertions(+), 104 deletions(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index b2306086a5e..8c69681e60f 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -540,11 +540,11 @@ export class EditorToolbar extends Component { filetype: file.type }, // Callback for errors which cannot be fixed using retries - onError: function (error) { - console.log("Failed because: " + error); - }, + // onError: function (error: string) { + // return console.log("Failed because: " + error); + // }, // Callback for reporting upload progress - onProgress: function (bytesUploaded, bytesTotal) { + onProgress: function (bytesUploaded: number, bytesTotal: number) { var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); console.log(bytesUploaded, bytesTotal, percentage + "%"); }, @@ -577,13 +577,6 @@ export class EditorToolbar extends Component { this.setState({ thumbUrl: event.target.value }); }; - hideModal = () => { - this.setState({ showUploadModal: false }); - }; - showModal = () => { - this.setState({ showUploadModal: true }); - }; - render() { const { gallery, fragments, image, link, mobileImage } = this.state; const { global, sm, activeUser, showEmoji = true, showGif } = this.props; @@ -757,92 +750,20 @@ export class EditorToolbar extends Component { )} -
) => { - this.showModal(); - // e.stopPropagation(); - // const el = this.videoInput.current; - // if (el) el.click(); - }} - > - +
+
- - - - Add File - - -
-
- - ) => this.onChange(e, "video")} - /> - ) => this.onChange(e, "thumbnail")} - /> - - - - - - - - - -
- -
-
-
-
-
{ +export const VideoUpload = (props: any) => { + const { + postingKey, + onChange, + handlePostingKey, + videoUrl, + handleVideoUrlChange, + thumbUrl, + handleThumbUrlChange, + logMe, + uploadInfo + } = props; - const [selectedFile, setSelectedFile]: any = useState(""); - - const onVideoUpload = () => { - console.log(selectedFile); - }; + const [selectedFile, setSelectedFile] = useState(""); + const [showModal, setShowModal] = useState(false) + + const hideModal = () => { + setShowModal(false) + } + + const modalBody = ( +
+
+ + ) => onChange(e, "video")} + /> + ) => onChange(e, "thumbnail")} + /> + + + + + + + + + +
+ +
+
+
+ ) return ( -
-
{ videoSvg }
+
+
setShowModal(true)}> + { videoSvg } +
+
+ + + Add File + + + {modalBody} + + +
) } From 13fd8b4689153fe0445632af40aa5ddbac9696e6 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Thu, 1 Jun 2023 13:11:53 +0100 Subject: [PATCH 13/49] change styles --- .../video-upload-threespeak/index.scss | 7 +++- .../video-upload-threespeak/index.tsx | 39 +++++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/common/components/video-upload-threespeak/index.scss b/src/common/components/video-upload-threespeak/index.scss index 6d4b92ef7ee..ebd8715f0ba 100644 --- a/src/common/components/video-upload-threespeak/index.scss +++ b/src/common/components/video-upload-threespeak/index.scss @@ -24,4 +24,9 @@ right: 0px; border-radius: 10px; vertical-align: 5px; - } \ No newline at end of file + } + + label{ + cursor: pointer; + } + \ No newline at end of file diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 8f1fc3afbeb..0ce3c586b06 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -17,7 +17,6 @@ export const VideoUpload = (props: any) => { uploadInfo } = props; - const [selectedFile, setSelectedFile] = useState(""); const [showModal, setShowModal] = useState(false) const hideModal = () => { @@ -28,27 +27,14 @@ export const VideoUpload = (props: any) => {
+ ) => onChange(e, "video")} /> - ) => onChange(e, "thumbnail")} - /> - - - - { /> + + ) => onChange(e, "thumbnail")} + /> { required={true} /> + + + +
- -
- -
- -
- ) + const onChange: any = (event: { target: { files: any[] } }, type: string) => { + let file = event.target.files[0]; + + let upload: any = new tus.Upload(file, { + // Endpoint is the upload creation URL from your tus server + endpoint: tusEndPoint, + // Retry delays will enable tus-js-client to automatically retry on errors + retryDelays: [0, 3000, 5000, 10000, 20000], + // Attach additional meta data about the file for the server + metadata: { + filename: file.name, + filetype: file.type + }, + // Callback for errors which cannot be fixed using retries + onError: function (error: Error) { + return console.log( error); + }, + // Callback for reporting upload progress + onProgress: function (bytesUploaded: number, bytesTotal: number) { + let vPercentage; + let tPercentage; + if (type === "video") { + vPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + setVideoPercentage(vPercentage) + // self.setState({bytesUploaded, bytesTotal, percentage}) + } else { + tPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + setThumbPercenrage(tPercentage) + // self.setState({bytesUploaded, bytesTotal, thumbPercentage}) + } + }, + // Callback for once the upload is completed + onSuccess: function () { + console.log("File %s", upload.file?.name); + console.log("URL %s", upload?.url.replace("https://uploads.3speak.tv/files/", "")); + let file = upload?.url.replace(this.endpoint, ""); + if (type === "video") { + setVideoUrl(file); + setFileName(upload.file?.name); + setFileSize(upload.file?.size); + } else { + setThumbUrl(file); + setFileName(upload.file?.name); + setFileSize(upload.file?.size); + } + } + }); + upload.start(); + }; + + const handleFileChange = (e: ChangeEvent) => { + const file: any = e?.target?.files[0]; + onChange(e, "video") + console.log(file) + setSelectedFile(URL?.createObjectURL(file)); + }; + + const uploadInfo = async ()=> { + console.log("testing if it works...") + const data = await uploadVideoInfo(activeUser!.username, videoUrl, thumbUrl, fileName, fileSize) + setVideoId(data._id) + setIsNsfwC(data.isNsfwContent) + console.log(data) + } + + const checkStat = async () => { + const token = await threespeakAuth(activeUser!.username) + await getAllVideoStatuses(token) + console.log(await getAllVideoStatuses(token)) + console.log(accessToken) + } + + const updateSpeakVideo = async () => { + const token = await threespeakAuth(activeUser!.username) + console.log(videoId) + console.log(token, description, videoId, title, tags) + updateInfo(token, description, videoId, title, tags, isNsfwC) + } + + const uploadVideoModal = ( +
+
+ + +
+ {Number(videoPercentage) > 0 && <> +
+ {`${videoPercentage}%`} + } +
+ {/* {`${fileName}(${bytesUploaded}/${bytesTotal})kb`} */} +
+
+ + ) => onChange(e, "thumbnail")} + /> +
+ {Number(thumbPercentage) > 0 && <> +
+ {`${thumbPercentage}%`} + } +
+
+ + + +
+) + +const updateVideoModal = ( +
+
+ +
+
+ + +
+
+) return (
@@ -104,10 +200,14 @@ export const VideoUpload = (props: any) => { // size="lg" > - Add File + + {step === "upload" &&

Upload Video

} + {step === "update" &&

Update Video

} +
- {modalBody} + {step === "upload" && uploadVideoModal} + {step === "update" && updateVideoModal}
diff --git a/src/common/img/svg.tsx b/src/common/img/svg.tsx index c215978db84..680f0f27043 100644 --- a/src/common/img/svg.tsx +++ b/src/common/img/svg.tsx @@ -1992,6 +1992,13 @@ export const videoSvg = ( fill="currentColor" className="bi bi-camera-video" viewBox="0 0 16 16"> - + ) + +export const uploadSvgV = ( + + + + +) \ No newline at end of file diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index f0fc48a190f..f2ee092e130 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -1075,7 +1075,7 @@ class SubmitPage extends BaseComponent { })}
)} - {EditorToolbar({ ...this.props })} + {EditorToolbar({ ...this.props, body: body, tags: tags, title: title })}
Date: Mon, 12 Jun 2023 23:04:45 +0100 Subject: [PATCH 15/49] video gallery --- src/common/api/threespeak.ts | 5 - .../components/editor-toolbar/index.tsx | 2 +- .../components/video-gallery/index.scss | 105 +++++++++ src/common/components/video-gallery/index.tsx | 176 +++++++++++++++ .../video-upload-threespeak/index.tsx | 206 +++++++++++------- 5 files changed, 407 insertions(+), 87 deletions(-) create mode 100644 src/common/components/video-gallery/index.scss create mode 100644 src/common/components/video-gallery/index.tsx diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 1ca16d84c73..b45c33de43b 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -26,10 +26,7 @@ export const threespeakAuth = async (username: string) => { let access_token = Memo?.decode(postingAuthKey!, memo_string); access_token = access_token.replace("#", ""); - console.log(access_token) const user = await getTokenValidated(access_token, username); - - console.log(`User is ${JSON.stringify(user)}`); return access_token } catch (err) { console.log(err); @@ -63,7 +60,6 @@ export const uploadVideoInfo = async (username: string, videoUrl: string, thumbU thumbUrl, username ); - console.log(`Video upload response: ${JSON.stringify(data)}`); return data }; @@ -131,7 +127,6 @@ export const updateInfo = async (accessToken: string, postBody: string, videoId: axios.post(`${studioEndPoint}/mobile/api/update_info`, data, { headers }) .then(response => { - console.log("successfully updated") console.log(response.data); // Do something with the response data }) .catch(error => { diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index a6c773aad98..2fa910faf34 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -484,7 +484,6 @@ export class EditorToolbar extends Component { e.stopPropagation(); const el = this.fileInput.current; if (el) { - console.log(el) el.click()}; }} > @@ -571,6 +570,7 @@ export class EditorToolbar extends Component { description={this.props.body} activeUser={activeUser} tags={this.props.tags} + global={global} />
diff --git a/src/common/components/video-gallery/index.scss b/src/common/components/video-gallery/index.scss new file mode 100644 index 00000000000..7e700fcfa16 --- /dev/null +++ b/src/common/components/video-gallery/index.scss @@ -0,0 +1,105 @@ +@import "src/style/colors"; +@import "src/style/variables"; +@import "src/style/bootstrap_vars"; +@import "src/style/mixins"; + +.video-list{ + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; + font-size: 12px; + + .video-list-body{ + flex: 1; + display: flex; + flex-direction: column; + // gap: 5px; + width: 220px; + // max-height: 200px; + // margin-right: 10px; + + .list-image{ + width: 100%; + + img{ + width: 230px; + height: 150px; + object-fit: cover; + border-radius: 10px; + } + } + + + .list-details-wrapper{ + display: flex; + flex-direction: column; + gap: 5px; + margin-top: 5px; + width: 100%; + + .list-title{ + display: flex; + align-items: center; + justify-content: space-between; + width:230px; + + .details-title{ + // flex: 1; + font-size: 16px; + // width:230px; + } + .details-svg{ + // width:230px; + // flex: 1; + font-size: 15px; + cursor: pointer; + color: $dark-sky-blue; + } + } + + .list-date{ + display: flex; + align-items: center; + width: 230px; + justify-content: space-between; + + span{ + // flex: 1; + font-size: 12px; + } + + button{ + background-color: $dark-sky-blue; + width: 30%; + padding: 5px; + border-radius: 5px; + border: none; + color: inherit; + // flex: 1; + } + + .published{ + color: rgb(107, 243, 107); + } + .encoding{ + color: rgb(238, 238, 128); + } + .encoding-failed{ + color: rgb(241, 80, 80); + } + } + + } + + + } + } + + .video-status-picker{ + display: flex; + gap: 15px; + margin-bottom: 10px; + } + + \ No newline at end of file diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx new file mode 100644 index 00000000000..b6a4748d3c0 --- /dev/null +++ b/src/common/components/video-gallery/index.tsx @@ -0,0 +1,176 @@ +import React, { useEffect, useState } from 'react' +import LinearProgress from '../linear-progress'; +import PopoverConfirm from '../popover-confirm'; +import { deleteForeverSvg, informationVariantSvg } from '../../img/svg'; +import { Button, Modal, Tooltip } from 'react-bootstrap'; +import { _t } from '../../i18n'; +import "./index.scss" + +const VideoGallery = (props: any) => { + + const {showGaller, setShowGallery, checkStat, selectedFile} = props; + + const [loading, setLoading] = useState(false); + const [items, setItems] = useState([]); + + useEffect(()=> { + getAllStatus(); + }, []) + + const getAllStatus = async () => { + setLoading(true) + const data = await checkStat() + if (data){ + setItems(data) + setLoading(false) + } + } + + const hideModal = () => { + setShowGallery(false) + } + + const formatTime = (dateStr: string | number | Date) => { + const date: any = new Date(dateStr); + const now: any = new Date(); + + const difference = Math.abs(now - date); + const seconds = Math.floor(difference / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const months = Math.floor(days / 30); + const years = Math.floor(months / 12); + + if (years > 0) { + if (years === 1) { + return `${years} year ago` + } else { + return `${years} years ago`; + } + } else if (months > 0) { + if (months === 1) { + return `${months} day ago`; + } else { + return` ${months} months ago`; + } + } else if (days > 0) { + if (days === 1) { + return `${days} day ago`; + } else { + return `${days} days ago`; + } + } else if (hours > 0) { + if (hours === 1) { + return `${hours} day ago` + } else{ + return `${hours} hours ago`; + } + } else if (minutes > 0) { + if (minutes === 1) { + return `${minutes} day ago` + } else { + return `${minutes} minutes ago`; + } + } else { + return `${seconds} seconds ago`; + } + } + + const filterListByStatus = async (action?: string) => { + setLoading(true); + const data = await checkStat(); + let filtered; + + if (action) { + filtered = data.filter((video: any) => video.status === action); + setLoading(false) + return filtered; + } + + if (!action) return data; + + setLoading(false); + } + + const modalBodyTop = ( +
+ + + + + + + + + +
+ ) + + const modalBody = ( +
+ {loading && } + {items?.length > 0 && ( +
+ {items?.map((item: any) => { + return ( +
+
+ +
+
+
+ + {item.title.substring(0,15)}... + + + more... + +
+
+ + {formatTime(item.created)} + + {item.status === "publish_manual" ? : + item.status === "encoding_failed" ? Encoding failed❌ : + item.status === "published" ? Published✅ : + Encoding🟡} +
+
+
+ ) + })} +
+ )} + {!loading && items?.length === 0 &&
{_t("g.empty-list")}
} +
+ ) + + return ( + <> + setShowGallery(false)} + size="lg" className="gallery-modal"> + + Video {_t("gallery.title")} + + + {modalBodyTop} + {modalBody} + + + + ) +} + +export default VideoGallery \ No newline at end of file diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 93f2195ee03..512501df070 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -1,10 +1,11 @@ -import React, { useState, ChangeEvent, useEffect } from 'react' +import React, { useState, ChangeEvent, useEffect, useRef } from 'react' import { videoSvg, uploadSvgV } from '../../img/svg' import { Button, Modal } from "react-bootstrap"; import { _t } from '../../i18n'; import "./index.scss"; import { threespeakAuth, getAllVideoStatuses, uploadVideoInfo, updateInfo } from '../../api/threespeak'; import * as tus from "tus-js-client"; +import VideoGallery from "../video-gallery"; export const VideoUpload = (props: any) => { const { @@ -14,12 +15,16 @@ export const VideoUpload = (props: any) => { title, tags, activeUser, + global } = props; const tusEndPoint = "https://uploads.3speak.tv/files/"; + const fileInput = useRef(null); + const videoInput = useRef(null); const [showModal, setShowModal] = useState(false) const [selectedFile, setSelectedFile] = useState(null); + const [coverImage, setCoverImage] = useState(null) const [step, setStep] = useState("upload") const [videoId, setVideoId] = useState("") const [videoUrl, setVideoUrl] = useState("") @@ -28,11 +33,15 @@ export const VideoUpload = (props: any) => { const [fileSize, setFileSize] = useState(0) const [videoPercentage, setVideoPercentage] = useState("") const [thumbPercentage, setThumbPercenrage] = useState("") - const [ isNsfwC, setIsNsfwC] = useState(false) + const [ isNsfwC, setIsNsfwC] = useState(false); + const [showGaller, setShowGallery] = useState(false); + + const canUpload = thumbUrl && videoUrl + const canUpdate = thumbUrl && videoUrl && title && tags && description useEffect(() =>{ threespeakAuth(activeUser!.username) - },[]) + },[]); const hideModal = () => { setShowModal(false) @@ -62,11 +71,9 @@ export const VideoUpload = (props: any) => { if (type === "video") { vPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); setVideoPercentage(vPercentage) - // self.setState({bytesUploaded, bytesTotal, percentage}) } else { tPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); setThumbPercenrage(tPercentage) - // self.setState({bytesUploaded, bytesTotal, thumbPercentage}) } }, // Callback for once the upload is completed @@ -88,7 +95,14 @@ export const VideoUpload = (props: any) => { upload.start(); }; - const handleFileChange = (e: ChangeEvent) => { + const handleThumbnailChange = (e: ChangeEvent) => { + const file: any = e?.target?.files[0]; + onChange(e, "thumbnail") + console.log(file) + setCoverImage(URL?.createObjectURL(file)); + }; + + const handleVideoChange = (e: ChangeEvent) => { const file: any = e?.target?.files[0]; onChange(e, "video") console.log(file) @@ -105,9 +119,9 @@ export const VideoUpload = (props: any) => { const checkStat = async () => { const token = await threespeakAuth(activeUser!.username) - await getAllVideoStatuses(token) - console.log(await getAllVideoStatuses(token)) - console.log(accessToken) + const allStatus = await getAllVideoStatuses(token) + console.log(allStatus) + return allStatus; } const updateSpeakVideo = async () => { @@ -117,33 +131,34 @@ export const VideoUpload = (props: any) => { updateInfo(token, description, videoId, title, tags, isNsfwC) } - const uploadVideoModal = ( -
-
- - -
- {Number(videoPercentage) > 0 && <> -
- {`${videoPercentage}%`} - } -
- {/* {`${fileName}(${bytesUploaded}/${bytesTotal})kb`} */} -
-
- + const uploadVideoModal = ( +
+
+ + +
+ {Number(videoPercentage) > 0 && <> +
+ {`${videoPercentage}%`} + } +
+
+
+ ) => onChange(e, "thumbnail")} + onChange={handleThumbnailChange} />
{Number(thumbPercentage) > 0 && <> @@ -151,65 +166,94 @@ export const VideoUpload = (props: any) => { {`${thumbPercentage}%`} }
+
+
- - - -
-) + ) -const updateVideoModal = ( -
-
- -
-
- - -
-
-) + const updateVideoModal = ( +
+
+ +
+
+ + +
+
+ ); return (
-
setShowModal(true)}> +
{ videoSvg } + {activeUser && ( +
+
setShowModal(true)} + > + {_t("editor-toolbar.upload")} video +
+ {global.usePrivate && ( +
) => { + e.stopPropagation(); + setShowGallery(true) + // this.toggleGallery(); + }} + > + Video {_t("editor-toolbar.gallery")} +
+ )} +
+ )}
+
- - - {step === "upload" &&

Upload Video

} - {step === "update" &&

Update Video

} -
-
- - {step === "upload" && uploadVideoModal} - {step === "update" && updateVideoModal} - -
+ animation={false} + show={showModal} + centered={true} + onHide={hideModal} + keyboard={false} + className="add-image-modal" + // size="lg" + > + + + {step === "upload" &&

Upload Video

} + {step === "update" &&

Preview

} +
+
+ + {step === "upload" && uploadVideoModal} + {step === "update" && updateVideoModal} + +
) From 99c96836d2d8d99c2e78376cecf14f2360e62fc9 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Tue, 13 Jun 2023 19:04:44 +0100 Subject: [PATCH 16/49] fix translations --- src/common/components/video-gallery/index.tsx | 33 +++++------ .../video-upload-threespeak/index.scss | 6 ++ .../video-upload-threespeak/index.tsx | 55 ++++++++----------- src/common/i18n/locales/en-US.json | 23 ++++++++ 4 files changed, 67 insertions(+), 50 deletions(-) diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index b6a4748d3c0..6141cf4136b 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react' import LinearProgress from '../linear-progress'; -import PopoverConfirm from '../popover-confirm'; import { deleteForeverSvg, informationVariantSvg } from '../../img/svg'; import { Button, Modal, Tooltip } from 'react-bootstrap'; import { _t } from '../../i18n'; @@ -8,7 +7,7 @@ import "./index.scss" const VideoGallery = (props: any) => { - const {showGaller, setShowGallery, checkStat, selectedFile} = props; + const {showGaller, setShowGallery, checkStat} = props; const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); @@ -26,10 +25,6 @@ const VideoGallery = (props: any) => { } } - const hideModal = () => { - setShowGallery(false) - } - const formatTime = (dateStr: string | number | Date) => { const date: any = new Date(dateStr); const now: any = new Date(); @@ -97,23 +92,23 @@ const VideoGallery = (props: any) => {
+ }}>{_t("video-gallery.all")} + }}>{_t("video-gallery.published")} + }}>{_t("video-gallery.encoding")} + }}>{_t("video-gallery.encoded")} + }}>{_t("video-gallery.failed")}
) @@ -122,9 +117,9 @@ const VideoGallery = (props: any) => { {loading && } {items?.length > 0 && (
- {items?.map((item: any) => { + {items?.map((item: any, i: any) => { return ( -
+
@@ -134,17 +129,17 @@ const VideoGallery = (props: any) => { {item.title.substring(0,15)}... - more... + more...
{formatTime(item.created)} - {item.status === "publish_manual" ? : - item.status === "encoding_failed" ? Encoding failed❌ : - item.status === "published" ? Published✅ : - Encoding🟡} + {item.status === "publish_manual" ? : + item.status === "encoding_failed" ? {_t("video-gallery.failed")} : + item.status === "published" ? {_t("video-gallery.publish")} : + {_t("video-gallery.encoding")}}
@@ -173,4 +168,4 @@ const VideoGallery = (props: any) => { ) } -export default VideoGallery \ No newline at end of file +export default VideoGallery; \ No newline at end of file diff --git a/src/common/components/video-upload-threespeak/index.scss b/src/common/components/video-upload-threespeak/index.scss index b32e5c28b68..cc4aa2e8801 100644 --- a/src/common/components/video-upload-threespeak/index.scss +++ b/src/common/components/video-upload-threespeak/index.scss @@ -66,4 +66,10 @@ } } } + + .video-successfull{ + display: flex; + flex-direction: column; + gap: 5px; + } \ No newline at end of file diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 512501df070..a2bdd76d222 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -9,8 +9,6 @@ import VideoGallery from "../video-gallery"; export const VideoUpload = (props: any) => { const { - insertText, - accessToken, description, title, tags, @@ -43,10 +41,6 @@ export const VideoUpload = (props: any) => { threespeakAuth(activeUser!.username) },[]); - const hideModal = () => { - setShowModal(false) - } - const onChange: any = (event: { target: { files: any[] } }, type: string) => { let file = event.target.files[0]; @@ -78,8 +72,6 @@ export const VideoUpload = (props: any) => { }, // Callback for once the upload is completed onSuccess: function () { - console.log("File %s", upload.file?.name); - console.log("URL %s", upload?.url.replace("https://uploads.3speak.tv/files/", "")); let file = upload?.url.replace(this.endpoint, ""); if (type === "video") { setVideoUrl(file); @@ -98,43 +90,36 @@ export const VideoUpload = (props: any) => { const handleThumbnailChange = (e: ChangeEvent) => { const file: any = e?.target?.files[0]; onChange(e, "thumbnail") - console.log(file) setCoverImage(URL?.createObjectURL(file)); }; const handleVideoChange = (e: ChangeEvent) => { const file: any = e?.target?.files[0]; onChange(e, "video") - console.log(file) setSelectedFile(URL?.createObjectURL(file)); }; const uploadInfo = async ()=> { - console.log("testing if it works...") const data = await uploadVideoInfo(activeUser!.username, videoUrl, thumbUrl, fileName, fileSize) setVideoId(data._id) setIsNsfwC(data.isNsfwContent) - console.log(data) } const checkStat = async () => { const token = await threespeakAuth(activeUser!.username) const allStatus = await getAllVideoStatuses(token) - console.log(allStatus) return allStatus; } const updateSpeakVideo = async () => { - const token = await threespeakAuth(activeUser!.username) - console.log(videoId) - console.log(token, description, videoId, title, tags) - updateInfo(token, description, videoId, title, tags, isNsfwC) + const token = await threespeakAuth(activeUser!.username); + updateInfo(token, description, videoId, title, tags, isNsfwC); } const uploadVideoModal = (
- + { />
{Number(videoPercentage) > 0 && <> -
+
{`${videoPercentage}%`} }
- + { onClick={()=> { uploadInfo(); setStep("update") - }}>Upload Video + }}>{_t("video-upload.continue")}
- ) + ); const updateVideoModal = (
@@ -186,19 +171,26 @@ export const VideoUpload = (props: any) => {
+ >{_t("g.back")}
); + + const videoSuccessModal = ( +
+

{_t("video-upload.success")}

+ +
+ ) return (
@@ -210,7 +202,7 @@ export const VideoUpload = (props: any) => { className="sub-tool-menu-item" onClick={() => setShowModal(true)} > - {_t("editor-toolbar.upload")} video + {_t("video-upload.upload-video")}
{global.usePrivate && (
{ onClick={(e: React.MouseEvent) => { e.stopPropagation(); setShowGallery(true) - // this.toggleGallery(); }} > - Video {_t("editor-toolbar.gallery")} + {_t("video-upload.video-gallery")}
)}
@@ -238,20 +229,22 @@ export const VideoUpload = (props: any) => { animation={false} show={showModal} centered={true} - onHide={hideModal} + onHide={()=>setShowModal(false)} keyboard={false} className="add-image-modal" // size="lg" > - {step === "upload" &&

Upload Video

} - {step === "update" &&

Preview

} + {step === "upload" &&

{_t("video-upload.upload-video")}

} + {step === "update" &&

{_t("video-upload.preview")}

} + {step === "success" &&

{_t("video-upload.congrats")}

}
{step === "upload" && uploadVideoModal} {step === "update" && updateVideoModal} + {step === "success" && videoSuccessModal}
diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 439410a3e02..4507edb1d86 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1321,6 +1321,29 @@ "empty-body-alert": "Enter post body", "description": "Short description" }, + "video-upload":{ + "choose-video": "Choose video", + "choose-thumbnail": "Choose video", + "continue": "Continue", + "encode": "Enconde video", + "success":"Video has been uploaded successfully", + "finished": "Finished", + "upload-video": "Upload video", + "video-gallery": "Video gallery", + "preview": "Preview", + "congrats": "Congratulations" + }, + "video-gallery":{ + "all":"All", + "published":"Published", + "encoding":"Encoding", + "encoded":"Encoded", + "filed":"Failed", + "publish": "Publish", + "status-published": "Published✅", + "status-failed": "Encoding failed❌", + "status-encoding": "Encoding🟡" + }, "tag-selector": { "placeholder-empty": "Tags. First tag is main category. Sortable.", "placeholder-focus": "Enter tag", From ab50abc7adc412964d6f4db110197cfa15f0648f Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Wed, 14 Jun 2023 08:07:36 +0100 Subject: [PATCH 17/49] fix video info --- .../components/video-gallery/index.scss | 37 +++++-- src/common/components/video-gallery/index.tsx | 103 +++++++++++++++--- src/common/i18n/locales/en-US.json | 15 ++- 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/common/components/video-gallery/index.scss b/src/common/components/video-gallery/index.scss index 7e700fcfa16..311087d5e46 100644 --- a/src/common/components/video-gallery/index.scss +++ b/src/common/components/video-gallery/index.scss @@ -11,14 +11,11 @@ font-size: 12px; .video-list-body{ + position: relative; flex: 1; display: flex; flex-direction: column; - // gap: 5px; width: 220px; - // max-height: 200px; - // margin-right: 10px; - .list-image{ width: 100%; @@ -45,13 +42,9 @@ width:230px; .details-title{ - // flex: 1; font-size: 16px; - // width:230px; } .details-svg{ - // width:230px; - // flex: 1; font-size: 15px; cursor: pointer; color: $dark-sky-blue; @@ -65,7 +58,6 @@ justify-content: space-between; span{ - // flex: 1; font-size: 12px; } @@ -75,8 +67,6 @@ padding: 5px; border-radius: 5px; border: none; - color: inherit; - // flex: 1; } .published{ @@ -102,4 +92,29 @@ margin-bottom: 10px; } + .more-info{ + display: flex; + flex-direction: column; + position: absolute; + padding: 10px; + right: 30px; + justify-content: space-around; + width: 200px; + height: 200px; + border: 1px solid gray; + border-radius: 5px; + z-index: 999; + + @include themify(night) { + background: #283241; + color: $pinkish-grey; + border: 1px solid $dark; + } + + @include themify(day) { + background: $white; + color: $charcoal-grey; + border: 1px solid $white-five; + } + } \ No newline at end of file diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 6141cf4136b..67a45883af4 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react' import LinearProgress from '../linear-progress'; import { deleteForeverSvg, informationVariantSvg } from '../../img/svg'; -import { Button, Modal, Tooltip } from 'react-bootstrap'; +import { Button, Modal, ModalBody, Tooltip } from 'react-bootstrap'; import { _t } from '../../i18n'; import "./index.scss" @@ -11,6 +11,8 @@ const VideoGallery = (props: any) => { const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); + const[showMoreInfo, setShowMoreInfo] = useState(false); + const [hoveredItem, setHoveredItem] = useState(null); useEffect(()=> { getAllStatus(); @@ -45,7 +47,7 @@ const VideoGallery = (props: any) => { } } else if (months > 0) { if (months === 1) { - return `${months} day ago`; + return `${months} month ago`; } else { return` ${months} months ago`; } @@ -57,13 +59,13 @@ const VideoGallery = (props: any) => { } } else if (hours > 0) { if (hours === 1) { - return `${hours} day ago` + return `${hours} hour ago` } else{ return `${hours} hours ago`; } } else if (minutes > 0) { if (minutes === 1) { - return `${minutes} day ago` + return `${minutes} mintutes ago` } else { return `${minutes} minutes ago`; } @@ -86,7 +88,11 @@ const VideoGallery = (props: any) => { if (!action) return data; setLoading(false); - } + }; + + const getHoveredItem = (item: any) => { + setHoveredItem(item) + }; const modalBodyTop = (
@@ -110,7 +116,7 @@ const VideoGallery = (props: any) => { setItems(await filterListByStatus("encoding_failed")) }}>{_t("video-gallery.failed")}
- ) + ); const modalBody = (
@@ -128,7 +134,14 @@ const VideoGallery = (props: any) => { {item.title.substring(0,15)}... - + { + getHoveredItem(item) + setShowMoreInfo(true) + }} + onMouseOut={() => setShowMoreInfo(false)} + className="info-icon details-svg" + > more...
@@ -136,12 +149,74 @@ const VideoGallery = (props: any) => { {formatTime(item.created)} - {item.status === "publish_manual" ? : - item.status === "encoding_failed" ? {_t("video-gallery.failed")} : - item.status === "published" ? {_t("video-gallery.publish")} : - {_t("video-gallery.encoding")}} + {item.status === "publish_manual" ? + : + item.status === "encoding_failed" ? + + {_t("video-gallery.status-failed")} + : + item.status === "published" ? +
+ + {_t("video-gallery.status-published")} + + +
: + + {_t("video-gallery.status-encoding")} + }
+ {showMoreInfo && hoveredItem._id === item._id && +
+
+ + {_t("video-gallery.info-posted-from")} {item.app} + +
+
+ + {_t("video-gallery.info-created")} {formatTime(item.created)} + +
+
+ + {_t("video-gallery.info-status")} {item.status} + +
+
+ + {_t("video-gallery.info-views")} {item.views} + +
+
+ + {_t("video-gallery.info-title")} {item.title.substring(0, 20)}... + +
+
+ + {_t("video-gallery.info-description")} {item.description.substring(0, 20)}... + +
+
+ + {_t("video-gallery.info-duration")} {item.duration} + +
+
+ + {_t("video-gallery.info-rewards")} {`${item.declineRewards ? "Yes" : "No"}`} + +
+
+ + {_t("video-gallery.info-size")} {`${(item.size / (1024 * 1024)).toFixed(2)}MB`} + +
+
}
) })} @@ -149,10 +224,10 @@ const VideoGallery = (props: any) => { )} {!loading && items?.length === 0 &&
{_t("g.empty-list")}
}
- ) + ); return ( - <> +
setShowGallery(false)} size="lg" className="gallery-modal"> @@ -164,7 +239,7 @@ const VideoGallery = (props: any) => { {modalBody} - +
) } diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 4507edb1d86..c632fe97e23 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1338,11 +1338,20 @@ "published":"Published", "encoding":"Encoding", "encoded":"Encoded", - "filed":"Failed", - "publish": "Publish", + "failed":"Failed", + "status-encoded": "Publish", + "status-encoding": "Encoding🟡", "status-published": "Published✅", "status-failed": "Encoding failed❌", - "status-encoding": "Encoding🟡" + "info-posted-from": "Posted from:", + "info-created": "Created:", + "info-status": "Status:", + "info-views": "Views:", + "info-title": "Title:", + "info-description": "Description:", + "info-duration":"Duration:", + "info-rewards":"Decline rewards:", + "info-size":"File size:" }, "tag-selector": { "placeholder-empty": "Tags. First tag is main category. Sortable.", From ae2f6dbcfaf9c4f2d3d177f5ade2eafceb350de2 Mon Sep 17 00:00:00 2001 From: feruz Date: Fri, 16 Jun 2023 11:26:55 +0300 Subject: [PATCH 18/49] fix memo decoding with hivesigner --- package.json | 2 +- src/common/api/threespeak.ts | 108 ++-- .../video-upload-threespeak/index.tsx | 469 +++++++++--------- src/common/helper/hive-signer.ts | 15 + yarn.lock | 8 +- 5 files changed, 327 insertions(+), 275 deletions(-) diff --git a/package.json b/package.json index 2435ef8e615..0cbcaf36a77 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "express": "^4.17.3", "history": "^4.7.2", "hive-uri": "^0.2.3", - "hivesigner": "^3.2.8", + "hivesigner": "^3.3.4", "html-react-parser": "^1.2.1", "i18next": "^19.4.4", "i18next-browser-languagedetector": "^4.2.0", diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index b45c33de43b..b0442d79b2a 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -2,39 +2,39 @@ import { Memo } from "@hiveio/dhive"; import * as tus from "tus-js-client"; import axios from "axios"; import { getPostingKey } from "../helper/user-token"; - +import { getDecodedMemo } from "../helper/hive-signer"; const studioEndPoint = "https://studio.3speak.tv"; const tusEndPoint = "https://uploads.3speak.tv/files/"; const client = axios.create({}); - export const threespeakAuth = async (username: string) => { try { const postingAuthKey = getPostingKey(username); - + let response = await client.get( - `${studioEndPoint}/mobile/login?username=${username}`, + `${studioEndPoint}/mobile/login?username=${username}&hivesigner=true`, { withCredentials: false, headers: { "Content-Type": "application/json" } } - ); - const memo_string = response.data.memo; - let access_token = Memo?.decode(postingAuthKey!, memo_string); - - access_token = access_token.replace("#", ""); - const user = await getTokenValidated(access_token, username); - return access_token + ); + const memo_string = response.data.memo; + let { memoDecoded } = await getDecodedMemo(username, memo_string); + console.log("access_token", memoDecoded); + + memoDecoded = memoDecoded.replace("#", ""); + const user = await getTokenValidated(memoDecoded, username); + return memoDecoded; } catch (err) { console.log(err); throw err; } }; -export const getTokenValidated = async (jwt: string, username: string) => { +export const getTokenValidated = async (jwt: string, username: string) => { try { let response = await client.get( `${studioEndPoint}/mobile/login?username=${username}&access_token=${jwt}`, @@ -52,20 +52,25 @@ export const getTokenValidated = async (jwt: string, username: string) => { } }; -export const uploadVideoInfo = async (username: string, videoUrl: string, thumbUrl: string, oFileName: string, fileSize: number) => { - const data = await updateVideoInfo( - oFileName, - fileSize, - videoUrl, - thumbUrl, - username - ); - return data +export const uploadVideoInfo = async ( + username: string, + videoUrl: string, + thumbUrl: string, + oFileName: string, + fileSize: number +) => { + const data = await updateVideoInfo(oFileName, fileSize, videoUrl, thumbUrl, username); + return data; }; -export const updateVideoInfo = async (oFilename: string, fileSize: number, videoUrl: string, thumbnailUrl: string, username: string) => { - - const token = await threespeakAuth(username) +export const updateVideoInfo = async ( + oFilename: string, + fileSize: number, + videoUrl: string, + thumbnailUrl: string, + username: string +) => { + const token = await threespeakAuth(username); try { // const { activeUser } = this.props; const { data } = await axios.post( @@ -73,10 +78,10 @@ export const updateVideoInfo = async (oFilename: string, fileSize: number, video { filename: videoUrl, oFilename: oFilename, - size: fileSize, - duration: 40, + size: fileSize, + duration: 40, thumbnail: thumbnailUrl, - isReel: false , + isReel: false, owner: username }, { @@ -110,26 +115,33 @@ export const getAllVideoStatuses = async (accessToken: string) => { } }; -export const updateInfo = async (accessToken: string, postBody: string, videoId: string, title: string, tags: string[], isNsfwC: boolean) => { - - const data = { - videoId: videoId, - title: title, - description: postBody, - isNsfwContent: isNsfwC, - tags_v2: tags, - } +export const updateInfo = async ( + accessToken: string, + postBody: string, + videoId: string, + title: string, + tags: string[], + isNsfwC: boolean +) => { + const data = { + videoId: videoId, + title: title, + description: postBody, + isNsfwContent: isNsfwC, + tags_v2: tags + }; - const headers = { - "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}` - } + const headers = { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}` + }; - axios.post(`${studioEndPoint}/mobile/api/update_info`, data, { headers }) - .then(response => { - console.log(response.data); // Do something with the response data - }) - .catch(error => { - console.error('Error:', error); - }); -} \ No newline at end of file + axios + .post(`${studioEndPoint}/mobile/api/update_info`, data, { headers }) + .then((response) => { + console.log(response.data); // Do something with the response data + }) + .catch((error) => { + console.error("Error:", error); + }); +}; diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index a2bdd76d222..13b558f2f40 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -1,253 +1,278 @@ -import React, { useState, ChangeEvent, useEffect, useRef } from 'react' -import { videoSvg, uploadSvgV } from '../../img/svg' +import React, { useState, ChangeEvent, useEffect, useRef } from "react"; +import { videoSvg, uploadSvgV } from "../../img/svg"; import { Button, Modal } from "react-bootstrap"; -import { _t } from '../../i18n'; +import { _t } from "../../i18n"; import "./index.scss"; -import { threespeakAuth, getAllVideoStatuses, uploadVideoInfo, updateInfo } from '../../api/threespeak'; +import { + threespeakAuth, + getAllVideoStatuses, + uploadVideoInfo, + updateInfo +} from "../../api/threespeak"; import * as tus from "tus-js-client"; import VideoGallery from "../video-gallery"; +import useMount from "react-use/lib/useMount"; export const VideoUpload = (props: any) => { - const { - description, - title, - tags, - activeUser, - global - } = props; + const { description, title, tags, activeUser, global } = props; const tusEndPoint = "https://uploads.3speak.tv/files/"; const fileInput = useRef(null); const videoInput = useRef(null); - const [showModal, setShowModal] = useState(false) - const [selectedFile, setSelectedFile] = useState(null); - const [coverImage, setCoverImage] = useState(null) - const [step, setStep] = useState("upload") - const [videoId, setVideoId] = useState("") - const [videoUrl, setVideoUrl] = useState("") - const [thumbUrl, setThumbUrl] = useState("") - const [fileName, setFileName] = useState("") - const [fileSize, setFileSize] = useState(0) - const [videoPercentage, setVideoPercentage] = useState("") - const [thumbPercentage, setThumbPercenrage] = useState("") - const [ isNsfwC, setIsNsfwC] = useState(false); - const [showGaller, setShowGallery] = useState(false); - - const canUpload = thumbUrl && videoUrl - const canUpdate = thumbUrl && videoUrl && title && tags && description - - useEffect(() =>{ - threespeakAuth(activeUser!.username) - },[]); - - const onChange: any = (event: { target: { files: any[] } }, type: string) => { - let file = event.target.files[0]; - - let upload: any = new tus.Upload(file, { - // Endpoint is the upload creation URL from your tus server - endpoint: tusEndPoint, - // Retry delays will enable tus-js-client to automatically retry on errors - retryDelays: [0, 3000, 5000, 10000, 20000], - // Attach additional meta data about the file for the server - metadata: { - filename: file.name, - filetype: file.type - }, - // Callback for errors which cannot be fixed using retries - onError: function (error: Error) { - return console.log( error); - }, - // Callback for reporting upload progress - onProgress: function (bytesUploaded: number, bytesTotal: number) { - let vPercentage; - let tPercentage; - if (type === "video") { - vPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); - setVideoPercentage(vPercentage) - } else { - tPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); - setThumbPercenrage(tPercentage) - } - }, - // Callback for once the upload is completed - onSuccess: function () { - let file = upload?.url.replace(this.endpoint, ""); - if (type === "video") { - setVideoUrl(file); - setFileName(upload.file?.name); - setFileSize(upload.file?.size); - } else { - setThumbUrl(file); - setFileName(upload.file?.name); - setFileSize(upload.file?.size); - } - } - }); - upload.start(); - }; - - const handleThumbnailChange = (e: ChangeEvent) => { - const file: any = e?.target?.files[0]; - onChange(e, "thumbnail") - setCoverImage(URL?.createObjectURL(file)); - }; - - const handleVideoChange = (e: ChangeEvent) => { - const file: any = e?.target?.files[0]; - onChange(e, "video") - setSelectedFile(URL?.createObjectURL(file)); - }; - - const uploadInfo = async ()=> { - const data = await uploadVideoInfo(activeUser!.username, videoUrl, thumbUrl, fileName, fileSize) - setVideoId(data._id) - setIsNsfwC(data.isNsfwContent) - } + const [showModal, setShowModal] = useState(false); + const [selectedFile, setSelectedFile] = useState(null); + const [coverImage, setCoverImage] = useState(null); + const [step, setStep] = useState("upload"); + const [videoId, setVideoId] = useState(""); + const [videoUrl, setVideoUrl] = useState(""); + const [thumbUrl, setThumbUrl] = useState(""); + const [fileName, setFileName] = useState(""); + const [fileSize, setFileSize] = useState(0); + const [videoPercentage, setVideoPercentage] = useState(""); + const [thumbPercentage, setThumbPercenrage] = useState(""); + const [isNsfwC, setIsNsfwC] = useState(false); + const [showGaller, setShowGallery] = useState(false); + const [isMounted, setIsMounted] = useState(false); + + const canUpload = thumbUrl && videoUrl; + const canUpdate = thumbUrl && videoUrl && title && tags && description; - const checkStat = async () => { - const token = await threespeakAuth(activeUser!.username) - const allStatus = await getAllVideoStatuses(token) - return allStatus; - } + useMount(() => setIsMounted(true)); - const updateSpeakVideo = async () => { - const token = await threespeakAuth(activeUser!.username); - updateInfo(token, description, videoId, title, tags, isNsfwC); + useEffect(() => { + if (isMounted) { + threespeakAuth(activeUser!.username); } + }, []); - const uploadVideoModal = ( -
-
- - -
- {Number(videoPercentage) > 0 && <> -
- {`${videoPercentage}%`} - } -
-
-
- - -
- {Number(thumbPercentage) > 0 && <> -
- {`${thumbPercentage}%`} - } -
-
- -
+ const onChange: any = (event: { target: { files: any[] } }, type: string) => { + let file = event.target.files[0]; + + let upload: any = new tus.Upload(file, { + // Endpoint is the upload creation URL from your tus server + endpoint: tusEndPoint, + // Retry delays will enable tus-js-client to automatically retry on errors + retryDelays: [0, 3000, 5000, 10000, 20000], + // Attach additional meta data about the file for the server + metadata: { + filename: file.name, + filetype: file.type + }, + // Callback for errors which cannot be fixed using retries + onError: function (error: Error) { + return console.log(error); + }, + // Callback for reporting upload progress + onProgress: function (bytesUploaded: number, bytesTotal: number) { + let vPercentage; + let tPercentage; + if (type === "video") { + vPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + setVideoPercentage(vPercentage); + } else { + tPercentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2); + setThumbPercenrage(tPercentage); + } + }, + // Callback for once the upload is completed + onSuccess: function () { + let file = upload?.url.replace(this.endpoint, ""); + if (type === "video") { + setVideoUrl(file); + setFileName(upload.file?.name); + setFileSize(upload.file?.size); + } else { + setThumbUrl(file); + setFileName(upload.file?.name); + setFileSize(upload.file?.size); + } + } + }); + upload.start(); + }; + + const handleThumbnailChange = (e: ChangeEvent) => { + const file: any = e?.target?.files[0]; + onChange(e, "thumbnail"); + setCoverImage(URL?.createObjectURL(file)); + }; + + const handleVideoChange = (e: ChangeEvent) => { + const file: any = e?.target?.files[0]; + onChange(e, "video"); + setSelectedFile(URL?.createObjectURL(file)); + }; + + const uploadInfo = async () => { + const data = await uploadVideoInfo( + activeUser!.username, + videoUrl, + thumbUrl, + fileName, + fileSize ); + setVideoId(data._id); + setIsNsfwC(data.isNsfwContent); + }; + + const checkStat = async () => { + const token = await threespeakAuth(activeUser!.username); + const allStatus = await getAllVideoStatuses(token); + return allStatus; + }; + + const updateSpeakVideo = async () => { + const token = await threespeakAuth(activeUser!.username); + updateInfo(token, description, videoId, title, tags, isNsfwC); + }; - const updateVideoModal = ( -
-
- + const uploadVideoModal = ( +
+
+ + +
+ {Number(videoPercentage) > 0 && ( + <> +
+ {`${videoPercentage}%`} + + )}
-
- - +
+
+ + +
+ {Number(thumbPercentage) > 0 && ( + <> +
+ {`${thumbPercentage}%`} + + )}
- ); + +
+ ); - const videoSuccessModal = ( -
-

{_t("video-upload.success")}

- + const updateVideoModal = ( +
+
+ +
+
+ +
- ) - +
+ ); + + const videoSuccessModal = ( +
+

{_t("video-upload.success")}

+ +
+ ); + return (
-
- { videoSvg } - {activeUser && ( -
+
+ {videoSvg} + {activeUser && ( +
+
setShowModal(true)}> + {_t("video-upload.upload-video")} +
+ {global.usePrivate && (
setShowModal(true)} + onClick={(e: React.MouseEvent) => { + e.stopPropagation(); + setShowGallery(true); + }} > - {_t("video-upload.upload-video")} + {_t("video-upload.video-gallery")}
- {global.usePrivate && ( -
) => { - e.stopPropagation(); - setShowGallery(true) - }} - > - {_t("video-upload.video-gallery")} -
- )} -
- )} -
- + )} +
+ -
- setShowModal(false)} - keyboard={false} - className="add-image-modal" - // size="lg" + /> +
+ setShowModal(false)} + keyboard={false} + className="add-image-modal" + // size="lg" > - - - {step === "upload" &&

{_t("video-upload.upload-video")}

} - {step === "update" &&

{_t("video-upload.preview")}

} - {step === "success" &&

{_t("video-upload.congrats")}

} -
-
- - {step === "upload" && uploadVideoModal} - {step === "update" && updateVideoModal} - {step === "success" && videoSuccessModal} - -
-
+ + + {step === "upload" &&

{_t("video-upload.upload-video")}

} + {step === "update" &&

{_t("video-upload.preview")}

} + {step === "success" &&

{_t("video-upload.congrats")}

} +
+
+ + {step === "upload" && uploadVideoModal} + {step === "update" && updateVideoModal} + {step === "success" && videoSuccessModal} + +
+
- ) -} + ); +}; diff --git a/src/common/helper/hive-signer.ts b/src/common/helper/hive-signer.ts index 8f9d4efca40..dafff9095bd 100644 --- a/src/common/helper/hive-signer.ts +++ b/src/common/helper/hive-signer.ts @@ -1,4 +1,7 @@ +import hs from "hivesigner"; + import { b64uEnc } from "../util/b64"; +import { getAccessToken } from "./user-token"; export const getAuthUrl = (app: string, redir: string = `${window.location.origin}/auth`) => { const scope = @@ -13,6 +16,18 @@ export const getTokenUrl = (code: string, secret: string) => { return `https://hivesigner.com/api/oauth2/token?code=${code}&client_secret=${secret}`; }; +export const getDecodedMemo = (username: string, memo: string): Promise => { + // With hivesigner access token + let token = getAccessToken(username); + return token + ? new hs.Client({ + accessToken: token + }) + .decode(memo) + .then((r: any) => r) + : Promise.resolve(0); +}; + export interface HiveSignerMessage { signed_message: { type: string; diff --git a/yarn.lock b/yarn.lock index dfc48f5800d..714645e3238 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6106,10 +6106,10 @@ hive-uri@^0.2.4: resolved "https://registry.yarnpkg.com/hive-uri/-/hive-uri-0.2.4.tgz#6975cfa50790571084d31249e6e061ed3d4f7fde" integrity sha512-c61F16oVARU+eLvGy20JN7M9YK+DUexHPFGBlG39VHI9Ahxos8YNCY6Btmw9AL7Jlq5b4HtY0LvsOIqHQoOWhw== -hivesigner@^3.2.8: - version "3.2.8" - resolved "https://registry.yarnpkg.com/hivesigner/-/hivesigner-3.2.8.tgz#868dd77dcc96a6c25018f4ed6aa32dfae595a864" - integrity sha512-lSpN2123GLdpuaQLMOW0/Ux8+pbnaXTEvu3JpMNT2TcT8Ey9vG/pT+gnwqJ/sTAUTmge8OQtbZ0zIzaR9QS4Wg== +hivesigner@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/hivesigner/-/hivesigner-3.3.4.tgz#5ab19f25821eacb6683d86ee098e3868f028497e" + integrity sha512-n+fpsmc3FvkwXwhSTHJgChq97YeL2bEcJz/Awn9o+boFnIxqrxg4Y3i4sMMR8j+kJnwDV9c5JIMF4zQVxPSPJQ== dependencies: "@babel/runtime" "^7.13.9" cross-fetch "^3.0.6" From b3ad18438d71715e56c036ae62fbb1091addee3c Mon Sep 17 00:00:00 2001 From: feruz Date: Fri, 16 Jun 2023 22:04:33 +0300 Subject: [PATCH 19/49] linting --- src/common/api/threespeak.ts | 2 - .../components/editor-toolbar/index.tsx | 24 +- src/common/components/video-gallery/index.tsx | 374 +++++++++--------- src/common/i18n/locales/en-US.json | 28 +- src/common/img/svg.tsx | 44 ++- 5 files changed, 253 insertions(+), 219 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index b0442d79b2a..1ab848e948b 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -10,8 +10,6 @@ const client = axios.create({}); export const threespeakAuth = async (username: string) => { try { - const postingAuthKey = getPostingKey(username); - let response = await client.get( `${studioEndPoint}/mobile/login?username=${username}&hivesigner=true`, { diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 2fa910faf34..782d85c0e3c 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -36,7 +36,7 @@ import { gridSvg, emoticonHappyOutlineSvg, textShortSvg, - gifIcon, + gifIcon } from "../../img/svg"; import { VideoUpload } from "../video-upload-threespeak"; @@ -49,7 +49,7 @@ interface Props { showGif?: boolean; body: string; title: string; - tags: string[] + tags: string[]; } interface State { @@ -78,13 +78,12 @@ export class EditorToolbar extends Component { image: false, link: false, mobileImage: false, - shGif: false, + shGif: false }; holder = React.createRef(); fileInput = React.createRef(); videoInput = React.createRef(); - shouldComponentUpdate(nextProps: Readonly, nextState: Readonly): boolean { return ( @@ -484,7 +483,8 @@ export class EditorToolbar extends Component { e.stopPropagation(); const el = this.fileInput.current; if (el) { - el.click()}; + el.click(); + } }} > {_t("editor-toolbar.upload")} @@ -565,12 +565,12 @@ export class EditorToolbar extends Component {
-
@@ -660,4 +660,4 @@ export default (props: Props) => { tags: props.tags }; return ; -}; \ No newline at end of file +}; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 67a45883af4..f6de251132b 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -1,36 +1,36 @@ -import React, { useEffect, useState } from 'react' -import LinearProgress from '../linear-progress'; -import { deleteForeverSvg, informationVariantSvg } from '../../img/svg'; -import { Button, Modal, ModalBody, Tooltip } from 'react-bootstrap'; -import { _t } from '../../i18n'; -import "./index.scss" +import React, { useEffect, useState } from "react"; +import LinearProgress from "../linear-progress"; +import { deleteForeverSvg, informationVariantSvg } from "../../img/svg"; +import { Button, Modal, ModalBody, Tooltip } from "react-bootstrap"; +import { _t } from "../../i18n"; +import "./index.scss"; const VideoGallery = (props: any) => { - - const {showGaller, setShowGallery, checkStat} = props; + const { showGaller, setShowGallery, checkStat } = props; const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); - const[showMoreInfo, setShowMoreInfo] = useState(false); + const [showMoreInfo, setShowMoreInfo] = useState(false); const [hoveredItem, setHoveredItem] = useState(null); - useEffect(()=> { + useEffect(() => { getAllStatus(); - }, []) + }, []); const getAllStatus = async () => { - setLoading(true) - const data = await checkStat() - if (data){ - setItems(data) - setLoading(false) + setLoading(true); + const data = await checkStat(); + console.log(data); + if (data) { + setItems(data); + setLoading(false); } - } + }; const formatTime = (dateStr: string | number | Date) => { const date: any = new Date(dateStr); const now: any = new Date(); - + const difference = Math.abs(now - date); const seconds = Math.floor(difference / 1000); const minutes = Math.floor(seconds / 60); @@ -39,40 +39,40 @@ const VideoGallery = (props: any) => { const months = Math.floor(days / 30); const years = Math.floor(months / 12); - if (years > 0) { - if (years === 1) { - return `${years} year ago` - } else { - return `${years} years ago`; - } - } else if (months > 0) { - if (months === 1) { - return `${months} month ago`; - } else { - return` ${months} months ago`; - } - } else if (days > 0) { - if (days === 1) { - return `${days} day ago`; - } else { - return `${days} days ago`; - } - } else if (hours > 0) { - if (hours === 1) { - return `${hours} hour ago` - } else{ - return `${hours} hours ago`; - } - } else if (minutes > 0) { - if (minutes === 1) { - return `${minutes} mintutes ago` - } else { - return `${minutes} minutes ago`; - } + if (years > 0) { + if (years === 1) { + return `${years} year ago`; + } else { + return `${years} years ago`; + } + } else if (months > 0) { + if (months === 1) { + return `${months} month ago`; } else { - return `${seconds} seconds ago`; + return ` ${months} months ago`; } - } + } else if (days > 0) { + if (days === 1) { + return `${days} day ago`; + } else { + return `${days} days ago`; + } + } else if (hours > 0) { + if (hours === 1) { + return `${hours} hour ago`; + } else { + return `${hours} hours ago`; + } + } else if (minutes > 0) { + if (minutes === 1) { + return `${minutes} mintutes ago`; + } else { + return `${minutes} minutes ago`; + } + } else { + return `${seconds} seconds ago`; + } + }; const filterListByStatus = async (action?: string) => { setLoading(true); @@ -81,7 +81,7 @@ const VideoGallery = (props: any) => { if (action) { filtered = data.filter((video: any) => video.status === action); - setLoading(false) + setLoading(false); return filtered; } @@ -91,146 +91,168 @@ const VideoGallery = (props: any) => { }; const getHoveredItem = (item: any) => { - setHoveredItem(item) + setHoveredItem(item); }; const modalBodyTop = (
- + - + - + - + - +
); const modalBody = (
- {loading && } - {items?.length > 0 && ( -
- {items?.map((item: any, i: any) => { - return ( -
-
- -
-
-
- - {item.title.substring(0,15)}... - - { - getHoveredItem(item) - setShowMoreInfo(true) - }} - onMouseOut={() => setShowMoreInfo(false)} - className="info-icon details-svg" - > - more... - -
-
- - {formatTime(item.created)} - - {item.status === "publish_manual" ? - : - item.status === "encoding_failed" ? - - {_t("video-gallery.status-failed")} - : - item.status === "published" ? -
- - {_t("video-gallery.status-published")} - - -
: - - {_t("video-gallery.status-encoding")} - } -
-
- {showMoreInfo && hoveredItem._id === item._id && -
-
- - {_t("video-gallery.info-posted-from")} {item.app} - -
-
- - {_t("video-gallery.info-created")} {formatTime(item.created)} - -
-
- - {_t("video-gallery.info-status")} {item.status} - -
-
- - {_t("video-gallery.info-views")} {item.views} - -
-
- - {_t("video-gallery.info-title")} {item.title.substring(0, 20)}... - + {loading && } + {items?.length > 0 && ( +
+ {items?.map((item: any, i: any) => { + return ( +
+
+ +
+
+
+ {item.title.substring(0, 15)}... + { + getHoveredItem(item); + setShowMoreInfo(true); + }} + onMouseOut={() => setShowMoreInfo(false)} + className="info-icon details-svg" + > + more... + +
+
+ {formatTime(item.created)} + {item.status === "publish_manual" ? ( + + ) : item.status === "encoding_failed" ? ( + {_t("video-gallery.status-failed")} + ) : item.status === "published" ? ( +
+ {_t("video-gallery.status-published")} + +
+ ) : ( + {_t("video-gallery.status-encoding")} + )} +
+
+ {showMoreInfo && hoveredItem._id === item._id && ( +
+
+ + {_t("video-gallery.info-posted-from")} {item.app} + +
+
+ + {_t("video-gallery.info-created")} {formatTime(item.created)} + +
+
+ + {_t("video-gallery.info-status")} {item.status} + +
+
+ + {_t("video-gallery.info-views")} {item.views} + +
+
+ + {_t("video-gallery.info-title")} {item.title.substring(0, 20)}... + +
+
+ + {_t("video-gallery.info-description")} {item.description.substring(0, 20)} + ... + +
+
+ + {_t("video-gallery.info-duration")} {item.duration} + +
+
+ + {_t("video-gallery.info-rewards")} {`${item.declineRewards ? "Yes" : "No"}`} + +
+
+ + {_t("video-gallery.info-size")}{" "} + {`${(item.size / (1024 * 1024)).toFixed(2)}MB`} + +
+
+ )}
-
- - {_t("video-gallery.info-description")} {item.description.substring(0, 20)}... - -
-
- - {_t("video-gallery.info-duration")} {item.duration} - -
-
- - {_t("video-gallery.info-rewards")} {`${item.declineRewards ? "Yes" : "No"}`} - -
-
- - {_t("video-gallery.info-size")} {`${(item.size / (1024 * 1024)).toFixed(2)}MB`} - -
-
} -
- ) - })} -
- )} - {!loading && items?.length === 0 &&
{_t("g.empty-list")}
} + ); + })} +
+ )} + {!loading && items?.length === 0 &&
{_t("g.empty-list")}
}
); - + return (
- setShowGallery(false)} - size="lg" className="gallery-modal"> + setShowGallery(false)} + size="lg" + className="gallery-modal" + > Video {_t("gallery.title")} @@ -240,7 +262,7 @@ const VideoGallery = (props: any) => {
- ) -} + ); +}; -export default VideoGallery; \ No newline at end of file +export default VideoGallery; diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index c632fe97e23..03dd4d17c50 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1321,24 +1321,24 @@ "empty-body-alert": "Enter post body", "description": "Short description" }, - "video-upload":{ - "choose-video": "Choose video", - "choose-thumbnail": "Choose video", + "video-upload": { + "choose-video": "Video", + "choose-thumbnail": "Thumbnail", "continue": "Continue", - "encode": "Enconde video", - "success":"Video has been uploaded successfully", + "encode": "Send for encoding", + "success": "Video has been uploaded and queued for encoding", "finished": "Finished", "upload-video": "Upload video", "video-gallery": "Video gallery", "preview": "Preview", "congrats": "Congratulations" }, - "video-gallery":{ - "all":"All", - "published":"Published", - "encoding":"Encoding", - "encoded":"Encoded", - "failed":"Failed", + "video-gallery": { + "all": "All", + "published": "Published", + "encoding": "Encoding", + "encoded": "Encoded", + "failed": "Failed", "status-encoded": "Publish", "status-encoding": "Encoding🟡", "status-published": "Published✅", @@ -1349,9 +1349,9 @@ "info-views": "Views:", "info-title": "Title:", "info-description": "Description:", - "info-duration":"Duration:", - "info-rewards":"Decline rewards:", - "info-size":"File size:" + "info-duration": "Duration:", + "info-rewards": "Decline rewards:", + "info-size": "File size:" }, "tag-selector": { "placeholder-empty": "Tags. First tag is main category. Sortable.", diff --git a/src/common/img/svg.tsx b/src/common/img/svg.tsx index 680f0f27043..128b4d0bc96 100644 --- a/src/common/img/svg.tsx +++ b/src/common/img/svg.tsx @@ -1985,20 +1985,34 @@ export const dragSvg = ( ); export const videoSvg = ( - - - -) + + + +); export const uploadSvgV = ( - - - - -) \ No newline at end of file + + + + +); From 16f83b46cd892d3bacef86be20c71b06caecc291 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 19 Jun 2023 15:41:26 +0100 Subject: [PATCH 20/49] fix preview and gallery memo --- .../components/editor-toolbar/index.tsx | 1 + .../components/video-gallery/index.scss | 35 +++-- src/common/components/video-gallery/index.tsx | 139 +++++++++++------- .../video-upload-threespeak/index.tsx | 47 +++--- src/common/i18n/locales/en-US.json | 9 +- 5 files changed, 131 insertions(+), 100 deletions(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 782d85c0e3c..0182c09df5e 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -571,6 +571,7 @@ export class EditorToolbar extends Component { activeUser={activeUser} tags={this.props.tags} global={global} + insertText={this.insertText} />
diff --git a/src/common/components/video-gallery/index.scss b/src/common/components/video-gallery/index.scss index 311087d5e46..4e1e7dab628 100644 --- a/src/common/components/video-gallery/index.scss +++ b/src/common/components/video-gallery/index.scss @@ -5,8 +5,9 @@ .video-list{ display: flex; - flex-wrap: wrap; - gap: 10px; + flex-direction: column; + // flex-wrap: wrap; + gap: 15px; justify-content: center; font-size: 12px; @@ -15,17 +16,18 @@ flex: 1; display: flex; flex-direction: column; - width: 220px; - .list-image{ - width: 100%; - + align-items: center; + width: 100%; + // + // .list-image{ + // width: 100%; img{ - width: 230px; - height: 150px; + width: 80%; + height: 300px; object-fit: cover; border-radius: 10px; } - } + // } .list-details-wrapper{ @@ -33,13 +35,13 @@ flex-direction: column; gap: 5px; margin-top: 5px; - width: 100%; + width: 80%; .list-title{ display: flex; align-items: center; justify-content: space-between; - width:230px; + width:100%; .details-title{ font-size: 16px; @@ -51,17 +53,17 @@ } } - .list-date{ + .list-bottom-wrapper{ display: flex; align-items: center; - width: 230px; + width: 100%; justify-content: space-between; - span{ + .video-date{ font-size: 12px; } - button{ + .post-video-btn{ background-color: $dark-sky-blue; width: 30%; padding: 5px; @@ -97,7 +99,8 @@ flex-direction: column; position: absolute; padding: 10px; - right: 30px; + right: 70px; + top: 100px; justify-content: space-around; width: 200px; height: 200px; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index f6de251132b..25837e92d7b 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import LinearProgress from "../linear-progress"; import { deleteForeverSvg, informationVariantSvg } from "../../img/svg"; import { Button, Modal, ModalBody, Tooltip } from "react-bootstrap"; @@ -6,10 +6,11 @@ import { _t } from "../../i18n"; import "./index.scss"; const VideoGallery = (props: any) => { - const { showGaller, setShowGallery, checkStat } = props; + const { showGaller, setShowGallery, checkStat, insertText } = props; const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); + const [filterType, setFilterType] = useState('') const [showMoreInfo, setShowMoreInfo] = useState(false); const [hoveredItem, setHoveredItem] = useState(null); @@ -20,7 +21,7 @@ const VideoGallery = (props: any) => { const getAllStatus = async () => { setLoading(true); const data = await checkStat(); - console.log(data); + console.log(JSON.parse(data[0].beneficiaries)); if (data) { setItems(data); setLoading(false); @@ -74,32 +75,25 @@ const VideoGallery = (props: any) => { } }; - const filterListByStatus = async (action?: string) => { - setLoading(true); - const data = await checkStat(); - let filtered; - - if (action) { - filtered = data.filter((video: any) => video.status === action); - setLoading(false); - return filtered; - } - - if (!action) return data; - - setLoading(false); - }; + const videosDrafts = useMemo(() => { + if (!filterType) return items + return items.filter((video: any) => video.status === filterType) + }, [filterType]); const getHoveredItem = (item: any) => { setHoveredItem(item); }; + const embeddVideo = (videoUrl: string) => { + insertText(`") + } + const modalBodyTop = (
+ ) : item.status === "encoding_failed" ? ( {_t("video-gallery.status-failed")} ) : item.status === "published" ? ( @@ -186,11 +181,6 @@ const VideoGallery = (props: any) => {
{showMoreInfo && hoveredItem._id === item._id && (
-
- - {_t("video-gallery.info-posted-from")} {item.app} - -
{_t("video-gallery.info-created")} {formatTime(item.created)} @@ -198,33 +188,80 @@ const VideoGallery = (props: any) => {
- {_t("video-gallery.info-status")} {item.status} + {_t("video-gallery.info-views")} {item.views}
- {_t("video-gallery.info-views")} {item.views} + {_t("video-gallery.info-duration")} {item.duration}
- {_t("video-gallery.info-title")} {item.title.substring(0, 20)}... + {_t("video-gallery.info-size")}{" "} + {`${(item.size / (1024 * 1024)).toFixed(2)}MB`}
+
+ )} +
+ ); + })} +
+ ) : ( +
+ {items?.map((item: any, i: any) => { + return ( +
+ +
+
+ {item.title} + { + getHoveredItem(item); + setShowMoreInfo(true); + }} + onMouseOut={() => setShowMoreInfo(false)} + className="info-icon details-svg" + > + more... + +
+
+ {formatTime(item.created)} + {item.status === "publish_manual" ? ( + + ) : item.status === "encoding_failed" ? ( + {_t("video-gallery.status-failed")} + ) : item.status === "published" ? ( +
+ {_t("video-gallery.status-published")} + +
+ ) : ( + {_t("video-gallery.status-encoding")} + )} +
+
+ {showMoreInfo && hoveredItem._id === item._id && ( +
- {_t("video-gallery.info-description")} {item.description.substring(0, 20)} - ... + {_t("video-gallery.info-created")} {formatTime(item.created)}
- {_t("video-gallery.info-duration")} {item.duration} + {_t("video-gallery.info-views")} {item.views}
- {_t("video-gallery.info-rewards")} {`${item.declineRewards ? "Yes" : "No"}`} + {_t("video-gallery.info-duration")} {item.duration}
@@ -239,7 +276,7 @@ const VideoGallery = (props: any) => { ); })}
- )} + ) } {!loading && items?.length === 0 &&
{_t("g.empty-list")}
}
); diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 13b558f2f40..0d1e848128c 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -14,7 +14,7 @@ import VideoGallery from "../video-gallery"; import useMount from "react-use/lib/useMount"; export const VideoUpload = (props: any) => { - const { description, title, tags, activeUser, global } = props; + const { description, title, tags, activeUser, global, insertText } = props; const tusEndPoint = "https://uploads.3speak.tv/files/"; const fileInput = useRef(null); @@ -121,7 +121,7 @@ export const VideoUpload = (props: any) => { const allStatus = await getAllVideoStatuses(token); return allStatus; }; - + // Should be called when we are finally submitting post const updateSpeakVideo = async () => { const token = await threespeakAuth(activeUser!.username); updateInfo(token, description, videoId, title, tags, isNsfwC); @@ -173,9 +173,8 @@ export const VideoUpload = (props: any) => {
); - const updateVideoModal = ( + const previewVideo = (
); - const videoSuccessModal = ( -
-

{_t("video-upload.success")}

- -
- ); - return (
@@ -243,12 +235,15 @@ export const VideoUpload = (props: any) => {
)}
- +
+ +
{ {step === "upload" &&

{_t("video-upload.upload-video")}

} - {step === "update" &&

{_t("video-upload.preview")}

} - {step === "success" &&

{_t("video-upload.congrats")}

} + {step === "to-gallery" &&

{_t("video-upload.preview")}

}
{step === "upload" && uploadVideoModal} - {step === "update" && updateVideoModal} - {step === "success" && videoSuccessModal} + {step === "to-gallery" && previewVideo}
diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 03dd4d17c50..75def0eb4d1 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1331,6 +1331,7 @@ "upload-video": "Upload video", "video-gallery": "Video gallery", "preview": "Preview", + "to-gallery": "Go to gallery:", "congrats": "Congratulations" }, "video-gallery": { @@ -1339,18 +1340,14 @@ "encoding": "Encoding", "encoded": "Encoded", "failed": "Failed", - "status-encoded": "Publish", + "status-encoded": "Post", "status-encoding": "Encoding🟡", "status-published": "Published✅", "status-failed": "Encoding failed❌", - "info-posted-from": "Posted from:", "info-created": "Created:", - "info-status": "Status:", + "view-more": "More...:", "info-views": "Views:", - "info-title": "Title:", - "info-description": "Description:", "info-duration": "Duration:", - "info-rewards": "Decline rewards:", "info-size": "File size:" }, "tag-selector": { From def23571aeb30667fdf35b8e3030819bd18aa9ae Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Tue, 20 Jun 2023 17:07:18 +0100 Subject: [PATCH 21/49] fix encoder beneficiary --- .../components/editor-toolbar/index.tsx | 5 ++- src/common/components/video-gallery/index.tsx | 42 ++++++++++++------- .../video-upload-threespeak/index.tsx | 3 +- src/common/i18n/locales/en-US.json | 2 +- src/common/pages/submit.tsx | 18 ++++++-- 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 0182c09df5e..9623387ea26 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -50,6 +50,7 @@ interface Props { body: string; title: string; tags: string[]; + setVideoEncoderBeneficiary: any; } interface State { @@ -572,6 +573,7 @@ export class EditorToolbar extends Component { tags={this.props.tags} global={global} insertText={this.insertText} + setVideoEncoderBeneficiary={this.props.setVideoEncoderBeneficiary} />
@@ -658,7 +660,8 @@ export default (props: Props) => { showGif: props.showGif, body: props.body, title: props.title, - tags: props.tags + tags: props.tags, + setVideoEncoderBeneficiary: props.setVideoEncoderBeneficiary }; return ; }; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 25837e92d7b..82707c30755 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -1,12 +1,12 @@ import React, { useEffect, useMemo, useState } from "react"; import LinearProgress from "../linear-progress"; import { deleteForeverSvg, informationVariantSvg } from "../../img/svg"; -import { Button, Modal, ModalBody, Tooltip } from "react-bootstrap"; +import { Button, Modal, Tooltip } from "react-bootstrap"; import { _t } from "../../i18n"; import "./index.scss"; const VideoGallery = (props: any) => { - const { showGaller, setShowGallery, checkStat, insertText } = props; + const { showGaller, setShowGallery, checkStat, insertText, setVideoEncoderBeneficiary} = props; const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); @@ -21,12 +21,16 @@ const VideoGallery = (props: any) => { const getAllStatus = async () => { setLoading(true); const data = await checkStat(); - console.log(JSON.parse(data[0].beneficiaries)); if (data) { setItems(data); setLoading(false); } }; + + const setBeneficiary = (video: any) => { + const videoObj = JSON.parse(video.beneficiaries) + setVideoEncoderBeneficiary(videoObj) + } const formatTime = (dateStr: string | number | Date) => { const date: any = new Date(dateStr); @@ -85,7 +89,7 @@ const VideoGallery = (props: any) => { }; const embeddVideo = (videoUrl: string) => { - insertText(`") + insertText(`") } const modalBodyTop = ( @@ -142,7 +146,7 @@ const VideoGallery = (props: any) => { {loading && } {videosDrafts?.length > 0 && filterType !== '' ? (
- {(videosDrafts || items)?.map((item: any, i: any) => { + {(videosDrafts || items)?.map((item: any, i: number) => { return (
{/*
*/} @@ -159,12 +163,16 @@ const VideoGallery = (props: any) => { onMouseOut={() => setShowMoreInfo(false)} className="info-icon details-svg" > - {_t("video-gallery.more-info")} + {_t("video-gallery.view-more")} +
{formatTime(item.created)} {item.status === "publish_manual" ? ( - ) : item.status === "encoding_failed" ? ( @@ -172,7 +180,7 @@ const VideoGallery = (props: any) => { ) : item.status === "published" ? (
{_t("video-gallery.status-published")} - +
) : ( {_t("video-gallery.status-encoding")} @@ -210,7 +218,7 @@ const VideoGallery = (props: any) => {
) : (
- {items?.map((item: any, i: any) => { + {items?.map((item: any, i: number) => { return (
@@ -225,22 +233,24 @@ const VideoGallery = (props: any) => { onMouseOut={() => setShowMoreInfo(false)} className="info-icon details-svg" > - more... + {_t("video-gallery.view-more")}
-
- {formatTime(item.created)} +
+ {formatTime(item.created)} {item.status === "publish_manual" ? ( - ) : item.status === "encoding_failed" ? ( {_t("video-gallery.status-failed")} ) : item.status === "published" ? (
{_t("video-gallery.status-published")} - +
) : ( {_t("video-gallery.status-encoding")} diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 0d1e848128c..06518c41abe 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -14,7 +14,7 @@ import VideoGallery from "../video-gallery"; import useMount from "react-use/lib/useMount"; export const VideoUpload = (props: any) => { - const { description, title, tags, activeUser, global, insertText } = props; + const { description, title, tags, activeUser, global, insertText, setVideoEncoderBeneficiary } = props; const tusEndPoint = "https://uploads.3speak.tv/files/"; const fileInput = useRef(null); @@ -242,6 +242,7 @@ export const VideoUpload = (props: any) => { checkStat={checkStat} selectedFile={selectedFile} insertText={insertText} + setVideoEncoderBeneficiary={setVideoEncoderBeneficiary} />
diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 75def0eb4d1..670d955b6d2 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1345,7 +1345,7 @@ "status-published": "Published✅", "status-failed": "Encoding failed❌", "info-created": "Created:", - "view-more": "More...:", + "view-more": "More...", "info-views": "Views:", "info-duration": "Duration:", "info-size": "File size:" diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index f2ee092e130..abfd072a1a7 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -246,8 +246,8 @@ class SubmitPage extends BaseComponent { // delete active user from beneficiaries list if (activeUser) { const { beneficiaries } = this.state; - if (beneficiaries.find((x) => x.account === activeUser.username)) { - const b = [...beneficiaries.filter((x) => x.account !== activeUser.username)]; + if (beneficiaries.find((x: { account: string; }) => x.account === activeUser.username)) { + const b = [...beneficiaries.filter((x: { account: string; }) => x.account !== activeUser.username)]; this.stateSet({ beneficiaries: b }); } } @@ -541,7 +541,7 @@ class SubmitPage extends BaseComponent { beneficiaryDeleted = (username: string) => { const { beneficiaries } = this.state; - const b = [...beneficiaries.filter((x) => x.account !== username)]; + const b = [...beneficiaries.filter((x: { account: string; }) => x.account !== username)]; this.stateSet({ beneficiaries: b }, this.saveAdvanced); }; @@ -992,6 +992,10 @@ class SubmitPage extends BaseComponent { ); }; + setVideoEncoderBeneficiary = (beneficiary: BeneficiaryRoute[]) => { + this.stateSet({ beneficiaries: beneficiary }) + } + render() { const { title, @@ -1075,7 +1079,13 @@ class SubmitPage extends BaseComponent { })}
)} - {EditorToolbar({ ...this.props, body: body, tags: tags, title: title })} + {EditorToolbar({ + ...this.props, + body: body, + tags: tags, + title: title, + setVideoEncoderBeneficiary: this.setVideoEncoderBeneficiary + })}
Date: Wed, 21 Jun 2023 16:58:17 +0100 Subject: [PATCH 22/49] embed video fixes --- src/common/components/video-gallery/index.tsx | 38 +++++++++++++++---- src/common/i18n/locales/en-US.json | 1 + 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 82707c30755..cd71c27ce07 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -13,6 +13,7 @@ const VideoGallery = (props: any) => { const [filterType, setFilterType] = useState('') const [showMoreInfo, setShowMoreInfo] = useState(false); const [hoveredItem, setHoveredItem] = useState(null); + const [isEmbedded, setIsembedded] = useState(false); useEffect(() => { getAllStatus(); @@ -88,8 +89,25 @@ const VideoGallery = (props: any) => { setHoveredItem(item); }; - const embeddVideo = (videoUrl: string) => { - insertText(`") + const embeddVideo = (video: any) => { + const speakUrl = "https://3speak.tv/watch?v=" + const speakFile = `[![](${video.thumbUrl})](${speakUrl}${video.owner}/${video.permlink}) + + ▶️ [Watch on 3Speak](${speakUrl}${video.owner}/${video.permlink})` + + const element = ( + `
${speakFile}
+ --- + +
this is the body
+ + --- + +
▶️ [3Speak](${speakUrl}${video.owner}/${video.permlink})
+ ` + ) + insertText(element) + setIsembedded(true) } const modalBodyTop = ( @@ -169,9 +187,12 @@ const VideoGallery = (props: any) => {
{formatTime(item.created)} {item.status === "publish_manual" ? ( - @@ -239,9 +260,12 @@ const VideoGallery = (props: any) => {
{formatTime(item.created)} {item.status === "publish_manual" ? ( - @@ -301,7 +325,7 @@ const VideoGallery = (props: any) => { className="gallery-modal" > - Video {_t("gallery.title")} + {_t("video-gallery.title")} {modalBodyTop} diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 670d955b6d2..85942718cf1 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1336,6 +1336,7 @@ }, "video-gallery": { "all": "All", + "title":"Video gallery", "published": "Published", "encoding": "Encoding", "encoded": "Encoded", From 7048499ccd5f4242deae35b0432f94638921f967 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Fri, 23 Jun 2023 11:50:16 +0100 Subject: [PATCH 23/49] fix post publishing --- src/common/api/threespeak.ts | 15 ++++++--- .../components/editor-toolbar/index.tsx | 9 ------ src/common/components/video-gallery/index.tsx | 19 +++-------- .../video-upload-threespeak/index.tsx | 29 +++++++++-------- src/common/pages/submit.tsx | 32 ++++++++++++++----- 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 1ab848e948b..bdc52b0b36b 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -50,6 +50,7 @@ export const getTokenValidated = async (jwt: string, username: string) => { } }; +// THIS SHOULD BE REMOVED updateVideoInfo CAN BE USED DIRECTLY export const uploadVideoInfo = async ( username: string, videoUrl: string, @@ -97,13 +98,14 @@ export const updateVideoInfo = async ( } }; -export const getAllVideoStatuses = async (accessToken: string) => { +export const getAllVideoStatuses = async (username: string) => { + const token = await threespeakAuth(username); try { let response = await client.get(`${studioEndPoint}/mobile/api/my-videos`, { withCredentials: false, headers: { "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}` + Authorization: `Bearer ${token}` } }); return response.data; @@ -113,14 +115,17 @@ export const getAllVideoStatuses = async (accessToken: string) => { } }; -export const updateInfo = async ( - accessToken: string, +export const updateSpeakVideoInfo = async ( + username: string, postBody: string, videoId: string, title: string, tags: string[], isNsfwC: boolean ) => { + + const token = await threespeakAuth(username); + const data = { videoId: videoId, title: title, @@ -131,7 +136,7 @@ export const updateInfo = async ( const headers = { "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}` + Authorization: `Bearer ${token}` }; axios diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index 9623387ea26..fac153dc23a 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -47,9 +47,6 @@ interface Props { sm?: boolean; showEmoji?: boolean; showGif?: boolean; - body: string; - title: string; - tags: string[]; setVideoEncoderBeneficiary: any; } @@ -567,10 +564,7 @@ export class EditorToolbar extends Component {
{ sm: props.sm, showEmoji: props.showEmoji, showGif: props.showGif, - body: props.body, - title: props.title, - tags: props.tags, setVideoEncoderBeneficiary: props.setVideoEncoderBeneficiary }; return ; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index cd71c27ce07..f0bfc12d074 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -29,8 +29,7 @@ const VideoGallery = (props: any) => { }; const setBeneficiary = (video: any) => { - const videoObj = JSON.parse(video.beneficiaries) - setVideoEncoderBeneficiary(videoObj) + setVideoEncoderBeneficiary(video) } const formatTime = (dateStr: string | number | Date) => { @@ -91,20 +90,10 @@ const VideoGallery = (props: any) => { const embeddVideo = (video: any) => { const speakUrl = "https://3speak.tv/watch?v=" - const speakFile = `[![](${video.thumbUrl})](${speakUrl}${video.owner}/${video.permlink}) - - ▶️ [Watch on 3Speak](${speakUrl}${video.owner}/${video.permlink})` + const speakFile = `[![](${video.thumbUrl})](${speakUrl}${video.owner}/${video.permlink})` const element = ( - `
${speakFile}
- --- - -
this is the body
- - --- - -
▶️ [3Speak](${speakUrl}${video.owner}/${video.permlink})
- ` + `
${speakFile}
` ) insertText(element) setIsembedded(true) @@ -188,7 +177,7 @@ const VideoGallery = (props: any) => { {formatTime(item.created)} {item.status === "publish_manual" ? ( + +
); @@ -192,9 +207,17 @@ const VideoGallery = (props: any) => { {_t("video-gallery.status-published")}
+ ) : item.status === "deleted" ? ( +
+ {_t("video-gallery.status-deleted")} + {/* {deleteForeverSvg} */} +
) : ( {_t("video-gallery.status-encoding")} )} + {item.status === "publish_manual" && + + }
{showMoreInfo && hoveredItem._id === item._id && ( @@ -251,7 +274,8 @@ const VideoGallery = (props: any) => { {item.status === "publish_manual" ? ( - - - - - - - - - - +
+ {(() => { + let dropDownConfig: any; + dropDownConfig = { + history: "", + label: label, + items: [ + { + label: {_t("video-gallery.all")}, + onClick: () => { + setLabel(_t("video-gallery.all")); + setFiltered(items) + } + }, + { + label: {_t("video-gallery.published")}, + onClick: () => { + setLabel(_t("video-gallery.published")); + filterList("published") + } + }, + { + label: {_t("video-gallery.encoding")}, + onClick: () => { + const encoding = "encoding_ipfs" || "encoding_preparing" + setLabel(_t("video-gallery.encoding")); + filterList(encoding) + } + }, + { + label: {_t("video-gallery.encoded")}, + onClick: () => { + setLabel(_t("video-gallery.encoded")); + filterList("publish_manual") + } + }, + { + label: {_t("video-gallery.failed")}, + onClick: () => { + setLabel(_t("video-gallery.failed")); + filterList("encoding_failed") + } + }, + { + label: ( + {_t("video-gallery.status-deleted")} + ), + onClick: () => { + setLabel(_t("video-gallery.status-deleted")); + filterList("deleted") + } + }, + ] + }; + return ( +
+ +
+ ); + })()} +
- ); + ) const modalBody = (
{loading && } - {videosDrafts?.length > 0 && filterType !== '' ? ( -
- {(videosDrafts || items)?.map((item: any, i: number) => { + {filtered &&
+ {(filtered)?.map((item: any, i: number) => { return (
- {/*
*/} - - {/*
*/} + {/* Somehow video delays and make some unnecessary request, will test out later, could be due to network when i tested */} + {/* {item.status === "published" ? + : */} + + {/* // } */}
{item.title} @@ -248,9 +263,9 @@ const VideoGallery = (props: any) => {
); })} -
- ) : ( -
+
} + + {items && label === "All" &&
{items?.map((item: any, i: number) => { return (
@@ -322,9 +337,9 @@ const VideoGallery = (props: any) => {
); })} -
- ) } - {!loading && items?.length === 0 &&
{_t("g.empty-list")}
} +
} + + {!loading && items?.length === 0 || filtered?.length === 0 &&
{_t("g.empty-list")}
}
); @@ -341,7 +356,7 @@ const VideoGallery = (props: any) => { {_t("video-gallery.title")} - {modalBodyTop} + {dropDown} {modalBody} diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index 5ae489b8fbb..473eb9a2541 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -1008,8 +1008,23 @@ class SubmitPage extends BaseComponent { }; setVideoEncoderBeneficiary = async (video: any) => { + const videoBeneficiary = JSON.parse(video.beneficiaries) + const videoEncoders = [ + { + account: "spk.beneficiary", + src: "ECONDER_PAY", + weight: 900 + }, + { + account: "spk.beneficiary", + src: "ECONDER_PAY", + weight: 100 + } + ] + const joinedBeneficiary = [...videoBeneficiary, ...videoEncoders] + console.log([...videoBeneficiary, ...videoEncoders]) this.stateSet({ - beneficiaries: JSON.parse(video.beneficiaries), + beneficiaries: joinedBeneficiary, videoId: await video._id, isThreespeak: true, speakPermlink: video.permlink From fd27a86964f85ab2a9c16919e2b88ec57a2dd3ff Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Sat, 1 Jul 2023 23:03:27 +0100 Subject: [PATCH 26/49] persiting beneficiary and iPublished endpoint --- src/common/api/threespeak.ts | 2 - src/common/components/video-gallery/index.tsx | 16 ++--- .../video-upload-threespeak/index.tsx | 8 ++- src/common/pages/submit.tsx | 61 +++++++++++++------ 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index 1fbff6adc52..fc17dea1754 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -152,8 +152,6 @@ export const updateSpeakVideoInfo = async ( export const markAsPublished = async (username: string, videoId: string) => { const token = await threespeakAuth(username); - console.log(token) - const data = { videoId }; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 4bca7f53e9b..a02aa43fe41 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -4,7 +4,6 @@ import { deleteForeverSvg, informationVariantSvg } from "../../img/svg"; import { Button, Modal, Tooltip } from "react-bootstrap"; import { _t } from "../../i18n"; import "./index.scss"; -import { markAsPublished } from "../../api/threespeak"; import DropDown, { MenuItem } from "../dropdown"; const VideoGallery = (props: any) => { @@ -20,7 +19,7 @@ const VideoGallery = (props: any) => { useEffect(() => { getAllStatus(); - }, []); + }, [showGaller]); const getAllStatus = async () => { setLoading(true); @@ -91,10 +90,6 @@ const VideoGallery = (props: any) => { setHoveredItem(item); }; - const markVideo = async (item: any) => { - await markAsPublished(activeUser!.username, item._id) - }; - const embeddVideo = (video: any) => { const speakUrl = "https://3speak.tv/watch?v=" const speakFile = `[![](${video.thumbUrl})](${speakUrl}${video.owner}/${video.permlink})` @@ -180,15 +175,15 @@ const VideoGallery = (props: any) => { return (
{/* Somehow video delays and make some unnecessary request, will test out later, could be due to network when i tested */} - {/* {item.status === "published" ? + {item.status === "published" ? : */} + > : - {/* // } */} + }
{item.title} @@ -230,9 +225,6 @@ const VideoGallery = (props: any) => { ) : ( {_t("video-gallery.status-encoding")} )} - {item.status === "publish_manual" && - - }
{showMoreInfo && hoveredItem._id === item._id && ( diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 2401c0d3546..1ca2e0a6236 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -10,6 +10,7 @@ import { import * as tus from "tus-js-client"; import VideoGallery from "../video-gallery"; import useMount from "react-use/lib/useMount"; +import { success } from "../feedback"; export const VideoUpload = (props: any) => { const { activeUser, global, insertText, setVideoEncoderBeneficiary } = props; @@ -109,8 +110,11 @@ export const VideoUpload = (props: any) => { fileName, fileSize ); - setVideoId(data._id); - setIsNsfwC(data.isNsfwContent); + if (data) { + setVideoId(data._id); + setIsNsfwC(data.isNsfwContent); + success("Video succesfully uploaded"); + } }; const checkStat = async () => { diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index 473eb9a2541..268ab5d2763 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -87,7 +87,7 @@ import TextareaAutocomplete from "../components/textarea-autocomplete"; import Drafts from "../components/drafts"; import { AvailableCredits } from "../components/available-credits"; import { handleFloatingContainer } from "../components/floating-faq"; -import { updateSpeakVideoInfo } from "../api/threespeak"; +import { updateSpeakVideoInfo, markAsPublished } from "../api/threespeak"; setProxyBase(defaults.imageServer); @@ -104,6 +104,10 @@ interface Advanced { schedule: string | null; reblogSwitch: boolean; description: string | null; + isThreespeak: boolean; + videoId: string; + speakPermlink: string; + speakAuthor: string; } interface PreviewProps extends PostBase { @@ -177,10 +181,6 @@ interface State extends PostBase, Advanced { isDraftEmpty: boolean; drafts: boolean; showHelp: boolean; - // Speak states - isThreespeak: boolean; - videoId: string; - speakPermlink: ""; } class SubmitPage extends BaseComponent { @@ -217,9 +217,11 @@ class SubmitPage extends BaseComponent { isDraftEmpty: true, drafts: false, showHelp: false, + // Speakstates isThreespeak: false, videoId: "", - speakPermlink: "" + speakPermlink: "", + speakAuthor: "" }; _updateTimer: any = null; @@ -469,14 +471,19 @@ class SubmitPage extends BaseComponent { }; saveAdvanced = (): void => { - const { reward, beneficiaries, schedule, reblogSwitch, description } = this.state; + const { reward, beneficiaries, schedule, reblogSwitch, description, isThreespeak, videoId, speakPermlink, speakAuthor } = this.state; const advanced: Advanced = { reward, beneficiaries, schedule, reblogSwitch, - description + description, + // Speak Advanced + isThreespeak, + videoId, + speakPermlink, + speakAuthor }; ls.set("local_advanced", advanced); @@ -597,7 +604,12 @@ class SubmitPage extends BaseComponent { beneficiaries: [], schedule: null, reblogSwitch: false, - description: "" + description: "", + // Speak Advenaced + isThreespeak: false, + videoId: "", + speakPermlink: "", + speakAuthor: "" }, () => { this.saveAdvanced(); @@ -663,13 +675,18 @@ class SubmitPage extends BaseComponent { return true; }; + markVideo = async (videoId: string) => { + const { activeUser } = this.props; + await markAsPublished(activeUser!.username, videoId) + } + publish = async (): Promise => { if (!this.validate()) { return; } const { activeUser, history, addEntry } = this.props; - const { title, tags, body, description, reward, reblogSwitch, beneficiaries, videoId, isThreespeak, speakPermlink } = this.state; + const { title, tags, body, description, reward, reblogSwitch, beneficiaries, videoId, isThreespeak, speakPermlink, speakAuthor } = this.state; // clean body const cbody = body.replace(/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F-\x9F]/g, ""); @@ -685,6 +702,7 @@ class SubmitPage extends BaseComponent { let authorData = activeUser.data as FullAccount; let permlink = createPermlink(title); + console.log(isThreespeak) // permlink duplication check let c; @@ -722,7 +740,7 @@ class SubmitPage extends BaseComponent { comment(author, "", parentPermlink, permlink, title, cbody, jsonMeta, options, true) .then(() => { this.clearAdvanced(); - + // Create entry object in store const entry = { ...tempEntry({ @@ -739,12 +757,21 @@ class SubmitPage extends BaseComponent { percent_hbd: options.percent_hbd }; addEntry(entry); - + success(_t("submit.published")); this.clear(); const newLoc = makePathEntry(parentPermlink, author, permlink); history.push(newLoc); - }) + + //Mark speak video as published + if (isThreespeak && activeUser.username === speakAuthor ) { + success(`Video is processing, please wait for few seconds`) + setTimeout(() => { + this.markVideo(videoId) + }, 10000) + } + + }) .then(() => { if (isCommunity(tags[0]) && reblogSwitch) { reblog(author, author, permlink); @@ -1016,19 +1043,19 @@ class SubmitPage extends BaseComponent { weight: 900 }, { - account: "spk.beneficiary", + account: "threespeakleader", src: "ECONDER_PAY", weight: 100 } ] const joinedBeneficiary = [...videoBeneficiary, ...videoEncoders] - console.log([...videoBeneficiary, ...videoEncoders]) this.stateSet({ beneficiaries: joinedBeneficiary, videoId: await video._id, isThreespeak: true, - speakPermlink: video.permlink - }) + speakPermlink: video.permlink, + speakAuthor: video.owner + }, this.saveAdvanced) } render() { From 9afc1e42da891ab8c960992d347af695491e1c09 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Sun, 2 Jul 2023 22:19:16 +0100 Subject: [PATCH 27/49] fix video duration --- src/common/api/threespeak.ts | 18 +++---------- .../video-upload-threespeak/index.tsx | 26 ++++++++++++++----- src/common/pages/submit.tsx | 5 ++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/common/api/threespeak.ts b/src/common/api/threespeak.ts index fc17dea1754..dc92d018658 100644 --- a/src/common/api/threespeak.ts +++ b/src/common/api/threespeak.ts @@ -50,35 +50,23 @@ export const getTokenValidated = async (jwt: string, username: string) => { } }; -// THIS SHOULD BE REMOVED updateVideoInfo CAN BE USED DIRECTLY export const uploadVideoInfo = async ( - username: string, - videoUrl: string, - thumbUrl: string, - oFileName: string, - fileSize: number -) => { - const data = await updateVideoInfo(oFileName, fileSize, videoUrl, thumbUrl, username); - return data; -}; - -export const updateVideoInfo = async ( oFilename: string, fileSize: number, videoUrl: string, thumbnailUrl: string, - username: string + username: string, + duration: string ) => { const token = await threespeakAuth(username); try { - // const { activeUser } = this.props; const { data } = await axios.post( `${studioEndPoint}/mobile/api/upload_info?app=ecency`, { filename: videoUrl, oFilename: oFilename, size: fileSize, - duration: 40, + duration, thumbnail: thumbnailUrl, isReel: false, owner: username diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 1ca2e0a6236..4e96dfca593 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -33,6 +33,7 @@ export const VideoUpload = (props: any) => { const [isNsfwC, setIsNsfwC] = useState(false); const [showGaller, setShowGallery] = useState(false); const [isMounted, setIsMounted] = useState(false); + const [duration, setDuration] = useState(""); const canUpload = thumbUrl && videoUrl; @@ -44,6 +45,16 @@ export const VideoUpload = (props: any) => { // } }, []); + const getVideoDuration = () => { + if (videoRef.current) { + const { duration } = videoRef.current; + const minutes = Math.floor(duration / 60); + const seconds = Math.floor(duration % 60); + const videoDuration = `${minutes}:${seconds}` + setDuration(videoDuration); + } + }; + const onChange: any = (event: { target: { files: any[] } }, type: string) => { let file = event.target.files[0]; @@ -104,11 +115,12 @@ export const VideoUpload = (props: any) => { const uploadInfo = async () => { const data = await uploadVideoInfo( - activeUser!.username, + fileName, + fileSize, videoUrl, thumbUrl, - fileName, - fileSize + activeUser!.username, + duration ); if (data) { setVideoId(data._id); @@ -169,7 +181,7 @@ export const VideoUpload = (props: any) => { + {/* */}
) : item.status === "deleted" ? (
@@ -261,7 +262,16 @@ const VideoGallery = (props: any) => { {items?.map((item: any, i: number) => { return (
- + {item.status === "published" ? +
+ +
: + + }
{item.title} @@ -294,7 +304,7 @@ const VideoGallery = (props: any) => { ) : item.status === "published" ? (
{_t("video-gallery.status-published")} - + {/* */}
) : ( {_t("video-gallery.status-encoding")} diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index 423b4e6e432..bff2590d9f8 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -766,7 +766,7 @@ class SubmitPage extends BaseComponent { //Mark speak video as published if (isThreespeak && activeUser.username === speakAuthor ) { - success(`Video is processing, please wait for few seconds`) + success(`Don't refresh this page, wait for few seconds for video to process`) setTimeout(() => { this.markVideo(videoId) }, 10000) From f0679a2b0ce7d71736de8e615eef2726d90f2e66 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 3 Jul 2023 21:37:31 +0100 Subject: [PATCH 29/49] add confirm nsfw content --- .../components/editor-toolbar/index.tsx | 5 ++- src/common/components/video-gallery/index.tsx | 32 ++++++++++--- src/common/components/video-nsfw/index.scss | 16 +++++++ src/common/components/video-nsfw/index.tsx | 39 ++++++++++++++++ .../video-upload-threespeak/index.tsx | 3 +- src/common/i18n/locales/en-US.json | 5 +++ src/common/pages/submit.tsx | 45 +++++++++++++++---- 7 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 src/common/components/video-nsfw/index.scss create mode 100644 src/common/components/video-nsfw/index.tsx diff --git a/src/common/components/editor-toolbar/index.tsx b/src/common/components/editor-toolbar/index.tsx index fac153dc23a..48a2ca46e4d 100644 --- a/src/common/components/editor-toolbar/index.tsx +++ b/src/common/components/editor-toolbar/index.tsx @@ -48,6 +48,7 @@ interface Props { showEmoji?: boolean; showGif?: boolean; setVideoEncoderBeneficiary: any; + showConfirmNsfwModal: () => void; } interface State { @@ -568,6 +569,7 @@ export class EditorToolbar extends Component { global={global} insertText={this.insertText} setVideoEncoderBeneficiary={this.props.setVideoEncoderBeneficiary} + showConfirmNsfwModal={this.props.showConfirmNsfwModal} />
@@ -652,7 +654,8 @@ export default (props: Props) => { sm: props.sm, showEmoji: props.showEmoji, showGif: props.showGif, - setVideoEncoderBeneficiary: props.setVideoEncoderBeneficiary + setVideoEncoderBeneficiary: props.setVideoEncoderBeneficiary, + showConfirmNsfwModal: props.showConfirmNsfwModal }; return ; }; diff --git a/src/common/components/video-gallery/index.tsx b/src/common/components/video-gallery/index.tsx index 280e46a1f03..31bd276d9ce 100644 --- a/src/common/components/video-gallery/index.tsx +++ b/src/common/components/video-gallery/index.tsx @@ -7,7 +7,7 @@ import "./index.scss"; import DropDown, { MenuItem } from "../dropdown"; const VideoGallery = (props: any) => { - const { showGaller, setShowGallery, checkStat, insertText, setVideoEncoderBeneficiary, activeUser} = props; + const { showGaller, setShowGallery, checkStat, insertText, setVideoEncoderBeneficiary, activeUser, showConfirmNsfwModal} = props; const [loading, setLoading] = useState(false); const [items, setItems] = useState([]); @@ -15,7 +15,9 @@ const VideoGallery = (props: any) => { const [hoveredItem, setHoveredItem] = useState(null); const [isEmbedded, setIsembedded] = useState(false); const [label, setLabel] = useState("All"); - const [filtered, setFiltered] = useState([]) + const [filtered, setFiltered] = useState([]); + // const [confirmIsNsfw, setConfirmIsNsfw] = useState(false); + // const [isNsfw, setIsNsfw] = useState(false) useEffect(() => { getAllStatus(); @@ -101,6 +103,15 @@ const VideoGallery = (props: any) => { setIsembedded(true) }; + // const handleChange = () => { + // setIsNsfw(prevIsNsfw => { + // const updatedIsNsfw = !prevIsNsfw; + // console.log("updated isNsfw", updatedIsNsfw); + // console.log("isNsfw", isNsfw); + // return updatedIsNsfw; + // }); + // } + const dropDown = (
@@ -205,9 +216,10 @@ const VideoGallery = (props: any) => { @@ -345,6 +357,16 @@ const VideoGallery = (props: any) => {
); + // const confirmNsfw = ( + //
+ //
+ // + // + //
+ // + //
+ // ) + return (
{ + + const { showConfirmNsfw, hideConfirmNsfwModal, togleNsfwC, isNsfw } = props; + + const confirmNsfw = ( +
+
togleNsfwC() }> + + +
+ +
+ ) + return ( +
+ hideConfirmNsfwModal()} + size="lg" + className="gallery-modal" + > + + {_t("nsfw-content.title")} + + + {confirmNsfw} + + +
+ ) +} diff --git a/src/common/components/video-upload-threespeak/index.tsx b/src/common/components/video-upload-threespeak/index.tsx index 4e96dfca593..83e9bf8e19d 100644 --- a/src/common/components/video-upload-threespeak/index.tsx +++ b/src/common/components/video-upload-threespeak/index.tsx @@ -13,7 +13,7 @@ import useMount from "react-use/lib/useMount"; import { success } from "../feedback"; export const VideoUpload = (props: any) => { - const { activeUser, global, insertText, setVideoEncoderBeneficiary } = props; + const { activeUser, global, insertText, setVideoEncoderBeneficiary, showConfirmNsfwModal } = props; const tusEndPoint = "https://uploads.3speak.tv/files/"; const fileInput = useRef(null); @@ -255,6 +255,7 @@ export const VideoUpload = (props: any) => { insertText={insertText} setVideoEncoderBeneficiary={setVideoEncoderBeneficiary} activeUser={activeUser} + showConfirmNsfwModal={showConfirmNsfwModal} />
diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 016f2818b4a..4e2f2796ebc 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -1386,6 +1386,11 @@ "info-duration": "Duration:", "info-size": "File size:" }, + "nsfw-content": { + "title":"NSFW contents", + "warning": "Please check this if your content is NSFW", + "continue":"Continue" + }, "tag-selector": { "placeholder-empty": "Tags. First tag is main category. Sortable.", "placeholder-focus": "Enter tag", diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index bff2590d9f8..d522541668b 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -88,6 +88,7 @@ import Drafts from "../components/drafts"; import { AvailableCredits } from "../components/available-credits"; import { handleFloatingContainer } from "../components/floating-faq"; import { updateSpeakVideoInfo, markAsPublished } from "../api/threespeak"; +import { ConfirmNsfwContent } from "../components/video-nsfw"; setProxyBase(defaults.imageServer); @@ -109,6 +110,7 @@ interface Advanced { videoId: string; speakPermlink: string; speakAuthor: string; + isNsfw: boolean } interface PreviewProps extends PostBase { @@ -182,6 +184,7 @@ interface State extends PostBase, Advanced { isDraftEmpty: boolean; drafts: boolean; showHelp: boolean; + showConfirmNsfw: boolean; } class SubmitPage extends BaseComponent { @@ -222,7 +225,9 @@ class SubmitPage extends BaseComponent { isThreespeak: false, videoId: "", speakPermlink: "", - speakAuthor: "" + speakAuthor: "", + showConfirmNsfw: false, + isNsfw: false }; _updateTimer: any = null; @@ -472,7 +477,7 @@ class SubmitPage extends BaseComponent { }; saveAdvanced = (): void => { - const { reward, beneficiaries, schedule, reblogSwitch, description, isThreespeak, videoId, speakPermlink, speakAuthor } = this.state; + const { reward, beneficiaries, schedule, reblogSwitch, description, isThreespeak, videoId, speakPermlink, speakAuthor, isNsfw } = this.state; const advanced: Advanced = { reward, @@ -484,7 +489,8 @@ class SubmitPage extends BaseComponent { isThreespeak, videoId, speakPermlink, - speakAuthor + speakAuthor, + isNsfw }; ls.set("local_advanced", advanced); @@ -610,7 +616,8 @@ class SubmitPage extends BaseComponent { isThreespeak: false, videoId: "", speakPermlink: "", - speakAuthor: "" + speakAuthor: "", + isNsfw: false }, () => { this.saveAdvanced(); @@ -687,7 +694,7 @@ class SubmitPage extends BaseComponent { } const { activeUser, history, addEntry } = this.props; - const { title, tags, body, description, reward, reblogSwitch, beneficiaries, videoId, isThreespeak, speakPermlink, speakAuthor } = this.state; + const { title, tags, body, description, reward, reblogSwitch, beneficiaries, videoId, isThreespeak, speakPermlink, speakAuthor, isNsfw } = this.state; // clean body const cbody = body.replace(/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F-\x9F]/g, ""); @@ -723,7 +730,8 @@ class SubmitPage extends BaseComponent { if (isThreespeak && speakPermlink !== "") { permlink = speakPermlink; // update speak video with title, body and tags - updateSpeakVideoInfo(activeUser.username, body, videoId, title, tags, false) + updateSpeakVideoInfo(activeUser.username, body, videoId, title, tags, isNsfw) + console.log(isNsfw) } const [parentPermlink] = tags; @@ -1059,9 +1067,21 @@ class SubmitPage extends BaseComponent { }, this.saveAdvanced) } - checkContentType = () => { + showConfirmNsfwModal = () => { + this.setState({ showConfirmNsfw: true}) + } + hideConfirmNsfwModal = () => { + this.setState({ showConfirmNsfw: false}) + } + togleNsfwC = () => { + this.setState(prevState => ({ isNsfw: !prevState.isNsfw }), () => { + console.log("opposite", !this.state.isNsfw); + console.log("state", this.state.isNsfw); + }); + console.log("state out", this.state.isNsfw); } + render() { const { @@ -1148,7 +1168,8 @@ class SubmitPage extends BaseComponent { )} {EditorToolbar({ ...this.props, - setVideoEncoderBeneficiary: this.setVideoEncoderBeneficiary + setVideoEncoderBeneficiary: this.setVideoEncoderBeneficiary, + showConfirmNsfwModal: this.showConfirmNsfwModal })}
{ activeUser={(activeUser && activeUser.username) || ""} />
+ { this.state.showConfirmNsfw && + + } {activeUser ? ( Date: Mon, 3 Jul 2023 22:11:53 +0100 Subject: [PATCH 30/49] checkbox styles and save nsfw advanced --- src/common/components/video-nsfw/index.scss | 6 ++++++ src/common/components/video-nsfw/index.tsx | 2 +- src/common/pages/submit.tsx | 6 +----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/common/components/video-nsfw/index.scss b/src/common/components/video-nsfw/index.scss index c16be1b43e0..d9b32330f89 100644 --- a/src/common/components/video-nsfw/index.scss +++ b/src/common/components/video-nsfw/index.scss @@ -10,6 +10,12 @@ .nsfw-checkbox{ width: 20px; height: 20px; + + .nsfw-label{ + // font-size: 20px; + font: bold; + font-weight: 300; + } } } diff --git a/src/common/components/video-nsfw/index.tsx b/src/common/components/video-nsfw/index.tsx index d0d41d9b005..fb55e5fd271 100644 --- a/src/common/components/video-nsfw/index.tsx +++ b/src/common/components/video-nsfw/index.tsx @@ -11,7 +11,7 @@ export const ConfirmNsfwContent = (props: any) => {
togleNsfwC() }> - + {_t("nsfw-content.warning")}
*/} +
) : ( {_t("video-gallery.status-encoding")} @@ -357,16 +348,6 @@ const VideoGallery = (props: any) => {
); - // const confirmNsfw = ( - //
- //
- // - // - //
- // - //
- // ) - return (
Date: Wed, 19 Jul 2023 12:53:48 +0100 Subject: [PATCH 32/49] Merge branch 'development' of https://github.com/ecency/ecency-vision into feat/3speak-video-upload --- package.json | 5 +- src/client/index.tsx | 32 +- src/common/api/hive.ts | 17 +- src/common/api/operations.ts | 382 ++++- src/common/api/private-api.ts | 23 + src/common/app.tsx | 175 ++- .../components/community-card/index.tsx | 4 +- .../components/community-role-edit/index.tsx | 10 +- .../components/community-roles/index.tsx | 4 +- .../components/community-settings/index.tsx | 10 +- .../community-subscribers/index.tsx | 4 +- .../columns/add-column/_deck-add-column.scss | 5 +- .../add-column/deck-add-column-search-box.tsx | 2 +- .../deck-thread-item-viewer.tsx | 52 +- .../decks/columns/deck-items/_index.scss | 5 + .../deck-items/deck-search-list-item.tsx | 2 +- .../columns/deck-items/deck-thread-item.tsx | 48 +- .../decks/columns/deck-threads-column.tsx | 20 +- .../helpers/infinite-scroll-loader.tsx | 10 +- .../decks/deck-threads-form/index.tsx | 36 +- src/common/components/decks/index.tsx | 5 +- .../decks/utils/use-entry-checking.tsx | 2 +- .../components/entry-list-item/index.spec.tsx | 51 +- .../components/entry-list-item/index.tsx | 19 +- src/common/components/entry-list/index.tsx | 15 +- .../components/entry-menu/index.spec.tsx | 18 +- src/common/components/entry-menu/index.tsx | 969 ++++-------- .../entry-menu/menu-items-generator.ts | 250 ++++ .../components/entry-read-time/index.tsx | 15 +- .../components/entry-vote-btn/index.spec.tsx | 3 + .../components/entry-vote-btn/index.tsx | 29 +- .../__snapshots__/index.spec.tsx.snap | 2 +- .../__snapshots__/market-info.spec.tsx.snap | 8 +- .../api/currency-rate-query.tsx | 31 + .../components/market-swap-form/index.tsx | 49 +- .../market-swap-form/market-info.spec.tsx | 10 +- .../market-swap-form/market-info.tsx | 15 +- .../generic-order-item.tsx | 6 +- .../market-swap-active-orders/index.scss | 0 .../market-swap-active-orders/index.tsx | 10 +- .../components/market-swap-form/swap-mode.tsx | 4 +- .../__snapshots__/index.spec.tsx.snap | 2 +- .../components/post-body-lazy-renderer.tsx | 55 + .../__snapshots__/index.spec.tsx.snap | 2 +- src/common/components/rc-info/index.tsx | 7 + .../components/similar-entries/index.tsx | 2 +- .../components/static/static-navbar.tsx | 4 +- src/common/constants/contributors.json | 14 +- src/common/core/caches/communities-cache.ts | 23 + src/common/core/caches/entries-cache.tsx | 151 +- src/common/core/caches/index.ts | 2 + src/common/core/caches/pin-tracker-cache.ts | 49 + src/common/core/react-query.ts | 10 +- src/common/helper/onBoard-helper.ts | 29 + src/common/helper/test-helper.ts | 4 +- src/common/i18n/locales/ac-ace.json | 114 +- src/common/i18n/locales/ar-SA.json | 114 +- src/common/i18n/locales/az-AZ.json | 114 +- src/common/i18n/locales/bg-BG.json | 114 +- src/common/i18n/locales/bn-BD.json | 114 +- src/common/i18n/locales/da-DK.json | 114 +- src/common/i18n/locales/de-DE.json | 114 +- src/common/i18n/locales/el-GR.json | 114 +- src/common/i18n/locales/en-US.json | 74 +- src/common/i18n/locales/es-ES.json | 114 +- src/common/i18n/locales/et-EE.json | 114 +- src/common/i18n/locales/fa-IR.json | 114 +- src/common/i18n/locales/fi-FI.json | 116 +- src/common/i18n/locales/fil-PH.json | 114 +- src/common/i18n/locales/fr-FR.json | 114 +- src/common/i18n/locales/he-IL.json | 114 +- src/common/i18n/locales/hi-IN.json | 114 +- src/common/i18n/locales/hr-HR.json | 114 +- src/common/i18n/locales/hu-HU.json | 114 +- src/common/i18n/locales/id-ID.json | 114 +- src/common/i18n/locales/it-IT.json | 114 +- src/common/i18n/locales/ja-JP.json | 114 +- src/common/i18n/locales/ka-GE.json | 114 +- src/common/i18n/locales/kk-KZ.json | 114 +- src/common/i18n/locales/ko-KR.json | 114 +- src/common/i18n/locales/ku-TR.json | 114 +- src/common/i18n/locales/ky-KG.json | 114 +- src/common/i18n/locales/lt-LT.json | 114 +- src/common/i18n/locales/lv-LV.json | 114 +- src/common/i18n/locales/ms-MY.json | 114 +- src/common/i18n/locales/ne-NP.json | 114 +- src/common/i18n/locales/nl-NL.json | 114 +- src/common/i18n/locales/no-NO.json | 114 +- src/common/i18n/locales/pa-IN.json | 114 +- src/common/i18n/locales/pcm-NG.json | 114 +- src/common/i18n/locales/pl-PL.json | 114 +- src/common/i18n/locales/pt-PT.json | 114 +- src/common/i18n/locales/ro-RO.json | 114 +- src/common/i18n/locales/ru-RU.json | 126 +- src/common/i18n/locales/sk-SK.json | 114 +- src/common/i18n/locales/sl-SI.json | 114 +- src/common/i18n/locales/sr-CS.json | 114 +- src/common/i18n/locales/sv-SE.json | 114 +- src/common/i18n/locales/ta-IN.json | 114 +- src/common/i18n/locales/th-TH.json | 114 +- src/common/i18n/locales/tr-TR.json | 114 +- src/common/i18n/locales/uk-UA.json | 144 +- src/common/i18n/locales/ur-IN.json | 114 +- src/common/i18n/locales/ur-PK.json | 114 +- src/common/i18n/locales/uz-UZ.json | 114 +- src/common/i18n/locales/vi-VN.json | 114 +- src/common/i18n/locales/yo-NG.json | 114 +- src/common/i18n/locales/zh-CN.json | 114 +- src/common/i18n/locales/zh-TW.json | 114 +- src/common/img/svg.tsx | 32 +- src/common/pages/amp/amp-container.tsx | 46 - src/common/pages/amp/entry-amp-page.tsx | 1159 -------------- src/common/pages/community-functional.tsx | 66 +- src/common/pages/entry.tsx | 1326 ----------------- .../pages/{entry.scss => entry/_index.scss} | 2 +- .../pages/entry/deleted-post-screen.tsx | 104 ++ src/common/pages/entry/distance-detector.tsx | 44 + .../index-amp.css} | 4 + src/common/pages/entry/index-amp.tsx | 831 +++++++++++ src/common/pages/entry/index.tsx | 1001 +++++++++++++ src/common/pages/entry/loading-screen.tsx | 38 + src/common/pages/entry/props.type.ts | 12 + src/common/pages/onboard.scss | 114 ++ src/common/pages/onboard.tsx | 705 +++++++++ src/common/pages/sign-up.tsx | 83 +- src/common/pages/submit.tsx | 7 +- src/common/routes.ts | 1 + .../accounts/__snapshots__/index.spec.ts.snap | 1 + src/common/store/accounts/types.ts | 1 + src/common/store/actions.ts | 8 +- .../__snapshots__/index.spec.ts.snap | 1 + .../__snapshots__/index.test.ts.snap | 47 - src/common/store/communities/index.test.ts | 14 - src/common/store/communities/index.ts | 32 +- src/common/store/dynamic-props/index.ts | 3 +- src/common/store/dynamic-props/types.ts | 1 + .../__snapshots__/index.test.ts.snap | 30 - .../store/entry-pin-tracker/index.test.ts | 31 - src/common/store/entry-pin-tracker/index.ts | 100 -- src/common/store/entry-pin-tracker/types.ts | 26 - src/common/store/index.ts | 4 - src/common/store/initial-state.ts | 4 - src/common/tests/with-store.tsx | 2 +- src/common/util/b64.ts | 7 +- src/desktop/app/index.tsx | 18 +- src/desktop/app/main.dev.ts | 9 +- src/desktop/app/package.json | 2 +- src/desktop/package.json | 9 +- src/desktop/yarn.lock | 131 +- src/server/amp-template.tsx | 22 +- src/server/handlers/community.tsx | 21 +- src/server/handlers/entry.tsx | 13 + src/server/template.tsx | 41 +- src/server/util.ts | 6 +- tsconfig.json | 3 +- 155 files changed, 10642 insertions(+), 4391 deletions(-) create mode 100644 src/common/components/entry-menu/menu-items-generator.ts create mode 100644 src/common/components/market-swap-form/api/currency-rate-query.tsx rename src/common/components/{ => market-swap-form}/market-swap-active-orders/generic-order-item.tsx (82%) rename src/common/components/{ => market-swap-form}/market-swap-active-orders/index.scss (100%) rename src/common/components/{ => market-swap-form}/market-swap-active-orders/index.tsx (85%) create mode 100644 src/common/components/post-body-lazy-renderer.tsx create mode 100644 src/common/core/caches/communities-cache.ts create mode 100644 src/common/core/caches/pin-tracker-cache.ts create mode 100644 src/common/helper/onBoard-helper.ts delete mode 100644 src/common/pages/amp/amp-container.tsx delete mode 100644 src/common/pages/amp/entry-amp-page.tsx delete mode 100644 src/common/pages/entry.tsx rename src/common/pages/{entry.scss => entry/_index.scss} (99%) create mode 100644 src/common/pages/entry/deleted-post-screen.tsx create mode 100644 src/common/pages/entry/distance-detector.tsx rename src/common/pages/{amp/entry-amp-page.css => entry/index-amp.css} (99%) create mode 100644 src/common/pages/entry/index-amp.tsx create mode 100644 src/common/pages/entry/index.tsx create mode 100644 src/common/pages/entry/loading-screen.tsx create mode 100644 src/common/pages/entry/props.type.ts create mode 100644 src/common/pages/onboard.scss create mode 100644 src/common/pages/onboard.tsx delete mode 100644 src/common/store/communities/__snapshots__/index.test.ts.snap delete mode 100644 src/common/store/communities/index.test.ts delete mode 100644 src/common/store/entry-pin-tracker/__snapshots__/index.test.ts.snap delete mode 100644 src/common/store/entry-pin-tracker/index.test.ts delete mode 100644 src/common/store/entry-pin-tracker/index.ts delete mode 100644 src/common/store/entry-pin-tracker/types.ts diff --git a/package.json b/package.json index c407a24f70b..b45d8a640d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ecency-vision", - "version": "3.0.32", + "version": "3.0.35", "private": true, "license": "MIT", "scripts": { @@ -42,7 +42,9 @@ "i18next": "^19.4.4", "i18next-browser-languagedetector": "^4.2.0", "immutability-helper": "^3.0.2", + "js-base64": "^3.7.5", "js-cookie": "^2.2.1", + "js-md5": "^0.7.3", "lightweight-charts": "^3.8.0", "loadable-ts-transformer": "^1.0.0-alpha.3", "medium-zoom": "^1.0.6", @@ -99,6 +101,7 @@ "@types/express": "^4.17.0", "@types/jest": "^26.0.24", "@types/js-cookie": "^2.2.6", + "@types/js-md5": "^0.7.0", "@types/loadable__component": "^5.13.4", "@types/loadable__server": "^5.12.6", "@types/lodash": "^4.14.191", diff --git a/src/client/index.tsx b/src/client/index.tsx index 9d6a1e938e9..d818976bbbf 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -11,6 +11,8 @@ import { AppWindow } from "./window"; import "../style/style.scss"; import "./base-handlers"; import { loadableReady } from "@loadable/component"; +import { queryClient } from "../common/core"; +import { Hydrate, QueryClientProvider } from "@tanstack/react-query"; declare var window: AppWindow; @@ -37,11 +39,16 @@ if (process.env.NODE_ENV === "production") { loadableReady().then(() => { hydrate( - - - - - , + + {/*@ts-ignore*/} + + + + + + + + , document.getElementById("root") ); @@ -62,11 +69,16 @@ loadableReady().then(() => { if (module.hot) { module.hot.accept("../common/app", () => { hydrate( - - - - - , + + {/*@ts-ignore*/} + + + + + + + + , document.getElementById("root") ); }); diff --git a/src/common/api/hive.ts b/src/common/api/hive.ts index fdb1a66fa97..5da3780c022 100644 --- a/src/common/api/hive.ts +++ b/src/common/api/hive.ts @@ -49,6 +49,14 @@ export interface FeedHistory { }; } +export interface ChainProps { + account_creation_fee: string; + maximum_block_size: number; + hbd_interest_rate: number; + account_subsidy_budget: number; + account_subsidy_decay: number; +} + export interface RewardFund { recent_claims: string; reward_balance: string; @@ -226,6 +234,7 @@ export const getAccounts = (usernames: string[]): Promise => { savings_hbd_seconds_last_update: x.savings_hbd_seconds_last_update, savings_hbd_seconds: x.savings_hbd_seconds, next_vesting_withdrawal: x.next_vesting_withdrawal, + pending_claimed_accounts: x.pending_claimed_accounts, vesting_shares: x.vesting_shares, delegated_vesting_shares: x.delegated_vesting_shares, received_vesting_shares: x.received_vesting_shares, @@ -339,9 +348,13 @@ export const getFeedHistory = (): Promise => client.database.call(" export const getRewardFund = (): Promise => client.database.call("get_reward_fund", ["post"]); +export const getChainProps = (): Promise => + client.database.call("get_chain_properties"); + export const getDynamicProps = async (): Promise => { const globalDynamic = await getDynamicGlobalProperties(); const feedHistory = await getFeedHistory(); + const chainProps = await getChainProps(); const rewardFund = await getRewardFund(); const hivePerMVests = @@ -359,6 +372,7 @@ export const getDynamicProps = async (): Promise => { const totalVestingShares = parseAsset(globalDynamic.total_vesting_shares).amount; const virtualSupply = parseAsset(globalDynamic.virtual_supply).amount; const vestingRewardPercent = globalDynamic.vesting_reward_percent; + const accountCreationFee = chainProps.account_creation_fee; return { hivePerMVests, @@ -372,7 +386,8 @@ export const getDynamicProps = async (): Promise => { totalVestingFund, totalVestingShares, virtualSupply, - vestingRewardPercent + vestingRewardPercent, + accountCreationFee }; }; diff --git a/src/common/api/operations.ts b/src/common/api/operations.ts index 328d45b4384..922e861eca3 100644 --- a/src/common/api/operations.ts +++ b/src/common/api/operations.ts @@ -2,8 +2,12 @@ import hs from "hivesigner"; import { AccountUpdateOperation, + Authority, CustomJsonOperation, + KeyRole, Operation, + OperationName, + VirtualOperationName, PrivateKey, TransactionConfirmation } from "@hiveio/dhive"; @@ -1850,7 +1854,6 @@ export const Revoke = ( json_metadata: "" } ]; - return hiveClient.broadcast.sendOperations([op], key); }; @@ -1866,7 +1869,6 @@ export const RevokeHot = ( account_auths, key_auths }; - const op: Operation = [ "account_update", { @@ -1878,7 +1880,6 @@ export const RevokeHot = ( ]; const params: Parameters = { callback: `https://ecency.com/@${account}/permissions` }; - return hs.sendOperation(op, params, () => {}); }; @@ -1894,7 +1895,6 @@ export const RevokeKc = ( account_auths, key_auths }; - const op: Operation = [ "account_update", { @@ -1904,6 +1904,378 @@ export const RevokeKc = ( json_metadata: "" } ]; - return keychain.broadcast(account, [op], "Active"); }; + +// Create account with hive keychain +export const createAccountKc = async (data: any, creator_account: string) => { + try { + const { username, pub_keys, fee } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + const op_name: OperationName = "account_create"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [], + fee + }; + + const operation: Operation = [op_name, params]; + ops.push(operation); + try { + // For Keychain + const newAccount = await keychain.broadcast(creator_account, [operation], "Active"); + return newAccount; + } catch (err: any) { + console.log(err); + return err.jse_info.name; + } + } catch (err) { + return err; + } +}; + +// Create account with hive Hs +export const createAccountHs = async (data: any, creator_account: string, hash: string) => { + try { + const { username, pub_keys, fee } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + const op_name: OperationName = "account_create"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + + const params: any = { + creator: creator_account, + new_account_name: account.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [], + fee + }; + + const operation: Operation = [op_name, params]; + + try { + // For Hive Signer + const params: Parameters = { + callback: `https://ecency.com/onboard-friend/confirming/${hash}?tid={{id}}` + }; + const newAccount = hs.sendOperation(operation, params, () => {}); + return newAccount; + } catch (err: any) { + console.log(err); + return err.jse_info.name; + } + } catch (err) { + return err; + } +}; + +// Create account with hive key +export const createAccountKey = async ( + data: any, + creator_account: string, + creator_key: PrivateKey +) => { + try { + const { username, pub_keys, fee } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + let tokens: any = await hiveClient.database.getAccounts([creator_account]); + tokens = tokens[0]?.pending_claimed_accounts; + + let op_name: OperationName = "account_create"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account?.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [], + fee + }; + + const operation: Operation = [op_name, params]; + ops.push(operation); + + try { + // With Private Key + const newAccount = await hiveClient.broadcast.sendOperations(ops, creator_key); + return newAccount; + } catch (err: any) { + console.log(err.message); + return err.jse_info.name; + } + } catch (err) { + console.log(err); + return err; + } +}; + +// Create account with credit Kc +export const createAccountWithCreditKc = async (data: any, creator_account: string) => { + try { + const { username, pub_keys } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + let tokens: any = await hiveClient.database.getAccounts([creator_account]); + tokens = tokens[0]?.pending_claimed_accounts; + + let fee = null; + let op_name: OperationName = "create_claimed_account"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [] + }; + + if (fee) params.fee = fee; + const operation: Operation = [op_name, params]; + ops.push(operation); + try { + // For Keychain + const newAccount = await keychain.broadcast(creator_account, [operation], "Active"); + return newAccount; + } catch (err: any) { + return err.jse_info.name; + } + } catch (err) { + console.log(err); + return err; + } +}; + +// Create account with credit Hs +export const createAccountWithCreditHs = async ( + data: any, + creator_account: string, + hash: string +) => { + try { + const { username, pub_keys } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + let tokens: any = await hiveClient.database.getAccounts([creator_account]); + tokens = tokens[0]?.pending_claimed_accounts; + + let fee = null; + let op_name: OperationName = "create_claimed_account"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + + const params: any = { + creator: creator_account, + new_account_name: account.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [] + }; + + if (fee) params.fee = fee; + const operation: Operation = [op_name, params]; + + try { + // For Hive Signer + const params: Parameters = { + callback: `https://ecency.com/onboard-friend/confirming/${hash}?tid={{id}}` + }; + console.log(params); + const newAccount = hs.sendOperation(operation, params, () => {}); + return newAccount; + } catch (err: any) { + console.log(err); + return err.jse_info.name; + } + } catch (err) { + return err; + } +}; + +// Create account with credit key +export const createAccountWithCreditKey = async ( + data: any, + creator_account: string, + creator_key: PrivateKey +) => { + try { + const { username, pub_keys } = data; + + const account = { + name: username, + ...pub_keys, + active: false + }; + + let tokens: any = await hiveClient.database.getAccounts([creator_account]); + tokens = tokens[0]?.pending_claimed_accounts; + + let fee = null; + let op_name: OperationName = "create_claimed_account"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPublicKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePublicKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPublicKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account?.name, + owner, + active, + posting, + memo_key: account.memoPublicKey, + json_metadata: "", + extensions: [] + }; + + if (fee) params.fee = fee; + const operation: Operation = [op_name, params]; + ops.push(operation); + + try { + // With Private Key + const newAccount = await hiveClient.broadcast.sendOperations(ops, creator_key); + return newAccount; + } catch (err: any) { + console.log(err.message); + return err.jse_info.name; + } + } catch (err) { + return err; + } +}; diff --git a/src/common/api/private-api.ts b/src/common/api/private-api.ts index ddc5ddf1d48..0f5befc8846 100644 --- a/src/common/api/private-api.ts +++ b/src/common/api/private-api.ts @@ -162,6 +162,18 @@ export const getCurrencyTokenRate = (currency: string, token: string): Promise resp.data); +export const getCurrencyRates = (): Promise<{ + [currency: string]: { + quotes: { + [currency: string]: { + last_updated: string; + percent_change: number; + price: number; + }; + }; + }; +}> => axios.get(apiBase("/private-api/market-data/latest")).then((resp: any) => resp.data); + export const getUnreadNotificationCount = (username: string): Promise => { const data = { code: getAccessToken(username) }; @@ -617,3 +629,14 @@ export const deleteRecoveries = (username: string, recoveryId: string): Promise< const data = { code: getAccessToken(username), id: recoveryId }; return axios.post(apiBase(`/private-api/recoveries-delete`), data).then((resp) => resp.data); }; + +export const onboardEmail = (username: string, email: string, friend: string): Promise => { + const dataBody = { + username, + email, + friend + }; + return axios + .post(apiBase(`/private-api/account-create-friend`), dataBody) + .then((resp) => resp.data); +}; diff --git a/src/common/app.tsx b/src/common/app.tsx index 25d94d59d5c..6bd527dc653 100644 --- a/src/common/app.tsx +++ b/src/common/app.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import { Route, Switch } from "react-router-dom"; import EntryIndexContainer from "./pages/index"; -import EntryContainer from "./pages/entry"; +import { EntryScreen } from "./pages/entry"; import { SearchPageContainer, SearchMorePageContainer } from "./pages/search"; import { ProposalsIndexContainer, ProposalDetailContainer } from "./pages/proposals"; import NotFound from "./components/404"; @@ -25,8 +25,7 @@ import loadable from "@loadable/component"; import Announcement from "./components/announcement"; import FloatingFAQ from "./components/floating-faq"; import { useMappedStore } from "./store/use-mapped-store"; -import { QueryClientProvider } from "@tanstack/react-query"; -import { queryClient, EntriesCacheManager } from "./core"; +import { EntriesCacheManager } from "./core"; // Define lazy pages const ProfileContainer = loadable(() => import("./pages/profile-functional")); @@ -47,6 +46,9 @@ const AuthPage = (props: any) => ; const SubmitContainer = loadable(() => import("./pages/submit")); const SubmitPage = (props: any) => ; +const OnboardContainer = loadable(() => import("./pages/onboard")); +const OnboardPage = (props: any) => ; + const MarketContainer = loadable(() => import("./pages/market")); const MarketPage = (props: any) => ; @@ -62,10 +64,10 @@ const CommunityCreatePage = (props: any) => import("./pages/community-create-hs")); const CommunityCreateHSPage = (props: any) => ; -const EntryAMPContainer = loadable(() => import("./pages/amp/entry-amp-page")); +const EntryAMPContainer = loadable(() => import("./pages/entry/index-amp")); const EntryPage = (props: any) => { const [isAmp, setIsAmp] = useState(props.location.search.includes("?amps")); - return isAmp ? : ; + return isAmp ? : ; }; const PurchaseContainer = loadable(() => import("./pages/purchase")); @@ -88,93 +90,82 @@ const App = (props: any) => { }, []); return ( - - - {/*Excluded from production*/} - {/**/} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - + + {/*Excluded from production*/} + {/**/} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); }; diff --git a/src/common/components/community-card/index.tsx b/src/common/components/community-card/index.tsx index e75734be5e9..7f5fa371a7c 100644 --- a/src/common/components/community-card/index.tsx +++ b/src/common/components/community-card/index.tsx @@ -138,7 +138,6 @@ interface Props { signingKey: string; setSigningKey: (key: string) => void; addAccount: (data: Account) => void; - addCommunity: (data: Community) => void; } interface DialogInfo { @@ -389,8 +388,7 @@ export default (p: Props) => { signingKey: p.signingKey, setSigningKey: p.setSigningKey, activeUser: p.activeUser, - addAccount: p.addAccount, - addCommunity: p.addCommunity + addAccount: p.addAccount }; return ; diff --git a/src/common/components/community-role-edit/index.tsx b/src/common/components/community-role-edit/index.tsx index 7bf85d3ab34..66d4dfb8ff3 100644 --- a/src/common/components/community-role-edit/index.tsx +++ b/src/common/components/community-role-edit/index.tsx @@ -20,6 +20,7 @@ import { setUserRole, formatError } from "../../api/operations"; import { _t } from "../../i18n"; import { Tsx } from "../../i18n/helper"; import "./_index.scss"; +import { queryClient, QueryIdentifiers } from "../../core"; interface Props { global: Global; @@ -28,7 +29,6 @@ interface Props { user: string; role: string; roles: string[]; - addCommunity: (data: Community) => void; onHide: () => void; } @@ -61,7 +61,7 @@ export class CommunityRoleEdit extends BaseComponent { submit = async () => { const { user, role } = this.state; - const { community, activeUser, addCommunity, onHide } = this.props; + const { community, activeUser, onHide } = this.props; if (user.trim() === "") { this._input.current?.focus(); @@ -89,8 +89,10 @@ export class CommunityRoleEdit extends BaseComponent { team.find((x) => x[0] === user) === undefined ? [...team, [user, role, ""]] : team.map((x) => (x[0] === user ? [x[0], role, x[2]] : x)); - const nCom: Community = { ...clone(community), team: nTeam }; - addCommunity(nCom); + queryClient.setQueryData([QueryIdentifiers.COMMUNITY, community.name], { + ...clone(community), + ...{ ...clone(community), team: nTeam } + }); onHide(); }) .catch((err) => error(...formatError(err))) diff --git a/src/common/components/community-roles/index.tsx b/src/common/components/community-roles/index.tsx index 6bd8c465f06..43cd28581dd 100644 --- a/src/common/components/community-roles/index.tsx +++ b/src/common/components/community-roles/index.tsx @@ -25,7 +25,6 @@ interface Props { community: Community; activeUser: ActiveUser | null; addAccount: (data: Account) => void; - addCommunity: (data: Community) => void; } interface State { @@ -148,8 +147,7 @@ export default (p: Props) => { global: p.global, community: p.community, activeUser: p.activeUser, - addAccount: p.addAccount, - addCommunity: p.addCommunity + addAccount: p.addAccount }; return ; diff --git a/src/common/components/community-settings/index.tsx b/src/common/components/community-settings/index.tsx index 29ac5931536..6c21d401bd7 100644 --- a/src/common/components/community-settings/index.tsx +++ b/src/common/components/community-settings/index.tsx @@ -18,6 +18,7 @@ import { updateCommunity, formatError } from "../../api/operations"; import { _t } from "../../i18n"; import { handleInvalid, handleOnInput } from "../../util/input-util"; import "./_index.scss"; +import { queryClient, QueryIdentifiers } from "../../core"; const langOpts = [ { id: "af", name: "Afrikaans" }, @@ -125,7 +126,6 @@ interface Props { global: Global; community: Community; activeUser: ActiveUser; - addCommunity: (data: Community) => void; onHide: () => void; } @@ -168,7 +168,7 @@ export class CommunitySettings extends BaseComponent { }; submit = () => { - const { activeUser, community, addCommunity, onHide } = this.props; + const { activeUser, community, onHide } = this.props; const { title, about, description, lang, flag_text, is_nsfw } = this.state; const newProps = { title: cleanString(title), @@ -182,8 +182,10 @@ export class CommunitySettings extends BaseComponent { this.stateSet({ inProgress: true }); return updateCommunity(activeUser.username, community.name, newProps) .then(() => { - const nCom: Community = { ...clone(community), ...newProps }; - addCommunity(nCom); + queryClient.setQueryData([QueryIdentifiers.COMMUNITY, community.name], { + ...clone(community), + ...newProps + }); onHide(); }) .catch((err) => error(...formatError(err))) diff --git a/src/common/components/community-subscribers/index.tsx b/src/common/components/community-subscribers/index.tsx index fea03dc912b..268de00a42d 100644 --- a/src/common/components/community-subscribers/index.tsx +++ b/src/common/components/community-subscribers/index.tsx @@ -38,7 +38,6 @@ interface Props { community: Community; activeUser: ActiveUser | null; addAccount: (data: Account) => void; - addCommunity: (data: Community) => void; } interface State { @@ -195,8 +194,7 @@ export default (p: Props) => { global: p.global, community: p.community, activeUser: p.activeUser, - addAccount: p.addAccount, - addCommunity: p.addCommunity + addAccount: p.addAccount }; return ; diff --git a/src/common/components/decks/columns/add-column/_deck-add-column.scss b/src/common/components/decks/columns/add-column/_deck-add-column.scss index 8bca5089eee..db1c4637ea6 100644 --- a/src/common/components/decks/columns/add-column/_deck-add-column.scss +++ b/src/common/components/decks/columns/add-column/_deck-add-column.scss @@ -135,9 +135,10 @@ @include padding-top(1rem); .users-list-item { - display: flex; + display: grid; align-items: center; - gap: 1rem; + grid-template-columns: min-content 1fr min-content; + grid-gap: 1rem; cursor: pointer; @include padding-top(0.5rem); diff --git a/src/common/components/decks/columns/add-column/deck-add-column-search-box.tsx b/src/common/components/decks/columns/add-column/deck-add-column-search-box.tsx index 74a21b0df61..61a178d4279 100644 --- a/src/common/components/decks/columns/add-column/deck-add-column-search-box.tsx +++ b/src/common/components/decks/columns/add-column/deck-add-column-search-box.tsx @@ -144,7 +144,7 @@ export const DeckAddColumnSearchBox = ({
{i.name}
-
{i.description}
+
{i.description}
{isRecent && !!recentList?.length && (
- {activeUser?.username === entry.author && ( - - )} +
+ + {activeUser?.username === entry.author && ( + + )} +
)} {hasParent && !pure && ( diff --git a/src/common/components/decks/columns/deck-threads-column.tsx b/src/common/components/decks/columns/deck-threads-column.tsx index c0f6070735e..5bb106d5bbd 100644 --- a/src/common/components/decks/columns/deck-threads-column.tsx +++ b/src/common/components/decks/columns/deck-threads-column.tsx @@ -28,6 +28,14 @@ interface Props { draggable?: DraggableProvidedDragHandleProps; } +const MAX_ERROR_ATTEMPTS = 3; +const ERROR_ATTEMPTS_INTERVALS = { + 0: 3000, + 1: 10000, + 2: 20000, + 3: 30000 +}; + const DeckThreadsColumnComponent = ({ id, settings, history, draggable }: Props) => { const { register, detach, reloadingInitiated } = useContext(DeckThreadsContext); const { fetch } = useContext(DeckThreadsColumnManagerContext); @@ -61,6 +69,7 @@ const DeckThreadsColumnComponent = ({ id, settings, history, draggable }: Props) {} ) ); + const [nextPageError, setNextPageError] = useState(false); const previousEditingEntry = usePrevious(currentEditingEntry); const { updateColumnIntervalMs } = useContext(DeckGridContext); @@ -80,7 +89,9 @@ const DeckThreadsColumnComponent = ({ id, settings, history, draggable }: Props) } }, [reloadingInitiated]); - const fetchData = async (sinceEntries?: IdentifiableEntry[]) => { + const fetchData = async (sinceEntries?: IdentifiableEntry[], retries = 0) => { + setNextPageError(false); + try { if (data.length) { setIsReloading(true); @@ -120,6 +131,12 @@ const DeckThreadsColumnComponent = ({ id, settings, history, draggable }: Props) setIsEndReached(true); } } catch (e) { + if (retries < MAX_ERROR_ATTEMPTS && sinceEntries) { + setNextPageError(true); + setTimeout(() => { + fetchData(sinceEntries, retries + 1); + }, ERROR_ATTEMPTS_INTERVALS[retries]); + } console.error(e); } finally { setIsReloading(false); @@ -165,6 +182,7 @@ const DeckThreadsColumnComponent = ({ id, settings, history, draggable }: Props) ) : ( diff --git a/src/common/components/decks/columns/helpers/infinite-scroll-loader.tsx b/src/common/components/decks/columns/helpers/infinite-scroll-loader.tsx index c1d08e56cb4..f3012a752cb 100644 --- a/src/common/components/decks/columns/helpers/infinite-scroll-loader.tsx +++ b/src/common/components/decks/columns/helpers/infinite-scroll-loader.tsx @@ -5,16 +5,22 @@ interface Props { data: any[]; isEndReached: boolean; endReachedLabel?: string; + failed?: boolean; } export const InfiniteScrollLoader = ({ data, isEndReached, - endReachedLabel = _t("decks.columns.feed-end-reached") + endReachedLabel = _t("decks.columns.feed-end-reached"), + failed }: Props) => { return data.length > 0 ? (
- {isEndReached ? endReachedLabel : _t("decks.columns.infinite-loading")} + {failed + ? _t("decks.columns.infinite-failed") + : isEndReached + ? endReachedLabel + : _t("decks.columns.infinite-loading")}
) : ( <> diff --git a/src/common/components/decks/deck-threads-form/index.tsx b/src/common/components/decks/deck-threads-form/index.tsx index b34c8efae15..7bb6528572c 100644 --- a/src/common/components/decks/deck-threads-form/index.tsx +++ b/src/common/components/decks/deck-threads-form/index.tsx @@ -26,6 +26,7 @@ interface Props { onSuccess?: (reply: Entry) => void; hideAvatar?: boolean; entry?: ThreadItemEntry; + persistable?: boolean; } export const DeckThreadsForm = ({ @@ -35,7 +36,8 @@ export const DeckThreadsForm = ({ replySource, onSuccess, hideAvatar = false, - entry + entry, + persistable = false }: Props) => { const rootRef = useRef(null); useClickAway(rootRef, () => setFocused(false)); @@ -48,10 +50,13 @@ export const DeckThreadsForm = ({ PREFIX + "_local_draft", {} ); - const [threadHost, setThreadHost] = useLocalStorage(PREFIX + "_dtf_th", "ecency.waves"); - const [text, setText] = useLocalStorage(PREFIX + "_dtf_t", ""); - const [image, setImage] = useLocalStorage(PREFIX + "_dtf_i", null); - const [imageName, setImageName] = useLocalStorage(PREFIX + "_dtf_in", null); + const [persistedForm, setPersistedForm] = useLocalStorage>(PREFIX + "_dtf_f"); + + const [threadHost, setThreadHost] = useState("ecency.waves"); + const [text, setText] = useState(""); + const [image, setImage] = useState(null); + const [imageName, setImageName] = useState(null); + const [disabled, setDisabled] = useState(true); const [loading, setLoading] = useState(false); const [focused, setFocused] = useState(false); @@ -79,6 +84,26 @@ export const DeckThreadsForm = ({ } }, [entry]); + useEffect(() => { + if (persistable) { + setThreadHost(threadHost ? threadHost : persistedForm?.threadHost); + setText(text ? text : persistedForm?.text); + setImage(image ? image : persistedForm?.image); + setImageName(imageName ? imageName : persistedForm?.imageName); + } + }, [persistedForm]); + + useEffect(() => { + if (persistable) { + setPersistedForm({ + threadHost, + text, + image, + imageName + }); + } + }, [threadHost, text, image, imageName]); + const submit = async () => { if (!activeUser) { toggleUIProp("login"); @@ -134,6 +159,7 @@ export const DeckThreadsForm = ({ setImageName(null); _t("decks.threads-form.successfully-created"); } catch (e) { + console.error(e); } finally { setLoading(false); } diff --git a/src/common/components/decks/index.tsx b/src/common/components/decks/index.tsx index ae98cdb2b7a..014e61b506c 100644 --- a/src/common/components/decks/index.tsx +++ b/src/common/components/decks/index.tsx @@ -8,8 +8,7 @@ import { History } from "history"; import { DeckToolbar } from "./deck-toolbar/deck-toolbar"; import { DeckFloatingManager } from "./deck-floating-manager"; import { DeckLoader } from "./deck-loader"; -import { DeckThreadsFormManager } from "./deck-threads-form"; -import { DeckThreadsForm } from "./deck-threads-form"; +import { DeckThreadsForm, DeckThreadsFormManager } from "./deck-threads-form"; import { DeckThreadsManager } from "./columns/deck-threads-manager"; import SSRSuspense from "../ssr-suspense"; import { classNameObject } from "../../helper/class-name-object"; @@ -61,7 +60,7 @@ export const Decks = ({ history }: Props) => { isExpanded={isExpanded} setIsExpanded={setIsExpanded} /> - + {isDecksLoading ? ( ) : ( diff --git a/src/common/components/decks/utils/use-entry-checking.tsx b/src/common/components/decks/utils/use-entry-checking.tsx index e273d4b574d..3f2f01f100e 100644 --- a/src/common/components/decks/utils/use-entry-checking.tsx +++ b/src/common/components/decks/utils/use-entry-checking.tsx @@ -11,7 +11,7 @@ export function useEntryChecking( ) { const { activeUser } = useMappedStore(); - const isLocal = ({ post_id }: Entry) => post_id === 1 || typeof post_id === "string"; + const isLocal = ({ post_id }: Entry) => post_id === 1 || typeof post_id === "string" || !post_id; return useInterval( async () => { diff --git a/src/common/components/entry-list-item/index.spec.tsx b/src/common/components/entry-list-item/index.spec.tsx index 6484bac8e07..19f69e3ee9d 100644 --- a/src/common/components/entry-list-item/index.spec.tsx +++ b/src/common/components/entry-list-item/index.spec.tsx @@ -21,6 +21,8 @@ import { ListStyle } from "../../store/global/types"; import EntryListItem from "./index"; import { withStore } from "../../tests/with-store"; import { activeUserMaker } from "../../store/helper"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { queryClient } from "../../core"; mockDate.set(1591398131176); @@ -36,7 +38,6 @@ const defProps = { reblogs: emptyReblogs, entry: entryInstance1, ui: UiInstance, - entryPinTracker: {}, signingKey: "", asAuthor: "", promoted: false, @@ -58,9 +59,11 @@ const defProps = { it("(1) Default render", async () => { const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); @@ -76,9 +79,11 @@ it("(2) Grid view", async () => { } }; const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); @@ -96,9 +101,11 @@ it("(3) Nsfw", async () => { } }; const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); @@ -118,9 +125,11 @@ it("(4) Nsfw with active user", async () => { activeUser: activeUserMaker("foo") }; const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); @@ -143,9 +152,11 @@ it("(5) Nsfw but allowed", async () => { } }; const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); @@ -160,9 +171,11 @@ it("(6) Cross post. Bottom menu", async () => { }; const renderer = await withStore( - - - , + + + + + , defProps ); await allOver(); diff --git a/src/common/components/entry-list-item/index.tsx b/src/common/components/entry-list-item/index.tsx index e970bc26242..1112e9c828e 100644 --- a/src/common/components/entry-list-item/index.tsx +++ b/src/common/components/entry-list-item/index.tsx @@ -15,7 +15,6 @@ import { User } from "../../store/users/types"; import { ActiveUser } from "../../store/active-user/types"; import { Reblogs } from "../../store/reblogs/types"; import { UI, ToggleType } from "../../store/ui/types"; -import { EntryPinTracker } from "../../store/entry-pin-tracker/types"; import ProfileLink from "../profile-link/index"; import Tag from "../tag"; @@ -34,16 +33,7 @@ import { Tsx } from "../../i18n/helper"; import _c from "../../util/fix-class-names"; import truncate from "../../util/truncate"; -import { - repeatSvg, - pinSvg, - commentSvg, - muteSvg, - volumeOffSvg, - closeSvg, - downArrowSvg, - menuDownSvg -} from "../../img/svg"; +import { repeatSvg, pinSvg, commentSvg, volumeOffSvg } from "../../img/svg"; import defaults from "../../constants/defaults.json"; import { ProfilePopover } from "../profile-popover"; @@ -62,14 +52,12 @@ interface Props { location: Location; global: Global; dynamicProps: DynamicProps; - communities: Communities; community?: Community | null; users: User[]; activeUser: ActiveUser | null; reblogs: Reblogs; entry: Entry; ui: UI; - entryPinTracker: EntryPinTracker; signingKey: string; asAuthor: string; promoted: boolean; @@ -85,10 +73,7 @@ interface Props { addReblog: (author: string, permlink: string) => void; deleteReblog: (author: string, permlink: string) => void; toggleUIProp: (what: ToggleType | "login") => void; - addCommunity: (data: Community) => void; - trackEntryPin: (entry: Entry) => void; setSigningKey: (key: string) => void; - setEntryPin: (entry: Entry, pin: boolean) => void; muted?: boolean; pinEntry?: (entry: Entry | null) => void; } @@ -121,8 +106,6 @@ export default class EntryListItem extends Component { !isEqual(this.props.dynamicProps, nextProps.dynamicProps) || !isEqual(this.props.activeUser, nextProps.activeUser) || !isEqual(this.props.reblogs, nextProps.reblogs) || - !isEqual(this.props.communities, nextProps.communities) || - !isEqual(this.props.entryPinTracker, nextProps.entryPinTracker) || !isEqual(this.state, nextState) ); } diff --git a/src/common/components/entry-list/index.tsx b/src/common/components/entry-list/index.tsx index 42aa6c94042..06af6a7b86d 100644 --- a/src/common/components/entry-list/index.tsx +++ b/src/common/components/entry-list/index.tsx @@ -1,7 +1,7 @@ import React, { Component } from "react"; import { History, Location } from "history"; -import { Global, ProfileFilter } from "../../store/global/types"; -import { Account, FullAccount } from "../../store/accounts/types"; +import { Global } from "../../store/global/types"; +import { Account } from "../../store/accounts/types"; import { DynamicProps } from "../../store/dynamic-props/types"; import { Entry } from "../../store/entries/types"; import { Community, Communities } from "../../store/communities/types"; @@ -11,7 +11,6 @@ import { Reblogs } from "../../store/reblogs/types"; import { UI, ToggleType } from "../../store/ui/types"; import EntryListItem from "../entry-list-item/index"; -import { EntryPinTracker } from "../../store/entry-pin-tracker/types"; import MessageNoData from "../message-no-data"; import { _t } from "../../i18n"; import LinearProgress from "../linear-progress"; @@ -27,14 +26,12 @@ interface Props { dynamicProps: DynamicProps; entries: Entry[]; promotedEntries: Entry[]; - communities: Communities; community?: Community | null; users: User[]; activeUser: ActiveUser | null; reblogs: Reblogs; loading: boolean; ui: UI; - entryPinTracker: EntryPinTracker; signingKey: string; account?: Account; match?: match; @@ -47,10 +44,7 @@ interface Props { addReblog: (author: string, permlink: string) => void; deleteReblog: (author: string, permlink: string) => void; toggleUIProp: (what: ToggleType) => void; - addCommunity: (data: Community) => void; - trackEntryPin: (entry: Entry) => void; setSigningKey: (key: string) => void; - setEntryPin: (entry: Entry, pin: boolean) => void; pinEntry?: (entry: Entry | null) => void; } @@ -237,13 +231,11 @@ export default (p: Props) => { dynamicProps: p.dynamicProps, entries: p.entries, promotedEntries: p.promotedEntries, - communities: p.communities, community: p.community, users: p.users, activeUser: p.activeUser, reblogs: p.reblogs, ui: p.ui, - entryPinTracker: p.entryPinTracker, signingKey: p.signingKey, addAccount: p.addAccount, updateEntry: p.updateEntry, @@ -254,10 +246,7 @@ export default (p: Props) => { addReblog: p.addReblog, deleteReblog: p.deleteReblog, toggleUIProp: p.toggleUIProp, - addCommunity: p.addCommunity, - trackEntryPin: p.trackEntryPin, setSigningKey: p.setSigningKey, - setEntryPin: p.setEntryPin, loading: p.loading, account: p.account, match: p.match, diff --git a/src/common/components/entry-menu/index.spec.tsx b/src/common/components/entry-menu/index.spec.tsx index 05e6c0ebf3d..40254f6d010 100644 --- a/src/common/components/entry-menu/index.spec.tsx +++ b/src/common/components/entry-menu/index.spec.tsx @@ -2,11 +2,14 @@ import React from "react"; import { createBrowserHistory } from "history"; -import { EntryMenu } from "./index"; +import EntryMenu from "./index"; import TestRenderer from "react-test-renderer"; import { entryInstance1, globalInstance, dynamicPropsIntance1 } from "../../helper/test-helper"; +import { withStore } from "../../tests/with-store"; +import { queryClient } from "../../core"; +import { QueryClientProvider } from "@tanstack/react-query"; const defProps = { history: createBrowserHistory(), @@ -15,7 +18,6 @@ const defProps = { activeUser: null, entry: entryInstance1, communities: [], - entryPinTracker: {}, signingKey: "", setSigningKey: () => {}, updateActiveUser: () => {}, @@ -29,7 +31,11 @@ const defProps = { it("(1) Default render", () => { const props = { ...defProps }; - const renderer = TestRenderer.create(); + const renderer = withStore( + + + + ); expect(renderer.toJSON()).toMatchSnapshot(); }); @@ -38,6 +44,10 @@ it("(2) Separated sharing buttons", () => { ...defProps, separatedSharing: true }; - const renderer = TestRenderer.create(); + const renderer = withStore( + + + + ); expect(renderer.toJSON()).toMatchSnapshot(); }); diff --git a/src/common/components/entry-menu/index.tsx b/src/common/components/entry-menu/index.tsx index 2794028c3fa..a2662f01a7a 100644 --- a/src/common/components/entry-menu/index.tsx +++ b/src/common/components/entry-menu/index.tsx @@ -1,255 +1,97 @@ -import React from "react"; - +import React, { useEffect } from "react"; import { History } from "history"; - -import BaseComponent from "../base"; - -import { ActiveUser } from "../../store/active-user/types"; import { Entry, EntryStat } from "../../store/entries/types"; -import { Communities, Community, ROLES } from "../../store/communities/types"; -import { EntryPinTracker } from "../../store/entry-pin-tracker/types"; -import { Global } from "../../store/global/types"; -import { Account, FullAccount } from "../../store/accounts/types"; -import { DynamicProps } from "../../store/dynamic-props/types"; -import { ToggleType } from "../../store/ui/types"; - +import { FullAccount } from "../../store/accounts/types"; import { clone } from "../../store/util"; - import EditHistory from "../edit-history"; -import EntryShare, { shareReddit, shareTwitter, shareFacebook } from "../entry-share"; +import EntryShare, { shareFacebook, shareReddit, shareTwitter } from "../entry-share"; import MuteBtn from "../mute-btn"; import Promote from "../promote"; import Boost from "../boost"; import ModalConfirm from "../modal-confirm"; -import { error, info, success } from "../feedback"; -import DropDown, { MenuItem } from "../dropdown"; +import { error, success } from "../feedback"; +import DropDown from "../dropdown"; import CrossPost from "../cross-post"; - -import isCommunity from "../../helper/is-community"; - import { _t } from "../../i18n"; - -import clipboard from "../../util/clipboard"; - -import { deleteComment, formatError, pinPost, updateProfile } from "../../api/operations"; +import { deleteComment, formatError, updateProfile } from "../../api/operations"; import { getAccount } from "../../api/hive"; - -import * as bridgeApi from "../../api/bridge"; - -import { - dotsHorizontal, - deleteForeverSvg, - pencilOutlineSvg, - pinSvg, - historySvg, - shareVariantSvg, - linkVariantSvg, - volumeOffSvg, - redditSvg, - twitterSvg, - facebookSvg, - bullHornSvg, - rocketLaunchSvg, - shuffleVariantSvg -} from "../../img/svg"; +import { dotsHorizontal, facebookSvg, redditSvg, shareVariantSvg, twitterSvg } from "../../img/svg"; import "./_index.scss"; import { useMappedStore } from "../../store/use-mapped-store"; +import { useMenuItemsGenerator } from "./menu-items-generator"; +import { useCommunityCache, useCommunityPin } from "../../core"; interface Props { history: History; - global: Global; - dynamicProps: DynamicProps; - activeUser: ActiveUser | null; entry: Entry; extraMenuItems?: any[]; - communities: Communities; - entryPinTracker: EntryPinTracker; separatedSharing?: boolean; alignBottom?: boolean; - signingKey: string; - setSigningKey: (key: string) => void; - addAccount: (data: Account) => void; - updateActiveUser: (data?: Account) => void; - updateEntry: (entry: any) => void; - addCommunity: (data: Community) => void; - trackEntryPin: (entry: Entry) => void; - setEntryPin: (entry: Entry, pin: boolean) => void; - toggleUIProp: (what: ToggleType) => void; toggleEdit?: () => void; pinEntry?: (entry: Entry | null) => void; } -interface State { - cross: boolean; - share: boolean; - editHistory: boolean; - delete_: boolean; - pin: boolean; - pinKey: string; - unpin: boolean; - mute: boolean; - promote: boolean; - boost: boolean; -} - -export class EntryMenu extends BaseComponent { - state: State = { - cross: false, - share: false, - editHistory: false, - delete_: false, - pin: false, - pinKey: "", - unpin: false, - mute: false, - promote: false, - boost: false - }; +const EntryMenu = ({ + history, + entry, + separatedSharing = false, + alignBottom, + extraMenuItems, + toggleEdit, + pinEntry +}: Props) => { + const { + global, + activeUser, + dynamicProps, + signingKey, + setSigningKey, + addAccount, + updateActiveUser, + updateEntry + } = useMappedStore(); - componentDidMount() { - const { activeUser } = this.props; + const { data: community } = useCommunityCache(entry.category); + const { mutateAsync: pinPost } = useCommunityPin(entry, community); + const { + menuItems, + cross, + setCross, + share, + setShare, + editHistory, + setEditHistory, + delete_, + setDelete_, + pin, + setPin, + pinKey, + setPinKey, + unpin, + setUnpin, + mute, + setMute, + promote, + setPromote, + boost, + setBoost + } = useMenuItemsGenerator( + entry, + community, + separatedSharing, + toggleEdit, + history, + extraMenuItems + ); + + useEffect(() => { if (!activeUser) { return; } + }, []); - const { trackEntryPin, entry } = this.props; - trackEntryPin(entry); - - if (this.getCommunity()) { - return; - } - - const { addCommunity } = this.props; - - if (isCommunity(entry.category)) { - bridgeApi.getCommunity(entry.category, activeUser.username).then((r) => { - if (r) { - addCommunity(r); - } - }); - } - } - - toggleCross = () => { - const { cross } = this.state; - this.stateSet({ cross: !cross }); - }; - - toggleShare = () => { - const { share } = this.state; - this.stateSet({ share: !share }); - }; - - toggleEditHistory = () => { - const { editHistory } = this.state; - this.stateSet({ editHistory: !editHistory }); - }; - - toggleDelete = () => { - const { delete_ } = this.state; - this.stateSet({ delete_: !delete_ }); - }; - - togglePin = (key?: string) => { - const { pin } = this.state; - this.stateSet({ pin: !pin, pinKey: key ? key : "" }); - }; - - toggleUnpin = (key?: string) => { - const { unpin } = this.state; - this.stateSet({ unpin: !unpin, pinKey: key ? key : "" }); - }; - - toggleMute = () => { - const { mute } = this.state; - this.stateSet({ mute: !mute }); - }; - - togglePromote = () => { - const { promote } = this.state; - this.stateSet({ promote: !promote }); - }; - - toggleBoost = () => { - const { boost } = this.state; - this.stateSet({ boost: !boost }); - }; - - getCommunity = (): Community | null => { - const { communities, entry } = this.props; - - return communities.find((x) => x.name === entry.category) || null; - }; - - canMute = () => { - const { activeUser } = this.props; - - const community = this.getCommunity(); - - return activeUser && community - ? !!community.team.find((m) => { - return ( - m[0] === activeUser.username && - [ROLES.OWNER.toString(), ROLES.ADMIN.toString(), ROLES.MOD.toString()].includes(m[1]) - ); - }) - : false; - }; - - canPin = () => { - const { activeUser, entry } = this.props; - - const community = this.getCommunity(); - const ownEntry = (activeUser && activeUser.username === entry.author) || !community; - - return activeUser && community - ? !!community.team.find((m) => { - return ( - m[0] === activeUser.username && - [ROLES.OWNER.toString(), ROLES.ADMIN.toString(), ROLES.MOD.toString()].includes(m[1]) - ); - }) - : ownEntry; - }; - - canPinBothOptions = () => { - const { activeUser, entry } = this.props; - - const community = this.getCommunity(); - const ownEntry = activeUser && activeUser.username === entry.author; - - return activeUser && community && ownEntry - ? !!community.team.find((m) => { - return ( - m[0] === activeUser.username && - [ROLES.OWNER.toString(), ROLES.ADMIN.toString(), ROLES.MOD.toString()].includes(m[1]) - ); - }) - : false; - }; - - copyAddress = () => { - const { entry, activeUser } = this.props; - let u; - if (activeUser?.username) { - u = `https://ecency.com/${entry.category}/@${entry.author}/${entry.permlink}?referral=${activeUser.username}`; - } else { - u = `https://ecency.com/${entry.category}/@${entry.author}/${entry.permlink}`; - } - clipboard(u); - success(_t("entry.address-copied")); - }; - - edit = () => { - const { entry, history } = this.props; - - const u = `/@${entry.author}/${entry.permlink}/edit`; - history.push(u); - }; - - delete = () => { - const { history, activeUser, entry } = this.props; + const deleteAction = () => deleteComment(activeUser!.username, entry.author, entry.permlink) .then(() => { history.push("/"); @@ -257,35 +99,27 @@ export class EntryMenu extends BaseComponent { .catch((e) => { error(...formatError(e)); }); - }; - pinToCommunity = (pin: boolean) => { - const { entry, activeUser, setEntryPin, updateEntry } = this.props; - const community = this.getCommunity(); + const pinToCommunity = async (pin: boolean) => { + try { + await pinPost(pin); - pinPost(activeUser!.username, community!.name, entry.author, entry.permlink, pin) - .then(() => { - setEntryPin(entry, pin); - - // Update the entry in store - const nStats: EntryStat = { ...clone(entry.stats), is_pinned: pin }; - const nEntry: Entry = { ...clone(entry), stats: nStats }; - updateEntry(nEntry); + // Update the entry in store + const nStats: EntryStat = { ...clone(entry.stats), is_pinned: pin }; + const nEntry: Entry = { ...clone(entry), stats: nStats }; + updateEntry(nEntry); - if (pin) { - success(_t("entry-menu.pin-success")); - } else { - success(_t("entry-menu.unpin-success")); - } - }) - .catch((err) => { - error(...formatError(err)); - }); + if (pin) { + success(_t("entry-menu.pin-success")); + } else { + success(_t("entry-menu.unpin-success")); + } + } catch (e) { + error(...formatError(e)); + } }; - pinToBlog = (pin: boolean) => { - const { entry, activeUser, addAccount, updateActiveUser } = this.props; - + const pinToBlog = async (pin: boolean) => { const ownEntry = activeUser && activeUser.username === entry.author; const { profile, name } = activeUser!.data as FullAccount; @@ -299,20 +133,19 @@ export class EntryMenu extends BaseComponent { location: profile?.location || "", pinned: entry.permlink }; - updateProfile(activeUser.data, newProfile) - .then((r) => { - success(_t("entry-menu.pin-success")); - return getAccount(name); - }) - .then((account) => { - // update reducers - addAccount(account); - updateActiveUser(account); - this.props.pinEntry && this.props.pinEntry(pin ? entry : null); - }) - .catch(() => { - error(_t("g.server-error")); - }); + + try { + await updateProfile(activeUser.data, newProfile); + success(_t("entry-menu.pin-success")); + + const account = await getAccount(name); + // update reducers + addAccount(account); + updateActiveUser(account); + pinEntry?.(pin ? entry : null); + } catch (e) { + error(_t("g.server-error")); + } } else if (ownEntry && !pin && profile && activeUser) { const newProfile = { name: profile?.name || "", @@ -323,470 +156,166 @@ export class EntryMenu extends BaseComponent { location: profile?.location || "", pinned: "" }; - updateProfile(activeUser.data, newProfile) - .then((r) => { - success(_t("entry-menu.unpin-success")); - return getAccount(name); - }) - .then((account) => { - // update reducers - addAccount(account); - updateActiveUser(account); - this.props.pinEntry && this.props.pinEntry(pin ? entry : null); - }) - .catch(() => { - error(_t("g.server-error")); - }); - } - }; - - toggleLoginModal = () => { - this.props.toggleUIProp("login"); - }; - - render() { - const { - global, - activeUser, - entry, - entryPinTracker, - alignBottom, - separatedSharing, - extraMenuItems, - toggleEdit - } = this.props; - - const activeUserWithProfile = activeUser?.data as FullAccount; - const profile = activeUserWithProfile && activeUserWithProfile.profile; - const isComment = !!entry.parent_author; - - const ownEntry = activeUser && activeUser.username === entry.author; - const community: any = this.getCommunity(); - const canPinToCommunity = - community?.context?.role !== "guest" && community?.context?.role !== "member"; - - // const editable = ownEntry && !isComment; - const editable = ownEntry; - const deletable = - ownEntry && !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout); - - let menuItems: MenuItem[] = []; - - if (activeUser && !isComment && isCommunity(entry.category)) { - menuItems = [ - { - label: _t("entry-menu.cross-post"), - onClick: this.toggleCross, - icon: shuffleVariantSvg - } - ]; - } - - if (!separatedSharing) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.share"), - onClick: this.toggleShare, - icon: shareVariantSvg - } - ]; - } - - if (global.usePrivate) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.edit-history"), - onClick: this.toggleEditHistory, - icon: historySvg - } - ]; - } - - if (editable) { - menuItems = [ - ...menuItems, - ...[ - { - label: _t("g.edit"), - // onClick: this.edit, - onClick: isComment && toggleEdit ? toggleEdit : this.edit, - icon: pencilOutlineSvg - } - ] - ]; - } - - if (deletable) { - menuItems = [ - ...menuItems, - ...[ - { - label: _t("g.delete"), - onClick: this.toggleDelete, - icon: deleteForeverSvg - } - ] - ]; - } - - if (this.canPinBothOptions()) { - if ( - entryPinTracker[`${entry.author}-${entry.permlink}`] && - entry.permlink === profile?.pinned - ) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.unpin-from-community"), - onClick: () => this.toggleUnpin("community"), - icon: pinSvg - }, - { - label: _t("entry-menu.unpin-from-blog"), - onClick: () => this.toggleUnpin("blog"), - icon: pinSvg - } - ]; - } else if (entryPinTracker[`${entry.author}-${entry.permlink}`]) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.unpin-from-community"), - onClick: () => this.toggleUnpin("community"), - icon: pinSvg - }, - { - label: _t("entry-menu.pin-to-blog"), - onClick: () => this.togglePin("blog"), - icon: pinSvg - } - ]; - } else if (entry.permlink === profile?.pinned) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.pin-to-community"), - onClick: () => this.togglePin("community"), - icon: pinSvg - }, - { - label: _t("entry-menu.unpin-from-blog"), - onClick: () => this.toggleUnpin("blog"), - icon: pinSvg - } - ]; - } else { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.pin-to-blog"), - onClick: () => this.togglePin("blog"), - icon: pinSvg - }, - { - label: _t("entry-menu.pin-to-community"), - onClick: () => this.togglePin("community"), - icon: pinSvg - } - ]; - } - } else if (this.canPin() || activeUser) { - if (entryPinTracker[`${entry.author}-${entry.permlink}`] && canPinToCommunity) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.unpin-from-community"), - onClick: () => this.toggleUnpin("community"), - icon: pinSvg - } - ]; - } else if (entry.permlink === profile?.pinned) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.unpin-from-blog"), - onClick: () => this.toggleUnpin("blog"), - icon: pinSvg - } - ]; - } else if (ownEntry) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.pin-to-blog"), - onClick: () => this.togglePin("blog"), - icon: pinSvg - } - ]; - } else if (isCommunity(entry.category) && canPinToCommunity) { - menuItems = [ - ...menuItems, - { - label: _t("entry-menu.pin-to-community"), - onClick: () => this.togglePin("community"), - icon: pinSvg - } - ]; + try { + await updateProfile(activeUser.data, newProfile); + success(_t("entry-menu.unpin-success")); + + const account = await getAccount(name); + // update reducers + addAccount(account); + updateActiveUser(account); + pinEntry?.(pin ? entry : null); + } catch (e) { + error(_t("g.server-error")); } } + }; - if (this.canMute()) { - const isMuted = !!entry.stats?.gray; - menuItems = [ - ...menuItems, - ...[ - { - label: isMuted ? _t("entry-menu.unmute") : _t("entry-menu.mute"), - onClick: this.toggleMute, - icon: volumeOffSvg - } - ] - ]; - } - - if (global.usePrivate) { - menuItems = [ - ...menuItems, - ...[ - { - label: _t("entry-menu.promote"), - onClick: activeUser !== null ? this.togglePromote : this.toggleLoginModal, - icon: bullHornSvg - }, - { - label: _t("entry-menu.boost"), - onClick: activeUser !== null ? this.toggleBoost : this.toggleLoginModal, - icon: rocketLaunchSvg - } - ] - ]; - } - - menuItems = [ - ...menuItems, - { - label: _t("entry.address-copy"), - onClick: this.copyAddress, - icon: linkVariantSvg - } - ]; - - if (extraMenuItems) { - menuItems = [...menuItems, ...extraMenuItems]; - } - - if (menuItems) { - let deleteItems = menuItems.filter((item) => item.label === _t("g.delete")); - if (deleteItems.length === 1) { - let items = menuItems.filter((item) => item.label !== ""); - menuItems = items; - } - let updatedItems: MenuItem[] = []; - menuItems.forEach((item) => { - if ( - item.label === _t("entry-menu.promote") || - item.label === _t("entry-menu.boost") || - item.label === _t("entry-menu.pin") || - item.label === _t("entry-menu.unpin") - ) { - updatedItems.unshift(item); - } else { - updatedItems.push(item); - } - }); - menuItems = updatedItems; - } - - const menuConfig = { - history: this.props.history, - label: "", - icon: dotsHorizontal, - items: menuItems - }; - - const { cross, share, editHistory, delete_, pin, unpin, mute, promote, boost } = this.state; - // const community = this.getCommunity(); - - return ( -
- {separatedSharing && ( -
-
- {shareVariantSvg} + return ( +
+ {separatedSharing && ( +
+
setShare(false)}> + {shareVariantSvg} +
+
+
{ + shareReddit(entry); + }} + > + {redditSvg} +
+
{ + shareTwitter(entry); + }} + > + {twitterSvg}
-
-
{ - shareReddit(entry); - }} - > - {redditSvg} -
-
{ - shareTwitter(entry); - }} - > - {twitterSvg} -
-
{ - shareFacebook(entry); - }} - > - {facebookSvg} -
+
{ + shareFacebook(entry); + }} + > + {facebookSvg}
- )} - - - {activeUser && cross && ( - { - this.toggleCross(); - - const { history } = this.props; - history.push(`/created/${community}`); - }} - /> - )} - {share && } - {editHistory && } - {delete_ && ( - { - this.delete(); - this.toggleDelete(); - }} - onCancel={this.toggleDelete} - /> - )} - {pin && ( - { - if (this.state.pinKey === "community") { - this.pinToCommunity(true); - } else if (this.state.pinKey === "blog") { - this.pinToBlog(true); - } - // this.pin(true); - this.togglePin(); - }} - onCancel={this.togglePin} - /> - )} - {unpin && ( - { - if (this.state.pinKey === "community") { - this.pinToCommunity(false); - } else if (this.state.pinKey === "blog") { - this.pinToBlog(false); - } - // this.pin(false); - this.toggleUnpin(); - }} - onCancel={this.toggleUnpin} - /> - )} - {community && - activeUser && - mute && - MuteBtn({ - community, - entry, - activeUser: activeUser, - onlyDialog: true, - onSuccess: (entry, mute) => { - const { updateEntry } = this.props; - updateEntry(entry); - this.toggleMute(); - - if (pin) { - success(_t("entry-menu.mute-success")); - } else { - success(_t("entry-menu.unmute-success")); - } - }, - onCancel: this.toggleMute - })} - {activeUser && promote && ( - - )} - {activeUser && boost && ( - - )} -
- ); - } -} - -export default ( - p: Pick< - Props, - | "entry" - | "history" - | "separatedSharing" - | "alignBottom" - | "extraMenuItems" - | "toggleEdit" - | "pinEntry" - > -) => { - const { - global, - activeUser, - communities, - entryPinTracker, - dynamicProps, - signingKey, - setSigningKey, - addAccount, - updateActiveUser, - updateEntry, - addCommunity, - trackEntryPin, - setEntryPin, - toggleUIProp - } = useMappedStore(); - - const props: Props = { - history: p.history, - global, - dynamicProps, - activeUser, - entry: p.entry, - communities, - entryPinTracker, - separatedSharing: p.separatedSharing, - alignBottom: p.alignBottom, - signingKey, - extraMenuItems: p.extraMenuItems, - setSigningKey, - addAccount, - updateActiveUser, - updateEntry, - addCommunity, - trackEntryPin, - setEntryPin, - toggleUIProp, - toggleEdit: p.toggleEdit, - pinEntry: p.pinEntry - }; - - return ; +
+ )} + + + {activeUser && cross && ( + setCross(false)} + onSuccess={(community) => { + setCross(false); + history.push(`/created/${community}`); + }} + /> + )} + {share && setShare(false)} />} + {editHistory && setEditHistory(false)} />} + {delete_ && ( + { + deleteAction(); + setDelete_(false); + }} + onCancel={() => setDelete_(false)} + /> + )} + {pin && ( + { + if (pinKey === "community") { + pinToCommunity(true); + } else if (pinKey === "blog") { + pinToBlog(true); + } + setPin(false); + setPinKey(""); + }} + onCancel={() => { + setPin(false); + setPinKey(""); + }} + /> + )} + {unpin && ( + { + if (pinKey === "community") { + pinToCommunity(false); + } else if (pinKey === "blog") { + pinToBlog(false); + } + setUnpin(false); + setPinKey(""); + }} + onCancel={() => { + setUnpin(false); + setPinKey(""); + }} + /> + )} + {community && + activeUser && + mute && + MuteBtn({ + community, + entry, + activeUser: activeUser, + onlyDialog: true, + onSuccess: (entry, mute) => { + updateEntry(entry); + setMute(false); + + if (pin) { + success(_t("entry-menu.mute-success")); + } else { + success(_t("entry-menu.unmute-success")); + } + }, + onCancel: () => setMute(false) + })} + {activeUser && promote && ( + setPromote(false)} + global={global} + signingKey={signingKey} + setSigningKey={setSigningKey} + updateActiveUser={updateActiveUser} + /> + )} + {activeUser && boost && ( + setBoost(false)} + dynamicProps={dynamicProps} + updateActiveUser={updateActiveUser} + signingKey={signingKey} + setSigningKey={setSigningKey} + global={global} + /> + )} +
+ ); }; + +export default EntryMenu; diff --git a/src/common/components/entry-menu/menu-items-generator.ts b/src/common/components/entry-menu/menu-items-generator.ts new file mode 100644 index 00000000000..86cb6990598 --- /dev/null +++ b/src/common/components/entry-menu/menu-items-generator.ts @@ -0,0 +1,250 @@ +import { useEffect, useState } from "react"; +import { MenuItem } from "../dropdown"; +import { _t } from "../../i18n"; +import { + bullHornSvg, + deleteForeverSvg, + historySvg, + linkVariantSvg, + pencilOutlineSvg, + pinSvg, + rocketLaunchSvg, + shareVariantSvg, + shuffleVariantSvg, + volumeOffSvg +} from "../../img/svg"; +import { Entry } from "../../store/entries/types"; +import { useMappedStore } from "../../store/use-mapped-store"; +import { Community, ROLES } from "../../store/communities/types"; +import clipboard from "../../util/clipboard"; +import { success } from "../feedback"; +import { FullAccount } from "../../store/accounts/types"; +import { History } from "history"; +import isCommunity from "../../helper/is-community"; +import { useCommunityPinCache } from "../../core"; + +export function useMenuItemsGenerator( + entry: Entry, + community: Community | null, + separatedSharing: boolean, + toggleEdit: (() => void) | undefined, + history: History, + extraMenuItems?: MenuItem[] +) { + const { activeUser, global, toggleUIProp } = useMappedStore(); + const { data: isPinned } = useCommunityPinCache(entry); + + const [cross, setCross] = useState(false); + const [share, setShare] = useState(false); + const [editHistory, setEditHistory] = useState(false); + const [delete_, setDelete_] = useState(false); + const [pin, setPin] = useState(false); + const [pinKey, setPinKey] = useState(""); + const [unpin, setUnpin] = useState(false); + const [mute, setMute] = useState(false); + const [promote, setPromote] = useState(false); + const [boost, setBoost] = useState(false); + const [canMute, setCanMute] = useState(false); + const [menuItems, setMenuItems] = useState([]); + + useEffect(() => { + generate(); + }, []); + + useEffect(() => { + generate(); + }, [isPinned, activeUser, global, community, canMute, separatedSharing, extraMenuItems]); + + useEffect(() => { + setCanMute( + activeUser && community + ? !!community.team.find( + (m) => + m[0] === activeUser.username && + [ROLES.OWNER.toString(), ROLES.ADMIN.toString(), ROLES.MOD.toString()].includes(m[1]) + ) + : false + ); + }, [activeUser]); + + const generate = () => { + const isComment = !!entry.parent_author; + const isOwn = !!activeUser && activeUser.username === entry.author; + const isCross = activeUser && !isComment && isCommunity(entry.category); + const isDeletable = isOwn && !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout); + const activeUserWithProfile = activeUser?.data as FullAccount; + const profile = activeUserWithProfile && activeUserWithProfile.profile; + const canUnpinCommunity = isTeamManager() && isPinned; + const canUnpinBlog = isOwn && entry.permlink === profile?.pinned; + const canPinCommunity = isTeamManager() && !canUnpinCommunity; + const canPinBlog = isOwn && !canUnpinBlog; + + setMenuItems([ + ...(isOwn + ? [ + { + label: _t("g.edit"), + onClick: + isComment && toggleEdit + ? toggleEdit + : () => history.push(`/@${entry.author}/${entry.permlink}/edit`), + icon: pencilOutlineSvg + } + ] + : []), + ...(isCross + ? [ + { + label: _t("entry-menu.cross-post"), + onClick: () => setCross(!cross), + icon: shuffleVariantSvg + } + ] + : []), + ...(canMute + ? [ + { + label: !!entry.stats?.gray ? _t("entry-menu.unmute") : _t("entry-menu.mute"), + onClick: () => setMute(!mute), + icon: volumeOffSvg + } + ] + : []), + ...(extraMenuItems ?? []), + ...(global.usePrivate + ? [ + { + label: _t("entry-menu.edit-history"), + onClick: () => setEditHistory(!editHistory), + icon: historySvg + }, + { + label: _t("entry-menu.promote"), + onClick: + activeUser !== null ? () => setPromote(!promote) : () => toggleUIProp("login"), + icon: bullHornSvg + }, + { + label: _t("entry-menu.boost"), + onClick: activeUser !== null ? () => setBoost(!boost) : () => toggleUIProp("login"), + icon: rocketLaunchSvg + }, + { + label: _t("entry.address-copy"), + onClick: copyAddress, + icon: linkVariantSvg + } + ] + : []), + ...(!separatedSharing + ? [ + { + label: _t("entry-menu.share"), + onClick: () => setShare(!share), + icon: shareVariantSvg + } + ] + : []), + ...(canUnpinCommunity + ? [ + { + label: _t("entry-menu.unpin-from-community"), + onClick: () => toggleUnpin("community"), + icon: pinSvg + } + ] + : []), + ...(canUnpinBlog + ? [ + { + label: _t("entry-menu.unpin-from-blog"), + onClick: () => toggleUnpin("blog"), + icon: pinSvg + } + ] + : []), + ...(canPinCommunity + ? [ + { + label: _t("entry-menu.pin-to-community"), + onClick: () => togglePin("community"), + icon: pinSvg + } + ] + : []), + ...(canPinBlog + ? [ + { + label: _t("entry-menu.pin-to-blog"), + onClick: () => togglePin("blog"), + icon: pinSvg + } + ] + : []), + ...(isDeletable + ? [ + { + label: _t("g.delete"), + onClick: () => setDelete_(!delete_), + icon: deleteForeverSvg + } + ] + : []) + ]); + }; + + const copyAddress = () => { + let u; + if (activeUser?.username) { + u = `https://ecency.com/${entry.category}/@${entry.author}/${entry.permlink}?referral=${activeUser.username}`; + } else { + u = `https://ecency.com/${entry.category}/@${entry.author}/${entry.permlink}`; + } + clipboard(u); + success(_t("entry.address-copied")); + }; + + const togglePin = (key = "") => { + setPin(!pin); + setPinKey(key); + }; + + const toggleUnpin = (key = "") => { + setUnpin(!unpin); + setPinKey(key); + }; + + const isTeamManager = () => + activeUser && community + ? !!community.team.find((m) => { + return ( + m[0] === activeUser.username && + [ROLES.OWNER.toString(), ROLES.ADMIN.toString(), ROLES.MOD.toString()].includes(m[1]) + ); + }) + : false; + + return { + menuItems, + cross, + setCross, + share, + setShare, + editHistory, + setEditHistory, + delete_, + setDelete_, + pin, + setPin, + pinKey, + setPinKey, + unpin, + setUnpin, + mute, + setMute, + promote, + setPromote, + boost, + setBoost + }; +} diff --git a/src/common/components/entry-read-time/index.tsx b/src/common/components/entry-read-time/index.tsx index 2f42be30f8f..e9c4f88892d 100644 --- a/src/common/components/entry-read-time/index.tsx +++ b/src/common/components/entry-read-time/index.tsx @@ -1,9 +1,6 @@ import React, { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import { OverlayTrigger, Tooltip } from "react-bootstrap"; -import { getActiveVotes } from "../../api/hive"; - -import { prepareVotes } from "../entry-votes"; import { _t } from "../../i18n"; import { informationVariantSvg } from "../../img/svg"; @@ -28,10 +25,14 @@ export const ReadTime = (props: any) => { }, [entry]); const getTopCurator = async () => { - const curator = props.entry.active_votes.reduce((prev: ActiveVotes, curr: ActiveVotes) => { - return prev.rshares! > curr.rshares! ? prev : curr; - }); - setTopCurator(curator.voter); + if (entry.active_votes?.length > 0) { + const curator = + entry.active_votes && + entry.active_votes.reduce((prev: ActiveVotes, curr: ActiveVotes) => { + return prev.rshares! > curr.rshares! ? prev : curr; + }); + setTopCurator(curator.voter); + } }; const calculateExtras = async () => { diff --git a/src/common/components/entry-vote-btn/index.spec.tsx b/src/common/components/entry-vote-btn/index.spec.tsx index ea6ab5a25df..8e903468296 100644 --- a/src/common/components/entry-vote-btn/index.spec.tsx +++ b/src/common/components/entry-vote-btn/index.spec.tsx @@ -64,6 +64,9 @@ describe("(1) Dialog", () => { account: accountFull, isPostSlider: false, previousVotedValue: null, + isVoted: () => { + return { upVoted: true, downVoted: false }; + }, onClick: () => {}, setTipDialogMounted: () => {}, updateWalletValues: () => {}, diff --git a/src/common/components/entry-vote-btn/index.tsx b/src/common/components/entry-vote-btn/index.tsx index e10b8bb7a2a..706aca40a78 100644 --- a/src/common/components/entry-vote-btn/index.tsx +++ b/src/common/components/entry-vote-btn/index.tsx @@ -84,6 +84,7 @@ interface VoteDialogProps { updateWalletValues: () => void; onClick: (percent: number, estimated: number) => void; handleClickAway: () => void; + isVoted: () => { upVoted: boolean; downVoted: boolean }; } interface VoteDialogState { @@ -232,22 +233,6 @@ export class VoteDialog extends Component { this.setState({ mode: m }); }; - isVoted = () => { - const { activeUser } = this.props; - - if (!activeUser) { - return { upVoted: false, downVoted: false }; - } - - const { active_votes: votes } = this.props.entry; - - const upVoted = votes && votes.some((v) => v.voter === activeUser.username && v.rshares >= 0); - - const downVoted = votes && votes.some((v) => v.voter === activeUser.username && v.rshares < 0); - - return { upVoted, downVoted }; - }; - upVoteClicked = () => { const { onClick, @@ -256,7 +241,7 @@ export class VoteDialog extends Component { entry: { post_id } } = this.props; const { upSliderVal, initialVoteValues } = this.state; - const { upVoted } = this.isVoted(); + const { upVoted } = this.props.isVoted(); if (!upVoted || (upVoted && initialVoteValues.up !== upSliderVal)) { const estimated = Number(this.estimate(upSliderVal).toFixed(3)); onClick(upSliderVal, estimated); @@ -280,7 +265,7 @@ export class VoteDialog extends Component { entry: { post_id } } = this.props; const { downSliderVal, initialVoteValues } = this.state; - const { downVoted } = this.isVoted(); + const { downVoted } = this.props.isVoted(); if (!downVoted || (downVoted && initialVoteValues.down !== downSliderVal)) { const estimated = Number(this.estimate(downSliderVal).toFixed(3)); @@ -507,11 +492,11 @@ export class EntryVoteBtn extends BaseComponent { if (!activeUser) { return { upVoted: false, downVoted: false }; } - const { active_votes: votes } = this.props.entry; - - const upVoted = votes && votes.some((v) => v.voter === activeUser.username && v.rshares > 0); + const { active_votes: votes } = this.props.entry; + const upVoted = votes && votes.some((v) => v.voter === activeUser.username && v.rshares >= 0); const downVoted = votes && votes.some((v) => v.voter === activeUser.username && v.rshares < 0); + return { upVoted, downVoted }; }; @@ -603,6 +588,7 @@ export class EntryVoteBtn extends BaseComponent { } ${inProgress ? "in-progress" : ""} voted` ); } + let tooltipClass = ""; if (dialog) { if (!upVoted || !downVoted) { @@ -658,6 +644,7 @@ export class EntryVoteBtn extends BaseComponent { updateWalletValues={this.ensureAccount} onClick={this.vote} handleClickAway={this.handleClickAway} + isVoted={this.isVoted} />
diff --git a/src/common/components/entry-votes/__snapshots__/index.spec.tsx.snap b/src/common/components/entry-votes/__snapshots__/index.spec.tsx.snap index ac20d7d7115..b30dcddb64c 100644 --- a/src/common/components/entry-votes/__snapshots__/index.spec.tsx.snap +++ b/src/common/components/entry-votes/__snapshots__/index.spec.tsx.snap @@ -65,7 +65,7 @@ Array [ className="fade alert alert-warning show" role="alert" > - You have pending votes. Please, wait a minute and re-open this dialog to see your vote. + Content has pending votes. Please, wait a minute and refresh this dialog to see new votes.
,
- ($ - 12.000 + ( + Calculating in + + USD ) diff --git a/src/common/components/market-swap-form/api/currency-rate-query.tsx b/src/common/components/market-swap-form/api/currency-rate-query.tsx new file mode 100644 index 00000000000..4d1747ff5f9 --- /dev/null +++ b/src/common/components/market-swap-form/api/currency-rate-query.tsx @@ -0,0 +1,31 @@ +import { useQuery } from "@tanstack/react-query"; +import { QueryIdentifiers } from "../../../core"; +import { MarketAsset } from "../market-pair"; +import { getCurrencyTokenRate } from "../../../api/private-api"; +import { useMappedStore } from "../../../store/use-mapped-store"; + +export function useCurrencyRateQuery(fromAsset: MarketAsset, toAsset: MarketAsset) { + const { global } = useMappedStore(); + + /** + * Show value till 2 digits in fraction + * @param value – source + * @returns formatted number + */ + const formatTillPresentDigits = (value: number) => { + const magnitude = -Math.floor(Math.log10(value) + 1); + return +value.toFixed(magnitude + 2); + }; + + return useQuery( + [QueryIdentifiers.SWAP_FORM_CURRENCY_RATE, global.currency, fromAsset, toAsset], + async () => { + const fromAccountRate = await getCurrencyTokenRate(global.currency, fromAsset); + const toAccountRate = await getCurrencyTokenRate(global.currency, toAsset); + return [formatTillPresentDigits(fromAccountRate), formatTillPresentDigits(toAccountRate)]; + }, + { + refetchInterval: 30000 // in ms + } + ); +} diff --git a/src/common/components/market-swap-form/index.tsx b/src/common/components/market-swap-form/index.tsx index 1f2d3818685..078f2c883bd 100644 --- a/src/common/components/market-swap-form/index.tsx +++ b/src/common/components/market-swap-form/index.tsx @@ -7,7 +7,6 @@ import { MarketAsset, MarketPairs } from "./market-pair"; import { ActiveUser } from "../../store/active-user/types"; import { getBalance } from "./api/get-balance"; import { getHiveMarketRate, HiveMarketRateListener } from "./api/hive"; -import { getCGMarket } from "./api/coingecko-api"; import { MarketSwapFormStep } from "./form-step"; import { SignMethods } from "./sign-methods"; import { Global } from "../../store/global/types"; @@ -16,6 +15,9 @@ import { checkSvg, swapSvg } from "../../img/svg"; import { MarketSwapFormSuccess } from "./market-swap-form-success"; import "./index.scss"; import { classNameObject } from "../../helper/class-name-object"; +import { useCurrencyRateQuery } from "./api/currency-rate-query"; +import { useQueryClient } from "@tanstack/react-query"; +import { QueryIdentifiers } from "../../core"; export interface Props { activeUser: ActiveUser | null; @@ -48,8 +50,12 @@ export const MarketSwapForm = ({ const [balance, setBalance] = useState(""); const [marketRate, setMarketRate] = useState(0); - const [usdFromMarketRate, setUsdFromMarketRate] = useState(0); - const [usdToMarketRate, setUsdToMarketRate] = useState(0); + + /** + * These rates use for showing from asset = to asset in account currency(see account settings) + */ + const [accountFromMarketRate, setAccountFromMarketRate] = useState(0); + const [accountToMarketRate, setAccountToMarketRate] = useState(0); const [disabled, setDisabled] = useState(false); const [isAmountMoreThanBalance, setIsAmountMoreThanBalance] = useState(false); @@ -58,10 +64,33 @@ export const MarketSwapForm = ({ const [tooMuchSlippage, setTooMuchSlippage] = useState(false); + const { data } = useCurrencyRateQuery(fromAsset, toAsset); + const query = useQueryClient(); + useEffect(() => { fetchMarket(); }, []); + useEffect(() => { + fetchMarket(); + }, [global.currency]); + + useEffect(() => { + query.invalidateQueries([ + QueryIdentifiers.SWAP_FORM_CURRENCY_RATE, + global.currency, + fromAsset, + toAsset + ]); + }, [fromAsset, toAsset, global.currency]); + + useEffect(() => { + if (data) { + setAccountFromMarketRate(data[0]); + setAccountToMarketRate(data[1]); + } + }, [data]); + useEffect(() => { if (activeUser) setBalance(getBalance(fromAsset, activeUser)); }, [activeUser]); @@ -82,8 +111,8 @@ export const MarketSwapForm = ({ getHiveMarketRate(fromAsset).then((rate) => setMarketRate(rate)); if (activeUser) setBalance(getBalance(fromAsset, activeUser)); - setUsdFromMarketRate(usdToMarketRate); - setUsdToMarketRate(usdFromMarketRate); + setAccountFromMarketRate(accountToMarketRate); + setAccountToMarketRate(accountFromMarketRate); }, [fromAsset]); const swap = () => { @@ -98,10 +127,6 @@ export const MarketSwapForm = ({ setDisabled(true); setMarketRate(await getHiveMarketRate(fromAsset)); setDisabled(false); - - const [fromUsdRate, toUsdRate] = await getCGMarket(fromAsset, toAsset); - setUsdFromMarketRate(fromUsdRate); - setUsdToMarketRate(toUsdRate); }; const submit = () => { @@ -168,7 +193,7 @@ export const MarketSwapForm = ({ value={from} setValue={(v) => setFrom(v)} setAsset={(v) => setFromAsset(v)} - usdRate={usdFromMarketRate} + usdRate={accountFromMarketRate} disabled={ step === MarketSwapFormStep.SIGN || step === MarketSwapFormStep.SUCCESS || @@ -220,7 +245,7 @@ export const MarketSwapForm = ({ value={to} setValue={(v) => setTo(v)} setAsset={(v) => setToAsset(v)} - usdRate={usdToMarketRate} + usdRate={accountToMarketRate} disabled={true} hideChevron={true} /> @@ -229,7 +254,7 @@ export const MarketSwapForm = ({ marketRate={marketRate} toAsset={toAsset} fromAsset={fromAsset} - usdFromMarketRate={usdFromMarketRate} + usdFromMarketRate={accountFromMarketRate} />
{isInvalidFrom ? ( diff --git a/src/common/components/market-swap-form/market-info.spec.tsx b/src/common/components/market-swap-form/market-info.spec.tsx index 8a492c6ee10..22dda592fe9 100644 --- a/src/common/components/market-swap-form/market-info.spec.tsx +++ b/src/common/components/market-swap-form/market-info.spec.tsx @@ -1,7 +1,9 @@ import { MarketInfo, Props } from "./market-info"; import { MarketAsset } from "./market-pair"; -import renderer from "react-test-renderer"; import React from "react"; +import { withStore } from "../../tests/with-store"; +import { queryClient } from "../../core"; +import { QueryClientProvider } from "@tanstack/react-query"; it("should render market rate", function () { const props: Props = { @@ -11,6 +13,10 @@ it("should render market rate", function () { toAsset: MarketAsset.HIVE, usdFromMarketRate: 12 }; - const component = renderer.create(); + const component = withStore( + + + + ); expect(component.toJSON()).toMatchSnapshot(); }); diff --git a/src/common/components/market-swap-form/market-info.tsx b/src/common/components/market-swap-form/market-info.tsx index f21cd5a830a..f55b2252122 100644 --- a/src/common/components/market-swap-form/market-info.tsx +++ b/src/common/components/market-swap-form/market-info.tsx @@ -2,6 +2,8 @@ import React from "react"; import { _t } from "../../i18n"; import { ListGroup, ListGroupItem } from "react-bootstrap"; import { MarketAsset } from "./market-pair"; +import { useMappedStore } from "../../store/use-mapped-store"; +import { useCurrencyRateQuery } from "./api/currency-rate-query"; export interface Props { className: string; @@ -18,11 +20,22 @@ export const MarketInfo = ({ marketRate, usdFromMarketRate }: Props) => { + const { global } = useMappedStore(); + const { isFetching, isError } = useCurrencyRateQuery(fromAsset, toAsset); + return (
1 {fromAsset} = {marketRate.toFixed(3)} {toAsset} - (${usdFromMarketRate.toFixed(3)}) + {isError ? ( + <> + ) : ( + + ({isFetching ? _t("market.calculating-in") : usdFromMarketRate} + + {global.currency.toUpperCase()}) + + )} diff --git a/src/common/components/market-swap-active-orders/generic-order-item.tsx b/src/common/components/market-swap-form/market-swap-active-orders/generic-order-item.tsx similarity index 82% rename from src/common/components/market-swap-active-orders/generic-order-item.tsx rename to src/common/components/market-swap-form/market-swap-active-orders/generic-order-item.tsx index 9555973cabc..acf570d33fa 100644 --- a/src/common/components/market-swap-active-orders/generic-order-item.tsx +++ b/src/common/components/market-swap-form/market-swap-active-orders/generic-order-item.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { arrowRightSvg } from "../../img/svg"; -import { dateToFullRelative } from "../../helper/parse-date"; +import { arrowRightSvg } from "../../../img/svg"; +import { dateToFullRelative } from "../../../helper/parse-date"; import { Button } from "react-bootstrap"; -import { _t } from "../../i18n"; +import { _t } from "../../../i18n"; interface Props { from: string; diff --git a/src/common/components/market-swap-active-orders/index.scss b/src/common/components/market-swap-form/market-swap-active-orders/index.scss similarity index 100% rename from src/common/components/market-swap-active-orders/index.scss rename to src/common/components/market-swap-form/market-swap-active-orders/index.scss diff --git a/src/common/components/market-swap-active-orders/index.tsx b/src/common/components/market-swap-form/market-swap-active-orders/index.tsx similarity index 85% rename from src/common/components/market-swap-active-orders/index.tsx rename to src/common/components/market-swap-form/market-swap-active-orders/index.tsx index b5fd1cca5ec..a3bac87988a 100644 --- a/src/common/components/market-swap-active-orders/index.tsx +++ b/src/common/components/market-swap-form/market-swap-active-orders/index.tsx @@ -1,11 +1,11 @@ import React, { useEffect, useState } from "react"; import { FormLabel, ListGroup, ListGroupItem } from "react-bootstrap"; -import { ActiveUser } from "../../store/active-user/types"; -import { getOpenOrder, OpenOrdersData } from "../../api/hive"; +import { ActiveUser } from "../../../store/active-user/types"; +import { getOpenOrder, OpenOrdersData } from "../../../api/hive"; import { GenericOrderItem } from "./generic-order-item"; -import { _t } from "../../i18n"; -import BuySellHiveDialog, { TransactionType } from "../buy-sell-hive"; -import { Global } from "../../store/global/types"; +import { _t } from "../../../i18n"; +import BuySellHiveDialog, { TransactionType } from "../../buy-sell-hive"; +import { Global } from "../../../store/global/types"; import "./index.scss"; interface Props { diff --git a/src/common/components/market-swap-form/swap-mode.tsx b/src/common/components/market-swap-form/swap-mode.tsx index d464b91b3bd..ae5a27f42e2 100644 --- a/src/common/components/market-swap-form/swap-mode.tsx +++ b/src/common/components/market-swap-form/swap-mode.tsx @@ -1,9 +1,9 @@ import React from "react"; -import { MarketSwapForm } from "../../components/market-swap-form"; +import { MarketSwapForm } from "./index"; import { Button, Col, Row } from "react-bootstrap"; import { _t } from "../../i18n"; import { Link } from "react-router-dom"; -import { MarketSwapActiveOrders } from "../../components/market-swap-active-orders"; +import { MarketSwapActiveOrders } from "./market-swap-active-orders"; import { useMappedStore } from "../../store/use-mapped-store"; import "./_swap-mode.scss"; diff --git a/src/common/components/open-orders/__snapshots__/index.spec.tsx.snap b/src/common/components/open-orders/__snapshots__/index.spec.tsx.snap index abc5e874e12..c5dad2d8358 100644 --- a/src/common/components/open-orders/__snapshots__/index.spec.tsx.snap +++ b/src/common/components/open-orders/__snapshots__/index.spec.tsx.snap @@ -37,7 +37,7 @@ exports[`(1) Open orders render default 1`] = ` - 23 years ago + 24 years ago ([]); + const [hashes, setHashes] = useState([]); + + useEffect(() => { + lazyBuild(); + }, []); + useEffect(() => { + lazyBuild(); + }, [rawBody]); + + const lazyBuild = () => { + const renderedBody = renderPostBody(rawBody); + const tree = document.createElement("div"); + tree.innerHTML = renderedBody; + + const nextHashes: string[] = []; + const linesToRender: number[] = []; + const nextLines: Element[] = []; + + for (let i = 0; i < tree.children.length; i++) { + const child = tree.children.item(i)!!; + + const hash = md5(child.innerHTML); + const existingHash = hashes[i]; + + if (hash !== existingHash) { + linesToRender.push(i); + } + + nextHashes.push(hash); + nextLines.push(child); + } + + setHashes(nextHashes); + setResult(nextLines); + }; + + return ( +
+ {result.map((line, i) => ( +

+ ))} +

+ ); +} diff --git a/src/common/components/preferences/__snapshots__/index.spec.tsx.snap b/src/common/components/preferences/__snapshots__/index.spec.tsx.snap index 4c7f42ec408..415de778eb8 100644 --- a/src/common/components/preferences/__snapshots__/index.spec.tsx.snap +++ b/src/common/components/preferences/__snapshots__/index.spec.tsx.snap @@ -343,7 +343,7 @@ exports[`(1) Default render 1`] = ` type="button" > { const [voteAmount, setVoteAmount] = useState(0); const [transferAmount, setTransferAmount] = useState(0); const [customJsonAmount, setCustomJsonAmount] = useState(0); + const [claimAccountAmount, setClaimAccountAmount] = useState(0); const showModal = () => { fetchRCData(); @@ -98,6 +99,7 @@ export const ResourceCreditsInfo = (props: any) => { const transferCost = operationCosts.transfer_operation.avg_cost; const voteCost = operationCosts.vote_operation.avg_cost; const customJsonOperationsCosts = operationCosts.custom_json_operation.avg_cost; + const createClaimAccountCost = Number(operationCosts.claim_account_operation.avg_cost); const commentCount: number = Math.ceil(Number(availableResourceCredit) / commentCost); const votetCount: number = Math.ceil(Number(availableResourceCredit) / voteCost); @@ -105,10 +107,14 @@ export const ResourceCreditsInfo = (props: any) => { const customJsonCount: number = Math.ceil( Number(availableResourceCredit) / customJsonOperationsCosts ); + const createClaimAccountCount: number = Math.floor( + Number(availableResourceCredit) / createClaimAccountCost + ); setCommentAmount(commentCount); setVoteAmount(votetCount); setTransferAmount(transferCount); setCustomJsonAmount(customJsonCount); + setClaimAccountAmount(createClaimAccountCount); }; rcOperationsCost(); }) @@ -217,6 +223,7 @@ export const ResourceCreditsInfo = (props: any) => {
  • {`${_t("rc-info.votes")} ${voteAmount}`}
  • {`${_t("rc-info.transfers")} ${transferAmount}`}
  • {`${_t("rc-info.reblogs-follows")} ${customJsonAmount}`}
  • +
  • {`${_t("rc-info.claim-accounts")} ${claimAccountAmount}`}
  • diff --git a/src/common/components/similar-entries/index.tsx b/src/common/components/similar-entries/index.tsx index 340e94cfc56..43d85d96566 100644 --- a/src/common/components/similar-entries/index.tsx +++ b/src/common/components/similar-entries/index.tsx @@ -65,7 +65,7 @@ export class SimilarEntries extends BaseComponent { // 3 tags and decrease until there is enough relevant posts if (json_metadata && json_metadata.tags && Array.isArray(json_metadata.tags)) { tags = json_metadata.tags - .filter((x: string) => x !== "") + .filter((x: string) => x && x !== "") .filter((x: string) => !isCommunity(x)) .filter((x: string, ind: number) => ind < retry) .join(","); diff --git a/src/common/components/static/static-navbar.tsx b/src/common/components/static/static-navbar.tsx index 3ca4372c859..12878754545 100644 --- a/src/common/components/static/static-navbar.tsx +++ b/src/common/components/static/static-navbar.tsx @@ -11,7 +11,7 @@ export const StaticNavbar = ({ fullVersionUrl }: Props) => {
    Logo {
    Logo([QueryIdentifiers.COMMUNITY, category], { + queryFn: () => (isCommunity(category) ? bridgeApi.getCommunity(category) : null), + initialData: null + }); + + useEffect(() => { + if (invalidate) { + client.invalidateQueries([QueryIdentifiers.COMMUNITY, category]); + } + }, []); + + return query; +} diff --git a/src/common/core/caches/entries-cache.tsx b/src/common/core/caches/entries-cache.tsx index 8d5e8e3884c..6104053af75 100644 --- a/src/common/core/caches/entries-cache.tsx +++ b/src/common/core/caches/entries-cache.tsx @@ -1,8 +1,17 @@ -import React, { createContext, useContext, useState } from "react"; -import { useQuery, useQueryClient } from "@tanstack/react-query"; +import React, { createContext, useContext, useEffect, useState } from "react"; +import { + DefinedQueryObserverResult, + useMutation, + useQuery, + useQueryClient +} from "@tanstack/react-query"; import { Entry, EntryVote } from "../../store/entries/types"; -import { QueryIdentifiers } from "../react-query"; +import { queryClient, QueryIdentifiers } from "../react-query"; import { makePath } from "../../components/entry-link"; +import * as bridgeApi from "../../api/bridge"; +import { useMappedStore } from "../../store/use-mapped-store"; +import dmca from "../../constants/dmca.json"; +import { commentHistory } from "../../api/private-api"; export const EntriesCacheContext = createContext<{ getByLink: (link: string) => Entry | undefined; @@ -24,21 +33,27 @@ export const EntriesCacheManager = ({ children }: { children: any }) => { const queryClient = useQueryClient(); const updateCache = (entries: Entry[], skipInvalidation = false) => { - entries.forEach((e) => cache.set(makePath(e.category, e.author, e.permlink), e)); + entries.forEach((e) => { + if (dmca.some((rx: string) => new RegExp(rx).test(`${e.author}/${e.permlink}`))) { + e.body = "This post is not available due to a copyright/fraudulent claim."; + e.title = ""; + } + cache.set(makePath("", e.author, e.permlink), e); + }); if (!skipInvalidation) { // Invalidate queries which fetches entry details(only after cache updating) entries.forEach((entry) => queryClient.invalidateQueries([ QueryIdentifiers.ENTRY, - makePath(entry.category, entry.author, entry.permlink) + makePath("", entry.author, entry.permlink) ]) ); } }; const addReply = (entry: Entry, reply: Entry) => { - const cached = cache.get(makePath(entry.category, entry.author, entry.permlink))!!; + const cached = cache.get(makePath("", entry.author, entry.permlink))!!; updateCache([ { @@ -52,7 +67,7 @@ export const EntriesCacheManager = ({ children }: { children: any }) => { const updateRepliesCount = (entry: Entry, count: number) => { updateCache([ { - ...cache.get(makePath(entry.category, entry.author, entry.permlink))!!, + ...cache.get(makePath("", entry.author, entry.permlink))!!, children: count } ]); @@ -62,12 +77,14 @@ export const EntriesCacheManager = ({ children }: { children: any }) => { return cache.get(link); }; - const updateVotes = (entry: Entry, votes: EntryVote[], estimated: number) => { + const updateVotes = (entry: Entry, votes: EntryVote[], payout: number) => { updateCache([ { - ...cache.get(makePath(entry.category, entry.author, entry.permlink))!!, + ...cache.get(makePath("", entry.author, entry.permlink))!!, active_votes: votes, - total_votes: votes.length + total_votes: votes.length, + payout, + pending_payout_value: String(payout) } ]); }; @@ -81,26 +98,110 @@ export const EntriesCacheManager = ({ children }: { children: any }) => { ); }; -export function useEntryCache(initialEntry: T) { - const { getByLink } = useContext(EntriesCacheContext); +export function useEntryReFetch(entry: Entry | null) { + const [key, setKey] = useState(""); + + useEffect(() => { + if (entry) { + setKey(makePath(entry.category, entry.author, entry.permlink)); + } + }, [entry]); + + return useMutation( + ["FETCH_ENTRY", key], + () => bridgeApi.getPost(entry?.author, entry?.permlink), + { + onSuccess: (response) => queryClient.setQueryData([QueryIdentifiers.ENTRY, key], response) + } + ); +} +export function useDeletedEntryCache(author: string, permlink: string) { return useQuery( - [ - QueryIdentifiers.ENTRY, - makePath(initialEntry.category, initialEntry.author, initialEntry.permlink) - ], + [QueryIdentifiers.DELETED_ENTRY, makePath("", author, permlink)], + async () => { + const history = await commentHistory(author, permlink); + const { body, title, tags } = history.list[0]; + return { + body, + title, + tags + }; + }, { - initialData: initialEntry, - queryFn: () => { - const entry = getByLink( - makePath(initialEntry.category, initialEntry.author, initialEntry.permlink) - ) as T; - if (!entry) { - return initialEntry; - } + initialData: null, + refetchOnMount: false + } + ); +} + +export function useEntryCache(initialEntry: T): DefinedQueryObserverResult; +export function useEntryCache( + category: string, + author: string, + permlink: string +): DefinedQueryObserverResult; +export function useEntryCache( + initialOrPath: T | string, + author?: string, + permlink?: string +) { + const { getByLink, updateCache } = useContext(EntriesCacheContext); + const { addEntry, updateEntry, entries } = useMappedStore(); + + const queryKey = + typeof initialOrPath === "string" + ? makePath("", author!!, permlink!!) + : makePath("", initialOrPath.author, initialOrPath.permlink); + + const query = useQuery( + [QueryIdentifiers.ENTRY, queryKey], + async () => { + const entry = getByLink(queryKey) as T; - return entry; + if (!entry && typeof initialOrPath === "string") { + const response = await bridgeApi.getPost(author, permlink); + + // update cache value to getting from there next time + if (response) { + updateCache([response]); + } + return response; + } else if (!entry) { + updateCache([initialOrPath as T]); + return initialOrPath as T; } + + return entry; + }, + { + initialData: typeof initialOrPath === "string" ? null : initialOrPath } ); + + useEffect(() => { + if (query.data) { + if (getExistingEntryFromStore()) { + updateEntry(query.data); + } else { + addEntry(query.data); + } + } + }, [query.data]); + + const getExistingEntryFromStore = () => { + const groupKeys = Object.keys(entries); + let entry: Entry | undefined; + + for (const k of groupKeys) { + entry = entries[k].entries.find((x) => x.author === author && x.permlink === permlink); + if (entry) { + break; + } + } + + return entry; + }; + + return query; } diff --git a/src/common/core/caches/index.ts b/src/common/core/caches/index.ts index 09cb56466c7..337c056d468 100644 --- a/src/common/core/caches/index.ts +++ b/src/common/core/caches/index.ts @@ -1 +1,3 @@ export * from "./entries-cache"; +export * from "./communities-cache"; +export * from "./pin-tracker-cache"; diff --git a/src/common/core/caches/pin-tracker-cache.ts b/src/common/core/caches/pin-tracker-cache.ts new file mode 100644 index 00000000000..a0d316340c9 --- /dev/null +++ b/src/common/core/caches/pin-tracker-cache.ts @@ -0,0 +1,49 @@ +import { Entry } from "../../store/entries/types"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { QueryIdentifiers } from "../react-query"; +import { dataLimit, getPostsRanked } from "../../api/bridge"; +import { pinPost } from "../../api/operations"; +import { useMappedStore } from "../../store/use-mapped-store"; +import { Community } from "../../store/communities/types"; +import isCommunity from "../../helper/is-community"; + +export function useCommunityPinCache(entry: Entry) { + const { data: rankedPosts } = useQuery( + [QueryIdentifiers.COMMUNITY_RANKED_POSTS, entry.category], + () => + isCommunity(entry.category) + ? getPostsRanked("created", "", "", dataLimit, entry.category) + : null, + { + initialData: null + } + ); + + return useQuery( + [QueryIdentifiers.ENTRY_PIN_TRACK, entry.post_id], + async () => + rankedPosts?.find( + (x) => + x.author === entry.author && x.permlink === entry.permlink && x.stats?.is_pinned === true + ) !== undefined, + { + initialData: false + } + ); +} + +export function useCommunityPin(entry: Entry, community: Community | null) { + const { activeUser } = useMappedStore(); + const queryClient = useQueryClient(); + + return useMutation( + ["PIN_COMMUNITY"], + (pin: boolean) => + pinPost(activeUser!.username, community!.name, entry.author, entry.permlink, pin), + { + onSuccess: (data, pin) => { + queryClient.setQueryData([QueryIdentifiers.ENTRY_PIN_TRACK, entry.post_id], pin); + } + } + ); +} diff --git a/src/common/core/react-query.ts b/src/common/core/react-query.ts index 2d38743c0af..54e78f83941 100644 --- a/src/common/core/react-query.ts +++ b/src/common/core/react-query.ts @@ -11,5 +11,13 @@ export const queryClient = new QueryClient({ export enum QueryIdentifiers { COMMUNITY_THREADS = "community-threads", THREADS = "threads", - ENTRY = "entry" + ENTRY = "entry", + DELETED_ENTRY = "deleted-entry", + ENTRY_PIN_TRACK = "entry-pin-track", + COMMUNITY = "community", + COMMUNITY_RANKED_POSTS = "community-ranked-posts", + DECK_USER = "deck-user", + DECK_COMMUNITY = "deck-community", + + SWAP_FORM_CURRENCY_RATE = "swap-form-currency-rate" } diff --git a/src/common/helper/onBoard-helper.ts b/src/common/helper/onBoard-helper.ts new file mode 100644 index 00000000000..d72582f0501 --- /dev/null +++ b/src/common/helper/onBoard-helper.ts @@ -0,0 +1,29 @@ +import { KeyRole, PrivateKey } from "@hiveio/dhive"; +import { randomBytes } from "crypto"; + +export const getPrivateKeys = (username: any, password: any) => { + const roles: Array = ["owner", "active", "posting", "memo"]; + type keysType = { + ownerPubkey: string; + activePubkey: string; + postingPubkey: string; + memoPubkey: string; + }; + const privKeys: keysType = { + ownerPubkey: "", + activePubkey: "", + postingPubkey: "", + memoPubkey: "" + }; + roles.forEach((role) => { + privKeys[role] = PrivateKey.fromLogin(username, password, role).toString(); + privKeys[`${role}Pubkey`] = PrivateKey.from(privKeys[role]).createPublic().toString(); + }); + + return privKeys; +}; + +export const generatePassword = async (length: number) => { + const password = `P${PrivateKey.fromSeed(randomBytes(length).toString("hex")).toString()}`; + return password; +}; diff --git a/src/common/helper/test-helper.ts b/src/common/helper/test-helper.ts index eeee157d6de..32144cced57 100644 --- a/src/common/helper/test-helper.ts +++ b/src/common/helper/test-helper.ts @@ -94,6 +94,7 @@ export const fullAccountInstance: FullAccount = { savings_hbd_balance: "0.002 HBD", savings_hbd_seconds: "1235678", next_vesting_withdrawal: "1969-12-31T23:59:59", + pending_claimed_accounts: 0, vesting_shares: "151590.952150 VESTS", delegated_vesting_shares: "145395.758709 VESTS", savings_hbd_last_interest_payment: "2021-03-18T15:42:03", @@ -949,7 +950,8 @@ export const dynamicPropsIntance1: DynamicProps = { totalVestingFund: 147530899.832, totalVestingShares: 274146627336.063918, virtualSupply: 395012207.852, - vestingRewardPercent: 1500 + vestingRewardPercent: 1500, + accountCreationFee: "3.000 HIVE" }; export const notificationsInstance1: Notifications = { diff --git a/src/common/i18n/locales/ac-ace.json b/src/common/i18n/locales/ac-ace.json index d57d22df167..0d89a4a2aea 100644 --- a/src/common/i18n/locales/ac-ace.json +++ b/src/common/i18n/locales/ac-ace.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Seuleuso", "apply": "Meupakek", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Yakin neuh?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topik" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Watee", "sort-reputation": "Reputasi", "sort-percent": "Persentase", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "root {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ar-SA.json b/src/common/i18n/locales/ar-SA.json index f11d6a80d53..2d0cf7f84ba 100644 --- a/src/common/i18n/locales/ar-SA.json +++ b/src/common/i18n/locales/ar-SA.json @@ -58,6 +58,7 @@ "replies": "ردود", "done": "تم", "apply": "تطبيق", + "applying": "Applying...", "warning": "تحذير", "payout": "الدفعة", "learn-more": "تعلم المزيد في", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "هل أنت متأكد؟", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "المواضيع" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "الوقت", "sort-reputation": "السمعة", "sort-percent": "النسبة المئوية", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "بواسطة {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "إكمال تلقائي للإدخال", "post-placeholder": "اسم المستخدم/الرابط", "post-error": "عنوان نشر غير صالح", - "post-error-exists": "المنشور معزز مسبقاً", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "تم إرسال طلبك. سيتم تفعيله في بضع دقائق." }, "transfer": { diff --git a/src/common/i18n/locales/az-AZ.json b/src/common/i18n/locales/az-AZ.json index 1e0be46c88c..d9e929c9a77 100644 --- a/src/common/i18n/locales/az-AZ.json +++ b/src/common/i18n/locales/az-AZ.json @@ -58,6 +58,7 @@ "replies": "cavablar", "done": "Hazırdır", "apply": "Tətbiq et", + "applying": "Applying...", "warning": "Xəbərdarlıq", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Əminsiniz?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Mövzular" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Vaxt", "sort-reputation": "Nüfuz", "sort-percent": "Faiz", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}} ilə", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Etibarlı bir göndəriş ünvanı deyil", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Tələbiniz göndərildi. Bir neçə dəqiqəyə aktivləşdiriləcək." }, "transfer": { diff --git a/src/common/i18n/locales/bg-BG.json b/src/common/i18n/locales/bg-BG.json index e4f0705e677..a1be77c7596 100644 --- a/src/common/i18n/locales/bg-BG.json +++ b/src/common/i18n/locales/bg-BG.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Готово", "apply": "Потвърди", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Научи повече от нашия", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Сигурни ли сте?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Tеми" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Време", "sort-reputation": "Репутация", "sort-percent": "Процент", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "чрез {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Автоматично дописване", "post-placeholder": "потребителско име/permlink", "post-error": "Няма такъв адрес на публикация", - "post-error-exists": "Поста вече е промотиран", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Вашата заявка беше изпратена. Ще бъде активирана след няколко минути." }, "transfer": { diff --git a/src/common/i18n/locales/bn-BD.json b/src/common/i18n/locales/bn-BD.json index ece95d83b8c..a07e16c27a9 100644 --- a/src/common/i18n/locales/bn-BD.json +++ b/src/common/i18n/locales/bn-BD.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/da-DK.json b/src/common/i18n/locales/da-DK.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/da-DK.json +++ b/src/common/i18n/locales/da-DK.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/de-DE.json b/src/common/i18n/locales/de-DE.json index 0adb236dc59..339907e1a38 100644 --- a/src/common/i18n/locales/de-DE.json +++ b/src/common/i18n/locales/de-DE.json @@ -58,6 +58,7 @@ "replies": "Antworten", "done": "Fertig", "apply": "Anwenden", + "applying": "Applying...", "warning": "Warnung", "payout": "Auszahlung", "learn-more": "Erfahre mehr in unserer", @@ -71,7 +72,8 @@ "settings": "Einstellungen", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Bist du sicher?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "Das erste Zeichen sollte ein Buchstabe sein", "username-contains-symbols-error": "Der Benutzername sollte nur Buchstaben, Zahlen und Bindestriche enthalten", "username-contains-double-hyphens": "Es sollten keine doppelten Bindestriche enthalten sein", - "username-exists": "Dieser Benutzername ist bereits registriert. Bitte versuche es mit einem anderen" + "username-exists": "Dieser Benutzername ist bereits registriert. Bitte versuche es mit einem anderen", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Themen" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Neuen Swap starten", "signing": "Signieren..", "success-swap": "Erfolgreich getauscht!", + "calculating-in": "Calculating in", "advanced": { "history": "Historie", "stake": "Handelsbuch", @@ -576,7 +676,7 @@ "sort-timestamp": "Zeit", "sort-reputation": "Reputation", "sort-percent": "Prozent", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "über {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "benutzername/permlink", "post-error": "Keine gültige Post Adresse", - "post-error-exists": "Dieser Beitrag wurde bereits promotet", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Deine Anfrage wurde eingereicht. Diese wird in ein paar Minuten aktiviert." }, "transfer": { diff --git a/src/common/i18n/locales/el-GR.json b/src/common/i18n/locales/el-GR.json index 1354b4e8267..c3e8c53fe47 100644 --- a/src/common/i18n/locales/el-GR.json +++ b/src/common/i18n/locales/el-GR.json @@ -58,6 +58,7 @@ "replies": "απαντήσεις", "done": "Έτοιμο", "apply": "Εφαρμογή", + "applying": "Applying...", "warning": "Προειδοποίηση", "payout": "Πληρωμή", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Είστε σίγουρος;", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Θέματα" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Ώρα", "sort-reputation": "Φήμη", "sort-percent": "Ποσοστό", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "μέσω{{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Αυτόματη συμπλήρωση εισαγωγής", "post-placeholder": "όνομα χρήστη/μόνιμος σύνδεσμος", "post-error": "Μη έγκυρη διεύθυνση", - "post-error-exists": "Αυτή η δημοσίευση έχει ήδη προωθηθεί", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Το αίτημα σας καταχωρήθηκε. Θα ενεργοποιηθεί σε μερικά λεπτά." }, "transfer": { diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 311fa35d08c..1628e116741 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -226,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -491,7 +556,8 @@ "whats-new-description": "Keep in track the Ecency updates", "updates": "Updates", "release-list": "Release versions", - "current": "Current" + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { "save": "Save", @@ -574,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -781,7 +848,7 @@ "follows-you": "Follows you", "section-blog": "Blog", "section-posts": "Posts", - "section-trail": "Trail", + "section-trail": "Likes", "section-comments": "Comments", "section-replies": "Replies", "section-communities": "Communities", @@ -841,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", diff --git a/src/common/i18n/locales/es-ES.json b/src/common/i18n/locales/es-ES.json index 3b3a196c98e..d8f15bfddea 100644 --- a/src/common/i18n/locales/es-ES.json +++ b/src/common/i18n/locales/es-ES.json @@ -58,6 +58,7 @@ "replies": "respuestas", "done": "Completado", "apply": "Aplicar", + "applying": "Aplicando...", "warning": "Advertencia", "payout": "Pago", "learn-more": "Aprende más en nuestro", @@ -71,7 +72,8 @@ "settings": "Configuraciones", "confirm": "Confirmar", "username": "Nombre de Usuario", - "past-few-days": "los últimos días" + "past-few-days": "los últimos días", + "you": "Tú" }, "confirm": { "title": "¿Estás seguro?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "El primer carácter debe ser una letra", "username-contains-symbols-error": "Debe contener solamente letras, números, Signos de Puntuación", "username-contains-double-hyphens": "No debe contener Signos de Puntuación dobles", - "username-exists": "Este nombre de usuario ya está registrado. Por favor, prueba otro" + "username-exists": "Este nombre de usuario ya está registrado. Por favor, prueba otro", + "referral-invalid": "Esta referencia no es válida. Por favor, prueba con otra", + "referral-min-length-error": "La longitud de la referencia debe tener al menos 3 caracteres", + "referral-max-length-error": "La longitud de la referencia no debe tener más de 16 caracteres" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Crea una cuenta para un amigo", + "asking": " Preguntar a un amigo", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Nombre de Usuario:", + "email": "Correo electrónico:", + "referral": "Referido:", + "copy-key": "Asegúrese de copiar o descargar tus claves.", + "download-keys": "Descargar claves", + "create-account-hive": "Pagar con HIVE", + "create-account-credit": "Pagar con Créditos de Cuenta ({{n}})", + "confirm-details": "Confirmar Detalles", + "share": "(Puedes enviar código a un amigo) Copiar código", + "copy-link": "Enlace de cuenta copiado correctamente", + "click-link": "Click here to continue", + "continue": "Continuar", + "public-active": "Clave Pública Activa:", + "public-memo": "Clave Pública de Memo:", + "public-owner": "Clave Pública de Propietario:", + "public-posting": "Clave Pública de Publicación:", + "login-warning": "¡Inicia sesión para crear una cuenta para Amigo!", + "pay-fee": "Tarifa de Cuenta de Pago", + "modal-title": "¿Estás seguro?", + "modal-confirm": "Confirmar", + "file-warning": "Por favor, maneja tus contraseñas y tus claves privadas con precaución extra. Tu cuenta ya no será accesible si pierdes tu contraseña. Nosotros no conservamos la copia, es confidencial, solamente tú tienes acceso a ella.", + "recommend": "Recomendamos que,", + "recommend-print": "IMPRIMAS este archivo y lo almacenes de forma segura.", + "recommend-use": "NUNCA uses tu clave o contraseña de propietario en aplicaciones no confiables.", + "recommend-save": "Guarda todas sus claves dentro de un gestor de contraseñas y/o monedero móvil Ecency, ya que las necesitarás con frecuencia.", + "recommend-third-party": "No mantengas este archivo al alcance de terceros.", + "account-info": "Información de su cuenta de Hive;", + "keys-use": "Para qué se pueden usar tus claves;", + "owner-private": "Clave Privada Propietaria:", + "active-private": "Clave Privada Activa:", + "posting-private": "Clave Privada de Publicación:", + "memo-private": "Clave Privada de Memo:", + "owner": "Clave Propietaria:", + "active": "Clave Activa:", + "posting": "Clave de Publicación:", + "memo": "Clave Memo:", + "owner-use": "Cambiar contraseña, cambiar claves, Recuperar cuenta", + "active-use": "Transferencia de fondos, Encender/Apagar Poder, Votar Testigos/Propuestas", + "posting-use": "Publicación, Comentario, Voto, Reblog, Seguimiento, Actualizaciones del Perfil", + "memo-use": "Enviar/Ver mensajes cifrados en transferencias", + "copy-tooltip": "Copiar contraseña", + "regenerate-password": "Regeneración de la contraseña", + "copy-password": "Contraseña copiada correctamente", + "copy-info-message": "Copiar enlace abajo y ENVIAR a un amigo", + "success-message": "Has creado correctamente la cuenta ", + "sign-title": "Firmar transacción con ", + "failed-title": "Ha fallado", + "failed-subtitle": "Transacción fallida", + "failed-message": "Error al crear la cuenta", + "try-again": "Inténtalo de nuevo", + "sign-header-title": "Firmar Transacción", + "sign-sub-title": "Firmar tu transacción" }, "trending-tags": { "title": "Temas" @@ -399,6 +466,12 @@ "auth-required-title": "Se requiere autorización", "auth-required-desc": "Tienes que estar autorizado para ver las notificaciones", "wave": "Ola", + "simple": "Simple", + "advanced": "Avanzado", + "author": "Autor", + "choose-one": "Escoge uno", + "user": "Usuario", + "search-query": "Consulta de búsqueda", "columns": { "view-full-post": "Ver post completo", "user": "Usuario", @@ -432,8 +505,9 @@ "transfers": "Transacciones", "delegations": "Delegaciones", "search-query": "Consulta de búsqueda", - "enter-search-query": "Escribe una consulta de búsqueda y explora todos los posts", + "enter-search-query": "Configura una consulta de búsqueda y explora todos los posts", "blogs": "Blogs", + "feeds": "Muro de amigos", "posts": "Publicaciones", "comments": "Comentarios", "all-history": "Todo el historial", @@ -459,9 +533,34 @@ "see-full-thread": "Ver hilo completo", "no-currency-data": "Sin datos", "hide-replies": "Ocultar respuestas", - "filters": "Filtros" + "filters": "Filtros", + "market-swap-form": "Formulario de intercambio de mercado", + "market": "Mercado", + "swap-form": "Formulario de intercambio", + "msf-description": "Cambia tus fondos rápidamente con latencia cero.", + "faq": "Centro de ayuda", + "faq-subtitle": "Preguntas Frecuentes (FAQ)", + "faq-description": "Encuentra respuesta a todas tus preguntas sobre Ecency en nuestro centro de ayuda.", + "no-replies": "No hay respuestas todavía", + "add-new-reply": "Añadir una nueva respuesta", + "no-content": "Sin contenido", + "infinite-loading": "Cargando 🌊...", + "end-reached": "Has llegado al final de 🌊.", + "feed-end-reached": "Ha llegado al final del Feed.", + "topics-subtitle": "El más popular", + "replied-to": "respondido a", + "edit-wave": "Editar", + "updated": "Editado hace {{n}}", + "balance": "Balance", + "whats-new": "Novedades", + "whats-new-description": "Mantente al tanto de las actualizaciones de Ecency", + "updates": "Actualizaciones", + "release-list": "Versiones de lanzamiento", + "current": "Actual", + "infinite-failed": "Vaya, la búsqueda falló. Siéntate, estamos reintentando..." }, "threads-form": { + "save": "Guardar", "publish": "¡Publicarlo!", "create-regular-post": "Crear mensaje largo", "input-placeholder": "¿Qué está pasando?", @@ -541,6 +640,7 @@ "start-new-one": "Iniciar nuevo Intercambio", "signing": "Firmando..", "success-swap": "¡Intercambiado con éxito!", + "calculating-in": "Calculating in", "advanced": { "history": "Historial", "stake": "Libro de órdenes", @@ -576,7 +676,7 @@ "sort-timestamp": "Hora", "sort-reputation": "Reputación", "sort-percent": "Porcentaje", - "pending-message": "Tienes votos pendientes. Por favor, espera un minuto y vuelve a abrir este diálogo para ver tu voto." + "pending-message": "El contenido tiene votos pendientes. Por favor, espera un minuto y actualiza este diálogo para ver nuevos votos." }, "entry": { "via-app": "a través de {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Publicaciones / Comentarios:", "votes": "Votos:", "reblogs-follows": "Reblogs / Seguidos:", + "claim-accounts": "Reclamar créditos de cuenta:", "no-outgoing": "No hay delegación saliente", "no-incoming": "No hay delegación entrante", "delegate-title": "Delegar", @@ -1072,7 +1173,8 @@ "post-hint": "Sugerencia de autocompletado", "post-placeholder": "usuario/permlink", "post-error": "No es una dirección de una publicación válida", - "post-error-exists": "El post ya está promocionado", + "post-boosted-exists": "Este contenido ya está impulsado", + "post-promoted-exists": "Este contenido ya está promocionado", "success-message": "Tu solicitud enviada. Será activada en un par de minutos." }, "transfer": { diff --git a/src/common/i18n/locales/et-EE.json b/src/common/i18n/locales/et-EE.json index c1c2b3b908c..edd29e27acf 100644 --- a/src/common/i18n/locales/et-EE.json +++ b/src/common/i18n/locales/et-EE.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Valmis", "apply": "Kinnita", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Olete kindel?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Teemad" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Kellaaeg", "sort-reputation": "Maine", "sort-percent": "Protsendid", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}} kaudu", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/fa-IR.json b/src/common/i18n/locales/fa-IR.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/fa-IR.json +++ b/src/common/i18n/locales/fa-IR.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/fi-FI.json b/src/common/i18n/locales/fi-FI.json index 083461dfe56..88fa21b64ec 100644 --- a/src/common/i18n/locales/fi-FI.json +++ b/src/common/i18n/locales/fi-FI.json @@ -58,6 +58,7 @@ "replies": "vastaukset", "done": "Valmis", "apply": "Käytä", + "applying": "Applying...", "warning": "Varoitus", "payout": "Palkkioita", "learn-more": "Lue lisää meidän", @@ -71,7 +72,8 @@ "settings": "Asetukset", "confirm": "Vahvista", "username": "Käyttäjänimi", - "past-few-days": "viime päivinä" + "past-few-days": "viime päivinä", + "you": "You" }, "confirm": { "title": "Oletko varma?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "Ensimmäisen merkin on oltava kirjain", "username-contains-symbols-error": "Pitäisi sisältää vain kirjaimia, numeroita ja tavuviivoja", "username-contains-double-hyphens": "Ei saa sisältää kaksinkertaisia tavuviivoja", - "username-exists": "Tämä nimimerkki on jo käytössä! Kokeile toista" + "username-exists": "Tämä nimimerkki on jo käytössä! Kokeile toista", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Aiheet" @@ -399,6 +466,12 @@ "auth-required-title": "Valtuutus vaaditaan", "auth-required-desc": "Sinulla on oltava valtuus nähdä ilmoituksia", "wave": "Aalto", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "Näytä koko julkaisu", "user": "Käyttäjä", @@ -432,8 +505,9 @@ "transfers": "Siirrot", "delegations": "Valtuutukset", "search-query": "Hakulauseke", - "enter-search-query": "Kirjoita hakusana ja tutki kaikkia viestejä", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogit", + "feeds": "Friends Feed", "posts": "Julkaisut", "comments": "Kommentit", "all-history": "Koko historia", @@ -459,9 +533,34 @@ "see-full-thread": "Katso koko lanka", "no-currency-data": "Ei tietoja", "hide-replies": "Piilota vastaukset", - "filters": "Suodattimet" + "filters": "Suodattimet", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Julkaise!", "create-regular-post": "Luo pitkä artikkeli", "input-placeholder": "Mitä tapahtuu?", @@ -541,6 +640,7 @@ "start-new-one": "Aloita uusi Vaihto", "signing": "Kirjataan..", "success-swap": "Vaihdettu onnistuneesti!", + "calculating-in": "Calculating in", "advanced": { "history": "Historia", "stake": "Tilauskanta", @@ -576,7 +676,7 @@ "sort-timestamp": "Aika", "sort-reputation": "Maine", "sort-percent": "Prosenttiosuus", - "pending-message": "Sinulla on odottavia äänestyksiä. Odota hetki ja avaa tämä dialogi uudelleen nähdäksesi äänesi." + "pending-message": "Sisältö odottaa ääniä. Odota hetki ja päivitä tämä ikkuna nähdäksesi uudet äänet." }, "entry": { "via-app": "{{app}} kautta", @@ -808,6 +908,7 @@ "comments-posts": "Julkaisut/Kommentit:", "votes": "Äänet:", "reblogs-follows": "Uudelleenjaot / Seuraamiset:", + "claim-accounts": "Claim account credits:", "no-outgoing": "Ei meneviä valtuutuksia", "no-incoming": "Ei saapuvia siirtoja", "delegate-title": "Valtuuta", @@ -1072,7 +1173,8 @@ "post-hint": "Automaattitäydennys", "post-placeholder": "käyttäjänimi/permlink", "post-error": "Osoite ei kelpaa", - "post-error-exists": "Julkaisu on jo korostettu", + "post-boosted-exists": "Tämä sisältö on jo tehostettu", + "post-promoted-exists": "Tämä sisältö on jo korostettu", "success-message": "Pyyntösi lähetetty. Se aktivoituu muutaman minuutin kuluttua." }, "transfer": { @@ -1360,7 +1462,7 @@ "post-scheduler": { "title": "Ajasta", "btn-label": "Ajasta", - "error-message": "Please select a valid future date and time." + "error-message": "Syötä kelvollinen tuleva päivämäärä sekä aika." }, "notification": { "popup-title": "Sinulle on uusi ilmoitus", diff --git a/src/common/i18n/locales/fil-PH.json b/src/common/i18n/locales/fil-PH.json index 7d730c78758..0932095df09 100644 --- a/src/common/i18n/locales/fil-PH.json +++ b/src/common/i18n/locales/fil-PH.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Tapos", "apply": "I-apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Sigurado ka ba?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Mga paksa" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Oras", "sort-reputation": "Reputasyon", "sort-percent": "Porsyento", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Awtomatikong paglagay", "post-placeholder": "bansag/permanenteng ugnayan", "post-error": "Hindi isang balidong address", - "post-error-exists": "Ang post ay tapos nang naisulong", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Naisumite na ang iyong hiling. Magiging aktibo ito sa ilang sandali." }, "transfer": { diff --git a/src/common/i18n/locales/fr-FR.json b/src/common/i18n/locales/fr-FR.json index dd4ff9b1097..33fdde1f086 100644 --- a/src/common/i18n/locales/fr-FR.json +++ b/src/common/i18n/locales/fr-FR.json @@ -58,6 +58,7 @@ "replies": "réponses", "done": "Terminé", "apply": "Appliquer", + "applying": "Applying...", "warning": "Avertissement", "payout": "Paiement", "learn-more": "Apprenez‐en davantage dans notre", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Êtes-vous sûr ?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Sujets" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Heure", "sort-reputation": "Réputation", "sort-percent": "Pourcentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Saisie automatique", "post-placeholder": "nom d'utilisateur/permlink", "post-error": "N'est pas une adresse de post valide", - "post-error-exists": "Ce post est déjà promu", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Votre demande a été envoyée. Elle sera activée dans quelques minutes." }, "transfer": { diff --git a/src/common/i18n/locales/he-IL.json b/src/common/i18n/locales/he-IL.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/he-IL.json +++ b/src/common/i18n/locales/he-IL.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/hi-IN.json b/src/common/i18n/locales/hi-IN.json index 7a425ccd3b1..c816ff76ea6 100644 --- a/src/common/i18n/locales/hi-IN.json +++ b/src/common/i18n/locales/hi-IN.json @@ -58,6 +58,7 @@ "replies": "जवाब", "done": "पूर्ण हुवा", "apply": "लागू करें", + "applying": "Applying...", "warning": "चेतावनी", "payout": "भुगतान", "learn-more": "हमारे में और जानें", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "क्या आपको यकीन है?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "विषय" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "समय", "sort-reputation": "प्रतिष्ठा", "sort-percent": "प्रतिशत", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": " {{app}} के माध्यम से", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "स्वतः पूर्ण इनपुट", "post-placeholder": "उपयोगकर्ता नाम / स्थायी लिंक", "post-error": "मान्य पोस्ट पता नहीं", - "post-error-exists": "पद पहले से पदोन्नत है", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "आपका अनुरोध सबमिट कर दिया गया है यह एक दो मिनट में सक्रिय हो जाएगा।" }, "transfer": { diff --git a/src/common/i18n/locales/hr-HR.json b/src/common/i18n/locales/hr-HR.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/hr-HR.json +++ b/src/common/i18n/locales/hr-HR.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/hu-HU.json b/src/common/i18n/locales/hu-HU.json index c373f4c5321..8a10def1466 100644 --- a/src/common/i18n/locales/hu-HU.json +++ b/src/common/i18n/locales/hu-HU.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Biztos vagy benne?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Témák" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Idő", "sort-reputation": "Reputáció", "sort-percent": "Százalék", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}}-n keresztül", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "felhasználónév/permlink", "post-error": "Nem érvényes bejegyzés cím", - "post-error-exists": "A bejegyzés már hirdetett", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Kérésed rögzítve. Néhány perc múlva aktiválódik." }, "transfer": { diff --git a/src/common/i18n/locales/id-ID.json b/src/common/i18n/locales/id-ID.json index 25f7ab10ec4..61737d90639 100644 --- a/src/common/i18n/locales/id-ID.json +++ b/src/common/i18n/locales/id-ID.json @@ -58,6 +58,7 @@ "replies": "balasan", "done": "Selesai", "apply": "Terapkan", + "applying": "Applying...", "warning": "Peringatan", "payout": "Bayaran", "learn-more": "Pelajari lebih banyak di", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Apakah anda yakin?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topik" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Waktu", "sort-reputation": "Reputasi", "sort-percent": "Persentasi", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "melalui {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Pengisian nama Otomatis", "post-placeholder": "nama pengguna/tautan permanen", "post-error": "Bukan alamat postingan yang valid", - "post-error-exists": "Postingan ini sudah dipromosikan", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Permintaan Anda terkirim. Ia akan diaktifkan dalam beberapa menit." }, "transfer": { diff --git a/src/common/i18n/locales/it-IT.json b/src/common/i18n/locales/it-IT.json index 1e97350f81c..8e8d3eb5b77 100644 --- a/src/common/i18n/locales/it-IT.json +++ b/src/common/i18n/locales/it-IT.json @@ -58,6 +58,7 @@ "replies": "risposte", "done": "Fatto", "apply": "Applica", + "applying": "Applying...", "warning": "Attenzione", "payout": "Ricompensa", "learn-more": "Scopri di più su", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Sei sicuro?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Argomenti" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Data e ora", "sort-reputation": "Reputazione", "sort-percent": "Percentuale", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "attraverso {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Input di completamento automatico", "post-placeholder": "nome utente/permalink", "post-error": "Non è un indirizzo valido di un post", - "post-error-exists": "Il post risulta già promosso", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "La tua richiesta è stata inviata. Sarà attivata in un paio di minuti." }, "transfer": { diff --git a/src/common/i18n/locales/ja-JP.json b/src/common/i18n/locales/ja-JP.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ja-JP.json +++ b/src/common/i18n/locales/ja-JP.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ka-GE.json b/src/common/i18n/locales/ka-GE.json index 15f105796c2..c6d8584d9cf 100644 --- a/src/common/i18n/locales/ka-GE.json +++ b/src/common/i18n/locales/ka-GE.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/kk-KZ.json b/src/common/i18n/locales/kk-KZ.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/kk-KZ.json +++ b/src/common/i18n/locales/kk-KZ.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ko-KR.json b/src/common/i18n/locales/ko-KR.json index 90e56e3d588..f8d373adb9a 100644 --- a/src/common/i18n/locales/ko-KR.json +++ b/src/common/i18n/locales/ko-KR.json @@ -58,6 +58,7 @@ "replies": "댓글", "done": "완료", "apply": "적용", + "applying": "Applying...", "warning": "경고", "payout": "보상", "learn-more": "더 자세히 알아보기", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "정말 진행하시겠습니까?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "주제" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "시간", "sort-reputation": "명성도순", "sort-percent": "비율", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}}에서 작성되었습니다", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "자동완성", "post-placeholder": "사용자 이름/퍼머링크", "post-error": "유효한 글 주소가 아닙니다", - "post-error-exists": "이미 홍보된 글입니다", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "요청이 제출되었으며 몇 분 안에 활성화될 것입니다." }, "transfer": { diff --git a/src/common/i18n/locales/ku-TR.json b/src/common/i18n/locales/ku-TR.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ku-TR.json +++ b/src/common/i18n/locales/ku-TR.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ky-KG.json b/src/common/i18n/locales/ky-KG.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ky-KG.json +++ b/src/common/i18n/locales/ky-KG.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/lt-LT.json b/src/common/i18n/locales/lt-LT.json index 9f46b4cd0af..d0aa0c5c445 100644 --- a/src/common/i18n/locales/lt-LT.json +++ b/src/common/i18n/locales/lt-LT.json @@ -58,6 +58,7 @@ "replies": "atsakymai", "done": "Atlikta", "apply": "Pritaikyti", + "applying": "Applying...", "warning": "Įspėjimas", "payout": "Išmoka", "learn-more": "Sužinokite daugiau mūsų", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Ar esate įsitikinę?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Temos" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Laikas", "sort-reputation": "Reputacija", "sort-percent": "Procentai", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "per {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Automatinė įvestis", "post-placeholder": "vartotojovardas/permlink", "post-error": "Neteisingas įrašo adresas", - "post-error-exists": "Šis įrašas jau paspartintas", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Jūsų prašymas priimtas. Aktyvuosis per kelias minutes." }, "transfer": { diff --git a/src/common/i18n/locales/lv-LV.json b/src/common/i18n/locales/lv-LV.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/lv-LV.json +++ b/src/common/i18n/locales/lv-LV.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ms-MY.json b/src/common/i18n/locales/ms-MY.json index 0d0af4638da..27b46aff316 100644 --- a/src/common/i18n/locales/ms-MY.json +++ b/src/common/i18n/locales/ms-MY.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ne-NP.json b/src/common/i18n/locales/ne-NP.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ne-NP.json +++ b/src/common/i18n/locales/ne-NP.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/nl-NL.json b/src/common/i18n/locales/nl-NL.json index 4ab785ba01f..7119c824f8f 100644 --- a/src/common/i18n/locales/nl-NL.json +++ b/src/common/i18n/locales/nl-NL.json @@ -58,6 +58,7 @@ "replies": "antwoorden", "done": "Klaar", "apply": "Toepassen", + "applying": "Applying...", "warning": "Waarschuwing", "payout": "Uitbetaling", "learn-more": "Leer meer in onze", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Weet je het zeker?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Onderwerpen" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start nieuwe omwisseling", "signing": "Bezig met ondertekenen..", "success-swap": "Omwisselen gelukt!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Tijd", "sort-reputation": "Reputatie", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Geen geldig e-mailadres", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/no-NO.json b/src/common/i18n/locales/no-NO.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/no-NO.json +++ b/src/common/i18n/locales/no-NO.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/pa-IN.json b/src/common/i18n/locales/pa-IN.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/pa-IN.json +++ b/src/common/i18n/locales/pa-IN.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/pcm-NG.json b/src/common/i18n/locales/pcm-NG.json index 8eceb666186..bf152c3b1c7 100644 --- a/src/common/i18n/locales/pcm-NG.json +++ b/src/common/i18n/locales/pcm-NG.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/pl-PL.json b/src/common/i18n/locales/pl-PL.json index 2a6dbcd9e14..ddff17db948 100644 --- a/src/common/i18n/locales/pl-PL.json +++ b/src/common/i18n/locales/pl-PL.json @@ -58,6 +58,7 @@ "replies": "odpowiedzi", "done": "Zakończono", "apply": "Zastosuj", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Jesteś pewien?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Tematy" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Czas", "sort-reputation": "Reputacja", "sort-percent": "Odsetek", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "przez {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autouzupełnianie wprowadzania", "post-placeholder": "nazwa użytkownika/permlink", "post-error": "Nie prawidłowy adres wpisu", - "post-error-exists": "Ten post jest już promowany", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Twoje zapytanie zostało złożone. Zostanie ono aktywowane za kilka minut." }, "transfer": { diff --git a/src/common/i18n/locales/pt-PT.json b/src/common/i18n/locales/pt-PT.json index f386eae1ce8..8d0d6f88eaf 100644 --- a/src/common/i18n/locales/pt-PT.json +++ b/src/common/i18n/locales/pt-PT.json @@ -58,6 +58,7 @@ "replies": "respostas", "done": "Feito", "apply": "Aplicar", + "applying": "Applying...", "warning": "Aviso", "payout": "Pagamento", "learn-more": "Saiba mais em", @@ -71,7 +72,8 @@ "settings": "Ajustes", "confirm": "Confirmar", "username": "Usuário", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Tem a certeza?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Criar para um amigo", + "asking": " Pedir a um amigo", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "E-mail:", + "referral": "Referência:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pagar com HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continuar", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirmar", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "O que é possível fazer com as suas chaves;", + "owner-private": "Chave privativa de Proprietário:", + "active-private": "Chave privativa Ativa:", + "posting-private": "Chave privativa de Postagem:", + "memo-private": "Chave Memo privada:", + "owner": "Chave do Proprietário:", + "active": "Chave Ativa:", + "posting": "Chave de Postagem:", + "memo": "Chave Memo:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Recriar a senha", + "copy-password": "Senha copiada com successo", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Tópicos" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "Usuário", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Iniciar nova troca", "signing": "Entrando..", "success-swap": "Trocado com sucesso!", + "calculating-in": "Calculating in", "advanced": { "history": "Hitórico", "stake": "Livro de ordens", @@ -576,7 +676,7 @@ "sort-timestamp": "Tempo", "sort-reputation": "Reputação", "sort-percent": "Percentagem", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegar", @@ -1072,7 +1173,8 @@ "post-hint": "Auto completar a entrada", "post-placeholder": "usuário/link permanente", "post-error": "Endereço do post não é valido", - "post-error-exists": "A publicação já foi promovida", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Seu pedido foi enviado. Ele será ativado em alguns minutos." }, "transfer": { diff --git a/src/common/i18n/locales/ro-RO.json b/src/common/i18n/locales/ro-RO.json index 0e2807c3531..f3f2ca9bccf 100644 --- a/src/common/i18n/locales/ro-RO.json +++ b/src/common/i18n/locales/ro-RO.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Ești sigur?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Subiecte" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Nu este o adresă de postare validă", - "post-error-exists": "Postarea a fost deja promovată", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Cererea a fost trimisă. Va fi activat în câteva minute." }, "transfer": { diff --git a/src/common/i18n/locales/ru-RU.json b/src/common/i18n/locales/ru-RU.json index 69f9de16705..d95a3a60d1b 100644 --- a/src/common/i18n/locales/ru-RU.json +++ b/src/common/i18n/locales/ru-RU.json @@ -58,6 +58,7 @@ "replies": "ответы", "done": "Готово", "apply": "Применить", + "applying": "Применяется...", "warning": "Внимание", "payout": "Выплата", "learn-more": "Узнайте больше в нашем", @@ -71,7 +72,8 @@ "settings": "Настройки", "confirm": "Подтвердить", "username": "Имя пользователя", - "past-few-days": "последние несколько дней" + "past-few-days": "последние несколько дней", + "you": "Вы" }, "confirm": { "title": "Вы уверены?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "Первый символ должен быть буквой", "username-contains-symbols-error": "Должно содержать только буквы, цифры и дефисы", "username-contains-double-hyphens": "Не должно содержать двойные дефисы", - "username-exists": "Это имя пользователя уже зарегистрировано. Пожалуйста, подберите другое" + "username-exists": "Это имя пользователя уже зарегистрировано. Пожалуйста, подберите другое", + "referral-invalid": "Этот реферал недействителен. Пожалуйста, попробуйте другого", + "referral-min-length-error": "Длина имени реферала должна быть не менее трёх символов", + "referral-max-length-error": "Длина имени реферала должна быть не более 16 символов" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Создать друга", + "asking": " Спросить у друга", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Имя пользователя:", + "email": "Эл. почта:", + "referral": "Реферал:", + "copy-key": "Убедитесь, что вы скопировали или загрузили ключи.", + "download-keys": "Скачать ключи", + "create-account-hive": "Оплатить с помощью HIVE", + "create-account-credit": "Оплатить кредитами со счета ({{n}})", + "confirm-details": "Подтвердить данные", + "share": "(Вы можете отправить код другу) Копировать код", + "copy-link": "Ссылка на аккаунт успешно скопирована", + "click-link": "Click here to continue", + "continue": "Продолжить", + "public-active": "Публичный активный ключ:", + "public-memo": "Публичный мемо ключ:", + "public-owner": "Публичный ключ владельца:", + "public-posting": "Публичный постинг ключ:", + "login-warning": "Войдите, чтобы создать учетную запись для друга!", + "pay-fee": "Оплатить комиссию по счёту", + "modal-title": "Вы уверены?", + "modal-confirm": "Подтвердить", + "file-warning": "Пожалуйста, обращайтесь со своим паролем и закрытыми ключами с особой осторожностью. Ваша учетная запись станет недоступна, если вы потеряете пароль. Мы не храним его копию, это конфиденциально, только у вас есть к нему доступ.", + "recommend": "Мы рекомендуем,", + "recommend-print": "РАСПЕЧАТАЙТЕ этот файл и храните в безопасном месте.", + "recommend-use": "НИКОГДА не используйте пароль/ключ владельца в ненадежных приложениях.", + "recommend-save": "Сохраните все свои ключи в менеджере паролей и/или мобильном кошельке Ecency, так как они будут часто вам нужны.", + "recommend-third-party": "Не храните этот файл в доступном для третьих лиц месте.", + "account-info": "Информация о вашем аккаунте Hive;", + "keys-use": "Для чего можно использовать ваши ключи;", + "owner-private": "Приватный ключ владельца:", + "active-private": "Приватный активный ключ:", + "posting-private": "Приватный постинг ключ:", + "memo-private": "Приватный мемо ключ:", + "owner": "Ключ владельца:", + "active": "Активный ключ:", + "posting": "Постинг ключ:", + "memo": "Мемо ключ:", + "owner-use": "Изменить пароль, Изменить ключи, Восстановить аккаунт", + "active-use": "Перевод средств, Повышение/Понижение силы, голосование за Свидетелей/Предложения", + "posting-use": "Публиковать, Комментировать, Голосовать, Репост, Обновление профиля", + "memo-use": "Отправка/Просмотр зашифрованных сообщений о переводах", + "copy-tooltip": "Копировать пароль", + "regenerate-password": "Создать новый пароль", + "copy-password": "Пароль успешно скопирован", + "copy-info-message": "Скопировать ссылку ниже и ОТПРАВИТЬ другу", + "success-message": "Учётная запись успешно создана ", + "sign-title": "Подписать транзакцию с ", + "failed-title": "Не удалось", + "failed-subtitle": "Транзакция не удалась", + "failed-message": "Не удалось создать аккаунт", + "try-again": "Повторить попытку", + "sign-header-title": "Подписать транзакцию", + "sign-sub-title": "Подпишите транзакцию" }, "trending-tags": { "title": "Темы" @@ -399,6 +466,12 @@ "auth-required-title": "Требуется авторизация", "auth-required-desc": "Вы должны быть авторизованы для просмотра уведомлений", "wave": "Помахать рукой", + "simple": "Простой", + "advanced": "Дополнительно", + "author": "Автор", + "choose-one": "Выберите один", + "user": "Пользователь", + "search-query": "Поисковый запрос", "columns": { "view-full-post": "Посмотреть полный пост", "user": "Пользователь", @@ -432,8 +505,9 @@ "transfers": "Переводы", "delegations": "Делегации", "search-query": "Поисковый запрос", - "enter-search-query": "Введите поисковый запрос и исследуйте все посты", + "enter-search-query": "Настройте поисковый запрос и просмотрите все сообщения", "blogs": "Блоги", + "feeds": "Лента друзей", "posts": "Посты", "comments": "Комментарии", "all-history": "Вся история", @@ -459,9 +533,34 @@ "see-full-thread": "Посмотреть всю тему", "no-currency-data": "Нет данных", "hide-replies": "Скрыть ответы", - "filters": "Фильтры" + "filters": "Фильтры", + "market-swap-form": "Форма обмена", + "market": "Маркет", + "swap-form": "Форма обмена", + "msf-description": "Быстро обменивайте свои средства с нулевой задержкой.", + "faq": "Справочный центр", + "faq-subtitle": "FAQ", + "faq-description": "Найдите ответы на все вопросы о Ecency в нашем справочном центре.", + "no-replies": "Ответов пока нет", + "add-new-reply": "Добавить новый ответ", + "no-content": "Нет содержимого", + "infinite-loading": "Загрузка 🌊...", + "end-reached": "Вы достигли конца 🌊.", + "feed-end-reached": "Вы достигли конца ленты.", + "topics-subtitle": "Самые популярные", + "replied-to": "ответил на", + "edit-wave": "Редактировать", + "updated": "Отредактировано {{n}} назад", + "balance": "Баланс", + "whats-new": "Что нового", + "whats-new-description": "Следите за обновлениями Ecency", + "updates": "Обновления", + "release-list": "Релиз версии", + "current": "Текущая", + "infinite-failed": "Упс, не удалось загрузить. Подождите, мы попытаемся снова..." }, "threads-form": { + "save": "Сохранить", "publish": "Опубликовать!", "create-regular-post": "Создать длинный пост", "input-placeholder": "Что интересного вокруг?", @@ -541,6 +640,7 @@ "start-new-one": "Начать новый обмен", "signing": "Войти..", "success-swap": "Успешно изменено!", + "calculating-in": "Calculating in", "advanced": { "history": "История", "stake": "Список ордеров", @@ -576,7 +676,7 @@ "sort-timestamp": "Время", "sort-reputation": "Репутация", "sort-percent": "Процент", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Контент ожидает голосования. Пожалуйста, подождите минуту и обновите это диалоговое окно, чтобы увидеть новые голоса." }, "entry": { "via-app": "через {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Посты / Комментарии:", "votes": "Голоса:", "reblogs-follows": "Репосты / Подписки:", + "claim-accounts": "Запросить кредиты учетной записи:", "no-outgoing": "Нет исходящей делегации", "no-incoming": "Нет входящей делегации", "delegate-title": "Делегировать", @@ -1072,7 +1173,8 @@ "post-hint": "Автозаполнение ввода", "post-placeholder": "имя/ссылка", "post-error": "Недействительный адрес", - "post-error-exists": "Этот пост уже рекламировался", + "post-boosted-exists": "Этот контент уже усилен", + "post-promoted-exists": "Этот контент уже продвигается", "success-message": "Ваш запрос отправлен. Он будет выполнен через пару минут." }, "transfer": { @@ -1360,7 +1462,7 @@ "post-scheduler": { "title": "Расписание", "btn-label": "Расписание", - "error-message": "Please select a valid future date and time." + "error-message": "Пожалуйста, выберите правильную дату и время в будущем." }, "notification": { "popup-title": "У вас есть новое уведомление", @@ -1700,7 +1802,7 @@ "what-is-ecency-body": "

    Ecency — это децентрализованная социальная сеть, работающая на блокчейне < a href=\"https://hive.io\" target=\"_blank\" rel=\"noopener noreferrer\">Hive.

    Ecency — это дом свободы слова и возможность получения вознаграждения для создателей контента.

    Проект основан @good-karma в августе 2016 года как альтернативная социальная сеть без цензуры, контролируемая пользователями, неизменная и с открытым исходным кодом. Есть много независимых и добровольных участников, которые работают вместе, чтобы донести идеи свободы до масс.

    Ecency — это центр сообществ, основанный на передовых технологиях, к тому же пользователи получают оплату за потраченное время, ресурсы и обучение, имея при этом полный контроль над своей учётной записью, сообществами и контентом. Благодаря простоте использования пользователи не только учатся, но и становятся инвесторами, основоположниками нового Интернета.

    ", "what-is-hive-header": "Что такое блокчейн Hive?", "what-is-hive-body": "

    Hive – это блокчейн, разработанный как быстрая, бесплатная, децентрализованная, не подвергающаяся цензуре платформа для приложений Web3.0 со встроенными функциями, с помощью которых заинтересованные пользователи могут получать вознаграждение, голосовать, курировать, публиковать, играть в игры, торговать – без посредников, т.е. децентрализованно. Токены блокчейна Hive: HIVE, HIVE DOLLARS, HIVE POWER.

    ", - "what-is-difference-header": "В чем отличие от других социальных сетей?", + "what-is-difference-header": "В чём отличие от других социальных сетей?", "what-is-difference-body": "

    Основное отличие Ecency заключается в том, что система работает на блокчейне, это означает, что контент неизменен и не подлежит цензуре. Вы полностью владеете своим сообществом и учетной записью, никто, кроме вас, не имеет контроля над данными. Расширение возможностей истинной свободы слова. Ecency также является проектом с открытым исходным кодом, полезным и инновационным, созданным и принадлежащим пользователям. Мы стремимся к совершенству!

    ", "why-choose-ecency-header": "Почему я должен выбрать Ecency?", "why-choose-ecency-body": "

    Специализированный набор функций, который позволит вам творить и вдохновлять свою аудиторию и сообщество. Мобильное приложение Ecency, позволит получать информацию на ходу. С настольным приложением вы всегда можете быть уверены, что получите информацию без цензуры прямо из блокчейна, т.к. сайт охватывает тысячи авторов со всего мира. Современные меры безопасности, создают условия, чтобы ваши приватные ключи всегда оставались зашифрованными и недоступными для злоумышленников. Быстрый и красивый веб-сайт поможет вам заявить о себе в сети Интернет, получить доступ к информации, привлечь лояльных подписчиков и читателей. Создайте свое сообщество с Ecency, воспользуйтесь преимуществами новых технологий блокчейна и контентом без цензуры, настоящей свободы слова!

    ", @@ -1708,8 +1810,8 @@ "how-ecency-works-body": "

    Ecency хранит и считывает данные из блокчейна, поэтому данные всегда доступны и не подвержены цензуре. Ecency награждает создателей контента встроенным механизмом стимулирования блокчейна, токенами (HIVE, HIVE DOLLARS, HIVE POWER), а также баллами. Токены можно покупать и продавать на крупных криптовалютных биржах (например, Binance, Bittrex). Баллы можно использовать внутри платформы и обменивать на товары, услуги.

    ", "how-to-join-header": "Как присоединиться к Ecency?", "how-to-join-body": "

    Перейдите на страницу https://ecency.com/signup?referral=ecency и создайте учётную запись. После регистрации вы получите электронное письмо с дальнейшими инструкциями. Ваш пароль — это мастер-пароль к вашей учетной записи. Пожалуйста, храните его в безопасном месте, если вы потеряете свой пароль, вы в конечном итоге потеряете доступ к своей учетной записи и своим средствам. Учётные записи не могут быть деактивированы или удалены, имена учетных записей также не могут быть изменены. Учётная запись вместе со всей её активностью постоянно хранится в блокчейне. Без пароля учётные записи не могут быть восстановлены, храните ключи в безопасном месте.

    ", - "how-to-signin-header": "Как войти в Ecency?", - "how-to-signin-body": "

    Вы можете войти в Ecency, используя свое имя пользователя, мастер-пароль или активные приватные ключи. Мы очень серьезно относимся к безопасности, поэтому никогда не храним ваши личные ключи. В мобильном приложении ключи дополнительно шифруются PIN-кодом, на веб-сайте никогда не сохраняются. Вы также можете использовать службу аутентификации Hivesigner OAuth2, чтобы легко входить в систему, управлять и выполнять различные действия.

    ", + "how-to-signin-header": "Как авторизоваться на Ecency?", + "how-to-signin-body": "

    Вы можете авторизоваться, используя своё имя пользователя, мастер-пароль или активные приватные ключи. Мы очень серьезно относимся к безопасности, поэтому никогда не храним ваши ключи. В мобильном приложении ключи дополнительно шифруются PIN-кодом и также не сохраняются. Вы также можете использовать службу аутентификации Hivesigner OAuth2, чтобы легко входить в систему, управлять и выполнять различные действия.

    ", "how-referrals-work-header": "Как работает реферальная система?", "how-referrals-work-body": "

    Реферальная система проста, вы можете пригласить своих друзей, добавив свое имя пользователя в эту ссылку: https://ecency.com/signup?referral=username и поделиться ею с друзьями. Как только ваши друзья присоединятся к Ecency и заработают свои первые 250 баллов, вы получите 100 баллов. Нет ограничений на количество рефералов и сумму вознаграждения.

    ", "what-is-points-header": "Что такое Баллы Ecency и как их использовать?", @@ -1741,7 +1843,7 @@ "source-label-header": "Метки источника контента, что это такое?", "source-label-body": "

    Источник контента помогает понять, как он был опубликован. В некоторых случаях вы можете увидеть имя стороннего клиента, которое указывает на то, что контент был опубликован из приложения, отличного от Ecency. Авторы иногда используют сторонние клиентские приложения для управления своими блогами, сообществами. Сторонние клиенты - это программные инструменты, используемые авторами, поэтому они не связаны с контентом и не отражают его взгляды. Контент может быть создан непосредственно людьми или, в некоторых случаях, автоматизирован приложением.

    ", "how-to-contribute-header": "Как внести свой вклад в Ecency?", - "how-to-contribute-body": "

    Наши замечательные участники помогают формировать Ecency. Вы можете стать частью этого движения, присоединившись к нашей команде переводчиков: веб-сайтов, мобильных приложений, внося свой вклад в развитие идей, разработку, дизайн и работу с социальными сетями. Мы делаем все возможное, чтобы поддержать наших участников!

    ", + "how-to-contribute-body": "

    Наши замечательные участники помогают формировать Ecency. Вы можете стать частью этого движения, присоединившись к команде переводчиков: сайта и мобильного приложения, внося свой вклад в развитие идей, разработку, дизайн и работу с социальными сетями. Мы делаем все возможное, чтобы поддержать наших участников!

    ", "why-refund-points-header": "Почему происходит возврат средств в бустинге?", "why-refund-points-body": "

    В течении 24 часов наши кураторы просматривают и оценивают качество контента. Возврат средств может произойти по нескольким причинам, например: плагиат, злоупотребления, фишинг или спам, а также если пост слишком стар для курирования, так как в процессе новые посты становится более приоритетными для проверки.

    ", "can-change-username-header": "Могу ли я изменить свое имя пользователя?", @@ -1779,7 +1881,7 @@ "what-powering-down-header": "Как понизить силу?", "what-powering-down-body": "

    Hive Power можно отключить в тех же кошельках, где его можно включить. Когда вы включите понижение силы, HIVE Power не будет сразу доступен как HIVE. Он конвертируется в 13 равных частей и еженедельно переводится в ваш кошелёк HIVE, причем первая часть становится доступной только через неделю после начала понижения.

    ", "why-different-keys-header": "Почему ключи разные?", - "why-different-keys-body": "

    Существуют разные ключи с соответствующими разрешениями для того, что вы делаете.

    • Ключи публикации — этот ключ следует использовать для действий в социальных сетях, таких как публикация, комментирование и голосование. Этот ключ имеет ограниченный набор разрешений и не может использоваться для денежных действий. Таким образом, вы не можете потерять деньги, если кто-то другой получит доступ к этому ключу.
    • Активный ключ — этот ключ имеет дополнительные разрешения для более конфиденциальных денежных действий, таких как передача и обмен токенов. При выполнении действия, связанного с кошельком, вам может быть предложено пройти аутентификацию с помощью вашего активного ключа. Вы должны вводить свой активный ключ только в приложения, которым вы доверяете, потому что любой, у кого есть доступ к этому ключу, может получить ваши токены. Сделайте себе одолжение и сохраните этот ключ в безопасном месте, чтобы не потерять токены в будущем.
    • Ключ владельца - это самый мощный ключ, потому что он может изменить любой ключ учетной записи, включая ключ владельца. В идеале он должен храниться в автономном режиме и использоваться только для восстановления скомпрометированной учетной записи.

    ", + "why-different-keys-body": "

    Существуют разные ключи с соответствующими разрешениями для различных действий.

    • Постинг ключ. Этот ключ следует использовать для действий в социальных сетях, таких как публикация, комментирование и голосование. Этот ключ имеет ограниченный набор разрешений и не может использоваться для денежных операций. Таким образом, вы не потеряете деньги, если кто-то другой получит доступ к этому ключу.
    • Активный ключ — этот ключ имеет дополнительные разрешения для более конфиденциальных денежных действий, таких как передача и обмен токенов. При выполнении действия, связанного с кошельком, вам может быть предложено пройти аутентификацию с помощью вашего активного ключа. Вы должны вводить свой активный ключ только в приложения, которым доверяете, потому что любой, у кого есть доступ к этому ключу, может получить ваши токены. Сделайте себе одолжение и сохраните этот ключ в безопасном месте, чтобы не потерять токены в будущем.
    • Ключ владельца — самый мощный ключ, поскольку он может изменить любой ключ учётной записи, включая ключ владельца. В идеале он должен храниться в автономном режиме и использоваться только для восстановления взломанного аккаунта.

    ", "stolen-hive-hbd-header": "Что я могу сделать, если мои токены Hive dollar или Hive украдены или отправлены на неправильный счет?", "stolen-hive-hbd-body": "

    Ничего не поделать, если ваши ликвидные токены украдены или отправлены на неправильный счет. Но если ваши токены находятся в Hive Power, их невозможно украсть мгновенно, т. е. время полного вывода из силы составляет 13 недель, а вывод из сейфа три с половиной дня. Выставлять ордера, переводить в Hive Power или отправять средства в сейф может быть более безопасным.", "what-are-tags-header": "Что такое теги или темы?", diff --git a/src/common/i18n/locales/sk-SK.json b/src/common/i18n/locales/sk-SK.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/sk-SK.json +++ b/src/common/i18n/locales/sk-SK.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/sl-SI.json b/src/common/i18n/locales/sl-SI.json index f6f79a1f479..60987689aab 100644 --- a/src/common/i18n/locales/sl-SI.json +++ b/src/common/i18n/locales/sl-SI.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/sr-CS.json b/src/common/i18n/locales/sr-CS.json index 04c6157f2b6..bc43e01a944 100644 --- a/src/common/i18n/locales/sr-CS.json +++ b/src/common/i18n/locales/sr-CS.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Gotovo", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Da li ste sigurni?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Теме" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Vreme", "sort-reputation": "Reputacija", "sort-percent": "Procenat", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "putem {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autokompletirani ulaz", "post-placeholder": "korisničko ime/permanentna veza", "post-error": "Nevažeća adresa objave", - "post-error-exists": "Objava je već promovisana", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Vaš zahtev je podnet. Biće aktivirano za nekoliko minuta." }, "transfer": { diff --git a/src/common/i18n/locales/sv-SE.json b/src/common/i18n/locales/sv-SE.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/sv-SE.json +++ b/src/common/i18n/locales/sv-SE.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ta-IN.json b/src/common/i18n/locales/ta-IN.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ta-IN.json +++ b/src/common/i18n/locales/ta-IN.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/th-TH.json b/src/common/i18n/locales/th-TH.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/th-TH.json +++ b/src/common/i18n/locales/th-TH.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/tr-TR.json b/src/common/i18n/locales/tr-TR.json index c450c6a2284..5fce82d3ca5 100644 --- a/src/common/i18n/locales/tr-TR.json +++ b/src/common/i18n/locales/tr-TR.json @@ -58,6 +58,7 @@ "replies": "yanıtlar", "done": "Bitti", "apply": "Uygula", + "applying": "Applying...", "warning": "Dikkat", "payout": "Ödeme", "learn-more": "Daha fazla bilgi edinin", @@ -71,7 +72,8 @@ "settings": "Ayarlar", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Emin misiniz?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Konular" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Tarih", "sort-reputation": "İtibar", "sort-percent": "Yüzde", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}} üzerinden", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Girdiyi otomatik olarak tamamla", "post-placeholder": "kullanıcı adı/kalıcı bağlantı", "post-error": "Gönderi adresi geçersizdir", - "post-error-exists": "Bu gönderi zaten tanıtıldı", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Talebiniz gönderildi. Birkaç dakika içinde etkinleştirilecektir." }, "transfer": { diff --git a/src/common/i18n/locales/uk-UA.json b/src/common/i18n/locales/uk-UA.json index 5bc6f69e7db..e100c2682f7 100644 --- a/src/common/i18n/locales/uk-UA.json +++ b/src/common/i18n/locales/uk-UA.json @@ -42,7 +42,7 @@ "off": "Вимкнути", "yes": "Так", "no": "Ні", - "hot": "feed", + "hot": "стрічка", "trending": "feed", "created": "feed", "muted": "muted", @@ -58,20 +58,22 @@ "replies": "відповіді", "done": "Виконано", "apply": "Застосувати", - "warning": "Warning", - "payout": "Payout", - "learn-more": "Learn more in our", + "applying": "Applying...", + "warning": "Попередження", + "payout": "Виплата", + "learn-more": "Дізнайтесь більше на", "faq": "ЧаПи", "when": "Коли", "price": "Ціна", - "more-results": "More results", - "close": "Close", - "loading": "Loading", - "stop": "Stop", - "settings": "Settings", + "more-results": "Більше результатів", + "close": "Закрити", + "loading": "Завантаження", + "stop": "Зупинити", + "settings": "Налаштування", "confirm": "Confirm", - "username": "Username", - "past-few-days": "the past few days" + "username": "Ім'я користувача", + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Ви впевнені?", @@ -80,20 +82,20 @@ }, "announcements": { "dismiss": "Dismiss", - "next": "Next", + "next": "Далі", "later": "Later" }, "floating-faq": { - "toggle-icon-info": "Click to expand", + "toggle-icon-info": "Клацніть, щоб розгорнути", "help": "Help", "welcome": "Welcome to Ecency", "need-help": "Need Help?", - "search-placeholder": "Search", + "search-placeholder": "Пошук", "suggestion": "Suggested articles", "contact": "Contact us", "submit": "Submit", "username": "username", - "message": "message", + "message": "повідомлення", "no-results": "No results found" }, "entry-filter": { @@ -107,7 +109,7 @@ "filter-feed-friends": "Друзі", "filter-feed-subscriptions": "Спільноти", "filter-global": "Global", - "filter-community": "My Community", + "filter-community": "Мої спільноти", "filter-controversial": "Controversial", "filter-rising": "Rising", "filter-global-part1": "This feed contains ", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Теми" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Час", "sort-reputation": "Репутація", "sort-percent": "Відсоток", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "через {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Автозаповнення", "post-placeholder": "ім'я користувача/постійне джерело", "post-error": "Недійсна поштова адреса", - "post-error-exists": "Допис вже просувають", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Ваш запит надіслано. Він активується через декілька хвилин." }, "transfer": { diff --git a/src/common/i18n/locales/ur-IN.json b/src/common/i18n/locales/ur-IN.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ur-IN.json +++ b/src/common/i18n/locales/ur-IN.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/ur-PK.json b/src/common/i18n/locales/ur-PK.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/ur-PK.json +++ b/src/common/i18n/locales/ur-PK.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/uz-UZ.json b/src/common/i18n/locales/uz-UZ.json index c1804fbf62f..a0d492615b3 100644 --- a/src/common/i18n/locales/uz-UZ.json +++ b/src/common/i18n/locales/uz-UZ.json @@ -58,6 +58,7 @@ "replies": "javoblar", "done": "Bajarildi", "apply": "Qabul qilish", + "applying": "Applying...", "warning": "Ogohlantirish", "payout": "To'lov", "learn-more": "Batafsil bizning", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Aminmisiz?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Mavzular" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Vaqt", "sort-reputation": "Reputatsiya", "sort-percent": "Foiz", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "{{app}} orqali", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Avtomatik kiritish", "post-placeholder": "foydalanuvchi/permlink", "post-error": "Pochta manzili noto‘g‘ri", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Sizning so'rovingiz yuborildi. U bir necha daqiqada faollashadi." }, "transfer": { diff --git a/src/common/i18n/locales/vi-VN.json b/src/common/i18n/locales/vi-VN.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/vi-VN.json +++ b/src/common/i18n/locales/vi-VN.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/yo-NG.json b/src/common/i18n/locales/yo-NG.json index 55558508011..b0c8ded3c7c 100644 --- a/src/common/i18n/locales/yo-NG.json +++ b/src/common/i18n/locales/yo-NG.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Bẹ̀rẹ̀ ìpààrọ̀ ọ̀tun", "signing": "Signing..", "success-swap": "Ìpààrọ̀ tí yanjú!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/i18n/locales/zh-CN.json b/src/common/i18n/locales/zh-CN.json index c9ccb62e4ac..424cc02a3e9 100644 --- a/src/common/i18n/locales/zh-CN.json +++ b/src/common/i18n/locales/zh-CN.json @@ -58,6 +58,7 @@ "replies": "回复", "done": "完成", "apply": "应用", + "applying": "Applying...", "warning": "警告", "payout": "收益", "learn-more": "了解更多", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "你确定吗?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "主题" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "时间", "sort-reputation": "信誉积分", "sort-percent": "百分比", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "通过 {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "自动完成输入", "post-placeholder": "用户名/许可链接", "post-error": "不是有效的帖子地址", - "post-error-exists": "帖子已被推广", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "您的请求已提交。它将在几分钟后激活。" }, "transfer": { diff --git a/src/common/i18n/locales/zh-TW.json b/src/common/i18n/locales/zh-TW.json index dfa62e9aa92..7a644fccd30 100644 --- a/src/common/i18n/locales/zh-TW.json +++ b/src/common/i18n/locales/zh-TW.json @@ -58,6 +58,7 @@ "replies": "replies", "done": "Done", "apply": "Apply", + "applying": "Applying...", "warning": "Warning", "payout": "Payout", "learn-more": "Learn more in our", @@ -71,7 +72,8 @@ "settings": "Settings", "confirm": "Confirm", "username": "Username", - "past-few-days": "the past few days" + "past-few-days": "the past few days", + "you": "You" }, "confirm": { "title": "Are you sure?", @@ -224,7 +226,72 @@ "username-no-ascii-first-letter-error": "First character should be a Letter", "username-contains-symbols-error": "Should contain Letters, Numbers, Hyphen only", "username-contains-double-hyphens": "Should not contain double Hyphens", - "username-exists": "This username already registered. Please, try another one" + "username-exists": "This username already registered. Please, try another one", + "referral-invalid": "This referral is invalid. Please, try another one", + "referral-min-length-error": "Length of referral should be at least 3 characters", + "referral-max-length-error": "Length of referral should be no more than 16 characters" + }, + "onboard": { + "title-active-user": "Onboard a friend", + "title-visitor": "Ask from a friend", + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating": "Create for a friend", + "asking": " Ask from a friend", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager and/or Ecency mobile wallet, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" }, "trending-tags": { "title": "Topics" @@ -399,6 +466,12 @@ "auth-required-title": "Authorization required", "auth-required-desc": "You've to be authorized to see notifications", "wave": "Wave", + "simple": "Simple", + "advanced": "Advanced", + "author": "Author", + "choose-one": "Choose one", + "user": "User", + "search-query": "Search query", "columns": { "view-full-post": "View full post", "user": "User", @@ -432,8 +505,9 @@ "transfers": "Transfers", "delegations": "Delegations", "search-query": "Search query", - "enter-search-query": "Enter a search query and explore all posts", + "enter-search-query": "Configure a search query and explore all posts", "blogs": "Blogs", + "feeds": "Friends Feed", "posts": "Posts", "comments": "Comments", "all-history": "All history", @@ -459,9 +533,34 @@ "see-full-thread": "See full thread", "no-currency-data": "No data", "hide-replies": "Hide replies", - "filters": "Filters" + "filters": "Filters", + "market-swap-form": "Market swap form", + "market": "Market", + "swap-form": "Swapping form", + "msf-description": "Swap your funds quickie with zero latency.", + "faq": "Help center", + "faq-subtitle": "FAQ", + "faq-description": "Find answer to all your questions about Ecency in our help center.", + "no-replies": "No replies yet", + "add-new-reply": "Add new reply", + "no-content": "No content", + "infinite-loading": "Loading 🌊...", + "end-reached": "You've reached end of 🌊.", + "feed-end-reached": "You've reached end of feed.", + "topics-subtitle": "The most popular", + "replied-to": "replied to", + "edit-wave": "Edit", + "updated": "Edited {{n}} ago", + "balance": "Balance", + "whats-new": "What's new", + "whats-new-description": "Keep in track the Ecency updates", + "updates": "Updates", + "release-list": "Release versions", + "current": "Current", + "infinite-failed": "Oops, fetching failed. Sit tight, we are retrying..." }, "threads-form": { + "save": "Save", "publish": "Publish it!", "create-regular-post": "Create long post", "input-placeholder": "What's happening?", @@ -541,6 +640,7 @@ "start-new-one": "Start new Swap", "signing": "Signing..", "success-swap": "Successfully swapped!", + "calculating-in": "Calculating in", "advanced": { "history": "History", "stake": "Order book", @@ -576,7 +676,7 @@ "sort-timestamp": "Time", "sort-reputation": "Reputation", "sort-percent": "Percentage", - "pending-message": "You have pending votes. Please, wait a minute and re-open this dialog to see your vote." + "pending-message": "Content has pending votes. Please, wait a minute and refresh this dialog to see new votes." }, "entry": { "via-app": "via {{app}}", @@ -808,6 +908,7 @@ "comments-posts": "Posts / Comments:", "votes": "Votes:", "reblogs-follows": "Reblogs / Follows:", + "claim-accounts": "Claim account credits:", "no-outgoing": "No outgoing delegation", "no-incoming": "No incoming delegation", "delegate-title": "Delegate", @@ -1072,7 +1173,8 @@ "post-hint": "Autocomplete input", "post-placeholder": "username/permlink", "post-error": "Not a valid post address", - "post-error-exists": "The post is already promoted", + "post-boosted-exists": "This content is already boosted", + "post-promoted-exists": "This content is already promoted", "success-message": "Your request submitted. It will be activated in a couple minutes." }, "transfer": { diff --git a/src/common/img/svg.tsx b/src/common/img/svg.tsx index 128b4d0bc96..46faaee11d3 100644 --- a/src/common/img/svg.tsx +++ b/src/common/img/svg.tsx @@ -1193,7 +1193,7 @@ export const copyContent = ( height="24px" viewBox="0 0 24 24" width="24px" - fill="#FFFFFF" + fill="currentColor" > @@ -1963,6 +1963,36 @@ export const linkedinSvg = ( ); +export const downloadSvg = ( + + + + +); + +export const regenerateSvg = ( + + + +); + export const playListAddCheck = ( ) => { - return ( - <> - - - - {props.children} - - ); -}; diff --git a/src/common/pages/amp/entry-amp-page.tsx b/src/common/pages/amp/entry-amp-page.tsx deleted file mode 100644 index f52462af0ed..00000000000 --- a/src/common/pages/amp/entry-amp-page.tsx +++ /dev/null @@ -1,1159 +0,0 @@ -import React, { Fragment, Ref } from "react"; - -import { connect } from "react-redux"; -import { Link } from "react-router-dom"; -import { match } from "react-router"; -import moment from "moment"; - -import { - renderPostBody, - setProxyBase, - catchPostImage, - postBodySummary -} from "@ecency/render-helper"; - -import { Entry, EntryVote } from "../../store/entries/types"; -import { Community } from "../../store/communities/types"; -import { Account, FullAccount } from "../../store/accounts/types"; - -import EntryLink, { makePath as makeEntryPath } from "../../components/entry-link"; - -import BaseComponent from "../../components/base"; -import ProfileLink from "../../components/profile-link"; -import UserAvatar from "../../components/user-avatar"; -import Tag from "../../components/tag"; -import MdHandler from "../../components/md-handler"; -import Comment from "../../components/comment"; -import SimilarEntries from "../../components/similar-entries"; -import EditHistory from "../../components/edit-history"; -import { error } from "../../components/feedback"; -import Meta from "../../components/meta"; -import Theme from "../../components/theme/index"; -import Feedback from "../../components/feedback"; -import NotFound from "../../components/404"; -import AuthorInfoCard from "../../components/author-info-card"; - -import * as bridgeApi from "../../api/bridge"; -import { comment, formatError } from "../../api/operations"; - -import parseDate from "../../helper/parse-date"; -import entryCanonical from "../../helper/entry-canonical"; -import tempEntry from "../../helper/temp-entry"; -import appName from "../../helper/app-name"; -import { makeJsonMetaDataReply, createReplyPermlink } from "../../helper/posting"; -import isCommunity from "../../helper/is-community"; -import accountReputation from "../../helper/account-reputation"; - -import truncate from "../../util/truncate"; -import replaceLinkIdToDataId from "../../util/replace-link-id-to-data-id"; -import * as ss from "../../util/session-storage"; -import * as ls from "../../util/local-storage"; -import { crossPostMessage } from "../../helper/cross-post"; - -import { _t } from "../../i18n"; -import { Tsx } from "../../i18n/helper"; - -import { version } from "../../../../package.json"; - -import { PageProps, pageMapDispatchToProps, pageMapStateToProps } from "../common"; - -import defaults from "../../constants/defaults.json"; -import dmca from "../../constants/dmca.json"; - -import { getFollowing } from "../../api/hive"; -import { history } from "../../store"; -import { deleteForeverSvg, pencilOutlineSvg } from "../../img/svg"; -import entryDeleteBtn from "../../components/entry-delete-btn"; -import { SelectionPopover } from "../../components/selection-popover"; -import { commentHistory } from "../../api/private-api"; -import { getPost } from "../../api/bridge"; -import { StaticNavbar } from "../../components/static"; -import "./entry-amp-page.css"; -import { Helmet } from "react-helmet"; - -setProxyBase(defaults.imageServer); - -interface MatchParams { - category: string; - permlink: string; - username: string; -} - -interface Props extends PageProps { - match: match; - account: Account; - updateWalletValues: () => void; -} - -interface State { - loading: boolean; - replying: boolean; - showIfNsfw: boolean; - edit: boolean; - comment: string; - editHistory: boolean; - showProfileBox: boolean; - entryIsMuted: boolean; - selection: string; - isCommented: boolean; - isMounted: boolean; - postIsDeleted: boolean; - deletedEntry: { title: string; body: string; tags: any } | null; -} - -class EntryPage extends BaseComponent { - state: State = { - loading: false, - replying: false, - edit: false, - showIfNsfw: false, - editHistory: false, - comment: "", - isCommented: false, - showProfileBox: false, - entryIsMuted: false, - isMounted: false, - selection: "", - postIsDeleted: false, - deletedEntry: null - }; - - commentInput: Ref; - - constructor(props: Props) { - super(props); - this.commentInput = React.createRef(); - } - - viewElement: HTMLDivElement | undefined; - - componentDidMount() { - this.ensureEntry(); - this.fetchMutedUsers(); - const entry = this.getEntry(); - - const { location, global } = this.props; - if (global.usePrivate && location.search === "?history") { - this.toggleEditHistory(); - } - window.addEventListener("scroll", this.detect); - window.addEventListener("resize", this.detect); - let replyDraft = ss.get(`reply_draft_${entry?.author}_${entry?.permlink}`); - replyDraft = (replyDraft && replyDraft.trim()) || ""; - this.setState({ isMounted: true, selection: replyDraft }); - } - - componentDidUpdate(prevProps: Readonly, prevStates: State): void { - const { location } = this.props; - if (location.pathname !== prevProps.location.pathname) { - this.setState({ isMounted: false }); - this.ensureEntry(); - } - if (prevProps.activeUser !== this.props.activeUser) { - if (this.state.edit) { - this.setState({ edit: false }); - } - } - } - - componentWillUnmount() { - const p1 = new Promise((resolve, reject) => { - resolve(window.removeEventListener("scroll", this.detect)); - }); - const p2 = new Promise((resolve, reject) => { - resolve(window.removeEventListener("resize", this.detect)); - }); - Promise.all([p1, p2]); - this.setState({ isMounted: false }); - } - - loadDeletedEntry = (author: string, permlink: string) => { - commentHistory(author, permlink) - .then((resp) => { - this.stateSet({ - deletedEntry: { - body: resp.list[0].body, - title: resp.list[0].title, - tags: resp.list[0].tags - }, - loading: false - }); - }) - .catch(() => { - error(_t("g.server-error")); - }) - .finally(() => {}); - }; - - // detects distance between title and comments section sets visibility of profile card - detect = () => { - const { showProfileBox } = this.state; - const infoCard: HTMLElement | null = document.getElementById("avatar-fixed-container"); - const top = this?.viewElement?.getBoundingClientRect()?.top || 120; - - if (infoCard != null && window.scrollY > 180 && top && !(top <= 0)) { - infoCard.classList.replace("invisible", "visible"); - if (!showProfileBox) { - this.setState({ showProfileBox: true }); - } - } else if (infoCard != null && window.scrollY <= 180) { - infoCard.classList.replace("visible", "invisible"); - if (showProfileBox) { - this.setState({ showProfileBox: false }); - } - } else if (top && top <= 0 && infoCard !== null) { - infoCard.classList.replace("visible", "invisible"); - if (showProfileBox) { - this.setState({ showProfileBox: false }); - } - } else return; - }; - - updateReply = (text: string) => { - const entry = this.getEntry(); - const { activeUser, updateReply } = this.props; - - if (entry) { - const { permlink, parent_author: parentAuthor, parent_permlink: parentPermlink } = entry; - const jsonMeta = makeJsonMetaDataReply(entry.json_metadata.tags || ["ecency"], version); - - this.stateSet({ replying: true }); - - comment( - activeUser?.username!, - parentAuthor!, - parentPermlink!, - permlink, - "", - text, - jsonMeta, - null - ) - .then(() => { - const nReply: Entry = { - ...entry, - body: text - }; - - this.setState({ comment: text, isCommented: true }); - ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); - updateReply(nReply); // update store - this.toggleEdit(); // close comment box - this.reload(); - }) - .catch((e) => { - error(...formatError(e)); - }) - .finally(() => { - this.stateSet({ replying: false, isCommented: false }); - }); - } - }; - - toggleEdit = () => { - const { edit } = this.state; - this.stateSet({ edit: !edit }); - }; - - deleted = async () => { - const { deleteReply } = this.props; - let entry = this.getEntry(); - entry && deleteReply(entry); - ls.set(`deletedComment`, entry?.post_id); - history?.goBack(); - }; - - toggleEditHistory = () => { - const { editHistory } = this.state; - this.stateSet({ editHistory: !editHistory }); - }; - - ensureEntry = async () => { - const { match, addEntry, updateEntry, addCommunity, activeUser, history } = this.props; - const entry = this.getEntry(); - const { category, username, permlink } = match.params; - const author = username.replace("@", ""); - - let reducerFn = updateEntry; - - if (!entry) { - // let urlPartOne = match.url.split('/')[1]; - // let urlPartTwo = match.url.split('/')[2]; - // let isInvalidUrl = urlPartOne == urlPartTwo; - // if(isInvalidUrl){ - // let address: any = match.url.split('/'); - // address.shift(); - // address.shift(); - // address = address.join("/"); - // history.push('/' + address); - // } else { - // The entry isn't in reducer. Fetch it and add to reducer. - this.stateSet({ loading: true }); - reducerFn = addEntry; - // } - } else { - const updated = moment.utc(entry.updated); - const now = moment.utc(Date.now()); - - const diffMs = now.diff(updated); - const duration = moment.duration(diffMs); - if (duration.asSeconds() < 10) { - // don't re-fetch recently updated post. - return; - } - } - - bridgeApi - .getPost(author, permlink) - .then((entry) => { - if (entry) { - reducerFn(entry); - this.stateSet({ loading: false }); - } - - if (isCommunity(category)) { - this.stateSet({ loading: false }); - return bridgeApi.getCommunity(category, activeUser?.username); - } - - return null; - }) - .then((data: Community | null) => { - if (data) { - addCommunity(data); - } - }) - .catch((e) => { - let errorMessage = e.jse_info && e.jse_info; - let arr = []; - for (let p in errorMessage) arr.push(errorMessage[p]); - errorMessage = arr.toString().replace(/,/g, ""); - if (errorMessage && errorMessage.length > 0 && errorMessage.includes("was deleted")) { - this.setState({ postIsDeleted: true, loading: true }); - this.loadDeletedEntry(author, permlink); - } - }) - .finally(() => { - this.stateSet({ isMounted: true }); - }); - }; - - getEntry = (): Entry | undefined => { - const { entries, match } = this.props; - const { username, permlink } = match.params; - const author = username.replace("@", ""); - - const groupKeys = Object.keys(entries); - let entry: Entry | undefined = undefined; - - for (const k of groupKeys) { - entry = entries[k].entries.find((x) => x.author === author && x.permlink === permlink); - if (entry) { - if (dmca.some((rx: string) => new RegExp(rx).test(`${entry?.author}/${entry?.permlink}`))) { - entry.body = "This post is not available due to a copyright/fraudulent claim."; - entry.title = ""; - } - break; - } - } - - return entry; - }; - - getCommunity = (): Community | null => { - const { communities, match } = this.props; - const { category } = match.params; - return communities.find((x) => x.name === category) || null; - }; - - afterVote = (votes: EntryVote[], estimated: number) => { - const _entry = this.getEntry()!; - const { updateEntry } = this.props; - - const { payout } = _entry; - const newPayout = payout + estimated; - if (_entry.active_votes) { - updateEntry({ - ..._entry, - active_votes: votes, - payout: newPayout, - pending_payout_value: String(newPayout) - }); - } else { - getPost(_entry.author, _entry.permlink) - .then((entry) => { - if (entry) { - return updateEntry({ - ..._entry, - active_votes: [...entry.active_votes, ...votes], - payout: newPayout, - pending_payout_value: String(newPayout) - }); - } - return; - }) - .catch((e) => { - console.log(e); - }); - } - }; - - replySubmitted = (text: string) => { - const entry = this.getEntry()!; - const { activeUser, addReply, updateEntry } = this.props; - - if (!activeUser || !activeUser.data.__loaded) { - return; - } - - const { author: parentAuthor, permlink: parentPermlink } = entry; - const author = activeUser.username; - const permlink = createReplyPermlink(entry.author); - const tags = entry.json_metadata.tags || ["ecency"]; - - const jsonMeta = makeJsonMetaDataReply(tags, version); - - this.stateSet({ replying: true }); - - comment(author, parentAuthor, parentPermlink, permlink, "", text, jsonMeta, null, true) - .then(() => { - const nReply = tempEntry({ - author: activeUser.data as FullAccount, - permlink, - parentAuthor, - parentPermlink, - title: "", - body: text, - tags, - description: null - }); - - // add new reply to store - addReply(nReply); - - // remove reply draft - ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); - this.stateSet({ isCommented: true }); - - if (entry.children === 0) { - // Activate discussion section with first comment. - const nEntry: Entry = { - ...entry, - children: 1 - }; - - updateEntry(nEntry); - } - }) - .catch((e) => { - error(...formatError(e)); - }) - .finally(() => { - this.stateSet({ replying: false, isCommented: false }); - }); - }; - - resetSelection = () => { - this.setState({ selection: "" }); - }; - - reload = () => { - this.stateSet({ loading: true }); - this.ensureEntry(); - }; - - fetchMutedUsers = () => { - const { activeUser } = this.props; - const entry = this.getEntry()!; - if (activeUser && entry) { - getFollowing(activeUser.username, "", "ignore", 100).then((r) => { - if (r) { - let filterList = r.map((user) => user.following); - if (!this.state.entryIsMuted) { - this.setState({ entryIsMuted: filterList.includes(entry.author) }); - } - } - }); - } - }; - - getCommentAmpUrl = (url: string) => { - const index = url.indexOf("#"); - if (index > -1) { - return url.slice(0, index) + "?amps"; - } - return url; - }; - - render() { - const { - replying, - showIfNsfw, - editHistory, - entryIsMuted, - edit, - comment /*commentText,*/, - isMounted, - postIsDeleted, - deletedEntry, - showProfileBox - } = this.state; - const { global, history, match, location } = this.props; - - const entry = this.getEntry(); - if (postIsDeleted) { - const { username, permlink } = match.params; - const author = username.replace("@", ""); - - return ( -

    - - {deletedEntry && ( -
    - -
    -
    -
    -
    - {!global.isMobile && showProfileBox && ( - - )} -
    -
    -
    -
    -
    -
    - {_t("entry.deleted-content-warning")} - - {_t("points.history")} - {" "} - {_t("g.logs")}. -
    -
    -

    {deletedEntry!.title}

    -
    -
    - {editHistory && ( - - )} -
    - {SimilarEntries({ - ...this.props, - entry: { - permlink, - author, - json_metadata: { tags: deletedEntry.tags } - } as any, - display: "" - })} -
    -
    -
    -
    -
    - )} -
    - ); - } - - if (!entry) { - return NotFound({ ...this.props }); - } - - let setRef = (el: HTMLDivElement) => { - this.viewElement = el; - }; - - const originalEntry = entry.original_entry || null; - - const community = this.getCommunity(); - - const reputation = accountReputation(entry.author_reputation); - const published = moment(parseDate(entry.created)); - const modified = moment(parseDate(entry.updated)); - - // Sometimes tag list comes with duplicate items - const tags = entry.json_metadata.tags && [...new Set(entry.json_metadata.tags)]; - // If category is not present in tags then add - if (entry.category && tags && tags[0] !== entry.category) { - tags.splice(0, 0, entry.category); - } - const app = appName(entry.json_metadata.app); - const appShort = app.split("/")[0].split(" ")[0]; - - const { activeUser } = this.props; - - const isComment = !!entry.parent_author; - const ownEntry = activeUser && activeUser.username === entry.author; - const isHidden = entry?.net_rshares < -7000000000 && entry?.active_votes.length > 3; // 1000 HPstat - const isMuted = entry?.stats?.gray && entry?.net_rshares >= 0 && entry?.author_reputation >= 0; - const isLowReputation = - entry?.stats?.gray && entry?.net_rshares >= 0 && entry?.author_reputation < 0; - const mightContainMutedComments = activeUser && entryIsMuted && !isComment && !ownEntry; - - // Meta config - const url = entryCanonical(entry, true) || ""; - - const nsfw = entry.json_metadata.tags && entry.json_metadata.tags.includes("nsfw"); - - const metaProps = { - title: `${truncate(entry.title, 67)}`, - description: `${truncate(postBodySummary(entry.body, 210), 140)} by @${entry.author}`, - url: entry.url, - canonical: url, - image: - catchPostImage(entry, 1200, 1000, global.canUseWebp ? "webp" : "match") || - `https://ecency.com/og.jpg`, - published: published.toISOString(), - modified: modified.toISOString(), - tag: tags ? (isCommunity(tags[0]) ? tags[1] : tags[0]) : "", - keywords: tags && tags.join(", ") - }; - let containerClasses = global.isElectron - ? "app-content entry-page mt-0 pt-6" - : "app-content entry-page"; - - return ( - <> - - - - - -
    -
    - {originalEntry && ( -
    -
    - {_t("entry.cross-post-by")} - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - - {`@${entry.author}`} -
    - ) - })} -
    -
    - {Tag({ - ...this.props, - tag: entry.category, - type: "link", - children:
    {entry.community_title}
    - })} - {_t("entry.cross-post-community")} -
    -
    - {'"'} - {crossPostMessage(entry.body)} - {'"'} -
    -
    - )} -
    - - - - - - - - - - - - - {(() => { - if (nsfw && !showIfNsfw && !global.nsfw) { - return ( -
    -
    - NSFW -
    -
    - { - e.preventDefault(); - this.stateSet({ showIfNsfw: true }); - }} - > - {_t("nsfw.reveal")} - {" "} - {_t("g.or").toLowerCase()}{" "} - {activeUser && ( - <> - {_t("nsfw.settings-1")}{" "} - { - e.preventDefault(); - history.push(`/@${activeUser.username}/settings`); - }} - > - {_t("nsfw.settings-2")} - - {"."} - - )} - {!activeUser && ( - <> - - - - {"."} - - )} -
    -
    - ); - } - - return ( - <> - {(() => { - // Cross post body - if (originalEntry) { - const published = moment(parseDate(originalEntry.created)); - const reputation = accountReputation(originalEntry.author_reputation); - const renderedBody = { - __html: renderPostBody(originalEntry.body, false, global.canUseWebp) - }; - - return ( - <> -
    -

    {originalEntry.title}

    -
    - {ProfileLink({ - ...this.props, - username: originalEntry.author, - children: ( -
    - -
    - ) - })} - -
    -
    - {ProfileLink({ - ...this.props, - username: originalEntry.author, - children: ( -
    - - - - - {reputation} - -
    - ) - })} -
    - -
    - - {published.fromNow()} - - -
    - {_t("entry.community-in")} - {Tag({ - ...this.props, - tag: originalEntry.category, - type: "link", - children: ( -
    - {originalEntry.community - ? originalEntry.community_title - : `#${originalEntry.category}`} -
    - ) - })} -
    -
    -
    - -
    -
    -
    {}} - /> - - ); - } - - const _entry_body = replaceLinkIdToDataId(entry.body); - let renderedBody = { - __html: renderPostBody( - isComment ? (comment.length > 0 ? comment : _entry_body) : _entry_body, - false, - global.canUseWebp - ) - }; - const ctitle = entry.community ? entry.community_title : ""; - let extraItems = - ownEntry && isComment - ? [ - { - label: _t("g.edit"), - onClick: this.toggleEdit, - icon: pencilOutlineSvg - } - ] - : []; - if ( - !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout) && - ownEntry && - isComment - ) { - extraItems = [ - ...extraItems, - { - label: "", - onClick: () => {}, - icon: entryDeleteBtn({ - ...this.props, - entry, - setDeleteInProgress: (value) => this.setState({ loading: value }), - onSuccess: this.deleted, - children: ( - - {deleteForeverSvg} {_t("g.delete")} - - ) - }) - } - ]; - } - - return ( - <> -
    - {isMuted && ( -
    - - - - - -
    - )} - - {isHidden && ( -
    - {_t("entry.hidden-warning")} -
    - )} - - {isLowReputation && ( -
    - {_t("entry.lowrep-warning")} -
    - )} - - {mightContainMutedComments && ( -
    - {_t("entry.comments-hidden")} -
    - )} - - {isComment && ( -
    -
    RE: {entry.title}
    -
    - {_t("entry.comment-entry-title")} -
    -

    {entry.title}

    -
      -
    • - - {_t("entry.comment-entry-go-root")} - -
    • - {entry.depth > 1 && ( -
    • - - {_t("entry.comment-entry-go-parent")} - -
    • - )} -
    -
    - )} -

    {entry.title}

    -
    - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - -
    - ) - })} - -
    -
    - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - - - - - {reputation} - -
    - ) - })} -
    - -
    - - {published.fromNow()} - - -
    - {_t("entry.community-in")} - {Tag({ - ...this.props, - tag: entry.category, - type: "link", - children: ( -
    - {entry.community - ? entry.community_title - : `#${entry.category}`} -
    - ) - })} -
    -
    -
    - -
    -
    - - {!edit ? ( - <> - { - this.setState({ selection: `>${text}\n\n` }); - (this.commentInput! as any).current!.focus(); - }} - > -
    - - - ) : ( - Comment({ - ...this.props, - defText: entry.body, - submitText: _t("g.update"), - cancellable: true, - onSubmit: this.updateReply, - onCancel: this.toggleEdit, - inProgress: replying, - autoFocus: true, - inputRef: this.commentInput, - entry: entry - }) - )} - - {/* {this.setState({selection: `>${text}\n\n`}); (this.commentInput! as any).current!.focus();}}> -
    - */} - - ); - })()} - - {!global.isMobile && ( -
    - {showProfileBox && } -
    - )} - -
    -
    - {tags && - tags.map((t, i) => { - if (typeof t === "string") { - if ( - entry.community && - entry.community_title && - t === entry.community - ) { - return ( - - {Tag({ - ...this.props, - tag: { - name: entry.community, - title: entry.community_title - }, - type: "link", - children:
    {t}
    - })} -
    - ); - } - - return ( - - {Tag({ - ...this.props, - tag: t.trim(), - type: "link", - children:
    {t}
    - })} -
    - ); - } else { - return; - } - })} -
    -
    -
    - {published.fromNow()} -
    - - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - {entry.author} - - {reputation} - -
    - ) - })} - {app && ( - <> - - - - )} -
    -
    - - {originalEntry && ( - - )} - - {!originalEntry && - !isComment && - SimilarEntries({ - ...this.props, - entry, - display: !activeUser ? "" : "d-none" - })} - - {!originalEntry && - !isComment && - SimilarEntries({ - ...this.props, - entry, - display: !activeUser ? "d-none" : "" - })} - - ); - })()} -
    -
    -
    - - ); - } -} - -export default connect(pageMapStateToProps, pageMapDispatchToProps)(EntryPage as any); diff --git a/src/common/pages/community-functional.tsx b/src/common/pages/community-functional.tsx index 522efd7ae69..afc690ad097 100644 --- a/src/common/pages/community-functional.tsx +++ b/src/common/pages/community-functional.tsx @@ -35,6 +35,8 @@ import { EntryListContent } from "../components/entry-list"; import { connect } from "react-redux"; import { withPersistentScroll } from "../components/with-persistent-scroll"; import "./community.scss"; +import { QueryIdentifiers, useCommunityCache } from "../core"; +import { useQueryClient } from "@tanstack/react-query"; interface MatchParams { filter: string; @@ -50,19 +52,24 @@ export const CommunityPage = (props: Props) => { return props.location.search.replace("?", "").replace("q", "").replace("=", ""); }; - const [community, setCommunity] = useState(null); - const [account, setAccount] = useState(null); - const [loading, setLoading] = useState(true); + const queryClient = useQueryClient(); + const { data: community } = useCommunityCache(props.match.params.name); + + const [account, setAccount] = useState( + props.accounts.find(({ name }) => [props.match.params.name]) + ); const [typing, setTyping] = useState(false); const [search, setSearch] = useState(getSearchParam()); const [searchDataLoading, setSearchDataLoading] = useState(getSearchParam().length > 0); const [searchData, setSearchData] = useState([]); + const [isLoading, setIsLoading] = useState(false); const prevMatch = usePrevious(props.match); const prevActiveUser = usePrevious(props.activeUser); useEffect(() => { - ensureData(); + setIsLoading(true); + if (search.length) handleInputChange(search); const { match, fetchEntries } = props; @@ -73,6 +80,14 @@ export const CommunityPage = (props: Props) => { fetchSubscriptions(); }, []); + useEffect(() => { + if (community?.name === props.match.params.name) { + setIsLoading(false); + props.addAccount(community); + setAccount({ ...account, ...community }); + } + }, [community]); + useEffect(() => { const { match, fetchEntries } = props; const { filter, name } = match.params; @@ -84,7 +99,8 @@ export const CommunityPage = (props: Props) => { const { params: prevParams } = prevMatch; // community changed. fetch community and account data. - if (name !== prevParams.name) ensureData(); + if (name !== prevParams.name) + queryClient.invalidateQueries([QueryIdentifiers.COMMUNITY, match.params.name]); // community or filter changed if ((filter !== prevParams.filter || name !== prevParams.name) && EntryFilter[filter]) { @@ -108,36 +124,11 @@ export const CommunityPage = (props: Props) => { setSearchData( data.results.sort((a, b) => Date.parse(b.created_at) - Date.parse(a.created_at)) ); - setLoading(false); setSearchDataLoading(false); } } }; - const ensureData = async (): Promise => { - const { match, communities, addCommunity, accounts, addAccount, activeUser } = props; - - const name = match.params.name; - const community = communities.find((x) => x.name === name); - const account = accounts.find((x) => x.name === name); - - // Community or account data aren't in reducer. Show loading indicator. - if (!community || !account) setLoading(true); - try { - const data = await getCommunity(name, activeUser?.username); - if (data) { - addCommunity(data); - setCommunity(data); - } - if (data?.name === name) { - addAccount(data); - setAccount({ ...account, ...data }); - } - } finally { - setLoading(false); - } - }; - const fetchSubscriptions = async () => { const { activeUser, subscriptions, updateSubscriptions } = props; if (activeUser && subscriptions.length === 0) { @@ -158,8 +149,8 @@ export const CommunityPage = (props: Props) => { }; const reload = async () => { - setLoading(true); - await ensureData(); + queryClient.invalidateQueries([QueryIdentifiers.COMMUNITY, props.match.params.name]); + const { match, fetchEntries, invalidateEntries } = props; const { filter, name } = match.params; @@ -195,7 +186,7 @@ export const CommunityPage = (props: Props) => { }; const navBar = props.global.isElectron ? ( - + ) : ( ); @@ -215,12 +206,7 @@ export const CommunityPage = (props: Props) => { } >
    - +
    @@ -318,7 +304,7 @@ export const CommunityPage = (props: Props) => {
    - ) : loading ? ( + ) : isLoading ? ( <> {navBar} diff --git a/src/common/pages/entry.tsx b/src/common/pages/entry.tsx deleted file mode 100644 index 5d555945a1f..00000000000 --- a/src/common/pages/entry.tsx +++ /dev/null @@ -1,1326 +0,0 @@ -import React, { Fragment, Ref } from "react"; - -import { connect } from "react-redux"; -import { Link } from "react-router-dom"; -import { match } from "react-router"; -import moment from "moment"; -import { - renderPostBody, - setProxyBase, - catchPostImage, - postBodySummary -} from "@ecency/render-helper"; - -import { Entry, EntryVote } from "../store/entries/types"; -import { Community } from "../store/communities/types"; -import { Account, FullAccount } from "../store/accounts/types"; -import EntryLink, { makePath as makeEntryPath } from "../components/entry-link"; - -import BaseComponent from "../components/base"; -import ProfileLink from "../components/profile-link"; -import UserAvatar from "../components/user-avatar"; -import Tag from "../components/tag"; -import EntryVoteBtn from "../components/entry-vote-btn/index"; -import EntryPayout from "../components/entry-payout/index"; -import EntryVotes from "../components/entry-votes"; -import Discussion from "../components/discussion"; -import MdHandler from "../components/md-handler"; -import LinearProgress from "../components/linear-progress"; -import EntryReblogBtn from "../components/entry-reblog-btn/index"; -import Comment from "../components/comment"; -import CommentEngagement from "../components/comment-engagement"; -import SimilarEntries from "../components/similar-entries"; -import BookmarkBtn from "../components/bookmark-btn"; -import EditHistory from "../components/edit-history"; -import { error } from "../components/feedback"; -import Meta from "../components/meta"; -import Theme from "../components/theme/index"; -import Feedback from "../components/feedback"; -import NavBar from "../components/navbar/index"; -import NavBarElectron from "../../desktop/app/components/navbar"; -import NotFound from "../components/404"; -import ScrollToTop from "../components/scroll-to-top"; -import EntryBodyExtra from "../components/entry-body-extra"; -import EntryTipBtn from "../components/entry-tip-btn"; -import EntryMenu from "../components/entry-menu"; -import AuthorInfoCard from "../components/author-info-card"; -import ReadTime from "../components/entry-read-time"; -import Tooltip from "../components/tooltip"; - -import * as bridgeApi from "../api/bridge"; -import { comment, formatError } from "../api/operations"; - -import parseDate from "../helper/parse-date"; -import entryCanonical from "../helper/entry-canonical"; -import tempEntry from "../helper/temp-entry"; -import appName from "../helper/app-name"; -import { makeJsonMetaDataReply, createReplyPermlink } from "../helper/posting"; -import isCommunity from "../helper/is-community"; -import accountReputation from "../helper/account-reputation"; - -import truncate from "../util/truncate"; -import replaceLinkIdToDataId from "../util/replace-link-id-to-data-id"; -import * as ss from "../util/session-storage"; -import * as ls from "../util/local-storage"; -import { crossPostMessage } from "../helper/cross-post"; - -import { _t } from "../i18n"; -import { Tsx } from "../i18n/helper"; - -import { version } from "../../../package.json"; - -import { PageProps, pageMapDispatchToProps, pageMapStateToProps } from "./common"; - -import defaults from "../constants/defaults.json"; -import dmca from "../constants/dmca.json"; - -import { getFollowing } from "../api/hive"; -import { history } from "../store"; -import { - deleteForeverSvg, - pencilOutlineSvg, - informationVariantSvg, - rawContentSvg -} from "../img/svg"; -import entryDeleteBtn from "../components/entry-delete-btn"; -import { SelectionPopover } from "../components/selection-popover"; -import { commentHistory } from "../api/private-api"; -import { getPost } from "../api/bridge"; -import "./entry.scss"; - -setProxyBase(defaults.imageServer); - -interface MatchParams { - category: string; - permlink: string; - username: string; -} - -interface Props extends PageProps { - match: match; - account: Account; - updateWalletValues: () => void; -} - -interface State { - loading: boolean; - replying: boolean; - showIfNsfw: boolean; - edit: boolean; - comment: string; - editHistory: boolean; - showProfileBox: boolean; - showWordCount: boolean; - isRawContent: boolean; - entryIsMuted: boolean; - selection: string; - isCommented: boolean; - isMounted: boolean; - postIsDeleted: boolean; - deletedEntry: { title: string; body: string; tags: any } | null; -} - -class EntryPage extends BaseComponent { - state: State = { - loading: false, - replying: false, - edit: false, - showIfNsfw: false, - editHistory: false, - comment: "", - isCommented: false, - showProfileBox: false, - showWordCount: false, - isRawContent: false, - entryIsMuted: false, - isMounted: false, - selection: "", - postIsDeleted: false, - deletedEntry: null - }; - - commentInput: Ref; - - constructor(props: Props) { - super(props); - this.commentInput = React.createRef(); - } - - viewElement: HTMLDivElement | undefined; - - componentDidMount() { - this.ensureEntry(); - const { history } = this.props; - if (history?.location.search.includes("?referral")) { - const userName = history.location.search.split("=")[1]; - ls.set("referral", userName); - } - this.fetchMutedUsers(); - const entry = this.getEntry(); - - const { location, global } = this.props; - const queryParams = new URLSearchParams(location.search); - if (global.usePrivate && queryParams.has("history")) { - this.toggleEditHistory(); - } else if (global.usePrivate && queryParams.has("raw")) { - this.setState({ isRawContent: true }); - } - - window.addEventListener("scroll", this.detect); - window.addEventListener("resize", this.detect); - let replyDraft = ss.get(`reply_draft_${entry?.author}_${entry?.permlink}`); - replyDraft = (replyDraft && replyDraft.trim()) || ""; - - this.setState({ isMounted: true, selection: replyDraft }); - } - - componentDidUpdate(prevProps: Readonly, prevStates: State): void { - const { location } = this.props; - if (location.pathname !== prevProps.location.pathname) { - this.setState({ isMounted: false }); - this.ensureEntry(); - } - if (prevProps.activeUser !== this.props.activeUser) { - if (this.state.edit) { - this.setState({ edit: false }); - } - } - } - - componentWillUnmount() { - const p1 = new Promise((resolve, reject) => { - resolve(window.removeEventListener("scroll", this.detect)); - }); - const p2 = new Promise((resolve, reject) => { - resolve(window.removeEventListener("resize", this.detect)); - }); - Promise.all([p1, p2]); - this.setState({ isMounted: false }); - } - - loadDeletedEntry = (author: string, permlink: string) => { - commentHistory(author, permlink) - .then((resp) => { - this.stateSet({ - deletedEntry: { - body: resp.list[0].body, - title: resp.list[0].title, - tags: resp.list[0].tags - }, - loading: false - }); - }) - .catch(() => { - error(_t("g.server-error")); - }) - .finally(() => {}); - }; - - // detects distance between title and comments section sets visibility of profile card - detect = () => { - const { showProfileBox, showWordCount } = this.state; - const infoCard: HTMLElement | null = document.getElementById("avatar-fixed-container"); - const wordCounter: HTMLElement | null = document.getElementById("word-count"); - const top = this?.viewElement?.getBoundingClientRect()?.top || 120; - - if (infoCard != null && window.scrollY > 180 && top && !(top <= 0)) { - infoCard.classList.replace("invisible", "visible"); - if (!showProfileBox) { - this.setState({ showProfileBox: true }); - } - } else if (infoCard != null && window.scrollY <= 180) { - infoCard.classList.replace("visible", "invisible"); - if (showProfileBox) { - this.setState({ showProfileBox: false }); - } - } else if (top && top <= 0 && infoCard !== null) { - infoCard.classList.replace("visible", "invisible"); - if (showProfileBox) { - this.setState({ showProfileBox: false }); - } - } else return; - - if (top && top > 0) { - if (!showWordCount) { - this.setState({ showWordCount: true }); - } - } else if (top && top < 0) { - wordCounter?.classList.replace("visible", "invisible"); - if (showWordCount) { - this.setState({ showWordCount: false }); - } - } else return; - }; - - updateReply = (text: string) => { - const entry = this.getEntry(); - const { activeUser, updateReply } = this.props; - - if (entry) { - const { permlink, parent_author: parentAuthor, parent_permlink: parentPermlink } = entry; - const jsonMeta = makeJsonMetaDataReply(entry.json_metadata.tags || ["ecency"], version); - - this.stateSet({ replying: true }); - - comment( - activeUser?.username!, - parentAuthor!, - parentPermlink!, - permlink, - "", - text, - jsonMeta, - null - ) - .then(() => { - const nReply: Entry = { - ...entry, - body: text - }; - - this.setState({ comment: text, isCommented: true }); - ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); - updateReply(nReply); // update store - this.toggleEdit(); // close comment box - this.reload(); - }) - .catch((e) => { - error(...formatError(e)); - }) - .finally(() => { - this.stateSet({ replying: false, isCommented: false }); - }); - } - }; - - toggleEdit = () => { - const { edit } = this.state; - this.stateSet({ edit: !edit }); - }; - - toggleRawContent = () => { - const { isRawContent } = this.state; - this.setState({ isRawContent: !isRawContent }, this.handleURL); - }; - - handleURL = () => { - const { isRawContent } = this.state; - const { history } = this.props; - if (isRawContent) { - history.push(`${history.location.pathname}?raw`); - } else { - const queryParams = new URLSearchParams(location.search); - if (queryParams.has("raw")) { - queryParams.delete("raw"); - history.replace({ - search: queryParams.toString() - }); - } - } - }; - - deleted = async () => { - const { deleteReply } = this.props; - let entry = this.getEntry(); - entry && deleteReply(entry); - ls.set(`deletedComment`, entry?.post_id); - history?.goBack(); - }; - - toggleEditHistory = () => { - const { editHistory } = this.state; - this.stateSet({ editHistory: !editHistory }); - }; - - ensureEntry = async () => { - const { match, addEntry, updateEntry, addCommunity, activeUser, history } = this.props; - const entry = this.getEntry(); - const { category, username, permlink } = match.params; - const author = username.replace("@", ""); - - let reducerFn = updateEntry; - - if (!entry) { - // let urlPartOne = match.url.split('/')[1]; - // let urlPartTwo = match.url.split('/')[2]; - // let isInvalidUrl = urlPartOne == urlPartTwo; - // if(isInvalidUrl){ - // let address: any = match.url.split('/'); - // address.shift(); - // address.shift(); - // address = address.join("/"); - // history.push('/' + address); - // } else { - // The entry isn't in reducer. Fetch it and add to reducer. - this.stateSet({ loading: true }); - reducerFn = addEntry; - // } - } else { - const updated = moment.utc(entry.updated); - const now = moment.utc(Date.now()); - - const diffMs = now.diff(updated); - const duration = moment.duration(diffMs); - if (duration.asSeconds() < 10) { - // don't re-fetch recently updated post. - return; - } - } - - bridgeApi - .getPost(author, permlink) - .then((entry) => { - if (entry) { - reducerFn(entry); - } - if (isCommunity(category)) { - this.stateSet({ loading: false }); - return bridgeApi.getCommunity(category, activeUser?.username); - } - - return null; - }) - .then((data: Community | null) => { - if (data) { - addCommunity(data); - } - }) - .catch((e) => { - let errorMessage = e.jse_info && e.jse_info; - let arr = []; - for (let p in errorMessage) arr.push(errorMessage[p]); - errorMessage = arr.toString().replace(/,/g, ""); - if (errorMessage && errorMessage.length > 0 && errorMessage.includes("was deleted")) { - this.setState({ postIsDeleted: true, loading: true }); - this.loadDeletedEntry(author, permlink); - } - }) - .finally(() => { - this.stateSet({ isMounted: true, loading: false }); - }); - }; - - getEntry = (): Entry | undefined => { - const { entries, match } = this.props; - const { username, permlink } = match.params; - const author = username.replace("@", ""); - - const groupKeys = Object.keys(entries); - let entry: Entry | undefined = undefined; - - for (const k of groupKeys) { - entry = entries[k].entries.find((x) => x.author === author && x.permlink === permlink); - if (entry) { - if (dmca.some((rx: string) => new RegExp(rx).test(`${entry?.author}/${entry?.permlink}`))) { - entry.body = "This post is not available due to a copyright/fraudulent claim."; - entry.title = ""; - } - break; - } - } - - return entry; - }; - - getCommunity = (): Community | null => { - const { communities, match } = this.props; - const { category } = match.params; - return communities.find((x) => x.name === category) || null; - }; - - afterVote = (votes: EntryVote[], estimated: number) => { - const _entry = this.getEntry()!; - const { updateEntry } = this.props; - - const { payout } = _entry; - const newPayout = payout + estimated; - if (_entry.active_votes) { - updateEntry({ - ..._entry, - active_votes: votes, - payout: newPayout, - pending_payout_value: String(newPayout) - }); - } else { - getPost(_entry.author, _entry.permlink) - .then((entry) => { - if (entry) { - return updateEntry({ - ..._entry, - active_votes: [...entry.active_votes, ...votes], - payout: newPayout, - pending_payout_value: String(newPayout) - }); - } - return; - }) - .catch((e) => { - console.log(e); - }); - } - }; - - replySubmitted = (text: string) => { - const entry = this.getEntry()!; - const { activeUser, addReply, updateEntry } = this.props; - - if (!activeUser || !activeUser.data.__loaded) { - return; - } - - const { author: parentAuthor, permlink: parentPermlink } = entry; - const author = activeUser.username; - const permlink = createReplyPermlink(entry.author); - const tags = entry.json_metadata.tags || ["ecency"]; - - const jsonMeta = makeJsonMetaDataReply(tags, version); - - this.stateSet({ replying: true }); - - comment(author, parentAuthor, parentPermlink, permlink, "", text, jsonMeta, null, true) - .then(() => { - const nReply = tempEntry({ - author: activeUser.data as FullAccount, - permlink, - parentAuthor, - parentPermlink, - title: "", - body: text, - tags, - description: null - }); - - // add new reply to store - addReply(nReply); - - // remove reply draft - ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); - this.stateSet({ isCommented: true }); - - if (entry.children === 0) { - // Activate discussion section with first comment. - const nEntry: Entry = { - ...entry, - children: 1 - }; - - updateEntry(nEntry); - } - }) - .catch((e) => { - error(...formatError(e)); - }) - .finally(() => { - this.stateSet({ replying: false, isCommented: false }); - }); - }; - - resetSelection = () => { - this.setState({ selection: "" }); - }; - - reload = () => { - this.stateSet({ loading: true }); - this.ensureEntry(); - }; - - fetchMutedUsers = () => { - const { activeUser } = this.props; - const entry = this.getEntry()!; - if (activeUser && entry) { - getFollowing(activeUser.username, "", "ignore", 100).then((r) => { - if (r) { - let filterList = r.map((user) => user.following); - if (!this.state.entryIsMuted) { - this.setState({ entryIsMuted: filterList.includes(entry.author) }); - } - } - }); - } - }; - - render() { - const { - loading, - replying, - showIfNsfw, - editHistory, - entryIsMuted, - edit, - comment, - postIsDeleted, - deletedEntry, - showProfileBox, - showWordCount - } = this.state; - const { - global, - history, - match, - location, - dynamicProps, - users, - setActiveUser, - ui, - updateActiveUser, - toggleUIProp, - deleteUser, - account, - updateWalletValues - } = this.props; - const { isRawContent } = this.state; - - let navBar = global.isElectron ? ( - NavBarElectron({ - ...this.props, - reloadFn: this.reload, - reloading: loading - }) - ) : ( - - ); - - if (loading) { - navBar = ( - <> - {navBar} -
    -
    -
    - -
    -
    -
    - - ); - return navBar; - } - - const entry = this.getEntry(); - if (postIsDeleted) { - const { username, permlink } = match.params; - const author = username.replace("@", ""); - - return ( -
    - {navBar} - {deletedEntry && ( -
    - - -
    -
    -
    -
    - {!global.isMobile && showProfileBox && ( - - )} -
    -
    -
    -
    -
    -
    - {_t("entry.deleted-content-warning")} - - {_t("points.history")} - {" "} - {_t("g.logs")}. -
    -
    -

    {deletedEntry!.title}

    -
    -
    - {editHistory && ( - - )} -
    - {SimilarEntries({ - ...this.props, - entry: { - permlink, - author, - json_metadata: { tags: deletedEntry.tags } - } as any, - display: "" - })} -
    -
    -
    -
    -
    - )} -
    - ); - } - - if (!entry) { - return NotFound({ ...this.props }); - } - - let setRef = (el: HTMLDivElement) => { - this.viewElement = el; - }; - - const originalEntry = entry.original_entry || null; - - const community = this.getCommunity(); - - const reputation = accountReputation(entry.author_reputation); - const published = moment(parseDate(entry.created)); - const modified = moment(parseDate(entry.updated)); - - // Sometimes tag list comes with duplicate items - const tags = entry.json_metadata.tags && [...new Set(entry.json_metadata.tags)]; - // If category is not present in tags then add - if (entry.category && tags && tags[0] !== entry.category) { - tags.splice(0, 0, entry.category); - } - const app = appName(entry.json_metadata.app); - const appShort = app.split("/")[0].split(" ")[0]; - - const { activeUser } = this.props; - - const isComment = !!entry.parent_author; - const ownEntry = activeUser && activeUser.username === entry.author; - const isHidden = entry?.net_rshares < -7000000000 && entry?.active_votes.length > 3; // 1000 HP - const isMuted = entry?.stats?.gray && entry?.net_rshares >= 0 && entry?.author_reputation >= 0; - const isLowReputation = - entry?.stats?.gray && entry?.net_rshares >= 0 && entry?.author_reputation < 0; - const mightContainMutedComments = activeUser && entryIsMuted && !isComment && !ownEntry; - - // Meta config - const url = entryCanonical(entry) || ""; - - const nsfw = entry.json_metadata.tags && entry.json_metadata.tags.includes("nsfw"); - const ncount = - this.props.notifications.unread > 0 ? `(${this.props.notifications.unread}) ` : ""; - - const metaProps = { - title: `${ncount}${truncate(entry.title, 67)}`, - description: `${ - entry.json_metadata?.description - ? entry.json_metadata?.description - : truncate(postBodySummary(entry.body, 210), 140) - } by @${entry.author}`, - url: entry.url, - canonical: url, - image: catchPostImage(entry, 600, 500, global.canUseWebp ? "webp" : "match"), - published: published.toISOString(), - modified: modified.toISOString(), - tag: tags ? (isCommunity(tags[0]) ? tags[1] : tags[0]) : "", - keywords: tags && tags.join(", "), - amp: `${defaults.base}${entry.url}?amps` - }; - let containerClasses = global.isElectron - ? "app-content entry-page mt-0 pt-6" - : "app-content entry-page"; - - return ( - <> - - - - - - {navBar} -
    - - -
    - {originalEntry && ( -
    -
    - {_t("entry.cross-post-by")} - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - - {`@${entry.author}`} -
    - ) - })} -
    -
    - {Tag({ - ...this.props, - tag: entry.category, - type: "link", - children:
    {entry.community_title}
    - })} - {_t("entry.cross-post-community")} -
    -
    - {'"'} - {crossPostMessage(entry.body)} - {'"'} -
    -
    - )} - - {(() => { - if (nsfw && !showIfNsfw && !global.nsfw) { - return ( -
    -
    - NSFW -
    -
    - { - e.preventDefault(); - this.stateSet({ showIfNsfw: true }); - }} - > - {_t("nsfw.reveal")} - {" "} - {_t("g.or").toLowerCase()}{" "} - {activeUser && ( - <> - {_t("nsfw.settings-1")}{" "} - { - e.preventDefault(); - history.push(`/@${activeUser.username}/settings`); - }} - > - {_t("nsfw.settings-2")} - - {"."} - - )} - {!activeUser && ( - <> - - - - {"."} - - )} -
    -
    - ); - } - - return ( - <> - {(() => { - // Cross post body - if (originalEntry) { - const published = moment(parseDate(originalEntry.created)); - const reputation = accountReputation(originalEntry.author_reputation); - const renderedBody = { - __html: renderPostBody(originalEntry.body, false, global.canUseWebp) - }; - - return ( - <> -
    -

    {originalEntry.title}

    -
    - {ProfileLink({ - ...this.props, - username: originalEntry.author, - children: ( -
    - -
    - ) - })} - -
    -
    - {ProfileLink({ - ...this.props, - username: originalEntry.author, - children: ( -
    - - - - - {reputation} - -
    - ) - })} -
    - -
    - - {published.fromNow()} - - -
    - {_t("entry.community-in")} - {Tag({ - ...this.props, - tag: originalEntry.category, - type: "link", - children: ( -
    - {originalEntry.community - ? originalEntry.community_title - : `#${originalEntry.category}`} -
    - ) - })} -
    -
    -
    - - {global.usePrivate && - BookmarkBtn({ - ...this.props, - entry: originalEntry - })} - -
    -
    -
    {}} - /> - - ); - } - - const _entry_body = replaceLinkIdToDataId(entry.body); - let renderedBody = { - __html: renderPostBody( - isComment ? (comment.length > 0 ? comment : _entry_body) : _entry_body, - false, - global.canUseWebp - ) - }; - const ctitle = entry.community ? entry.community_title : ""; - let extraItems = - ownEntry && isComment - ? [ - { - label: _t("g.edit"), - onClick: this.toggleEdit, - icon: pencilOutlineSvg - } - ] - : []; - if ( - !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout) && - ownEntry && - isComment - ) { - extraItems = [ - ...extraItems, - { - label: "", - onClick: () => {}, - icon: entryDeleteBtn({ - ...this.props, - entry, - setDeleteInProgress: (value) => this.setState({ loading: value }), - onSuccess: this.deleted, - children: ( - - {deleteForeverSvg} {_t("g.delete")} - - ) - }) - } - ]; - } - - return ( - <> -
    - {isMuted && ( -
    - - - - - -
    - )} - - {isHidden && ( -
    - {_t("entry.hidden-warning")} -
    - )} - - {isLowReputation && ( -
    - {_t("entry.lowrep-warning")} -
    - )} - - {mightContainMutedComments && ( -
    - {_t("entry.comments-hidden")} -
    - )} - - {isComment && ( -
    -
    RE: {entry.title}
    -
    - {_t("entry.comment-entry-title")} -
    -

    {entry.title}

    -
      -
    • - {_t("entry.comment-entry-go-root")} -
    • - {entry.depth > 1 && ( -
    • - - {_t("entry.comment-entry-go-parent")} - -
    • - )} -
    -
    - )} -

    {entry.title}

    -
    - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - -
    - ) - })} - -
    -
    - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - - - - - {reputation} - -
    - ) - })} -
    - -
    - - {published.fromNow()} - - -
    - {_t("entry.community-in")} - {Tag({ - ...this.props, - tag: entry.category, - type: "link", - children: ( -
    - {entry.community - ? entry.community_title - : `#${entry.category}`} -
    - ) - })} -
    -
    -
    - - - - - {!isComment && - global.usePrivate && - BookmarkBtn({ - ...this.props, - entry - })} - {!isComment && ( - - )} -
    -
    - - {!this.state.isRawContent ? ( - <> - {!edit ? ( - <> - { - this.setState({ selection: `>${text}\n\n` }); - (this.commentInput! as any).current!.focus(); - }} - > -
    - - - ) : ( - Comment({ - ...this.props, - defText: entry.body, - submitText: _t("g.update"), - cancellable: true, - onSubmit: this.updateReply, - onCancel: this.toggleEdit, - inProgress: replying, - autoFocus: true, - inputRef: this.commentInput, - entry: entry - }) - )} - - ) : ( -
    -                              {entry.body}
    -                            
    - )} - - {/* {this.setState({selection: `>${text}\n\n`}); (this.commentInput! as any).current!.focus();}}> -
    - */} - - - - ); - })()} - - {!global.isMobile && ( -
    - {showProfileBox && } -
    - )} - -
    -
    - {tags && - tags.map((t, i) => { - if (typeof t === "string") { - if ( - entry.community && - entry.community_title && - t === entry.community - ) { - return ( - - {Tag({ - ...this.props, - tag: { - name: entry.community, - title: entry.community_title - }, - type: "link", - children:
    {t}
    - })} -
    - ); - } - - return ( - - {Tag({ - ...this.props, - tag: t.trim(), - type: "link", - children:
    {t}
    - })} -
    - ); - } else { - return; - } - })} -
    -
    -
    - {published.fromNow()} -
    - - {ProfileLink({ - ...this.props, - username: entry.author, - children: ( -
    - {entry.author} - - {reputation} - -
    - ) - })} - {app && ( - <> - - - - - - - )} -
    -
    - - - - - {!ownEntry && } - - - - {rawContentSvg} - - - {BookmarkBtn({ - ...this.props, - entry - })} - -
    -
    - - {originalEntry && ( - - )} - - {!originalEntry && - !isComment && - SimilarEntries({ - ...this.props, - entry, - display: !activeUser ? "" : "d-none" - })} - - {Comment({ - ...this.props, - defText: this.state.selection, - submitText: _t("g.reply"), - resetSelection: this.resetSelection, - onSubmit: this.replySubmitted, - inProgress: replying, - isCommented: this.state.isCommented, - inputRef: this.commentInput, - entry: entry - })} - - {!originalEntry && - !isComment && - SimilarEntries({ - ...this.props, - entry, - display: !activeUser ? "d-none" : "" - })} - - {activeUser && entry.children === 0 && } - - - - ); - })()} - -
    -
    - {editHistory && } - - - ); - } -} - -export default connect(pageMapStateToProps, pageMapDispatchToProps)(EntryPage as any); diff --git a/src/common/pages/entry.scss b/src/common/pages/entry/_index.scss similarity index 99% rename from src/common/pages/entry.scss rename to src/common/pages/entry/_index.scss index c4732892139..4de8e9fd9a6 100644 --- a/src/common/pages/entry.scss +++ b/src/common/pages/entry/_index.scss @@ -1,4 +1,4 @@ -@import "../../style/vars_mixins"; +@import "../../../style/vars_mixins"; .circle-separator { border-radius: 50%; diff --git a/src/common/pages/entry/deleted-post-screen.tsx b/src/common/pages/entry/deleted-post-screen.tsx new file mode 100644 index 00000000000..7184c674c18 --- /dev/null +++ b/src/common/pages/entry/deleted-post-screen.tsx @@ -0,0 +1,104 @@ +import ScrollToTop from "../../components/scroll-to-top"; +import Theme from "../../components/theme"; +import AuthorInfoCard from "../../components/author-info-card"; +import { _t } from "../../i18n"; +import { renderPostBody } from "@ecency/render-helper"; +import React from "react"; +import NavBarElectron from "../../../desktop/app/components/navbar"; +import NavBar from "../../components/navbar"; +import { Props } from "./props.type"; +import EditHistory from "../../components/edit-history"; +import SimilarEntries from "../../components/similar-entries"; +import { StaticNavbar } from "../../components/static"; + +interface DeletedPostProps { + reload: () => void; + loading: boolean; + deletedEntry: { + title: string; + body: string; + tags: any; + }; + showProfileBox: boolean; + editHistory: boolean; + toggleEditHistory: () => void; + staticNav?: boolean; +} + +export const DeletedPostScreen = (props: Props & DeletedPostProps) => { + const nav = props.global.isElectron ? ( + NavBarElectron({ + ...props, + reloadFn: props.reload, + reloading: props.loading + }) + ) : ( + + ); + const staticNav = ; + + return ( +
    + {props.staticNav ? staticNav : nav} + {props.deletedEntry && ( +
    + + +
    +
    +
    +
    + {!props.global.isMobile && props.showProfileBox && ( + + )} +
    +
    +
    +
    +
    +
    + {_t("entry.deleted-content-warning")} + + {_t("points.history")} + {" "} + {_t("g.logs")}. +
    +
    +

    {props.deletedEntry!.title}

    +
    +
    + {props.editHistory && ( + + )} +
    + {SimilarEntries({ + ...props, + entry: { + permlink: props.match.params.permlink, + author: props.match.params.username.replace("@", ""), + json_metadata: { tags: props.deletedEntry.tags } + } as any, + display: "" + })} +
    +
    +
    +
    +
    + )} +
    + ); +}; diff --git a/src/common/pages/entry/distance-detector.tsx b/src/common/pages/entry/distance-detector.tsx new file mode 100644 index 00000000000..1193f4eccc5 --- /dev/null +++ b/src/common/pages/entry/distance-detector.tsx @@ -0,0 +1,44 @@ +import React, { MutableRefObject, useEffect } from "react"; + +export function useDistanceDetector( + entryControlsRef: MutableRefObject, + showProfileBox: boolean, + showWordCount: boolean, + setShowProfileBox: (v: boolean) => void, + setShowWordCount: (v: boolean) => void +) { + useEffect(() => { + window.addEventListener("scroll", detect); + window.addEventListener("resize", detect); + + return () => { + window.removeEventListener("scroll", detect); + window.removeEventListener("resize", detect); + }; + }, []); + + // detects distance between title and comments section sets visibility of profile card + const detect = () => { + const infoCard: HTMLElement | null = document.getElementById("avatar-fixed-container"); + const wordCounter: HTMLElement | null = document.getElementById("word-count"); + const top = entryControlsRef.current?.getBoundingClientRect().top || 120; + + if (infoCard != null && window.scrollY > 180 && top && !(top <= 0)) { + infoCard.classList.replace("invisible", "visible"); + setShowProfileBox(true); + } else if (infoCard != null && window.scrollY <= 180) { + infoCard.classList.replace("visible", "invisible"); + setShowProfileBox(false); + } else if (top && top <= 0 && infoCard !== null) { + infoCard.classList.replace("visible", "invisible"); + setShowProfileBox(false); + } else return; + + if (top && top > 0) { + setShowWordCount(true); + } else if (top && top < 0) { + wordCounter?.classList.replace("visible", "invisible"); + setShowWordCount(false); + } else return; + }; +} diff --git a/src/common/pages/amp/entry-amp-page.css b/src/common/pages/entry/index-amp.css similarity index 99% rename from src/common/pages/amp/entry-amp-page.css rename to src/common/pages/entry/index-amp.css index 44f1a0328ab..ebc3b324e39 100644 --- a/src/common/pages/amp/entry-amp-page.css +++ b/src/common/pages/entry/index-amp.css @@ -1869,3 +1869,7 @@ a[target="_blank"]:hover:after { .view-full-version { bottom: 24px; } + +.theme-night .entry-body * { + color: #fff; +} diff --git a/src/common/pages/entry/index-amp.tsx b/src/common/pages/entry/index-amp.tsx new file mode 100644 index 00000000000..74a8309b680 --- /dev/null +++ b/src/common/pages/entry/index-amp.tsx @@ -0,0 +1,831 @@ +import { connect } from "react-redux"; +import { pageMapDispatchToProps, pageMapStateToProps } from "../common"; +import Meta from "../../components/meta"; +import Theme from "../../components/theme"; +import { error } from "../../components/feedback"; +import MdHandler from "../../components/md-handler"; +import { StaticNavbar } from "../../components/static"; +import { _t } from "../../i18n"; +import ProfileLink from "../../components/profile-link"; +import Tag from "../../components/tag"; +import { crossPostMessage } from "../../helper/cross-post"; +import { Tsx } from "../../i18n/helper"; +import moment from "moment/moment"; +import parseDate from "../../helper/parse-date"; +import accountReputation from "../../helper/account-reputation"; +import { catchPostImage, postBodySummary, renderPostBody } from "@ecency/render-helper"; +import replaceLinkIdToDataId from "../../util/replace-link-id-to-data-id"; +import { deleteForeverSvg, pencilOutlineSvg } from "../../img/svg"; +import entryDeleteBtn from "../../components/entry-delete-btn"; +import { Link } from "react-router-dom"; +import EntryLink, { makePath as makeEntryPath } from "../../components/entry-link"; +import { SelectionPopover } from "../../components/selection-popover"; +import AuthorInfoCard from "../../components/author-info-card"; +import React, { Fragment, useEffect, useRef, useState } from "react"; +import usePrevious from "react-use/lib/usePrevious"; +import { Entry } from "../../store/entries/types"; +import { useDeletedEntryCache, useEntryCache, useEntryReFetch } from "../../core"; +import { useDistanceDetector } from "./distance-detector"; +import * as ls from "../../util/local-storage"; +import * as ss from "../../util/session-storage"; +import appName from "../../helper/app-name"; +import isCommunity from "../../helper/is-community"; +import { getFollowing } from "../../api/hive"; +import { comment as commentApi, formatError } from "../../api/operations"; +import { Props } from "./props.type"; +import truncate from "../../util/truncate"; +import entryCanonical from "../../helper/entry-canonical"; +import defaults from "../../constants/defaults.json"; +import { classNameObject } from "../../helper/class-name-object"; +import UserAvatar from "../../components/user-avatar"; +import { version } from "../../../../package.json"; +import Comment from "../../components/comment"; +import SimilarEntries from "../../components/similar-entries"; +import "./index-amp.css"; +import { DeletedPostScreen } from "./deleted-post-screen"; +import { NotFound } from "../../components/404"; +import { makeJsonMetaDataReply } from "../../helper/posting"; +import { LoadingScreen } from "./loading-screen"; + +const EntryAmpComponent = (props: Props) => { + const [loading, setLoading] = useState(false); + const [replying, setReplying] = useState(false); + const [edit, setEdit] = useState(false); + const [showIfNsfw, setShowIfNsfw] = useState(false); + const [editHistory, setEditHistory] = useState(false); + const [comment, setComment] = useState(""); + const [isCommented, setIsCommented] = useState(false); + const [showProfileBox, setShowProfileBox] = useState(false); + const [showWordCount, setShowWordCount] = useState(false); + const [isRawContent, setIsRawContent] = useState(false); + const [entryIsMuted, setEntryIsMuted] = useState(false); + const [selection, setSelection] = useState(""); + const [postIsDeleted, setPostIsDeleted] = useState(false); + const previousActiveUser = usePrevious(props.activeUser); + + // Entry state + const [published, setPublished] = useState(moment()); + const [modified, setModified] = useState(moment()); + const [tags, setTags] = useState([]); + const [tag, setTag] = useState(""); + const [keywords, setKeywords] = useState(""); + const [originalEntry, setOriginalEntry] = useState(); + const [nsfw, setNsfw] = useState(false); + const [isComment, setIsComment] = useState(false); + const [isOwnEntry, setIsOwnEntry] = useState(false); + const [isMuted, setIsMuted] = useState(false); + const [isHidden, setIsHidden] = useState(false); + const [isLowReputation, setIsLowReputation] = useState(false); + const [mightContainMutedComments, setMightContainMutedComments] = useState(false); + const [reputation, setReputation] = useState(0); + const [image, setImage] = useState(""); + const [app, setApp] = useState(""); + const [appShort, setAppShort] = useState(""); + + const commentsInputRef = useRef(null); + const entryControlsRef = useRef(null); + + const { data: entry, error: entryError } = useEntryCache( + props.match.params.category, + props.match.params.username.replace("@", ""), + props.match.params.permlink + ); + const { mutateAsync: reFetch } = useEntryReFetch(entry); + const { + data: deletedEntry, + refetch: fetchDeletedEntry, + isLoading: deleteEntryLoading + } = useDeletedEntryCache( + props.match.params.username.replace("@", ""), + props.match.params.permlink + ); + + useDistanceDetector( + entryControlsRef, + showProfileBox, + showWordCount, + setShowProfileBox, + setShowWordCount + ); + + useEffect(() => { + setLoading(true); + + if (props.history.location.search.includes("?referral")) { + const userName = props.history.location.search.split("=")[1]; + ls.set("referral", userName); + } + fetchMutedUsers(); + + const queryParams = new URLSearchParams(location.search); + if (props.global.usePrivate && queryParams.has("history")) { + setEditHistory(!editHistory); + } else if (props.global.usePrivate && queryParams.has("raw")) { + setIsRawContent(true); + } + + setSelection(ss.get(`reply_draft_${entry?.author}_${entry?.permlink}`)?.trim() ?? ""); + }, []); + + useEffect(() => { + setLoading(true); + }, [props.match.params.username, props.match.params.permlink, props.match.params.category]); + + useEffect(() => { + if (entry) { + setPublished(moment(parseDate(entry.created))); + setModified(moment(parseDate(entry.updated))); + setOriginalEntry(entry.original_entry); + setNsfw(entry.json_metadata.tags?.includes("nsfw") ?? false); + setIsComment(!!entry.parent_author); + setIsOwnEntry(props.activeUser?.username === entry.author); + setIsMuted(!!entry.stats?.gray && entry.net_rshares >= 0 && entry.author_reputation >= 0); + setIsHidden(entry?.net_rshares < -7000000000 && entry?.active_votes.length > 3); // 1000 HP + setIsLowReputation( + !!entry.stats?.gray && entry.net_rshares >= 0 && entry.author_reputation < 0 + ); + setMightContainMutedComments(!!props.activeUser && entryIsMuted && !isComment && !isOwnEntry); + setReputation(accountReputation(entry.author_reputation)); + setImage(catchPostImage(entry, 600, 500, props.global.canUseWebp ? "webp" : "match")); + const _app = appName(entry.json_metadata.app); + setApp(_app); + setAppShort(_app.split("/")[0].split(" ")[0]); + + const tags = entry.json_metadata.tags && [...new Set(entry.json_metadata.tags)]; + + if (tags) { + setTags(tags); + setTag(isCommunity(tags[0]) ? tags[1] : tags[0]); + setKeywords(tags.join(", ")); + } + + setLoading(false); + } + }, [entry]); + + useEffect(() => { + if (entry || deletedEntry) { + setLoading(false); + } + }, [entry, deletedEntry]); + + useEffect(() => { + if (entryError) { + let errorMessage = (entryError as any).jse_info && (entryError as any).jse_info; + let arr = []; + for (let p in errorMessage) arr.push(errorMessage[p]); + errorMessage = arr.toString().replace(/,/g, ""); + if (errorMessage && errorMessage.length > 0 && errorMessage.includes("was deleted")) { + setPostIsDeleted(true); + fetchDeletedEntry(); + } else { + setLoading(false); + } + } + }, [entryError]); + + useEffect(() => { + if (isRawContent) { + props.history.push(`${props.history.location.pathname}?raw`); + } else { + const queryParams = new URLSearchParams(location.search); + if (queryParams.has("raw")) { + queryParams.delete("raw"); + props.history.replace({ + search: queryParams.toString() + }); + } + } + }, [isRawContent]); + + useEffect(() => { + if (props.activeUser !== previousActiveUser) { + setEdit(false); + } + }, [props.activeUser]); + + const reload = () => reFetch(); + + const fetchMutedUsers = async () => { + if (props.activeUser && entry) { + const r = await getFollowing(props.activeUser.username, "", "ignore", 100); + if (r && !entryIsMuted) { + setEntryIsMuted(r.map((user) => user.following).includes(entry.author)); + } + } + }; + + const deleted = async () => { + const { deleteReply } = props; + entry && deleteReply(entry); + ls.set(`deletedComment`, entry?.post_id); + props.history?.goBack(); + }; + + const updateReply = async (text: string) => { + const { activeUser, updateReply } = props; + + if (entry) { + const { permlink, parent_author: parentAuthor, parent_permlink: parentPermlink } = entry; + const jsonMeta = makeJsonMetaDataReply(entry.json_metadata.tags || ["ecency"], version); + + setReplying(true); + + try { + await commentApi( + activeUser?.username!, + parentAuthor!, + parentPermlink!, + permlink, + "", + text, + jsonMeta, + null + ); + + setComment(text); + setIsCommented(true); + ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); + updateReply({ + ...entry, + body: text + }); // update store + setEdit(false); + reload(); + } catch (e) { + error(...formatError(e)); + } finally { + setReplying(false); + setIsCommented(false); + } + } + }; + + const notificationsCount = + props.notifications.unread > 0 ? `(${props.notifications.unread}) ` : ""; + + const getCommentAmpUrl = (url: string) => { + const index = url.indexOf("#"); + if (index > -1) { + return url.slice(0, index) + "?amps"; + } + return url; + }; + + return loading || deleteEntryLoading ? ( + + ) : postIsDeleted && deletedEntry ? ( + setEditHistory(!editHistory)} + deletedEntry={deletedEntry} + staticNav={true} + /> + ) : !entry ? ( + + ) : ( + <> + + + + +
    +
    + {originalEntry && ( +
    +
    + {_t("entry.cross-post-by")} + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + + {`@${entry.author}`} +
    + ) + })} +
    +
    + {Tag({ + ...props, + tag: entry.category, + type: "link", + children:
    {entry.community_title}
    + })} + {_t("entry.cross-post-community")} +
    +
    + {'"'} + {crossPostMessage(entry.body)} + {'"'} +
    +
    + )} +
    + + + + + + + + + + + + + {(() => { + if (nsfw && !showIfNsfw && !props.global.nsfw) { + return ( +
    +
    + NSFW +
    +
    + { + e.preventDefault(); + setShowIfNsfw(true); + }} + > + {_t("nsfw.reveal")} + {" "} + {_t("g.or").toLowerCase()}{" "} + {props.activeUser && ( + <> + {_t("nsfw.settings-1")}{" "} + { + e.preventDefault(); + props.history.push(`/@${props.activeUser!.username}/settings`); + }} + > + {_t("nsfw.settings-2")} + + {"."} + + )} + {!props.activeUser && ( + <> + + + + {"."} + + )} +
    +
    + ); + } + + return ( + <> + {(() => { + // Cross post body + if (originalEntry) { + const published = moment(parseDate(originalEntry.created)); + const reputation = accountReputation(originalEntry.author_reputation); + const renderedBody = { + __html: renderPostBody(originalEntry.body, false, props.global.canUseWebp) + }; + + return ( + <> +
    +

    {originalEntry.title}

    +
    + {ProfileLink({ + ...props, + username: originalEntry.author, + children: ( +
    + +
    + ) + })} + +
    +
    + {ProfileLink({ + ...props, + username: originalEntry.author, + children: ( +
    + + + + + {reputation} + +
    + ) + })} +
    + +
    + + {published.fromNow()} + + +
    + {_t("entry.community-in")} + {Tag({ + ...props, + tag: originalEntry.category, + type: "link", + children: ( +
    + {originalEntry.community + ? originalEntry.community_title + : `#${originalEntry.category}`} +
    + ) + })} +
    +
    +
    + +
    +
    +
    {}} + /> + + ); + } + + const _entry_body = replaceLinkIdToDataId(entry.body); + let renderedBody = { + __html: renderPostBody( + isComment ? (comment.length > 0 ? comment : _entry_body) : _entry_body, + false, + props.global.canUseWebp + ) + }; + const ctitle = entry.community ? entry.community_title : ""; + let extraItems = + isOwnEntry && isComment + ? [ + { + label: _t("g.edit"), + onClick: () => setEdit(!edit), + icon: pencilOutlineSvg + } + ] + : []; + if ( + !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout) && + isOwnEntry && + isComment + ) { + extraItems = [ + ...extraItems, + { + label: "", + onClick: () => {}, + icon: entryDeleteBtn({ + ...props, + entry, + setDeleteInProgress: (value) => setLoading(value), + onSuccess: deleted, + children: ( + + {deleteForeverSvg} {_t("g.delete")} + + ) + }) + } + ]; + } + + return ( + <> +
    + {isMuted && ( +
    + + + + + +
    + )} + + {isHidden && ( +
    + {_t("entry.hidden-warning")} +
    + )} + + {isLowReputation && ( +
    + {_t("entry.lowrep-warning")} +
    + )} + + {mightContainMutedComments && ( +
    + {_t("entry.comments-hidden")} +
    + )} + + {isComment && ( +
    +
    RE: {entry.title}
    +
    + {_t("entry.comment-entry-title")} +
    +

    {entry.title}

    +
      +
    • + + {_t("entry.comment-entry-go-root")} + +
    • + {entry.depth > 1 && ( +
    • + + {_t("entry.comment-entry-go-parent")} + +
    • + )} +
    +
    + )} +

    {entry.title}

    +
    + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + +
    + ) + })} + +
    +
    + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + + + + + {reputation} + +
    + ) + })} +
    + +
    + + {published.fromNow()} + + +
    + {_t("entry.community-in")} + {Tag({ + ...props, + tag: entry.category, + type: "link", + children: ( +
    + {entry.community + ? entry.community_title + : `#${entry.category}`} +
    + ) + })} +
    +
    +
    + +
    +
    + + {!edit ? ( + <> + { + setSelection(`>${text}\n\n`); + commentsInputRef.current!.focus(); + }} + > +
    + + + ) : ( + Comment({ + ...props, + defText: entry.body, + submitText: _t("g.update"), + cancellable: true, + onSubmit: updateReply, + onCancel: () => setEdit(!edit), + inProgress: replying, + autoFocus: true, + inputRef: commentsInputRef, + entry: entry + }) + )} + + ); + })()} + + {!props.global.isMobile && ( +
    + {showProfileBox && } +
    + )} + +
    +
    + {tags && + tags.map((t, i) => { + if (typeof t === "string") { + if (entry.community && entry.community_title && t === entry.community) { + return ( + + {Tag({ + ...props, + tag: { + name: entry.community, + title: entry.community_title + }, + type: "link", + children:
    {t}
    + })} +
    + ); + } + + return ( + + {Tag({ + ...props, + tag: t.trim(), + type: "link", + children:
    {t}
    + })} +
    + ); + } else { + return; + } + })} +
    +
    +
    + {published.fromNow()} +
    + + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + {entry.author} + + {reputation} + +
    + ) + })} + {app && ( + <> + + + + )} +
    +
    + + {originalEntry && ( + + )} + + {!originalEntry && + !isComment && + SimilarEntries({ + ...props, + entry, + display: !props.activeUser ? "" : "d-none" + })} + + {!originalEntry && + !isComment && + SimilarEntries({ + ...props, + entry, + display: !props.activeUser ? "d-none" : "" + })} + + ); + })()} +
    +
    +
    + + ); +}; + +export default connect(pageMapStateToProps, pageMapDispatchToProps)(EntryAmpComponent); diff --git a/src/common/pages/entry/index.tsx b/src/common/pages/entry/index.tsx new file mode 100644 index 00000000000..24bf59adc22 --- /dev/null +++ b/src/common/pages/entry/index.tsx @@ -0,0 +1,1001 @@ +import React, { Fragment, useContext, useEffect, useRef, useState } from "react"; +import { connect } from "react-redux"; +import { pageMapDispatchToProps, pageMapStateToProps } from "../common"; +import { Props } from "./props.type"; +import { LoadingScreen } from "./loading-screen"; +import { DeletedPostScreen } from "./deleted-post-screen"; +import NotFound from "../../components/404"; +import { Entry, EntryVote } from "../../store/entries/types"; +import Meta from "../../components/meta"; +import ScrollToTop from "../../components/scroll-to-top"; +import Theme from "../../components/theme"; +import Feedback, { error } from "../../components/feedback"; +import MdHandler from "../../components/md-handler"; +import truncate from "../../util/truncate"; +import { catchPostImage, postBodySummary, renderPostBody } from "@ecency/render-helper"; +import entryCanonical from "../../helper/entry-canonical"; +import moment from "moment/moment"; +import parseDate from "../../helper/parse-date"; +import isCommunity from "../../helper/is-community"; +import defaults from "../../constants/defaults.json"; +import NavBarElectron from "../../../desktop/app/components/navbar"; +import NavBar from "../../components/navbar"; +import EditHistory from "../../components/edit-history"; +import EntryBodyExtra from "../../components/entry-body-extra"; +import ReadTime from "../../components/entry-read-time"; +import { _t } from "../../i18n"; +import ProfileLink from "../../components/profile-link"; +import Tag from "../../components/tag"; +import { crossPostMessage } from "../../helper/cross-post"; +import { Tsx } from "../../i18n/helper"; +import accountReputation from "../../helper/account-reputation"; +import EntryMenu from "../../components/entry-menu"; +import replaceLinkIdToDataId from "../../util/replace-link-id-to-data-id"; +import { deleteForeverSvg, pencilOutlineSvg, rawContentSvg } from "../../img/svg"; +import entryDeleteBtn from "../../components/entry-delete-btn"; +import { Link } from "react-router-dom"; +import EntryLink, { makePath as makeEntryPath } from "../../components/entry-link"; +import { SelectionPopover } from "../../components/selection-popover"; +import AuthorInfoCard from "../../components/author-info-card"; +import Tooltip from "../../components/tooltip"; +import CommentEngagement from "../../components/comment-engagement"; +import { classNameObject } from "../../helper/class-name-object"; +import UserAvatar from "../../components/user-avatar"; +import BookmarkBtn from "../../components/bookmark-btn"; +import * as ls from "../../util/local-storage"; +import Comment from "../../components/comment"; +import SimilarEntries from "../../components/similar-entries"; +import { createReplyPermlink, makeJsonMetaDataReply } from "../../helper/posting"; +import { comment as commentApi, formatError } from "../../api/operations"; +import * as ss from "../../util/session-storage"; +import { version } from "../../../../package.json"; +import appName from "../../helper/app-name"; +import EntryVoteBtn from "../../components/entry-vote-btn/index"; +import EntryPayout from "../../components/entry-payout/index"; +import EntryVotes from "../../components/entry-votes"; +import Discussion from "../../components/discussion"; +import EntryReblogBtn from "../../components/entry-reblog-btn/index"; +import EntryTipBtn from "../../components/entry-tip-btn"; +import { BaseAccount, FullAccount } from "../../store/accounts/types"; +import tempEntry from "../../helper/temp-entry"; +import { + EntriesCacheContext, + useCommunityCache, + useDeletedEntryCache, + useEntryCache, + useEntryReFetch +} from "../../core"; +import "./_index.scss"; +import { getFollowing } from "../../api/hive"; +import { useDistanceDetector } from "./distance-detector"; +import usePrevious from "react-use/lib/usePrevious"; + +const EntryComponent = (props: Props) => { + const [loading, setLoading] = useState(false); + const [replying, setReplying] = useState(false); + const [edit, setEdit] = useState(false); + const [showIfNsfw, setShowIfNsfw] = useState(false); + const [editHistory, setEditHistory] = useState(false); + const [comment, setComment] = useState(""); + const [isCommented, setIsCommented] = useState(false); + const [showProfileBox, setShowProfileBox] = useState(false); + const [showWordCount, setShowWordCount] = useState(false); + const [isRawContent, setIsRawContent] = useState(false); + const [entryIsMuted, setEntryIsMuted] = useState(false); + const [selection, setSelection] = useState(""); + const [postIsDeleted, setPostIsDeleted] = useState(false); + const previousActiveUser = usePrevious(props.activeUser); + + // Entry state + const [published, setPublished] = useState(moment()); + const [modified, setModified] = useState(moment()); + const [tags, setTags] = useState([]); + const [tag, setTag] = useState(""); + const [keywords, setKeywords] = useState(""); + const [originalEntry, setOriginalEntry] = useState(); + const [nsfw, setNsfw] = useState(false); + const [isComment, setIsComment] = useState(false); + const [isOwnEntry, setIsOwnEntry] = useState(false); + const [isMuted, setIsMuted] = useState(false); + const [isHidden, setIsHidden] = useState(false); + const [isLowReputation, setIsLowReputation] = useState(false); + const [mightContainMutedComments, setMightContainMutedComments] = useState(false); + const [reputation, setReputation] = useState(0); + const [image, setImage] = useState(""); + const [app, setApp] = useState(""); + const [appShort, setAppShort] = useState(""); + + const commentsInputRef = useRef(null); + const entryControlsRef = useRef(null); + + const { updateVotes, updateCache } = useContext(EntriesCacheContext); + const { data: entry, error: entryError } = useEntryCache( + props.match.params.category, + props.match.params.username.replace("@", ""), + props.match.params.permlink + ); + const { mutateAsync: reFetch } = useEntryReFetch(entry); + const { data: community } = useCommunityCache(props.match.params.category); + const { + data: deletedEntry, + refetch: fetchDeletedEntry, + isLoading: deleteEntryLoading + } = useDeletedEntryCache( + props.match.params.username.replace("@", ""), + props.match.params.permlink + ); + + useDistanceDetector( + entryControlsRef, + showProfileBox, + showWordCount, + setShowProfileBox, + setShowWordCount + ); + + useEffect(() => { + setLoading(true); + + if (props.history.location.search.includes("?referral")) { + const userName = props.history.location.search.split("=")[1]; + ls.set("referral", userName); + } + fetchMutedUsers(); + + const queryParams = new URLSearchParams(location.search); + if (props.global.usePrivate && queryParams.has("history")) { + setEditHistory(!editHistory); + } else if (props.global.usePrivate && queryParams.has("raw")) { + setIsRawContent(true); + } + + setSelection(ss.get(`reply_draft_${entry?.author}_${entry?.permlink}`)?.trim() ?? ""); + }, []); + + useEffect(() => { + setLoading(true); + }, [props.match.params.username, props.match.params.permlink, props.match.params.category]); + + useEffect(() => { + if (entry) { + setPublished(moment(parseDate(entry.created))); + setModified(moment(parseDate(entry.updated))); + setOriginalEntry(entry.original_entry); + setNsfw(entry.json_metadata.tags?.includes("nsfw") ?? false); + setIsComment(!!entry.parent_author); + setIsOwnEntry(props.activeUser?.username === entry.author); + setIsMuted(!!entry.stats?.gray && entry.net_rshares >= 0 && entry.author_reputation >= 0); + setIsHidden(entry?.net_rshares < -7000000000 && entry?.active_votes.length > 3); // 1000 HP + setIsLowReputation( + !!entry.stats?.gray && entry.net_rshares >= 0 && entry.author_reputation < 0 + ); + setMightContainMutedComments(!!props.activeUser && entryIsMuted && !isComment && !isOwnEntry); + setReputation(accountReputation(entry.author_reputation)); + setImage(catchPostImage(entry, 600, 500, props.global.canUseWebp ? "webp" : "match")); + + const _app = appName(entry.json_metadata.app); + setApp(_app); + setAppShort(_app.split("/")[0].split(" ")[0]); + + const tags = (entry.json_metadata.tags && [...new Set(entry.json_metadata.tags)])?.filter( + (t) => !!t + ); + + if (tags && tags.length > 0) { + setTags(tags); + setTag(isCommunity(tags[0]) ? tags[1] : entry.category); + setKeywords(tags.join(", ")); + } else { + setTags([entry.category]); + setTag(entry.category); + setKeywords(entry.category); + } + + setLoading(false); + } + }, [entry]); + + useEffect(() => { + if (entry || deletedEntry) { + setLoading(false); + } + }, [entry, deletedEntry]); + + useEffect(() => { + if (entryError) { + let errorMessage = (entryError as any).jse_info && (entryError as any).jse_info; + let arr = []; + for (let p in errorMessage) arr.push(errorMessage[p]); + errorMessage = arr.toString().replace(/,/g, ""); + if (errorMessage && errorMessage.length > 0 && errorMessage.includes("was deleted")) { + setPostIsDeleted(true); + fetchDeletedEntry(); + } else { + setLoading(false); + } + } + }, [entryError]); + + useEffect(() => { + if (isRawContent) { + props.history.push(`${props.history.location.pathname}?raw`); + } else { + const queryParams = new URLSearchParams(location.search); + if (queryParams.has("raw")) { + queryParams.delete("raw"); + props.history.replace({ + search: queryParams.toString() + }); + } + } + }, [isRawContent]); + + useEffect(() => { + if (props.activeUser !== previousActiveUser) { + setEdit(false); + } + }, [props.activeUser]); + + const reload = () => reFetch(); + + const fetchMutedUsers = async () => { + if (props.activeUser && entry) { + const r = await getFollowing(props.activeUser.username, "", "ignore", 100); + if (r && !entryIsMuted) { + setEntryIsMuted(r.map((user) => user.following).includes(entry.author)); + } + } + }; + + const deleted = async () => { + const { deleteReply } = props; + entry && deleteReply(entry); + ls.set(`deletedComment`, entry?.post_id); + props.history?.goBack(); + }; + + const updateReply = async (text: string) => { + const { activeUser, updateReply } = props; + + if (entry) { + const { permlink, parent_author: parentAuthor, parent_permlink: parentPermlink } = entry; + const jsonMeta = makeJsonMetaDataReply(entry.json_metadata.tags || ["ecency"], version); + + setReplying(true); + + try { + await commentApi( + activeUser?.username!, + parentAuthor!, + parentPermlink!, + permlink, + "", + text, + jsonMeta, + null + ); + + setComment(text); + setIsCommented(true); + ss.remove(`reply_draft_${entry.author}_${entry.permlink}`); + updateReply({ + ...entry, + body: text + }); // update store + setEdit(false); + reload(); + } catch (e) { + error(...formatError(e)); + } finally { + setReplying(false); + setIsCommented(false); + } + } + }; + + const afterVote = async (votes: EntryVote[], estimated: number) => { + if (entry.active_votes) { + updateVotes(entry, votes, entry.payout + estimated); + } else { + await reFetch(); + } + }; + + const replySubmitted = async (text: string) => { + const { activeUser, addReply, updateEntry } = props; + + if (!activeUser || !activeUser.data.__loaded) { + return; + } + + const { author: parentAuthor, permlink: parentPermlink } = entry!!; + const author = activeUser.username; + const permlink = createReplyPermlink(entry!.author); + const tags = entry!.json_metadata.tags || ["ecency"]; + + const jsonMeta = makeJsonMetaDataReply(tags, version); + + setReplying(true); + try { + await commentApi( + author, + parentAuthor, + parentPermlink, + permlink, + "", + text, + jsonMeta, + null, + true + ); + + const nReply = tempEntry({ + author: activeUser.data as FullAccount, + permlink, + parentAuthor, + parentPermlink, + title: "", + body: text, + tags, + description: null + }); + + // add new reply to store + addReply(nReply); + + // remove reply draft + ss.remove(`reply_draft_${entry!.author}_${entry!.permlink}`); + setIsCommented(true); + + if (entry!.children === 0) { + // Activate discussion section with first comment. + updateCache([ + { + ...entry!!, + children: 1 + } + ]); + } + } catch (e) { + error(...formatError(e)); + } finally { + setReplying(false); + setIsCommented(false); + } + }; + + const notificationsCount = + props.notifications.unread > 0 ? `(${props.notifications.unread}) ` : ""; + + return loading || deleteEntryLoading ? ( + + ) : postIsDeleted && deletedEntry ? ( + setEditHistory(!editHistory)} + deletedEntry={deletedEntry} + /> + ) : !entry ? ( + + ) : ( + <> + + + + + + {props.global.isElectron ? ( + NavBarElectron({ + ...props, + reloadFn: reload, + reloading: loading + }) + ) : ( + + )} +
    + + +
    + {originalEntry && ( +
    +
    + {_t("entry.cross-post-by")} + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + + {`@${entry.author}`} +
    + ) + })} +
    +
    + {Tag({ + ...props, + tag: entry.category, + type: "link", + children:
    {entry.community_title}
    + })} + {_t("entry.cross-post-community")} +
    +
    + {'"'} + {crossPostMessage(entry.body)} + {'"'} +
    +
    + )} + + {(() => { + if (nsfw && !showIfNsfw && !props.global.nsfw) { + return ( +
    +
    + NSFW +
    +
    + { + e.preventDefault(); + setShowIfNsfw(true); + }} + > + {_t("nsfw.reveal")} + {" "} + {_t("g.or").toLowerCase()}{" "} + {props.activeUser && ( + <> + {_t("nsfw.settings-1")}{" "} + { + e.preventDefault(); + props.history.push(`/@${props.activeUser?.username}/settings`); + }} + > + {_t("nsfw.settings-2")} + + {"."} + + )} + {!props.activeUser && ( + <> + + + + {"."} + + )} +
    +
    + ); + } + + return ( + <> + {(() => { + // Cross post body + if (originalEntry) { + const published = moment(parseDate(originalEntry.created)); + const reputation = accountReputation(originalEntry.author_reputation); + const renderedBody = { + __html: renderPostBody(originalEntry.body, false, props.global.canUseWebp) + }; + + return ( + <> +
    +

    {originalEntry.title}

    +
    + {ProfileLink({ + ...props, + username: originalEntry.author, + children: ( +
    + +
    + ) + })} + +
    +
    + {ProfileLink({ + ...props, + username: originalEntry.author, + children: ( +
    + + + + + {reputation} + +
    + ) + })} +
    + +
    + + {published.fromNow()} + + +
    + {_t("entry.community-in")} + {Tag({ + ...props, + tag: originalEntry.category, + type: "link", + children: ( +
    + {originalEntry.community + ? originalEntry.community_title + : `#${originalEntry.category}`} +
    + ) + })} +
    +
    +
    + + {props.global.usePrivate && + BookmarkBtn({ + ...props, + entry: originalEntry + })} + +
    +
    +
    {}} + /> + + ); + } + + const _entry_body = replaceLinkIdToDataId(entry.body); + let renderedBody = { + __html: renderPostBody( + isComment ? (comment.length > 0 ? comment : _entry_body) : _entry_body, + false, + props.global.canUseWebp + ) + }; + const ctitle = entry.community ? entry.community_title : ""; + let extraItems = + isOwnEntry && isComment + ? [ + { + label: _t("g.edit"), + onClick: () => setEdit(!edit), + icon: pencilOutlineSvg + } + ] + : []; + if ( + !(entry.children > 0 || entry.net_rshares > 0 || entry.is_paidout) && + isOwnEntry && + isComment + ) { + extraItems = [ + ...extraItems, + { + label: "", + onClick: () => {}, + icon: entryDeleteBtn({ + ...props, + entry, + setDeleteInProgress: (value) => () => setLoading(true), + onSuccess: deleted, + children: ( + + {deleteForeverSvg} {_t("g.delete")} + + ) + }) + } + ]; + } + + return ( + <> +
    + {isMuted && ( +
    + + + + + +
    + )} + + {isHidden && ( +
    + {_t("entry.hidden-warning")} +
    + )} + + {isLowReputation && ( +
    + {_t("entry.lowrep-warning")} +
    + )} + + {mightContainMutedComments && ( +
    + {_t("entry.comments-hidden")} +
    + )} + + {isComment && ( +
    +
    RE: {entry.title}
    +
    + {_t("entry.comment-entry-title")} +
    +

    {entry.title}

    +
      +
    • + {_t("entry.comment-entry-go-root")} +
    • + {entry.depth > 1 && ( +
    • + + {_t("entry.comment-entry-go-parent")} + +
    • + )} +
    +
    + )} +

    {entry.title}

    +
    + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + +
    + ) + })} + +
    +
    + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + + + + + {reputation} + +
    + ) + })} +
    + +
    + + {published.fromNow()} + + +
    + {_t("entry.community-in")} + {Tag({ + ...props, + tag: entry.category, + type: "link", + children: ( +
    + {entry.community + ? entry.community_title + : `#${entry.category}`} +
    + ) + })} +
    +
    +
    + + + + + {!isComment && + props.global.usePrivate && + BookmarkBtn({ + ...props, + entry + })} + {!isComment && ( + + )} +
    +
    + + {!isRawContent ? ( + <> + {!edit ? ( + <> + { + setSelection(`>${text}\n\n`); + (commentsInputRef! as any).current!.focus(); + }} + > +
    + + + ) : ( + Comment({ + ...props, + defText: entry.body, + submitText: _t("g.update"), + cancellable: true, + onSubmit: updateReply, + onCancel: () => setEdit(!edit), + inProgress: replying, + autoFocus: true, + inputRef: commentsInputRef, + entry + }) + )} + + ) : ( +
    +                            {entry.body}
    +                          
    + )} + + + ); + })()} + + {!props.global.isMobile && ( +
    + {showProfileBox && } +
    + )} + +
    +
    + {tags && + tags.map((t, i) => { + if (typeof t === "string") { + if (entry.community && entry.community_title && t === entry.community) { + return ( + + {Tag({ + ...props, + tag: { + name: entry.community, + title: entry.community_title + }, + type: "link", + children:
    {t}
    + })} +
    + ); + } + + return ( + + {Tag({ + ...props, + tag: t.trim(), + type: "link", + children:
    {t}
    + })} +
    + ); + } else { + return; + } + })} +
    +
    +
    + {published.fromNow()} +
    + + {ProfileLink({ + ...props, + username: entry.author, + children: ( +
    + {entry.author} + + {reputation} + +
    + ) + })} + {app && ( + <> + + + + + + + )} +
    +
    + + + + + {!isOwnEntry && } + + + setIsRawContent(!isRawContent)} + > + {rawContentSvg} + + + {BookmarkBtn({ + ...props, + entry + })} + setEdit(!edit)} + /> +
    +
    + + {originalEntry && ( + + )} + + {!originalEntry && + !isComment && + SimilarEntries({ + ...props, + entry, + display: !props.activeUser ? "" : "d-none" + })} + + {Comment({ + ...props, + defText: selection, + submitText: _t("g.reply"), + resetSelection: () => setSelection(""), + onSubmit: replySubmitted, + inProgress: replying, + isCommented: isCommented, + inputRef: commentsInputRef, + entry: entry + })} + + {!originalEntry && + !isComment && + SimilarEntries({ + ...props, + entry, + display: !props.activeUser ? "d-none" : "" + })} + + {props.activeUser && entry.children === 0 && } + + + + ); + })()} + +
    +
    + {editHistory && setEditHistory(!editHistory)} />} + + + ); +}; + +export const EntryScreen = connect(pageMapStateToProps, pageMapDispatchToProps)(EntryComponent); diff --git a/src/common/pages/entry/loading-screen.tsx b/src/common/pages/entry/loading-screen.tsx new file mode 100644 index 00000000000..e6348318fcf --- /dev/null +++ b/src/common/pages/entry/loading-screen.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { Props } from "./props.type"; +import NavBar from "../../components/navbar/index"; +import NavBarElectron from "../../../desktop/app/components/navbar"; +import LinearProgress from "../../components/linear-progress"; +import { StaticNavbar } from "../../components/static"; + +interface LoadingProps { + loading: boolean; + reload: () => void; + staticNav?: boolean; +} + +export const LoadingScreen = (props: Props & LoadingProps) => { + const nav = props.global.isElectron ? ( + NavBarElectron({ + ...props, + reloadFn: props.reload, + reloading: props.loading + }) + ) : ( + + ); + const staticNav = ; + + return ( + <> + {props.staticNav ? staticNav : nav} +
    +
    +
    + +
    +
    +
    + + ); +}; diff --git a/src/common/pages/entry/props.type.ts b/src/common/pages/entry/props.type.ts new file mode 100644 index 00000000000..01cccd80b76 --- /dev/null +++ b/src/common/pages/entry/props.type.ts @@ -0,0 +1,12 @@ +import { PageProps } from "../common"; +import { match } from "react-router"; + +export interface Props extends PageProps { + match: match<{ + category: string; + permlink: string; + username: string; + }>; + account: Account; + updateWalletValues: () => void; +} diff --git a/src/common/pages/onboard.scss b/src/common/pages/onboard.scss new file mode 100644 index 00000000000..c10261d2be1 --- /dev/null +++ b/src/common/pages/onboard.scss @@ -0,0 +1,114 @@ +@import "../../style/vars_mixins"; + +.onboard-container { + display: flex; + flex-direction: column; + margin: auto; + padding: 20px; + margin-top: 70px; + width: 690px; + border-radius: 15px; + + @media (max-width: $md-break) { + width: 490px; + } + + @media (max-width: $sm-break) { + width: 340px; + } + + @include themify(day) { + background: lighten($steel-grey, 40); + } + + @include themify(night) { + background: $dark-grey-blue; + } + + .asking { + display: flex; + flex-direction: column; + + .reg-details { + display: flex; + flex-direction: column; + gap: 3px; + } + .asking-body { + @media (max-width: $md-break) { + width: 490px; + } + @media (max-width: $sm-break) { + width: 320px; + } + } + } + + .onboard-svg { + cursor: pointer; + } + + .creating { + display: flex; + flex-direction: column; + } + .creating-confirm { + display: flex; + flex-direction: column; + gap: 15px; + + .creating-confirm-bottom { + display: flex; + flex-direction: column; + gap: 10px; + align-items: center; + + .onboard-btn-container { + display: flex; + justify-content: center; + gap: 15px; + } + } + } + .login-warning { + display: flex; + justify-content: center; + } +} + +.create-account-dialog { + .create-account-dialog-header { + display: flex; + .create-account-main-title { + margin-top: 11px; + } + } + .model-content { + .confirm-title { + display: flex; + justify-content: center; + } + + .buttons { + display: flex; + justify-content: center; + .cancel-btn { + margin-left: 25px; + background: #6c757d; + border-color: #6c757d; + } + } + } + .create-account-success-dialog-header { + .create-account-main-title { + margin-top: 10px; + } + } + .success-dialog-body { + margin: 2rem 0 1.4rem 0; + .success-dialog-content { + text-align: center; + margin-bottom: 1.4rem; + } + } +} diff --git a/src/common/pages/onboard.tsx b/src/common/pages/onboard.tsx new file mode 100644 index 00000000000..1b714540470 --- /dev/null +++ b/src/common/pages/onboard.tsx @@ -0,0 +1,705 @@ +import React, { useEffect, useState } from "react"; +import { Button, Modal } from "react-bootstrap"; +import { match } from "react-router"; +import { PrivateKey } from "@hiveio/dhive"; +import { Link } from "react-router-dom"; + +import Meta from "../components/meta"; +import { connect } from "react-redux"; +import Theme from "../components/theme"; +import NavBar from "../components/navbar"; +import Feedback from "../components/feedback"; +import { success, error } from "../components/feedback"; +import Tooltip from "../components/tooltip"; +import LinearProgress from "../components/linear-progress"; +import keyOrHot from "../components/key-or-hot"; + +import { FullAccount } from "../store/accounts/types"; +import { pageMapDispatchToProps, pageMapStateToProps, PageProps } from "./common"; +import { + createAccountKc, + createAccountHs, + createAccountKey, + createAccountWithCreditKc, + createAccountWithCreditHs, + createAccountWithCreditKey +} from "../api/operations"; +import { onboardEmail } from "../api/private-api"; +import { generatePassword, getPrivateKeys } from "../helper/onBoard-helper"; +import { b64uDec, b64uEnc } from "../util/b64"; +import clipboard from "../util/clipboard"; + +import { copyContent, downloadSvg, regenerateSvg } from "../img/svg"; +import { _t } from "../i18n"; +import "./onboard.scss"; + +export interface AccountInfo { + email: string; + username: string; + referral: string; + keys: { + active: string; + activePubkey: string; + memo: string; + memoPubkey: string; + owner: string; + ownerPubkey: string; + posting: string; + postingPubkey: string; + }; +} + +export interface DecodeHash { + email: string; + username: string; + pubkeys: { + ownerPublicKey: string; + activePublicKey: string; + postingPublicKey: string; + memoPublicKey: string; + }; +} + +export interface ConfirmDetails { + label: string; + value: string; +} + +const createOptions = { + HIVE: "hive", + CREDIT: "credit" +}; + +interface MatchParams { + secret?: string; + type: string; + id: string; +} + +interface Props extends PageProps { + match: match; +} + +const Onboard = (props: Props) => { + const [masterPassword, setMasterPassword] = useState(""); + const [secret, setSecret] = useState(""); + const [accountInfo, setAccountInfo] = useState(); + const [decodedInfo, setDecodedInfo] = useState(); + const [showModal, setShowModal] = useState(false); + const [accountCredit, setAccountCredit] = useState(0); + const [createOption, setCreateOption] = useState(""); + const [fileIsDownloaded, setFileIsDownloaded] = useState(false); + const [innerWidth, setInnerWidth] = useState(0); + const [shortPassword, setShortPassword] = useState(""); + const [confirmDetails, setConfirmDetails] = useState(); + const [onboardUrl, setOnboardUrl] = useState(""); + const [step, setStep] = useState(0); + const [inProgress, setInprogress] = useState(false); + + useEffect(() => { + setOnboardUrl(`${window.location.origin}/onboard-friend/creating/`); + setInnerWidth(window.innerWidth); + try { + if (props.match.params.secret && props.match.params.type !== "asking") { + const decodedHash = JSON.parse(b64uDec(props.match.params.secret)); + setDecodedInfo(decodedHash); + } + } catch (err) { + console.log(err); + } + }, []); + + useEffect(() => { + if (props.match.params.type == "asking") { + initAccountKey(); + } + }, [accountInfo?.username]); + + useEffect(() => { + const { activeUser } = props; + (activeUser?.data as FullAccount) && + (activeUser?.data as FullAccount).pending_claimed_accounts && + setAccountCredit((activeUser?.data as FullAccount).pending_claimed_accounts); + }, [props.activeUser]); + + useEffect(() => { + if (decodedInfo) { + setConfirmDetails([ + { label: _t("onboard.username"), value: formatUsername(decodedInfo?.username) }, + { label: _t("onboard.public-owner"), value: decodedInfo?.pubkeys?.ownerPublicKey }, + { label: _t("onboard.public-active"), value: decodedInfo?.pubkeys?.activePublicKey }, + { label: _t("onboard.public-posting"), value: decodedInfo?.pubkeys?.postingPublicKey }, + { label: _t("onboard.public-memo"), value: decodedInfo?.pubkeys?.memoPublicKey } + ]); + } + }, [decodedInfo]); + + useEffect(() => { + window.addEventListener("resize", handleResize); + handleResize(); + return () => { + window.removeEventListener("resize", handleResize); + }; + }, [masterPassword]); + + const handleResize = () => { + setInnerWidth(window.innerWidth); + let password: string = ""; + if (window.innerWidth <= 768 && window.innerWidth > 577) { + password = masterPassword.substring(0, 32); + } else if (window.innerWidth <= 577) { + password = masterPassword.substring(0, 20); + } + setShortPassword(password); + }; + + const initAccountKey = async () => { + const urlInfo = props.match.url.split("/")[3]; + try { + const info = JSON.parse(b64uDec(urlInfo)); + const masterPassword: string = await generatePassword(32); + const keys: any = getPrivateKeys(info?.username, masterPassword); + // prepare object to encode + const pubkeys = { + activePublicKey: keys.activePubkey, + memoPublicKey: keys.memoPubkey, + ownerPublicKey: keys.ownerPubkey, + postingPublicKey: keys.postingPubkey + }; + + const dataToEncode = { + username: info.username, + email: info.email, + pubkeys + }; + // stringify object to encode + const stringifiedPubKeys = JSON.stringify(dataToEncode); + const hashedPubKeys = b64uEnc(stringifiedPubKeys); + setSecret(hashedPubKeys); + const accInfo = { + username: formatUsername(info.username), + email: formatEmail(info.email), + referral: formatUsername(info.referral), + keys + }; + setAccountInfo(accInfo); + setMasterPassword(masterPassword); + return masterPassword; + } catch (err: any) { + error(err?.message); + return null; + } + }; + + const sendMail = async () => { + const { activeUser } = props; + const username = decodedInfo!.username || accountInfo!.username; + const email = decodedInfo!.email || accountInfo!.email; + if (activeUser) { + await onboardEmail(username, formatEmail(email), activeUser?.username); + } + }; + + const splitUrl = (url: string) => { + return url.slice(0, 50); + }; + + const downloadKeys = async () => { + if (accountInfo) { + setFileIsDownloaded(false); + const { username, keys } = accountInfo; + const element = document.createElement("a"); + const keysToFile = ` + ${_t("onboard.file-warning")} + + ${_t("onboard.recommend")} + 1. ${_t("onboard.recommend-print")} + 2. ${_t("onboard.recommend-use")} + 3. ${_t("onboard.recommend-save")} + 4. ${_t("onboard.recommend-third-party")} + + ${_t("onboard.account-info")} + + Username: ${username} + + Password: ${masterPassword} + + ${_t("onboard.owner-private")} ${keys.owner} + + ${_t("onboard.active-private")} ${keys.active} + + ${_t("onboard.posting-private")} ${keys.posting} + + ${_t("onboard.memo-private")} ${keys.memo} + + + ${_t("onboard.keys-use")} + ${_t("onboard.owner")} ${_t("onboard.owner-use")} + ${_t("onboard.active")} ${_t("onboard.active-use")} + ${_t("onboard.posting")} ${_t("onboard.posting-use")} + ${_t("onboard.memo")} ${_t("onboard.memo-use")}`; + + const file = new Blob([keysToFile.replace(/\n/g, "\r\n")], { + type: "text/plain" + }); + element.href = URL.createObjectURL(file); + element.download = `${username}_hive_keys.txt`; + document.body.appendChild(element); + element.click(); + setFileIsDownloaded(true); + } + }; + + const formatUsername = (username: string) => { + return username?.replace(/\+/g, "-").replace(/=/g, "."); + }; + const formatEmail = (username: string) => { + return username?.replace(/\+/g, "-").replace(/=/g, ".").replace(/\//g, "_"); + }; + + const onKc = async (type: string) => { + const { activeUser, dynamicProps } = props; + if (activeUser) { + try { + if (type === createOptions.HIVE) { + const resp = await createAccountKc( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys, + fee: dynamicProps.accountCreationFee + }, + activeUser?.username + ); + if (resp.success == true) { + setInprogress(false); + setStep("success"); + sendMail(); + } else { + setStep("failed"); + } + } else { + const resp = await createAccountWithCreditKc( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys + }, + activeUser?.username + ); + if (resp.success == true) { + setInprogress(false); + setStep("success"); + sendMail(); + } else { + setStep("failed"); + } + } + } catch (err: any) { + if (err) { + setStep("failed"); + } + error(err.message); + } + } + }; + + const onKey = async (type: string, key: PrivateKey) => { + const { activeUser, dynamicProps } = props; + if (activeUser) { + try { + if (type === createOptions.HIVE) { + const resp = await createAccountKey( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys, + fee: dynamicProps.accountCreationFee + }, + activeUser?.username, + key + ); + if (resp.id) { + setInprogress(false); + setStep("success"); + sendMail(); + } else { + setStep("failed"); + } + } else { + const resp = await createAccountWithCreditKey( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys + }, + activeUser?.username, + key + ); + if (resp.id) { + setInprogress(false); + setStep("success"); + sendMail(); + } else { + setStep("failed"); + } + } + } catch (err: any) { + if (err) { + setStep("failed"); + } + error(err.message); + } + } + }; + + const onHot = async (type: string) => { + const { activeUser, dynamicProps } = props; + const dataToEncode = { + username: formatUsername(decodedInfo!.username), + email: formatEmail(decodedInfo!.email) + }; + const stringifiedPubKeys = JSON.stringify(dataToEncode); + const hashedInfo = b64uEnc(stringifiedPubKeys); + if (activeUser) { + try { + if (type === createOptions.HIVE) { + const resp = await createAccountHs( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys, + fee: dynamicProps.accountCreationFee + }, + activeUser?.username, + hashedInfo + ); + if (resp) { + setInprogress(false); + setShowModal(false); + // sendMail(); + } + } else { + const resp = await createAccountWithCreditHs( + { + username: formatUsername(decodedInfo!.username), + pub_keys: decodedInfo?.pubkeys + }, + activeUser?.username, + hashedInfo + ); + if (resp) { + setInprogress(false); + setShowModal(false); + // sendMail(); + } + } + } catch (err: any) { + if (err) { + setShowModal(false); + } + error(err.message); + } + } + }; + + const signTransactionModal = (type: string) => { + return ( + <> +
    +
    2
    +
    +
    {_t("onboard.sign-header-title")}
    +
    {_t("onboard.sign-sub-title")}
    +
    +
    + {inProgress && } + {keyOrHot({ + global: props.global, + activeUser: props.activeUser, + signingKey: props.signingKey, + setSigningKey: props.setSigningKey, + inProgress: inProgress, + onKey: (key) => { + onKey(type, key); + }, + onHot: () => { + onHot(type); + }, + onKc: () => { + onKc(type); + } + })} +

    + { + e.preventDefault(); + setShowModal(false); + }} + > + {_t("g.back")} + +

    + + ); + }; + + const successModalBody = () => { + return ( + <> +
    +
    2
    +
    +
    {_t("trx-common.success-title")}
    +
    {_t("trx-common.success-sub-title")}
    +
    +
    + +
    +
    + + {_t("onboard.success-message")} {decodedInfo?.username} + +
    +
    + + +
    +
    + + ); + }; + const failedModalBody = () => { + return ( + <> +
    +
    +
    +
    {_t("onboard.failed-title")}
    +
    {_t("onboard.failed-subtitle")}
    +
    +
    + +
    +
    + {_t("onboard.failed-message")} +
    +
    + + +
    +
    + + ); + }; + + const finish = () => { + setShowModal(false); + setStep(0); + }; + + return ( + <> + + + + + {props.match.params.type === "asking" && props.match.params.secret && ( +
    +
    +
    +

    {_t("onboard.confirm-details")}

    +
    + + {_t("onboard.username")} {accountInfo?.username} + + + {_t("onboard.email")} {accountInfo?.email} + + + {_t("onboard.referral")} {accountInfo?.referral} + +
    + {_t("onboard.copy-key")} +
    +
    + + {innerWidth <= 768 ? shortPassword + "..." : masterPassword} + + + { + clipboard(masterPassword); + success(_t("onboard.copy-password")); + }} + > + {copyContent} + + + + initAccountKey()}> + {regenerateSvg} + + +
    + + + {fileIsDownloaded && ( +
    + {!props.activeUser && <> +

    {_t("onboard.copy-info-message")}

    +
    + {splitUrl(onboardUrl + secret)}... + { + clipboard(onboardUrl + secret); + success(_t("onboard.copy-link")); + }} + > + {copyContent} + +
    + } + {props.activeUser && <> + + {_t("onboard.click-link")} + + } +
    + )} +
    +
    +
    +
    + )} + + {props.match.params.type === "creating" && props.match.params.secret && ( +
    + {props.activeUser ? ( +
    +

    {_t("onboard.confirm-details")}

    + {confirmDetails && ( + <> + {confirmDetails.map((field, index) => ( + + {field.label} + + {field.value} + + + ))} + + )} + +
    + {_t("onboard.pay-fee")} +
    + + +
    +
    +
    + ) : ( +
    {_t("onboard.login-warning")}
    + )} +
    + )} + + {props.match.params.type === "confirming" && ( +
    +
    + + {_t("onboard.success-message")} @{decodedInfo?.username} + +
    + +
    + )} + setShowModal(false)} + keyboard={false} + className="create-account-dialog modal-thin-header" + size="lg" + > + + + + +
    + {createOption === createOptions.HIVE && ( + + {step === "sign" && signTransactionModal(createOptions.HIVE)} + {step === "success" && successModalBody()} + {step === "failed" && failedModalBody()} + + )} + + {createOption === createOptions.CREDIT && ( + + {step === "sign" && signTransactionModal(createOptions.CREDIT)} + {step === "success" && successModalBody()} + {step === "failed" && failedModalBody()} + + )} +
    +
    +
    + + ); +}; + +export default connect(pageMapStateToProps, pageMapDispatchToProps)(Onboard); diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index af3e34cc53c..564223d20f1 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -22,6 +22,8 @@ import { Tsx } from "../i18n/helper"; import { handleInvalid, handleOnInput } from "../util/input-util"; import { getAccount } from "../api/hive"; import "./sign-up.scss"; +import { Link } from "react-router-dom"; +import { b64uEnc } from "../util/b64"; type FormChangeEvent = React.ChangeEvent; @@ -36,7 +38,9 @@ export const SignUp = (props: PageProps) => { const [username, setUsername] = useState(""); const [usernameError, setUsernameError] = useState(""); + const [referralError, setReferralError] = useState(""); const [usernameTouched, setUsernameTouched] = useState(false); + const [referralTouched, setReferralTouched] = useState(false); const [email, setEmail] = useState(""); const [referral, setReferral] = useState(""); @@ -48,6 +52,7 @@ export const SignUp = (props: PageProps) => { const [url, setUrl] = useState(""); const [isDisabled, setIsDisabled] = useState(false); const [registrationError, setRegistrationError] = useState(""); + const [urlHash, setUrlHash] = useState(""); const form = useRef(); const qrCodeRef = useRef(); @@ -119,6 +124,26 @@ export const SignUp = (props: PageProps) => { } }, [username, usernameTouched]); + useEffect(() => { + setReferralError(""); + setIsDisabled(false); + + if (!referral) { + return; + } + if (referral.length > 16) { + setReferralError(_t("sign-up.referral-max-length-error")); + setIsDisabled(true); + } else { + referral.split(".").some((item) => { + if (item.length < 3) { + setReferralError(_t("sign-up.referral-min-length-error")); + setIsDisabled(true); + } + }); + } + }, [referral, referralTouched]); + const regularRegister = async () => { setInProgress(true); try { @@ -154,6 +179,21 @@ export const SignUp = (props: PageProps) => { } }; + const encodeUrlInfo = (username: string, email: string, referral: string) => { + const accInfo = { + username, + email, + referral + }; + try { + const stringifiedInfo = JSON.stringify(accInfo); + const hashedInfo = b64uEnc(stringifiedInfo); + setUrlHash(hashedInfo); + } catch (err) { + console.log(err); + } + }; + return ( <> @@ -216,7 +256,7 @@ export const SignUp = (props: PageProps) => { return; } - if (usernameError) { + if (usernameError || referralError) { return; } @@ -226,9 +266,19 @@ export const SignUp = (props: PageProps) => { return; } + const referralIsValid = await getAccount(referral); + if (!referralIsValid && referral !== "") { + setReferralError(_t("sign-up.referral-invalid")); + return; + } + if (stage === Stage.FORM) { setStage(Stage.REGISTER_TYPE); } + + if ((username && email) || referral) { + encodeUrlInfo(username, email, referral); + } }} > @@ -264,8 +314,10 @@ export const SignUp = (props: PageProps) => { value={referral} onChange={(e: FormChangeEvent) => setReferral(e.target.value.toLowerCase())} disabled={lockReferral} + onBlur={() => setReferralTouched(true)} /> + {referralError} {!props.global.isElectron && (
    { {stage === Stage.REGISTER_TYPE ? (
    -
    +
    {_t("sign-up.free-account")}
    @@ -335,7 +387,7 @@ export const SignUp = (props: PageProps) => {
    )}
    -
    +
    {_t("sign-up.buy-account")}
    @@ -357,6 +409,31 @@ export const SignUp = (props: PageProps) => {
    + +
    +
    + {props.activeUser ? _t("onboard.title-active-user") : _t("onboard.title-visitor")} +
    +
    +

    {props.activeUser ? _t("onboard.description-active-user") : + _t("onboard.description-visitor")} +

    +
      + {props.activeUser &&
    • {_t("onboard.creating-description")}
    • } + {!props.activeUser &&
    • {_t("onboard.asking-description")}
    • } +
    +
    +
    + +
    +
    ) : ( <> diff --git a/src/common/pages/submit.tsx b/src/common/pages/submit.tsx index 9266a2db52b..a7138a2bc54 100644 --- a/src/common/pages/submit.tsx +++ b/src/common/pages/submit.tsx @@ -89,6 +89,7 @@ import { AvailableCredits } from "../components/available-credits"; import { handleFloatingContainer } from "../components/floating-faq"; import { updateSpeakVideoInfo, markAsPublished } from "../api/threespeak"; import { ConfirmNsfwContent } from "../components/video-nsfw"; +import { PostBodyLazyRenderer } from "../components/post-body-lazy-renderer"; setProxyBase(defaults.imageServer); @@ -129,7 +130,6 @@ class PreviewContent extends Component { render() { const { title, tags, body, global } = this.props; - let renderedPreview = renderPostBody(body, false, global.canUseWebp); return ( <>
    {title}
    @@ -149,10 +149,7 @@ class PreviewContent extends Component { })}
    -
    + ); } diff --git a/src/common/routes.ts b/src/common/routes.ts index 4bf63ecfe99..b79f4df04a3 100644 --- a/src/common/routes.ts +++ b/src/common/routes.ts @@ -10,6 +10,7 @@ export default { CONTRIBUTE: `/contribute`, FAQ: `/faq`, SIGN_UP: `/signup`, + ONBOARD: `/onboard-friend/:type/:secret?`, WHITE_PAPER: `/whitepaper`, MARKET: `/market`, PRIVACY: `/privacy-policy`, diff --git a/src/common/store/accounts/__snapshots__/index.spec.ts.snap b/src/common/store/accounts/__snapshots__/index.spec.ts.snap index 66986dfc222..b1e5fffea66 100644 --- a/src/common/store/accounts/__snapshots__/index.spec.ts.snap +++ b/src/common/store/accounts/__snapshots__/index.spec.ts.snap @@ -67,6 +67,7 @@ Array [ ], "weight_threshold": 1, }, + "pending_claimed_accounts": 0, "post_count": 261, "posting": Object { "account_auths": Array [ diff --git a/src/common/store/accounts/types.ts b/src/common/store/accounts/types.ts index fe6ab4b7a1b..5541dacb582 100644 --- a/src/common/store/accounts/types.ts +++ b/src/common/store/accounts/types.ts @@ -47,6 +47,7 @@ export interface FullAccount { savings_hbd_last_interest_payment: string; savings_hbd_seconds_last_update: string; next_vesting_withdrawal: string; + pending_claimed_accounts: number; delegated_vesting_shares: string; received_vesting_shares: string; vesting_withdraw_rate: string; diff --git a/src/common/store/actions.ts b/src/common/store/actions.ts index c6f7fd2f075..bfe5f83315c 100644 --- a/src/common/store/actions.ts +++ b/src/common/store/actions.ts @@ -8,6 +8,7 @@ import { setNsfw, toggleListStyle, toggleTheme, + newVersionChangeAct, unMuteNotifications } from "./global"; import { fetchTrendingTags } from "./trending-tags"; @@ -22,7 +23,6 @@ import { updateReply } from "./discussion"; import { addAccount } from "./accounts"; -import { addCommunity } from "./communities"; import { fetchTransactions, resetTransactions } from "./transactions"; import { addUser, deleteUser } from "./users"; import { setActiveUser, updateActiveUser } from "./active-user"; @@ -39,12 +39,11 @@ import { } from "./notifications"; import { fetchPoints, resetPoints } from "./points"; import { setSigningKey } from "./signing-key"; -import { setEntryPin, trackEntryPin } from "./entry-pin-tracker"; -import { savePageScroll } from "./persistent-page-scroll"; // @note Do not use it directly export const ACTIONS = { toggleTheme, + newVersionChangeAct, hideIntro, toggleListStyle, muteNotifications, @@ -67,7 +66,6 @@ export const ACTIONS = { addReply, deleteReply, addAccount, - addCommunity, fetchTransactions, resetTransactions, addUser, @@ -85,8 +83,6 @@ export const ACTIONS = { fetchPoints, resetPoints, setSigningKey, - trackEntryPin, - setEntryPin, updateNotificationsSettings, fetchNotificationsSettings, setNotificationsSettingsItem diff --git a/src/common/store/active-user/__snapshots__/index.spec.ts.snap b/src/common/store/active-user/__snapshots__/index.spec.ts.snap index 1f0c2227c12..01153e5e6f2 100644 --- a/src/common/store/active-user/__snapshots__/index.spec.ts.snap +++ b/src/common/store/active-user/__snapshots__/index.spec.ts.snap @@ -58,6 +58,7 @@ Object { ], "weight_threshold": 1, }, + "pending_claimed_accounts": 0, "post_count": 261, "posting": Object { "account_auths": Array [ diff --git a/src/common/store/communities/__snapshots__/index.test.ts.snap b/src/common/store/communities/__snapshots__/index.test.ts.snap deleted file mode 100644 index 55898aba27e..00000000000 --- a/src/common/store/communities/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,47 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`1- default state 1`] = `Array []`; - -exports[`2- addAct 1`] = ` -Array [ - Object { - "about": "To highlight true Gems of Hive community with User Retention as primary objective.", - "avatar_url": "", - "created_at": "2020-02-26 11:33:33", - "description": "This is a collective curation community formed by @appreciator, @rocky1 and @upmewhale. You can post your genuine and creative content in this community to get more support. - - -You can post in languages other than English. - -There are not many restrictions but just few simple ones and we expect you to adhere to them - -Join our discord group to keep yourself updated: -https://discord.gg/n98Kpmm", - "flag_text": "Plagiarism will be highly discouraged. -Hate Speech is not allowed", - "id": 1369030, - "is_nsfw": false, - "lang": "en", - "name": "hive-148441", - "num_authors": 1796, - "num_pending": 12481, - "settings": Object {}, - "subscribers": 4086, - "sum_pending": 17370, - "team": Array [ - Array [ - "hive-148441", - "owner", - "", - ], - Array [ - "bluemist", - "admin", - "", - ], - ], - "title": "GEMS", - "type_id": 1, - }, -] -`; diff --git a/src/common/store/communities/index.test.ts b/src/common/store/communities/index.test.ts deleted file mode 100644 index 74805ce26f7..00000000000 --- a/src/common/store/communities/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import reducer, { initialState, addAct } from "./index"; - -import { communityInstance1 } from "../../helper/test-helper"; - -let state = initialState; - -it("1- default state", () => { - expect(state).toMatchSnapshot(); -}); - -it("2- addAct", () => { - state = reducer(state, addAct(communityInstance1)); - expect(state).toMatchSnapshot(); -}); diff --git a/src/common/store/communities/index.ts b/src/common/store/communities/index.ts index 7ab153b37e7..eea524d6557 100644 --- a/src/common/store/communities/index.ts +++ b/src/common/store/communities/index.ts @@ -1,31 +1 @@ -import { Dispatch } from "redux"; - -import { Community, Communities, Actions, ActionTypes, AddAction } from "./types"; - -export const initialState: Communities = []; - -export default (state: Communities = initialState, action: Actions): Communities => { - switch (action.type) { - case ActionTypes.ADD: { - const { data } = action; - - return [...state.filter((x) => x.name !== data.name), data]; - } - default: - return state; - } -}; - -/* Actions */ -export const addCommunity = (data: Community) => (dispatch: Dispatch) => { - dispatch(addAct(data)); -}; - -/* Action Creators */ - -export const addAct = (data: Community): AddAction => { - return { - type: ActionTypes.ADD, - data - }; -}; +export * from "./types"; diff --git a/src/common/store/dynamic-props/index.ts b/src/common/store/dynamic-props/index.ts index 8558bd0040d..b477fa28f2c 100644 --- a/src/common/store/dynamic-props/index.ts +++ b/src/common/store/dynamic-props/index.ts @@ -16,7 +16,8 @@ export const initialState: State = { totalVestingFund: 1, totalVestingShares: 1, virtualSupply: 1, - vestingRewardPercent: 1 + vestingRewardPercent: 1, + accountCreationFee: "3.000 HIVE" }; export default (state: State = initialState, action: Actions): State => { diff --git a/src/common/store/dynamic-props/types.ts b/src/common/store/dynamic-props/types.ts index f8884cd7cfc..e7f03c93e1e 100644 --- a/src/common/store/dynamic-props/types.ts +++ b/src/common/store/dynamic-props/types.ts @@ -11,6 +11,7 @@ export interface DynamicProps { totalVestingShares: number; virtualSupply: number; vestingRewardPercent: number; + accountCreationFee: string; } export type State = DynamicProps; diff --git a/src/common/store/entry-pin-tracker/__snapshots__/index.test.ts.snap b/src/common/store/entry-pin-tracker/__snapshots__/index.test.ts.snap deleted file mode 100644 index 69b1150d939..00000000000 --- a/src/common/store/entry-pin-tracker/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`1- default state 1`] = `Object {}`; - -exports[`2- fetchAct 1`] = ` -Object { - "good-karma-awesome-hive": false, -} -`; - -exports[`3- fetchAct 1`] = ` -Object { - "foo-bar": false, - "good-karma-awesome-hive": false, -} -`; - -exports[`4- setAct 1`] = ` -Object { - "foo-bar": false, - "good-karma-awesome-hive": true, -} -`; - -exports[`5- setAct 1`] = ` -Object { - "foo-bar": false, - "good-karma-awesome-hive": false, -} -`; diff --git a/src/common/store/entry-pin-tracker/index.test.ts b/src/common/store/entry-pin-tracker/index.test.ts deleted file mode 100644 index 342f4f023ab..00000000000 --- a/src/common/store/entry-pin-tracker/index.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import reducer, { initialState, fetchAct, setAct } from "./index"; -import { entryInstance1 } from "../../helper/test-helper"; - -const entry = { ...entryInstance1 }; -const entry2 = { ...entryInstance1, ...{ author: "foo", permlink: "bar" } }; - -let state = initialState; - -it("1- default state", () => { - expect(state).toMatchSnapshot(); -}); - -it("2- fetchAct", () => { - state = reducer(state, fetchAct(entry)); - expect(state).toMatchSnapshot(); -}); - -it("3- fetchAct", () => { - state = reducer(state, fetchAct(entry2)); - expect(state).toMatchSnapshot(); -}); - -it("4- setAct", () => { - state = reducer(state, setAct(entry, true)); - expect(state).toMatchSnapshot(); -}); - -it("5- setAct", () => { - state = reducer(state, setAct(entry, false)); - expect(state).toMatchSnapshot(); -}); diff --git a/src/common/store/entry-pin-tracker/index.ts b/src/common/store/entry-pin-tracker/index.ts deleted file mode 100644 index b001b69b409..00000000000 --- a/src/common/store/entry-pin-tracker/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Dispatch } from "redux"; - -import { Entry } from "../entries/types"; -import { ActionTypes as ActiveUserActionTypes } from "../active-user/types"; -import { AppState } from "../index"; - -import { EntryPinTracker, Actions, ActionTypes, FetchAction, SetAction } from "./types"; - -import { CommonActionTypes } from "../common"; - -import { dataLimit, getPostsRanked } from "../../api/bridge"; - -export const initialState: EntryPinTracker = {}; - -export default (state: EntryPinTracker = initialState, action: Actions): EntryPinTracker => { - switch (action.type) { - case ActionTypes.FETCH: { - const key = `${action.author}-${action.permlink}`; - return { - ...state, - [key]: false - }; - } - case ActionTypes.SET: { - const key = `${action.author}-${action.permlink}`; - return { - ...state, - [key]: action.pinned - }; - } - case CommonActionTypes.LOCATION_CHANGE: - case ActiveUserActionTypes.LOGIN: - case ActiveUserActionTypes.LOGOUT: { - return { ...initialState }; - } - default: - return state; - } -}; - -export const trackEntryPin = (entry: Entry) => (dispatch: Dispatch, getState: () => AppState) => { - const { activeUser, entryPinTracker } = getState(); - - if (!activeUser) { - return; - } - - const key = `${entry.author}-${entry.permlink}`; - if (entryPinTracker[key] !== undefined) { - return; - } - - if (!entry.community_title) { - return; - } - - dispatch(fetchAct(entry)); - - getPostsRanked("created", "", "", dataLimit, entry.category) - .then((r) => { - if (r) { - const isPinned = - r.find( - (x) => - x.author === entry.author && - x.permlink === entry.permlink && - x.stats?.is_pinned === true - ) !== undefined; - dispatch(setAct(entry, isPinned)); - return; - } - - dispatch(setAct(entry, false)); - }) - .catch(() => { - dispatch(setAct(entry, false)); - }); -}; - -export const setEntryPin = (entry: Entry, pin: boolean) => (dispatch: Dispatch) => { - dispatch(setAct(entry, pin)); -}; - -/* Action Creators */ -export const fetchAct = (entry: Entry): FetchAction => { - return { - type: ActionTypes.FETCH, - author: entry.author, - permlink: entry.permlink - }; -}; - -export const setAct = (entry: Entry, pinned: boolean): SetAction => { - return { - type: ActionTypes.SET, - author: entry.author, - permlink: entry.permlink, - pinned - }; -}; diff --git a/src/common/store/entry-pin-tracker/types.ts b/src/common/store/entry-pin-tracker/types.ts deleted file mode 100644 index a2be0408329..00000000000 --- a/src/common/store/entry-pin-tracker/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { LoginAction, LogoutAction } from "../active-user/types"; - -import { LocationChangeAction } from "../common"; - -export type EntryPinTracker = Record; - -export enum ActionTypes { - FETCH = "@entry-pin-tracker/FETCH", - FETCHED = "@entry-pin-tracker/FETCHED", - SET = "@entry-pin-tracker/SET" -} - -export interface FetchAction { - type: ActionTypes.FETCH; - author: string; - permlink: string; -} - -export interface SetAction { - type: ActionTypes.SET; - author: string; - permlink: string; - pinned: boolean; -} - -export type Actions = FetchAction | SetAction | LoginAction | LogoutAction | LocationChangeAction; diff --git a/src/common/store/index.ts b/src/common/store/index.ts index a55ca8e763e..6516b87b8ff 100644 --- a/src/common/store/index.ts +++ b/src/common/store/index.ts @@ -9,7 +9,6 @@ import dynamicProps from "./dynamic-props"; import trendingTags from "./trending-tags"; import entries from "./entries"; import accounts from "./accounts"; -import communities from "./communities"; import transactions from "./transactions"; import users from "./users"; import activeUser from "./active-user"; @@ -20,7 +19,6 @@ import subscriptions from "./subscriptions"; import notifications from "./notifications"; import points from "./points"; import signingKey from "./signing-key"; -import entryPinTracker from "./entry-pin-tracker"; import persistentPageScroll from "./persistent-page-scroll"; import filterTagExtract from "../helper/filter-tag-extract"; @@ -31,7 +29,6 @@ let reducers = { trendingTags, entries, accounts, - communities, transactions, users, activeUser, @@ -42,7 +39,6 @@ let reducers = { notifications, points, signingKey, - entryPinTracker, persistentPageScroll }; diff --git a/src/common/store/initial-state.ts b/src/common/store/initial-state.ts index dc14065e2b7..07bfb58b9e3 100644 --- a/src/common/store/initial-state.ts +++ b/src/common/store/initial-state.ts @@ -4,7 +4,6 @@ import { initialState as globalInitialState } from "./global"; import { initialState as dynamicPropsInitialState } from "./dynamic-props"; import { initialState as trendingTagsInitialState } from "./trending-tags"; import { initialState as accountsInitialState } from "./accounts"; -import { initialState as communitiesInitialState } from "./communities"; import { initialState as transactionsInitialState } from "./transactions"; import { initialState as usersInitialState } from "./users"; import { initialState as activeUserInitialState } from "./active-user"; @@ -16,7 +15,6 @@ import { initialState as notificationsInitialState } from "./notifications"; import { initialState as entriesInitialState } from "./entries"; import { initialState as pointsInitialState } from "./points"; import { initialState as signingKeyInitialState } from "./signing-key"; -import { initialState as entryPinTrackerInitialState } from "./entry-pin-tracker"; import { initialState as persistentPageScrollInitialState } from "./persistent-page-scroll"; const initialState: AppState = { @@ -24,7 +22,6 @@ const initialState: AppState = { dynamicProps: dynamicPropsInitialState, trendingTags: trendingTagsInitialState, accounts: accountsInitialState, - communities: communitiesInitialState, transactions: transactionsInitialState, users: usersInitialState, activeUser: activeUserInitialState, @@ -36,7 +33,6 @@ const initialState: AppState = { entries: entriesInitialState, points: pointsInitialState, signingKey: signingKeyInitialState, - entryPinTracker: entryPinTrackerInitialState, persistentPageScroll: persistentPageScrollInitialState }; diff --git a/src/common/tests/with-store.tsx b/src/common/tests/with-store.tsx index ef402c187eb..86a1f054687 100644 --- a/src/common/tests/with-store.tsx +++ b/src/common/tests/with-store.tsx @@ -1,7 +1,7 @@ import React from "react"; import configureStore from "../store/configure"; import initialState from "../store/initial-state"; -import TestRenderer, { ReactTestInstance } from "react-test-renderer"; +import TestRenderer from "react-test-renderer"; import { Provider } from "react-redux"; import { activeUserInstance, diff --git a/src/common/util/b64.ts b/src/common/util/b64.ts index a7bfb136dbd..4a6a0b820b4 100644 --- a/src/common/util/b64.ts +++ b/src/common/util/b64.ts @@ -1,4 +1,9 @@ +import { Base64 } from "js-base64"; + const b64uLookup = { "/": "_", _: "/", "+": "-", "-": "+", "=": ".", ".": "=" }; export const b64uEnc = (str: string): string => - btoa(str).replace(/([+\/=])/g, (m) => b64uLookup[m]); + Base64.encode(str).replace(/(\+|\/|=)/g, (m) => b64uLookup[m]); + +export const b64uDec = (str: string): any => + Base64.decode(str).replace(/(-|_|\.)/g, (m) => b64uLookup[m]); diff --git a/src/desktop/app/index.tsx b/src/desktop/app/index.tsx index 153126b4569..bbbc9e6f8cf 100644 --- a/src/desktop/app/index.tsx +++ b/src/desktop/app/index.tsx @@ -32,6 +32,10 @@ import "../../style/style.scss"; import "../../client/base-handlers"; import "./context-menu"; +import log from "electron-log"; +import path from "path"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { queryClient } from "../../common/core"; declare var window: DesktopWindow; @@ -64,11 +68,13 @@ const store = configureStore(preloadedState); document.addEventListener("DOMContentLoaded", () => { render( - - - - - , + + + + + + + , document.getElementById("root") ); @@ -117,3 +123,5 @@ window.addEventListener("deep-link", (e) => { window["ipcRenderer"].on("update-available", (event: any, version: string) => { store.dispatch(newVersionChangeAct(version)); }); + +log.transports.file.resolvePath = () => path.join(__dirname, "logs/main.log"); diff --git a/src/desktop/app/main.dev.ts b/src/desktop/app/main.dev.ts index 6b17f4dd393..32d3a4e4d18 100644 --- a/src/desktop/app/main.dev.ts +++ b/src/desktop/app/main.dev.ts @@ -219,6 +219,11 @@ ipcMain.on("download-update", (event: any, version: any) => { }); ipcMain.on("update-restart", () => { - autoUpdater.quitAndInstall(); - console.log("Restart"); + setImmediate(() => { + app.removeAllListeners("window-all-closed"); + if (mainWindow != null) { + mainWindow.close(); + } + autoUpdater.quitAndInstall(); + }); }); diff --git a/src/desktop/app/package.json b/src/desktop/app/package.json index 31d67494272..313413d6276 100644 --- a/src/desktop/app/package.json +++ b/src/desktop/app/package.json @@ -3,7 +3,7 @@ "productName": "Ecency", "description": "Ecency desktop application reimagined for Windows, Mac, Linux users, start earning cryptocurrency!", "homepage": "https://ecency.com", - "version": "3.0.32", + "version": "3.0.35", "main": "./main.prod.js", "author": "Ecency ", "scripts": { diff --git a/src/desktop/package.json b/src/desktop/package.json index 02d4105bf24..a258e5ef04e 100644 --- a/src/desktop/package.json +++ b/src/desktop/package.json @@ -4,7 +4,7 @@ "description": "Ecency desktop application reimagined for Windows, Mac, Linux users, start earning cryptocurrency!", "private": false, "author": "Ecency ", - "version": "3.0.32", + "version": "3.0.35", "copyright": "© 2020, Ecency", "license": "MIT", "homepage": "https://ecency.com", @@ -126,6 +126,7 @@ "@babel/register": "^7.10.5", "@teamsupercell/typings-for-css-modules-loader": "^2.2.1", "@types/jest": "^26.0.24", + "@types/semver": "^7.5.0", "babel-plugin-dev-expression": "^0.2.2", "chalk": "^4.1.0", "concurrently": "^5.3.0", @@ -151,10 +152,10 @@ "@babel/plugin-syntax-import-meta": "^7.10.4", "electron-debug": "^3.1.0", "electron-log": "^4.2.4", - "electron-updater": "^4.3.4", + "electron-updater": "^6.1.1", "extract-text-webpack-plugin": "^4.0.0-beta.0", "react-hot-loader": "^4.12.21", - "source-map-support": "^0.5.19", - "sass-loader": "10.1.1" + "sass-loader": "10.1.1", + "source-map-support": "^0.5.19" } } diff --git a/src/desktop/yarn.lock b/src/desktop/yarn.lock index d5145caf7b9..ab9d496188b 100644 --- a/src/desktop/yarn.lock +++ b/src/desktop/yarn.lock @@ -517,10 +517,10 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/semver@^7.3.1": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb" - integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== +"@types/semver@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== "@types/yargs-parser@*": version "15.0.0" @@ -868,6 +868,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -960,11 +965,6 @@ async@^3.2.3: resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -1256,12 +1256,12 @@ builder-util-runtime@8.6.1: debug "^4.1.1" sax "^1.2.4" -builder-util-runtime@8.7.2: - version "8.7.2" - resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72" - integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA== +builder-util-runtime@9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.1.tgz#3184dcdf7ed6c47afb8df733813224ced4f624fd" + integrity sha512-2rLv/uQD2x+dJ0J3xtsmI12AlRyk7p45TEbE/6o/fbb633e/S3pPgm+ct+JHsoY7r39dKHnGEFk/AASRFdnXmA== dependencies: - debug "^4.1.1" + debug "^4.3.4" sax "^1.2.4" builder-util@22.3.6, builder-util@~22.3.6: @@ -2040,6 +2040,13 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2389,18 +2396,19 @@ electron-to-chromium@^1.3.723: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9" integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A== -electron-updater@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.5.tgz#4fb36f593a031c87ea07ee141c9f064d5deffb15" - integrity sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ== +electron-updater@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.1.1.tgz#4ede9b560936957b2b87181736f98b1621fa26fd" + integrity sha512-IBT3zJ4yO5UZMF2gOTC9HrlmG4OYSRtOiHKzNAShJvfuicdx6UaXoa6AvhcTxdx6zf/rJyFMRBISS9jhVwTfow== dependencies: - "@types/semver" "^7.3.1" - builder-util-runtime "8.7.2" - fs-extra "^9.0.1" - js-yaml "^3.14.0" - lazy-val "^1.0.4" + builder-util-runtime "9.2.1" + fs-extra "^10.1.0" + js-yaml "^4.1.0" + lazy-val "^1.0.5" + lodash.escaperegexp "^4.1.2" lodash.isequal "^4.5.0" - semver "^7.3.2" + semver "^7.3.8" + typed-emitter "^2.1.0" electron@^13.0.0: version "13.6.7" @@ -2933,7 +2941,7 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-extra@^10.0.0: +fs-extra@^10.0.0, fs-extra@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== @@ -2951,16 +2959,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" - integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^1.0.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -3886,7 +3884,7 @@ jest-worker@^26.2.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1, js-yaml@^3.14.0: +js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -3894,6 +3892,13 @@ js-yaml@^3.13.1, js-yaml@^3.14.0: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4028,6 +4033,11 @@ lazy-val@^1.0.4: resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q== +lazy-val@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d" + integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== + loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -4075,6 +4085,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== + lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5721,6 +5736,13 @@ rxjs@^6.5.2: dependencies: tslib "^1.9.0" +rxjs@^7.5.2: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -5826,27 +5848,22 @@ semver-diff@^3.1.1: semver "^6.3.0" "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.1.3: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@^7.1.3, semver@^7.3.2, semver@^7.3.8: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6553,6 +6570,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^2.1.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -6581,6 +6603,13 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb" + integrity sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA== + optionalDependencies: + rxjs "^7.5.2" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" diff --git a/src/server/amp-template.tsx b/src/server/amp-template.tsx index 504a768d965..52c7611ed22 100644 --- a/src/server/amp-template.tsx +++ b/src/server/amp-template.tsx @@ -9,18 +9,8 @@ import { ChunkExtractor, ChunkExtractorManager } from "@loadable/server"; import App from "../common/app"; import { AppState } from "../common/store"; import configureStore from "../common/store/configure"; - -let assets: any = require(process.env.RAZZLE_ASSETS_MANIFEST || ""); - -const cssLinksFromAssets = (assets: any, entrypoint: string) => { - return assets[entrypoint] - ? assets[entrypoint].css - ? assets[entrypoint].css - .map((asset: any) => ``) - .join("") - : "" - : ""; -}; +import { queryClient } from "../common/core"; +import { QueryClientProvider } from "@tanstack/react-query"; export const renderAmp = async (req: express.Request, state: AppState) => { const store = configureStore(state); @@ -34,9 +24,11 @@ export const renderAmp = async (req: express.Request, state: AppState) => { let markup = renderToString( - - - + + + + + ); diff --git a/src/server/handlers/community.tsx b/src/server/handlers/community.tsx index 3bfb0e9429b..d71ce74784f 100644 --- a/src/server/handlers/community.tsx +++ b/src/server/handlers/community.tsx @@ -1,7 +1,6 @@ import express from "express"; import { AppState } from "../../common/store"; -import { Community } from "../../common/store/communities/types"; import { Entry } from "../../common/store/entries/types"; import { makeGroupKey } from "../../common/store/entries"; @@ -15,17 +14,22 @@ import { optimizeEntries } from "../helper"; import { render } from "../template"; import { EntryFilter } from "../../common/store/global/types"; +import { queryClient, QueryIdentifiers } from "../../common/core"; +import isCommunity from "../../common/helper/is-community"; export default async (req: express.Request, res: express.Response) => { const { filter, name, section } = req.params; - - let communities: Community[] = []; try { - const community = await bridgeApi.getCommunity(name); - if (community) { - communities = [community]; - } - } catch (e) {} + await queryClient.fetchQuery([QueryIdentifiers.COMMUNITY, name], () => + isCommunity(name) ? bridgeApi.getCommunity(name) : null + ); + } catch (error) { + console.error( + `${new Date().toISOString()} ${ + bridgeApi.bridgeServer?.currentAddress + } ERROR fetching community ${name}` + ); + } let accounts = []; @@ -64,7 +68,6 @@ export default async (req: express.Request, res: express.Response) => { hasMore: true } }, - communities, accounts }; diff --git a/src/server/handlers/entry.tsx b/src/server/handlers/entry.tsx index 88a02419ee2..724666bcdaa 100644 --- a/src/server/handlers/entry.tsx +++ b/src/server/handlers/entry.tsx @@ -13,10 +13,23 @@ import { getAsAMP } from "../services"; import { getPost } from "../../common/api/hive"; import { parse } from "node-html-parser"; import moment from "moment"; +import { queryClient, QueryIdentifiers } from "../../common/core"; +import { makePath } from "../../common/components/entry-link"; export default async (req: Request, res: Response) => { const { category, author, permlink } = req.params; let entry: Entry | null = null; + try { + await queryClient.fetchQuery([QueryIdentifiers.ENTRY, makePath("", author, permlink)], () => + bridgeApi.getPost(author, permlink) + ); + } catch (error) { + console.error( + `${new Date().toISOString()} ${ + bridgeApi.bridgeServer?.currentAddress + } ERROR fetching @${author}/${permlink}` + ); + } if (permlink.indexOf(".") > -1) { console.error(`${new Date().toISOString()} ERROR permlink @${author}/${permlink}`); diff --git a/src/server/template.tsx b/src/server/template.tsx index 89e90b0a06d..ccdcb0d09a3 100644 --- a/src/server/template.tsx +++ b/src/server/template.tsx @@ -1,43 +1,17 @@ import express from "express"; - import React from "react"; import { Provider } from "react-redux"; import { renderToString } from "react-dom/server"; import { StaticRouter } from "react-router-dom"; - import { Helmet } from "react-helmet"; - import serialize from "serialize-javascript"; - import App from "../common/app"; - import { AppState } from "../common/store"; - import configureStore from "../common/store/configure"; import path from "path"; import { ChunkExtractor, ChunkExtractorManager } from "@loadable/server"; - -let assets: any = require(process.env.RAZZLE_ASSETS_MANIFEST || ""); - -const cssLinksFromAssets = (assets: any, entrypoint: string) => { - return assets[entrypoint] - ? assets[entrypoint].css - ? assets[entrypoint].css - .map((asset: any) => ``) - .join("") - : "" - : ""; -}; - -const jsScriptTagsFromAssets = (assets: any, entrypoint: any, extra = "") => { - return assets[entrypoint] - ? assets[entrypoint].js - ? assets[entrypoint].js - .map((asset: any) => ``) - .join("") - : "" - : ""; -}; +import { dehydrate, QueryClientProvider } from "@tanstack/react-query"; +import { queryClient } from "../common/core"; export const render = (req: express.Request, state: AppState) => { const store = configureStore(state); @@ -47,13 +21,16 @@ export const render = (req: express.Request, state: AppState) => { const statsFile = path.resolve("./build/loadable-stats.json"); // We create an extractor from the statsFile const extractor = new ChunkExtractor({ statsFile, entrypoints: ["client"] }); + const dehydratedState = dehydrate(queryClient); const markup = renderToString( - - - + + + + + ); @@ -66,6 +43,7 @@ export const render = (req: express.Request, state: AppState) => { const linkTags = extractor.getLinkTags(); const styleTags = extractor.getStyleTags(); + queryClient.clear(); return ` @@ -83,6 +61,7 @@ export const render = (req: express.Request, state: AppState) => {
    ${markup}
    ${scriptTags}