diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e9f091..44f1dfba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,21 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## 3.11.0 (2024-10-25) + ### 3.10.3 (2024-10-18) ### 3.10.2 (2024-09-12) - ### Bug Fixes -* skeleton style ([#646](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/issues/646)) ([644f00f](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/commit/644f00f03997b53aa304c80084d6c069f51c3808)) +- skeleton style ([#646](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/issues/646)) ([644f00f](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/commit/644f00f03997b53aa304c80084d6c069f51c3808)) ### 3.10.1 (2024-09-10) - ### Bug Fixes -* change provider export path ([4c4b0a2](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/commit/4c4b0a2c371c979880fd29ed04d9b97496dc125e)) +- change provider export path ([4c4b0a2](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/commit/4c4b0a2c371c979880fd29ed04d9b97496dc125e)) ## 3.10.0 (2024-09-02) diff --git a/package.json b/package.json index 4582fd7a..3ea4d4c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@amityco/ui-kit-open-source", - "version": "3.10.3", + "version": "3.11.0", "engines": { "node": ">=16", "pnpm": ">=8" @@ -39,12 +39,12 @@ "tsc": "tsc" }, "peerDependencies": { - "@amityco/ts-sdk": "^6.30.0", + "@amityco/ts-sdk": "^6.32.0", "react": ">=17.0.2", "react-dom": ">=17.0.2" }, "devDependencies": { - "@amityco/ts-sdk": "^6.30.0", + "@amityco/ts-sdk": "^6.32.0", "@eslint/js": "^9.4.0", "@storybook/addon-a11y": "^7.6.7", "@storybook/addon-actions": "^7.6.7", @@ -110,8 +110,8 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@hookform/error-message": "^2.0.1", "@hookform/resolvers": "^3.3.4", - "@lexical/link": "^0.16.1", - "@lexical/react": "^0.16.1", + "@lexical/link": "^0.18.0", + "@lexical/react": "^0.18.0", "@radix-ui/react-tabs": "^1.0.4", "@tanstack/react-query": "^5.28.14", "clsx": "^2.1.0", @@ -120,7 +120,7 @@ "filesize": "^9.0.11", "framer-motion": "^11.1.7", "hls.js": "^1.4.14", - "lexical": "^0.16.1", + "lexical": "^0.18.0", "linkify-react": "^4.1.3", "linkifyjs": "^4.1.3", "lodash": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 254f406e..25adf781 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,11 +24,11 @@ importers: specifier: ^3.3.4 version: 3.6.0(react-hook-form@7.52.0(react@18.3.1)) '@lexical/link': - specifier: ^0.16.1 - version: 0.16.1 + specifier: ^0.18.0 + version: 0.18.0 '@lexical/react': - specifier: ^0.16.1 - version: 0.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.18) + specifier: ^0.18.0 + version: 0.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.18) '@radix-ui/react-tabs': specifier: ^1.0.4 version: 1.1.0(@types/react-dom@18.3.0)(@types/react@17.0.80)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -54,8 +54,8 @@ importers: specifier: ^1.4.14 version: 1.5.11 lexical: - specifier: ^0.16.1 - version: 0.16.1 + specifier: ^0.18.0 + version: 0.18.0 linkify-react: specifier: ^4.1.3 version: 4.1.3(linkifyjs@4.1.3)(react@18.3.1) @@ -136,8 +136,8 @@ importers: version: 3.23.8 devDependencies: '@amityco/ts-sdk': - specifier: ^6.30.0 - version: 6.30.0 + specifier: ^6.32.0 + version: 6.32.0 '@eslint/js': specifier: ^9.4.0 version: 9.7.0 @@ -315,8 +315,8 @@ packages: '@adobe/css-tools@4.3.3': resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} - '@amityco/ts-sdk@6.30.0': - resolution: {integrity: sha512-kyW0ytV6Go3tAZ5EFmzeVLm2PE2jzgmlKnKygpK9iJPgY46wsGCVkhRFMCLMXGvpNPz3D1Tnmq+83wL/xNTJKg==} + '@amityco/ts-sdk@6.32.0': + resolution: {integrity: sha512-7CB8ofBWNS9wrRkt3ddnNQD0qSKz9A1WW1EnVLGORgJJtDyhkrHK2Qy9pgCpcUzA3YzbjYD9d+fxXI66fSBJIQ==} engines: {node: '>=12', npm: '>=6'} '@ampproject/remapping@2.3.0': @@ -1543,74 +1543,74 @@ packages: '@juggle/resize-observer@3.4.0': resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} - '@lexical/clipboard@0.16.1': - resolution: {integrity: sha512-0dWs/SwKS5KPpuf6fUVVt9vSCl6HAqcDGhSITw/okv0rrIlXTUT6WhVsMJtXfFxTyVvwMeOecJHvQH3i/jRQtA==} + '@lexical/clipboard@0.18.0': + resolution: {integrity: sha512-ybc+hx14wj0n2ZjdOkLcZ02MRB3UprXjpLDXlByFIuVcZpUxVcp3NzA0UBPOKXYKvdt0bmgjnAsFWM5OSbwS0w==} - '@lexical/code@0.16.1': - resolution: {integrity: sha512-pOC28rRZ2XkmI2nIJm50DbKaCJtk5D0o7r6nORYp4i0z+lxt5Sf2m82DL9ksUHJRqKy87pwJDpoWvJ2SAI0ohw==} + '@lexical/code@0.18.0': + resolution: {integrity: sha512-VB8fRHIrB8QTqyZUvGBMVWP2tpKe3ArOjPdWAqgrS8MVFldqUhuTHcW+XJFkVxcEBYCXynNT29YRYtQhfQ+vDQ==} - '@lexical/devtools-core@0.16.1': - resolution: {integrity: sha512-8CvGERGL7ySDVGLU+YPeq+JupIXsOFlXa3EuJ88koLKqXxYenwMleZgGqayFp6lCP78xqPKnATVeoOZUt/NabQ==} + '@lexical/devtools-core@0.18.0': + resolution: {integrity: sha512-gVgtEkLwGjz1frOmDpFJzDPFxPgAcC9n5ZaaZWHo5GLcptnQmkuLm1t+UInQWujXhFmcyJzfiqDaMJ8EIcb2Ww==} peerDependencies: react: '>=17.x' react-dom: '>=17.x' - '@lexical/dragon@0.16.1': - resolution: {integrity: sha512-Rvd60GIYN5kpjjBumS34EnNbBaNsoseI0AlzOdtIV302jiHPCLH0noe9kxzu9nZy+MZmjZy8Dx2zTbQT2mueRw==} + '@lexical/dragon@0.18.0': + resolution: {integrity: sha512-toD/y2/TgtG+eFVKXf65kDk/Mv02FwgmcGH18nyAabZnO1TLBaMYPkGFdTTZ8hVmQxqIu9nZuLWUbdIBMs8UWw==} - '@lexical/hashtag@0.16.1': - resolution: {integrity: sha512-G+YOxStAKs3q1utqm9KR4D4lCkwIH52Rctm4RgaVTI+4lvTaybeDRGFV75P/pI/qlF7/FvAYHTYEzCjtC3GNMQ==} + '@lexical/hashtag@0.18.0': + resolution: {integrity: sha512-bm+Sv7keguVYbUY0ngd+iAv2Owd3dePzdVkzkmw9Al8GPXkE5ll8fjq6Xjw2u3OVhf+9pTnesIo/AS7H+h0exw==} - '@lexical/history@0.16.1': - resolution: {integrity: sha512-WQhScx0TJeKSQAnEkRpIaWdUXqirrNrom2MxbBUc/32zEUMm9FzV7nRGknvUabEFUo7vZq6xTZpOExQJqHInQA==} + '@lexical/history@0.18.0': + resolution: {integrity: sha512-c87J4ke1Sae03coElJay2Ikac/4OcA2OmhtNbt2gAi/XBtcsP4mPuz1yZfZf9XIe+weekObgjinvZekQ2AFw0g==} - '@lexical/html@0.16.1': - resolution: {integrity: sha512-vbtAdCvQ3PaAqa5mFmtmrvbiAvjCu1iXBAJ0bsHqFXCF2Sba5LwHVe8dUAOTpfEZEMbiHfjul6b5fj4vNPGF2A==} + '@lexical/html@0.18.0': + resolution: {integrity: sha512-8lhba1DFnnobXgYm4Rk5Gr2tZedD4Gl6A/NKCt7whO/CET63vT3UnK2ggcVVgtIJG530Cv0bdZoJbJu5DauI5w==} - '@lexical/link@0.16.1': - resolution: {integrity: sha512-zG36gEnEqbIe6tK/MhXi7wn/XMY/zdivnPcOY5WyC3derkEezeLSSIFsC1u5UNeK5pbpNMSy4LDpLhi1Ww4Y5w==} + '@lexical/link@0.18.0': + resolution: {integrity: sha512-GCYcbNTSTwJk0lr+GMc8nn6Meq44BZs3QL2d1B0skpZAspd8yI53sRS6HDy5P+jW5P0dzyZr/XJAU4U+7zsEEg==} - '@lexical/list@0.16.1': - resolution: {integrity: sha512-i9YhLAh5N6YO9dP+R1SIL9WEdCKeTiQQYVUzj84vDvX5DIBxMPUjTmMn3LXu9T+QO3h1s2L/vJusZASrl45eAw==} + '@lexical/list@0.18.0': + resolution: {integrity: sha512-DEWs9Scbg3+STZeE2O0OoG8SWnKnxQccObBzyeHRjn4GAN6JA7lgcAzfrdgp0fNWTbMM/ku876MmXKGnqhvg9Q==} - '@lexical/mark@0.16.1': - resolution: {integrity: sha512-CZRGMLcxn5D+jzf1XnH+Z+uUugmpg1mBwTbGybCPm8UWpBrKDHkrscfMgWz62iRWz0cdVjM5+0zWpNElxFTRjQ==} + '@lexical/mark@0.18.0': + resolution: {integrity: sha512-QA4YWfTP5WWnCnoH/RmfcsSZyhhd7oeFWDpfP7S8Bbmhz6kiPwGcsVr+uRQBBT56AqEX167xX2rX8JR6FiYZqA==} - '@lexical/markdown@0.16.1': - resolution: {integrity: sha512-0sBLttMvfQO/hVaIqpHdvDowpgV2CoRuWo2CNwvRLZPPWvPVjL4Nkb73wmi8zAZsAOTbX2aw+g4m/+k5oJqNig==} + '@lexical/markdown@0.18.0': + resolution: {integrity: sha512-uSWwcK8eJw5C+waEhU5WoX8W+JxNZbKuFnZwsn5nsp+iQgqMj4qY6g0yJub4sq8vvh6jjl4vVXhXTq2up9aykw==} - '@lexical/offset@0.16.1': - resolution: {integrity: sha512-/i2J04lQmFeydUZIF8tKXLQTXiJDTQ6GRnkfv1OpxU4amc0rwGa7+qAz/PuF1n58rP6InpLmSHxgY5JztXa2jw==} + '@lexical/offset@0.18.0': + resolution: {integrity: sha512-KGlboyLSxQAH5PMOlJmyvHlbYXZneVnKiHpfyBV5IUX5kuyB/eZbQEYcJP9saekfQ5Xb1FWXWmsZEo+sWtrrZA==} - '@lexical/overflow@0.16.1': - resolution: {integrity: sha512-xh5YpoxwA7K4wgMQF/Sjl8sdjaxqesLCtH5ZrcMsaPlmucDIEEs+i8xxk+kDUTEY7y+3FvRxs4lGNgX8RVWkvQ==} + '@lexical/overflow@0.18.0': + resolution: {integrity: sha512-3ATTwttVgZtVLq60ZUWbpbXBbpuMa3PZD5CxSP3nulviL+2I4phvacV4WUN+8wMeq+PGmuarl+cYfrFL02ii3g==} - '@lexical/plain-text@0.16.1': - resolution: {integrity: sha512-GjY4ylrBZIaAVIF8IFnmW0XGyHAuRmWA6gKB8iTTlsjgFrCHFIYC74EeJSp309O0Hflg9rRBnKoX1TYruFHVwA==} + '@lexical/plain-text@0.18.0': + resolution: {integrity: sha512-L6yQpiwW0ZacY1oNwvRBxSuW2TZaUcveZLheJc8JzGcZoVxzII/CAbLZG8691VbNuKsbOURiNXZIsgwujKmo4Q==} - '@lexical/react@0.16.1': - resolution: {integrity: sha512-SsGgLt9iKfrrMRy9lFb6ROVPUYOgv6b+mCn9Al+TLqs/gBReDBi3msA7m526nrtBUKYUnjHdQ1QXIJzuKgOxcg==} + '@lexical/react@0.18.0': + resolution: {integrity: sha512-DLvIbTsjvFIFqm+9zvAjEwuZHAbSxzZf1AGqf1lLctlL/Ran0f+8EZOv5jttELTe7xISZ2+xSXTLRfyxhNwGXQ==} peerDependencies: react: '>=17.x' react-dom: '>=17.x' - '@lexical/rich-text@0.16.1': - resolution: {integrity: sha512-4uEVXJur7tdSbqbmsToCW4YVm0AMh4y9LK077Yq2O9hSuA5dqpI8UbTDnxZN2D7RfahNvwlqp8eZKFB1yeiJGQ==} + '@lexical/rich-text@0.18.0': + resolution: {integrity: sha512-xMANCB7WueMsmWK8qxik5FZN4ApyaHWHQILS9r4FTbdv/DlNepsR7Pt8kg2317xZ56NAueQLIdyyKYXG1nBrHw==} - '@lexical/selection@0.16.1': - resolution: {integrity: sha512-+nK3RvXtyQvQDq7AZ46JpphmM33pwuulwiRfeXR5T9iFQTtgWOEjsAi/KKX7vGm70BxACfiSxy5QCOgBWFwVJg==} + '@lexical/selection@0.18.0': + resolution: {integrity: sha512-mJoMhmxeZLfM9K2JMYETs9u179IkHQUlgtYG5GZJHjKx2iUn+9KvJ9RVssq+Lusi7C/N42wWPGNHDPdUvFtxXg==} - '@lexical/table@0.16.1': - resolution: {integrity: sha512-GWb0/MM1sVXpi1p2HWWOBldZXASMQ4c6WRNYnRmq7J/aB5N66HqQgJGKp3m66Kz4k1JjhmZfPs7F018qIBhnFQ==} + '@lexical/table@0.18.0': + resolution: {integrity: sha512-TeTAnuFAAgVjm1QE8adRB3GFWN+DUUiS4vzGq+ynPRCtNdpmW27NmTkRMyxKsetUtt7nIFfj4DvLvor4RwqIpA==} - '@lexical/text@0.16.1': - resolution: {integrity: sha512-Os/nKQegORTrKKN6vL3/FMVszyzyqaotlisPynvTaHTUC+yY4uyjM2hlF93i5a2ixxyiPLF9bDroxUP96TMPXg==} + '@lexical/text@0.18.0': + resolution: {integrity: sha512-MTHSBeq3K0+lqSsP5oysBMnY4tPVhB8kAa2xBnEc3dYgXFxEEvJwZahbHNX93EPObtJkxXfUuI63Al4G3lYK8A==} - '@lexical/utils@0.16.1': - resolution: {integrity: sha512-BVyJxDQi/rIxFTDjf2zE7rMDKSuEaeJ4dybHRa/hRERt85gavGByQawSLeQlTjLaYLVsy+x7wCcqh2fNhlLf0g==} + '@lexical/utils@0.18.0': + resolution: {integrity: sha512-4s9dVpBZjqIaA/1q2GtfWFjKsv2Wqhjer0Zw2mcl1TIVN0zreXxcTKN316QppAWmSQJxVGvkWHjjaZJwl6/TSw==} - '@lexical/yjs@0.16.1': - resolution: {integrity: sha512-QHw1bmzB/IypIV1tRWMH4hhwE1xX7wV+HxbzBS8oJAkoU5AYXM/kyp/sQicgqiwVfpai1Px7zatOoUDFgbyzHQ==} + '@lexical/yjs@0.18.0': + resolution: {integrity: sha512-rl7Rl9XIb3ygQEEHOFtACdXs3BE+UUUmdyNqB6kK9A6IRGz+w4Azp+qzt8It/t+c0oaSYHpAtcLNXg1amJz+kA==} peerDependencies: yjs: '>=13.5.22' @@ -5505,8 +5505,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lexical@0.16.1: - resolution: {integrity: sha512-+R05d3+N945OY8pTUjTqQrWoApjC+ctzvjnmNETtx9WmVAaiW0tQVG+AYLt5pDGY8dQXtd4RPorvnxBTECt9SA==} + lexical@0.18.0: + resolution: {integrity: sha512-3K/B0RpzjoW+Wj2E455wWXxkqxqK8UgdIiuqkOqdOsoSSo5mCkHOU6eVw7Nlmlr1MFvAMzGmz4RPn8NZaLQ2Mw==} lib0@0.2.94: resolution: {integrity: sha512-hZ3p54jL4Wpu7IOg26uC7dnEWiMyNlUrb9KoG7+xYs45WkQwpVvKFndVq2+pqLYKe1u8Fp3+zAfZHVvTK34PvQ==} @@ -7767,7 +7767,7 @@ snapshots: '@adobe/css-tools@4.3.3': {} - '@amityco/ts-sdk@6.30.0': + '@amityco/ts-sdk@6.32.0': dependencies: agentkeepalive: 4.5.0 axios: 1.7.2(debug@4.3.5) @@ -9179,149 +9179,151 @@ snapshots: '@juggle/resize-observer@3.4.0': {} - '@lexical/clipboard@0.16.1': + '@lexical/clipboard@0.18.0': dependencies: - '@lexical/html': 0.16.1 - '@lexical/list': 0.16.1 - '@lexical/selection': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/html': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/code@0.16.1': + '@lexical/code@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 prismjs: 1.29.0 - '@lexical/devtools-core@0.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@lexical/devtools-core@0.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@lexical/html': 0.16.1 - '@lexical/link': 0.16.1 - '@lexical/mark': 0.16.1 - '@lexical/table': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/html': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/mark': 0.18.0 + '@lexical/table': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@lexical/dragon@0.16.1': + '@lexical/dragon@0.18.0': dependencies: - lexical: 0.16.1 + lexical: 0.18.0 - '@lexical/hashtag@0.16.1': + '@lexical/hashtag@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/history@0.16.1': + '@lexical/history@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/html@0.16.1': + '@lexical/html@0.18.0': dependencies: - '@lexical/selection': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/link@0.16.1': + '@lexical/link@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/list@0.16.1': + '@lexical/list@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/mark@0.16.1': + '@lexical/mark@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/markdown@0.16.1': + '@lexical/markdown@0.18.0': dependencies: - '@lexical/code': 0.16.1 - '@lexical/link': 0.16.1 - '@lexical/list': 0.16.1 - '@lexical/rich-text': 0.16.1 - '@lexical/text': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/code': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/rich-text': 0.18.0 + '@lexical/text': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/offset@0.16.1': + '@lexical/offset@0.18.0': dependencies: - lexical: 0.16.1 + lexical: 0.18.0 - '@lexical/overflow@0.16.1': + '@lexical/overflow@0.18.0': dependencies: - lexical: 0.16.1 + lexical: 0.18.0 - '@lexical/plain-text@0.16.1': + '@lexical/plain-text@0.18.0': dependencies: - '@lexical/clipboard': 0.16.1 - '@lexical/selection': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/clipboard': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/react@0.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.18)': + '@lexical/react@0.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.18)': dependencies: - '@lexical/clipboard': 0.16.1 - '@lexical/code': 0.16.1 - '@lexical/devtools-core': 0.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@lexical/dragon': 0.16.1 - '@lexical/hashtag': 0.16.1 - '@lexical/history': 0.16.1 - '@lexical/link': 0.16.1 - '@lexical/list': 0.16.1 - '@lexical/mark': 0.16.1 - '@lexical/markdown': 0.16.1 - '@lexical/overflow': 0.16.1 - '@lexical/plain-text': 0.16.1 - '@lexical/rich-text': 0.16.1 - '@lexical/selection': 0.16.1 - '@lexical/table': 0.16.1 - '@lexical/text': 0.16.1 - '@lexical/utils': 0.16.1 - '@lexical/yjs': 0.16.1(yjs@13.6.18) - lexical: 0.16.1 + '@lexical/clipboard': 0.18.0 + '@lexical/code': 0.18.0 + '@lexical/devtools-core': 0.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@lexical/dragon': 0.18.0 + '@lexical/hashtag': 0.18.0 + '@lexical/history': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/mark': 0.18.0 + '@lexical/markdown': 0.18.0 + '@lexical/overflow': 0.18.0 + '@lexical/plain-text': 0.18.0 + '@lexical/rich-text': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/table': 0.18.0 + '@lexical/text': 0.18.0 + '@lexical/utils': 0.18.0 + '@lexical/yjs': 0.18.0(yjs@13.6.18) + lexical: 0.18.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-error-boundary: 3.1.4(react@18.3.1) transitivePeerDependencies: - yjs - '@lexical/rich-text@0.16.1': + '@lexical/rich-text@0.18.0': dependencies: - '@lexical/clipboard': 0.16.1 - '@lexical/selection': 0.16.1 - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/clipboard': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/selection@0.16.1': + '@lexical/selection@0.18.0': dependencies: - lexical: 0.16.1 + lexical: 0.18.0 - '@lexical/table@0.16.1': + '@lexical/table@0.18.0': dependencies: - '@lexical/utils': 0.16.1 - lexical: 0.16.1 + '@lexical/clipboard': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 - '@lexical/text@0.16.1': + '@lexical/text@0.18.0': dependencies: - lexical: 0.16.1 + lexical: 0.18.0 - '@lexical/utils@0.16.1': + '@lexical/utils@0.18.0': dependencies: - '@lexical/list': 0.16.1 - '@lexical/selection': 0.16.1 - '@lexical/table': 0.16.1 - lexical: 0.16.1 + '@lexical/list': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/table': 0.18.0 + lexical: 0.18.0 - '@lexical/yjs@0.16.1(yjs@13.6.18)': + '@lexical/yjs@0.18.0(yjs@13.6.18)': dependencies: - '@lexical/offset': 0.16.1 - lexical: 0.16.1 + '@lexical/offset': 0.18.0 + '@lexical/selection': 0.18.0 + lexical: 0.18.0 yjs: 13.6.18 '@lokesh.dhakar/quantize@1.3.0': {} @@ -14413,7 +14415,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lexical@0.16.1: {} + lexical@0.18.0: {} lib0@0.2.94: dependencies: diff --git a/src/core/providers/UiKitProvider/styles.tsx b/src/core/providers/UiKitProvider/styles.tsx index e6050d7c..d9e6f03c 100644 --- a/src/core/providers/UiKitProvider/styles.tsx +++ b/src/core/providers/UiKitProvider/styles.tsx @@ -1,5 +1,7 @@ import styled from 'styled-components'; +import skeletonCss from 'react-loading-skeleton/dist/skeleton.css?inline'; + export const UIStyles = styled.div` color-scheme: only light; ${({ theme }) => theme.typography.body}; diff --git a/src/index.ts b/src/index.ts index c1ebbc55..d90e5d41 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,31 +20,22 @@ export { useSDK as useAmitySDK } from '~/core/hooks/useSDK'; export { AmityUIKitManager } from '~/v4/core/AmityUIKitManager'; -export { ReactionList as AmityReactionList } from '~/v4/social/components/ReactionList'; +// v4 Export only components and pages related to Story feature import type { ReactionListProps } from '~/v4/social/components/ReactionList'; export type { ReactionListProps as AmityReactionListProps }; -export { LiveChat as AmityLiveChatPage } from '~/v4/chat/pages/LiveChat'; - -// v4 internal use only (Amity Console) -export { - StoryPreview as AmityStoryPreview, - StoryPreviewThumbnail as AmityStoryPreviewThumbnail, -} from './v4/social/internal-components/StoryPreview'; - // v4 Social export { - SocialHomePage as AmitySocialHomePage, AmityDraftStoryPage, ViewStoryPage as AmityViewStoryPage, StoryTargetSelectionPage as AmityStoryTargetSelectionPage, - PostDetailPage as AmityPostDetailPage, - SocialGlobalSearchPage as AmitySocialGlobalSearchPage, - MyCommunitiesSearchPage as AmityMyCommunitiesSearchPage, - SelectPostTargetPage as AmityPostTargetSelectionPage, - PostComposerPage as AmityPostComposerPage, - CommunityProfilePage as AmityCommunityProfilePage, } from '~/v4/social/pages'; +export { + ReactionList as AmityReactionListComponent, + CommentTray as AmityCommentTrayComponent, + StoryTab as AmityStoryTabComponent, +} from '~/v4/social/components/'; + export { HomePageTab as AmitySocialHomePageTab } from '~/v4/social/pages/SocialHomePage'; diff --git a/src/social/components/CommunityInfo/index.tsx b/src/social/components/CommunityInfo/index.tsx index 3ed33b2f..767ad2a2 100644 --- a/src/social/components/CommunityInfo/index.tsx +++ b/src/social/components/CommunityInfo/index.tsx @@ -9,10 +9,9 @@ import { useConfirmContext } from '~/core/providers/ConfirmProvider'; interface CommunityInfoProps { communityId: string; - stories: (Amity.Story | undefined)[]; } -const CommunityInfo = ({ communityId, stories }: CommunityInfoProps) => { +const CommunityInfo = ({ communityId }: CommunityInfoProps) => { const { community, communityCategories, diff --git a/src/social/constants.ts b/src/social/constants.ts index d863e575..31f739b6 100644 --- a/src/social/constants.ts +++ b/src/social/constants.ts @@ -55,6 +55,7 @@ export const Permissions = Object.freeze({ EditCommunityCategoryPermission: 'EDIT_COMMUNITY_CATEGORY', DeleteCommunityCategoryPermission: 'DELETE_COMMUNITY_CATEGORY', ManageStoryPermission: 'MANAGE_COMMUNITY_STORY', + CreatePivillegedPostPermission: 'CREATE_PRIVILEGED_POST', }); export const MAXIMUM_MENTIONEES = 30; diff --git a/src/social/hooks/useCommunityPermission.ts b/src/social/hooks/useCommunityPermission.ts index d107b767..17a1511e 100644 --- a/src/social/hooks/useCommunityPermission.ts +++ b/src/social/hooks/useCommunityPermission.ts @@ -1,8 +1,9 @@ import useSDK from '~/core/hooks/useSDK'; +import { Permissions } from '../constants'; import useCommunityModeratorsCollection from './collections/useCommunityModeratorsCollection'; const useCommunityPermission = ({ community }: { community?: Amity.Community | null }) => { - const { currentUserId, userRoles } = useSDK(); + const { currentUserId, userRoles, client } = useSDK(); const { moderators } = useCommunityModeratorsCollection(community?.communityId); const moderator = moderators.find((moderator) => moderator.userId === currentUserId); @@ -11,10 +12,18 @@ const useCommunityPermission = ({ community }: { community?: Amity.Community | n const isModerator = moderator != null; + const canCreatePost = + (community?.communityId && + client + ?.hasPermission(Permissions.CreatePivillegedPostPermission) + .community(community?.communityId)) || + community?.postSetting !== 'ONLY_ADMIN_CAN_POST'; + return { isModerator, canEdit: isGlobalAdmin || isModerator, canReview: isGlobalAdmin || isModerator, + canCreatePost: !!canCreatePost, }; }; diff --git a/src/social/pages/CommunityFeed/index.tsx b/src/social/pages/CommunityFeed/index.tsx index 690f9df8..9d3302cc 100644 --- a/src/social/pages/CommunityFeed/index.tsx +++ b/src/social/pages/CommunityFeed/index.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useMemo, useState } from 'react'; -import { SubscriptionLevels } from '@amityco/ts-sdk'; import { FormattedMessage } from 'react-intl'; import CommunityCreatedModal from '~/social/components/CommunityCreatedModal'; @@ -11,12 +10,12 @@ import MediaGallery from '~/social/components/MediaGallery'; import CommunityInfo from '~/social/components/CommunityInfo'; import CommunityMembers from '~/social/components/CommunityMembers'; import FeedHeaderTabs from '~/social/components/FeedHeaderTabs'; + import { CommunityFeedTabs } from './constants'; import { getTabs } from './utils'; import { DeclineBanner, Wrapper } from './styles'; -import useCommunityPermission from '~/social/hooks/useCommunityPermission'; -import useCommunitySubscription from '~/social/hooks/useCommunitySubscription'; +import useCommunityPermission from '~/social/hooks/useCommunityPermission'; import usePostsCollection from '~/social/hooks/collections/usePostsCollection'; import { @@ -27,7 +26,6 @@ import { StyledCommunitySideMenu, } from '../NewsFeed/styles'; -import { useNavigation } from '~/social/providers/NavigationProvider'; import { useGetActiveStoriesByTarget } from '~/v4/social/hooks/useGetActiveStories'; interface CommunityFeedProps { @@ -38,19 +36,9 @@ interface CommunityFeedProps { } const CommunityFeed = ({ communityId, isNewCommunity, isOpen, toggleOpen }: CommunityFeedProps) => { - const { goToDraftStoryPage } = useNavigation(); - const { stories } = useGetActiveStoriesByTarget({ - targetId: communityId, - targetType: 'community', - options: { - orderBy: 'asc', - sortBy: 'createdAt', - }, - }); - const community = useCommunity(communityId); - const { canReview } = useCommunityPermission({ community }); + const { canReview, canCreatePost } = useCommunityPermission({ community }); const { posts } = usePostsCollection({ targetId: communityId, @@ -87,7 +75,7 @@ const CommunityFeed = ({ communityId, isNewCommunity, isOpen, toggleOpen }: Comm - + )} diff --git a/src/v4/social/components/PostComment/PostComment.module.css b/src/v4/social/components/PostComment/PostComment.module.css deleted file mode 100644 index 17d6b628..00000000 --- a/src/v4/social/components/PostComment/PostComment.module.css +++ /dev/null @@ -1,175 +0,0 @@ -.postComment { - width: 100%; - display: grid; - grid-template-columns: min-content minmax(0, 1fr); - gap: 0.5rem; -} - -.postComment__deleteComment_container { - display: flex; - padding: 0.75rem 1rem; - align-items: flex-start; - gap: 1rem; - border-top: 1px solid var(--asc-color-base-shade4); - border-bottom: 1px solid var(--asc-color-base-shade4); -} - -.postComment__deleteComment_icon { - width: 1.25rem; - height: 1.25rem; - color: var(--asc-color-base-shade2); -} - -.postComment__deleteComment_text { - color: var(--asc-color-base-shade2); -} - -.postComment__avatar { - margin-right: 0.75rem; - display: inline-block; -} - -.postComment__details { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.postComment__content { - display: flex; - flex-direction: column; - gap: 0.25rem; - justify-content: center; - align-items: start; - background-color: var(--asc-color-base-shade4); - border-radius: 0 0.75rem 0.75rem; - padding: 0.75rem; - max-width: max-content; -} - -.postComment__content__username { - color: var(--asc-color-base-default); -} - -.postComment__content__text { - color: var(--asc-color-base-default); -} - -.postComment__secondRow { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; -} - -.postComment__secondRow__leftPane { - display: flex; - gap: 0.75rem; - align-items: center; -} - -.postComment__secondRow__timestamp { - display: flex; - color: var(--asc-color-base-shade2); - white-space: pre; -} - -.postComment__secondRow__rightPane { - display: flex; - gap: 0.25rem; - align-items: center; -} - -.postComment__secondRow__rightPane__like { - width: 1.25rem; - height: 1.25rem; -} - -.postComment__secondRow__like { - cursor: pointer; - color: var(--asc-color-base-shade2); -} - -.postComment__secondRow__like[data-is-liked='true'] { - color: var(--asc-color-primary-default); -} - -.postComment__secondRow__reply { - cursor: pointer; - color: var(--asc-color-base-shade2); -} - -.postComment__secondRow__actionButton { - cursor: pointer; - height: 1.25rem; - fill: var(--asc-color-secondary-shade2); -} - -.postComment__viewReply_button { - display: flex; - padding: 0.3125rem 0.75rem 0.3125rem 0.5rem; - cursor: pointer; - align-items: flex-start; - gap: 0.25rem; - background: var(--asc-color-background-default); - border: 1px solid var(--asc-color-base-shade4); - border-radius: 0.25rem; - width: max-content; -} - -.postComment__viewReply_icon { - color: var(--asc-color-secondary-shade1); - width: 1rem; - height: 1rem; -} - -.postComment__viewReply_text { - color: var(--asc-color-secondary-shade1); -} - -.postComment__edit { - display: flex; - gap: 0.5rem; -} - -.postComment__edit__inputWrap { - width: 100%; -} - -.postComment__edit__input { - display: flex; - height: 7.5rem; - padding: 0.75rem; - flex-direction: column; - align-items: flex-start; - gap: 0.25rem; - align-self: stretch; - background-color: var(--asc-color-base-shade4); - width: 100%; - border-radius: 0 0.75rem 0.75rem; -} - -.postComment__edit__buttonWrap { - display: flex; - gap: var(--asc-spacing-s1); - justify-content: flex-end; - margin-top: var(--asc-spacing-s1); -} - -.postComment__edit__button { - padding: 0.375rem 0.75rem; - cursor: pointer; -} - -.postComment__edit__cancelButton { - color: var(--asc-color-secondary-shade1); - border-radius: var(--asc-border-radius-sm); - border: 1px solid var(--asc-color-secondary-shade1); - background: var(--asc-color-background-default); -} - -.postComment__edit__saveButton { - color: var(--asc-color-white); - border-radius: var(--asc-border-radius-sm); - background: var(--asc-color-primary-default); -} diff --git a/src/v4/social/components/PostComment/PostComment.stories.tsx b/src/v4/social/components/PostComment/PostComment.stories.tsx deleted file mode 100644 index a003f065..00000000 --- a/src/v4/social/components/PostComment/PostComment.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import useOneComment from '~/mock/useOneComment'; - -import { PostComment } from './PostComment'; - -export default { - title: 'v4-social/components/PostComment', -}; - -export const PostCommentStory = { - render: () => { - const [comment] = useOneComment(); - - if (comment == null) return null; - - return ; - }, - - name: 'PostComment', -}; diff --git a/src/v4/social/components/PostComment/PostComment.tsx b/src/v4/social/components/PostComment/PostComment.tsx deleted file mode 100644 index 77acbdb2..00000000 --- a/src/v4/social/components/PostComment/PostComment.tsx +++ /dev/null @@ -1,297 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import { Typography, BottomSheet } from '~/v4/core/components'; -import { ModeratorBadge } from '~/v4/social/elements/ModeratorBadge'; -import { Timestamp } from '~/v4/social/elements/Timestamp'; -import { UserAvatar } from '~/v4/social/internal-components/UserAvatar'; -import styles from './PostComment.module.css'; -import { useAmityComponent } from '~/v4/core/hooks/uikit'; -import ReplyComment from '~/v4/icons/ReplyComment'; -import { PostReplyCommentList } from '../PostReplyCommentList/PostReplyCommentList'; -import { MinusCircleIcon } from '../../icons/index'; -import { Mentionees } from '~/v4/helpers/utils'; -import { CommentRepository, ReactionRepository } from '@amityco/ts-sdk'; -import { useConfirmContext } from '~/v4/core/providers/ConfirmProvider'; -import { LIKE_REACTION_KEY } from '../../constants/reactions'; -import { EditCancelButton } from '../../elements/EditCancelButton/EditCancelButton'; -import { SaveButton } from '../../elements/SaveButton/SaveButton'; -import clsx from 'clsx'; -import { PostCommentInput } from '../PostCommentComposer/PostCommentInput'; -import { CommentOptions } from '../CommentOptions/CommentOptions'; -import { CreateCommentParams } from '../PostCommentComposer/PostCommentComposer'; -import useCommentSubscription from '~/v4/core/hooks/subscriptions/useCommentSubscription'; -import { TextWithMention } from '../../internal-components/TextWithMention/TextWithMention'; -import millify from 'millify'; - -const EllipsisH = ({ ...props }: React.SVGProps) => ( - - - -); - -const Like = ({ ...props }: React.SVGProps) => ( - - - - - - - - - - -); - -interface PostCommentProps { - pageId?: string; - componentId?: string; - comment: Amity.Comment; - postTargetType: Amity.PostTargetType; - postTargetId: string; - onClickReply: (comment: Amity.Comment) => void; -} - -export const PostComment = ({ - pageId = '*', - componentId = 'comment_bubble', - comment, - postTargetType, - postTargetId, - onClickReply, -}: PostCommentProps) => { - const { accessibilityId, config, defaultConfig, isExcluded, uiReference, themeStyles } = - useAmityComponent({ - pageId, - componentId, - }); - - const { confirm } = useConfirmContext(); - - const [bottomSheetOpen, setBottomSheetOpen] = useState(false); - const [hasClickLoadMore, setHasClickLoadMore] = useState(false); - const [isEditing, setIsEditing] = useState(false); - const [commentData, setCommentData] = useState(); - - const toggleBottomSheet = () => setBottomSheetOpen((prev) => !prev); - - const isLiked = (comment.myReactions || []).some((reaction) => reaction === 'like'); - - const replyAmount = comment.childrenNumber; - - if (isExcluded) return null; - - const deleteComment = async () => - comment.commentId && CommentRepository.deleteComment(comment.commentId); - - const handleEditComment = () => { - setIsEditing(true); - }; - - const handleDeleteComment = () => { - confirm({ - pageId, - componentId, - title: 'Delete comment', - content: 'This comment will be permanently removed.', - cancelText: 'Cancel', - okText: 'Delete', - onOk: deleteComment, - }); - }; - - const handleLike = async () => { - if (!comment) return; - - if (!isLiked) { - await ReactionRepository.addReaction('comment', comment?.commentId, LIKE_REACTION_KEY); - } else { - await ReactionRepository.removeReaction('comment', comment?.commentId, LIKE_REACTION_KEY); - } - }; - - const handleSaveComment = useCallback(async () => { - if (!commentData || !comment.commentId) return; - - await CommentRepository.updateComment(comment.commentId, { - data: commentData.data, - mentionees: commentData.mentionees as Amity.UserMention[], - metadata: commentData.metadata, - }); - - setIsEditing(false); - }, [commentData]); - - useCommentSubscription({ - commentId: comment.commentId, - }); - - return ( -
- {comment.isDeleted ? ( -
- - - This comment has been deleted - -
- ) : isEditing ? ( -
- -
-
- { - setCommentData(value); - }} - maxLines={5} - mentionOffsetBottom={215} - /> -
-
- { - setIsEditing(false); - }} - /> - -
-
-
- ) : ( -
- -
-
- - {comment.creator?.displayName} - - - - - -
-
-
- - - {comment.createdAt !== comment.editedAt && ' (edited)'} - - -
- - {isLiked ? 'Liked' : 'Like'} - -
-
onClickReply(comment)}> - - Reply - -
- - setBottomSheetOpen(true)} - /> -
- {comment.reactionsCount > 0 && ( -
- {millify(comment.reactionsCount)} - -
- )} -
- - {replyAmount > 0 && !hasClickLoadMore && ( -
setHasClickLoadMore(true)} - > - - - View {replyAmount} {replyAmount > 1 ? 'replies' : 'reply'} - -
- )} - - {hasClickLoadMore && ( - - )} -
-
- )} - - - -
- ); -}; diff --git a/src/v4/social/components/PostComment/PostCommentSkeleton.module.css b/src/v4/social/components/PostComment/PostCommentSkeleton.module.css deleted file mode 100644 index 9539c2e3..00000000 --- a/src/v4/social/components/PostComment/PostCommentSkeleton.module.css +++ /dev/null @@ -1,51 +0,0 @@ -.postCommentSkeleton { - display: flex; - gap: 0.5rem; -} - -.postCommentSkeleton__avatar { - width: 2rem; - height: 2rem; - border-radius: 50%; - background: var(--asc-color-base-shade4); -} - -.postCommentSkeleton__details { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.postCommentSkeleton__content { - background-color: var(--asc-color-base-shade4); - border-radius: 0 0.75rem 0.75rem; - width: 13.875rem; - height: 4.25rem; -} - -.postCommentSkeleton__content__bar { - width: 10.3269rem; - height: 0.5rem; - border-radius: 0.75rem; - background: var(--asc-color-base-shade4); - padding-top: 0.19rem; - padding-bottom: 0.19rem; -} - -.postCommentSkeleton__animation { - animation: skeleton-pulse 1.5s ease-in-out infinite; -} - -@keyframes skeleton-pulse { - 0% { - opacity: 0.6; - } - - 50% { - opacity: 1; - } - - 100% { - opacity: 0.6; - } -} diff --git a/src/v4/social/components/PostComment/PostCommentSkeleton.stories.tsx b/src/v4/social/components/PostComment/PostCommentSkeleton.stories.tsx deleted file mode 100644 index 869f47b8..00000000 --- a/src/v4/social/components/PostComment/PostCommentSkeleton.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import useOnePost from '~/mock/useOnePost'; - -import { PostCommentSkeleton } from './PostCommentSkeleton'; - -export default { - title: 'v4-social/components/PostCommentSkeleton', -}; - -export const PostCommentSkeletonStory = { - render: () => { - const [post] = useOnePost(); - - if (post == null) return null; - - return ; - }, - - name: 'PostCommentSkeleton', -}; diff --git a/src/v4/social/components/PostComment/PostCommentSkeleton.tsx b/src/v4/social/components/PostComment/PostCommentSkeleton.tsx deleted file mode 100644 index 7ad2cbb0..00000000 --- a/src/v4/social/components/PostComment/PostCommentSkeleton.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import clsx from 'clsx'; - -import styles from './PostCommentSkeleton.module.css'; -import { useCustomization } from '~/v4/core/providers/CustomizationProvider'; -import { useGenerateStylesShadeColors } from '~/v4/core/providers/ThemeProvider'; -import { useAmityComponent } from '~/v4/core/hooks/uikit'; - -interface PostCommentSkeletonProps { - pageId?: string; -} - -export const PostCommentSkeleton = ({ pageId = '*' }: PostCommentSkeletonProps) => { - const componentId = 'post_comment'; - const { accessibilityId, isExcluded, themeStyles } = useAmityComponent({ - pageId, - componentId, - }); - - if (isExcluded) return null; - - return ( -
-
-
-
-
-
-
- ); -}; diff --git a/src/v4/social/components/PostComment/index.tsx b/src/v4/social/components/PostComment/index.tsx deleted file mode 100644 index 55aa2252..00000000 --- a/src/v4/social/components/PostComment/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export { PostComment } from './PostComment'; -export { PostCommentSkeleton } from './PostCommentSkeleton'; diff --git a/src/v4/social/components/PostCommentComposer/PostCommentComposer.module.css b/src/v4/social/components/PostCommentComposer/PostCommentComposer.module.css deleted file mode 100644 index 554f64b3..00000000 --- a/src/v4/social/components/PostCommentComposer/PostCommentComposer.module.css +++ /dev/null @@ -1,67 +0,0 @@ -.postCommentComposer__container { - position: relative; - display: flex; - flex-direction: row; - background-color: var(--asc-color-background-default); - align-items: flex-end; - padding: var(--asc-spacing-s1) 0 var(--asc-spacing-s1) var(--asc-spacing-m1); - border-top: 1px solid var(--asc-color-base-shade4); - width: 100%; -} - -.postCommentComposer__avatar { - width: 2rem; - height: 2rem; - margin-bottom: var(--asc-spacing-xxs2); - border-radius: var(--asc-border-radius-full); - margin-right: var(--asc-spacing-s1); -} - -.postCommentComposer__button { - border: none; - margin-bottom: var(--asc-spacing-xxs2); -} - -.postCommentComposer__button:hover { - background-color: transparent !important; -} - -.postCommentComposer__button:disabled { - color: var(--asc-color-primary-shade2); -} - -.postCommentComposer__input { - flex-grow: 1; - background-color: var(--asc-color-base-shade4); - border-radius: 1.25rem; - padding: 0.625rem 0.75rem; -} - -.postCommentComposer__replyContainer { - position: absolute; - left: 0; - width: 100%; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.625rem 1rem; - background-color: var(--asc-color-base-shade4); -} - -.postCommentComposer__replyContainer__text { - font-size: var(--asc-text-font-size-sm); - font-weight: var(--asc-text-font-weight-normal); - line-height: var(--asc-line-height-sm); - color: var(--asc-color-base-shade1); -} - -.postCommentComposer__replyContainer__username { - font-weight: var(--asc-text-font-weight-bold); -} - -.postCommentComposer__replyContainer__closeButton { - fill: var(--asc-color-base-shade2); - width: 1.25rem; - height: 1.25rem; - cursor: pointer; -} diff --git a/src/v4/social/components/PostCommentComposer/PostCommentComposer.tsx b/src/v4/social/components/PostCommentComposer/PostCommentComposer.tsx deleted file mode 100644 index cdf76dd7..00000000 --- a/src/v4/social/components/PostCommentComposer/PostCommentComposer.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Avatar, Button } from '~/v4/core/components/index'; -import { useUser } from '~/v4/core/hooks/objects/useUser'; -import { useImage } from '~/v4/core/hooks/useImage'; -import useSDK from '~/v4/core/hooks/useSDK'; -import User from '~/v4/icons/User'; -import { PostCommentInput, PostCommentInputRef } from './PostCommentInput'; -import styles from './PostCommentComposer.module.css'; -import { useMutation } from '@tanstack/react-query'; -import { CommentRepository } from '@amityco/ts-sdk'; -import Close from '~/v4/icons/Close'; -import { Mentionees, Metadata } from '~/v4/helpers/utils'; - -export type CreateCommentParams = { - data: { - text: string; - }; - mentionees: Mentionees; - metadata: Metadata; -}; - -export const PostCommentComposer = ({ - post, - replyTo, - onCancelReply, -}: { - post: Amity.Post; - replyTo?: Amity.Comment; - onCancelReply: () => void; -}) => { - const userId = useSDK().currentUserId; - const { user } = useUser(userId); - const avatarUrl = useImage({ fileId: user?.avatar?.fileId, imageSize: 'small' }); - const editorRef = useRef(null); - const composerRef = useRef(null); - - const [composerHeight, setComposerHeight] = useState(0); - - const [textValue, setTextValue] = useState({ - data: { - text: '', - }, - mentionees: [ - { - type: 'user', - userIds: [''], - }, - ], - metadata: {}, - }); - - const onChange = (val: any) => { - setTextValue(val); - }; - - const { mutateAsync } = useMutation({ - mutationFn: async ({ params }: { params: CreateCommentParams }) => { - const referenceId = replyTo ? replyTo.referenceId : post.postId; - const referenceType = replyTo ? replyTo.referenceType : 'post'; - const parentId = replyTo ? replyTo.commentId : undefined; - - await CommentRepository.createComment({ - referenceId, - referenceType, - parentId, - ...params, - mentionees: params.mentionees as Amity.UserMention[], - }); - }, - onError: (error) => {}, - onSuccess: () => { - setTextValue({ - data: { text: '' }, - mentionees: [], - metadata: {}, - }); - editorRef.current?.clearEditorState(); - onCancelReply(); - }, - }); - - useEffect(() => { - if (composerRef.current) { - setComposerHeight(composerRef.current.offsetHeight); - } - }, []); - - return ( -
-
- } /> -
-
- -
- - {replyTo && ( -
-
- Replying to - - {replyTo?.userId} - -
- -
- )} -
- ); -}; diff --git a/src/v4/social/components/PostCommentComposer/PostCommentInput.module.css b/src/v4/social/components/PostCommentComposer/PostCommentInput.module.css deleted file mode 100644 index daae1b98..00000000 --- a/src/v4/social/components/PostCommentComposer/PostCommentInput.module.css +++ /dev/null @@ -1,45 +0,0 @@ -.editorPlaceholder { - color: #999; - overflow: hidden; - position: absolute; - top: 0; - user-select: none; - pointer-events: none; -} - -.editorParagraph { - height: 100%; - width: 100%; - color: var(--asc-color-base-default); -} - -.editorParagraph span { - color: var(--asc-color-base-default); -} - -.editorContainer { - width: 100%; - height: 100%; - color: var(--asc-color-base-default); - max-height: calc(var(--asc-line-height-md) * var(--var-max-lines) + (0.62rem * 2)); - - /* padding: 0.62rem 1rem; */ - position: relative; - - p { - line-height: var(--asc-line-height-md); - font-size: var(--asc-text-font-size-md); - margin: 0; - } -} - -.editorEditableContent { - height: max-content; - max-height: calc(var(--asc-line-height-md) * var(--var-max-lines)); - overflow-y: scroll; -} - -.editorContainer :focus { - border: none; - outline: none; -} diff --git a/src/v4/social/components/PostCommentComposer/PostCommentInput.tsx b/src/v4/social/components/PostCommentComposer/PostCommentInput.tsx deleted file mode 100644 index 81a8f8ae..00000000 --- a/src/v4/social/components/PostCommentComposer/PostCommentInput.tsx +++ /dev/null @@ -1,298 +0,0 @@ -import React, { forwardRef, MutableRefObject, useImperativeHandle } from 'react'; -import { LexicalComposer } from '@lexical/react/LexicalComposer'; -import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'; -import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'; -import { ContentEditable } from '@lexical/react/LexicalContentEditable'; -import { EditorRefPlugin } from '@lexical/react/LexicalEditorRefPlugin'; -import { - $getRoot, - LexicalEditor, - SerializedLexicalNode, - SerializedTextNode, - SerializedRootNode, - SerializedParagraphNode, -} from 'lexical'; -import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'; -import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'; -import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin'; -import { - MentionNode, - SerializedMentionNode, -} from '~/v4/social/internal-components/MentionTextInput/MentionNodes'; -import styles from './PostCommentInput.module.css'; -import { PostCommentMentionInput } from '../PostCommentMentionInput'; -import { useMentionUsers } from '../../hooks/useMentionUser'; -import { CreateCommentParams } from '../PostCommentComposer/PostCommentComposer'; -import { Mentioned, Mentionees } from '~/v4/helpers/utils'; - -const theme = { - ltr: 'ltr', - rtl: 'rtl', - placeholder: styles.editorPlaceholder, - paragraph: styles.editorParagraph, -}; - -const editorConfig = { - namespace: 'PostCommentInput', - theme: theme, - onError(error: Error) { - throw error; - }, - nodes: [MentionNode], -}; - -interface EditorStateJson extends SerializedLexicalNode { - children: []; -} - -interface PostCommentInputProps { - postTargetType: Amity.PostTargetType; - postTargetId: string; - value?: CreateCommentParams; - mentionOffsetBottom?: number; - maxLines?: number; - placehoder?: string; - ref: MutableRefObject; - onChange: (data: CreateCommentParams) => void; -} - -export interface PostCommentInputRef { - clearEditorState: () => void; -} - -function editorStateToText(editor: LexicalEditor): CreateCommentParams { - const editorStateTextString: string[] = []; - const paragraphs = editor.getEditorState().toJSON().root.children as EditorStateJson[]; - - const mentioned: Mentioned[] = []; - const mentionees: { - type: Amity.Mention['type']; - userIds: string[]; - }[] = []; - let runningIndex = 0; - - paragraphs.forEach((paragraph) => { - const children = paragraph.children; - const paragraphText: string[] = []; - - children.forEach((child: { type: string; text: string; userId: string }) => { - if (child.text) { - paragraphText.push(child.text); - } - if (child.type === 'mention') { - mentioned.push({ - index: runningIndex, - length: child.text.length, - type: 'user', - userId: child.userId, - }); - - mentionees.push({ type: 'user', userIds: [child.userId] }); - } - runningIndex += child.text.length; - }); - runningIndex += 1; - editorStateTextString.push(paragraphText.join('')); - }); - - return { - data: { text: editorStateTextString.join('\n') }, - mentionees, - metadata: { - mentioned, - }, - }; -} - -function createRootNode(): SerializedRootNode { - return { - children: [], - direction: 'ltr', - format: '', - indent: 0, - type: 'root', - version: 1, - }; -} - -function createParagraphNode(): SerializedParagraphNode { - return { - children: [], - direction: 'ltr', - format: '', - indent: 0, - type: 'paragraph', - version: 1, - textFormat: 0, - }; -} - -function createSerializeTextNode(text: string): SerializedTextNode { - return { - detail: 0, - format: 0, - mode: 'normal', - style: '', - text, - type: 'text', - version: 1, - }; -} - -function createSerializeMentionNode(mention: Mentioned): SerializedMentionNode { - return { - detail: 0, - format: 0, - mode: 'normal', - style: '', - text: ('@' + mention.userId) as string, - type: 'mention', - version: 1, - mentionName: mention.userId as string, - displayName: mention.userId as string, - userId: mention.userId as string, - userInternalId: mention.userId as string, - userPublicId: mention.userId as string, - }; -} - -export function TextToEditorState(value: { - data: { text: string }; - metadata?: { - mentioned?: Mentioned[]; - }; - mentionees?: Mentionees; -}) { - const rootNode = createRootNode(); - - const textArray = value.data.text.split('\n'); - - const mentions = value.metadata?.mentioned; - - let start = 0; - let stop = -1; - let mentionRunningIndex = 0; - - for (let i = 0; i < textArray.length; i++) { - start = stop + 1; - stop = start + textArray[i].length; - - const paragraph = createParagraphNode(); - - if (Array.isArray(mentions) && mentions?.length > 0) { - let runningIndex = 0; - - while (runningIndex < textArray[i].length) { - if (mentionRunningIndex >= mentions.length) { - paragraph.children.push(createSerializeTextNode(textArray[i].slice(runningIndex))); - runningIndex = textArray[i].length; - break; - } - - if (mentions[mentionRunningIndex].index >= stop) { - paragraph.children.push(createSerializeTextNode(textArray[i])); - runningIndex = textArray[i].length; - } else { - const text = textArray[i].slice( - runningIndex, - runningIndex + mentions[mentionRunningIndex]?.index - start, - ); - - if (text) { - paragraph.children.push(createSerializeTextNode(text)); - } - - paragraph.children.push(createSerializeMentionNode(mentions[mentionRunningIndex])); - - runningIndex += - mentions[mentionRunningIndex].index + mentions[mentionRunningIndex].length - start; - - mentionRunningIndex++; - } - } - } - - if (!mentions || mentions?.length === 0) { - const textNode = createSerializeTextNode(textArray[i]); - paragraph.children.push(textNode); - } - - rootNode.children.push(paragraph); - } - - return { root: rootNode }; -} - -export const PostCommentInput = forwardRef( - ( - { - postTargetType, - postTargetId, - mentionOffsetBottom = 0, - value, - onChange, - maxLines = 10, - placehoder, - }, - ref, - ) => { - const editorRef = React.useRef(null); - const [queryMentionUser, setQueryMentionUser] = React.useState(null); - - const { mentionUsers } = useMentionUsers({ - displayName: queryMentionUser || '', - postTargetType: postTargetType, - postTargetId: postTargetId, - }); - - const clearEditorState = () => { - editorRef.current?.update(() => { - const root = $getRoot(); - root.clear(); - }); - }; - - useImperativeHandle(ref, () => ({ - clearEditorState, - })); - - return ( - -
- } - placeholder={ - placehoder ?
{placehoder}
: null - } - ErrorBoundary={LexicalErrorBoundary} - /> - { - onChange(editorStateToText(editor)); - }} - /> - - - - setQueryMentionUser(query)} - offsetBottom={mentionOffsetBottom} - /> -
-
- ); - }, -); diff --git a/src/v4/social/components/PostCommentComposer/index.tsx b/src/v4/social/components/PostCommentComposer/index.tsx deleted file mode 100644 index 9226b06e..00000000 --- a/src/v4/social/components/PostCommentComposer/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { PostCommentComposer } from './PostCommentComposer'; diff --git a/src/v4/social/components/PostCommentList/PostCommentList.module.css b/src/v4/social/components/PostCommentList/PostCommentList.module.css deleted file mode 100644 index fa8cceca..00000000 --- a/src/v4/social/components/PostCommentList/PostCommentList.module.css +++ /dev/null @@ -1,18 +0,0 @@ -.postCommentList__container { - display: flex; - flex-direction: column; - gap: 1rem; -} - -.postCommentList__viewAllComments__button { - width: 100%; - padding: var(--asc-spacing-s2) 0; - margin: auto; - border-top: 0.0625rem solid var(--asc-color-base-shade4); - cursor: pointer; - text-align: center; -} - -.postCommentList__container_intersection { - height: 1px; -} diff --git a/src/v4/social/components/PostCommentList/PostCommentList.tsx b/src/v4/social/components/PostCommentList/PostCommentList.tsx deleted file mode 100644 index 2cf0ef9f..00000000 --- a/src/v4/social/components/PostCommentList/PostCommentList.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React, { useRef } from 'react'; -import styles from './PostCommentList.module.css'; -import { PostComment } from '../PostComment/PostComment'; -import useIntersectionObserver from '~/v4/core/hooks/useIntersectionObserver'; -import useCommentsCollection from '../../hooks/collections/useCommentsCollection'; -import { useAmityComponent } from '~/v4/core/hooks/uikit/index'; -import useUserSubscription from '~/v4/core/hooks/subscriptions/useUserSubscription'; -import { CommentRepository, SubscriptionLevels } from '@amityco/ts-sdk'; -import useCommunitySubscription from '~/v4/core/hooks/subscriptions/useCommunitySubscription'; -import { usePaginator } from '~/v4/core/hooks/usePaginator'; -import { CommentAd } from '../../internal-components/CommentAd/CommentAd'; - -type PostCommentListProps = { - post: Amity.Post; - pageId?: string; - onClickReply: (comment: Amity.Comment) => void; -}; - -const isAmityAd = (item: Amity.Comment | Amity.InternalComment | Amity.Ad): item is Amity.Ad => { - return 'adId' in item; -}; - -export const PostCommentList = ({ post, pageId = '*', onClickReply }: PostCommentListProps) => { - const componentId = 'comment_tray_component'; - - const { themeStyles, accessibilityId } = useAmityComponent({ - componentId, - pageId, - }); - - const containerRef = useRef(null); - const intersectionRef = useRef(null); - - const { items, loadMore, hasMore, isLoading } = usePaginator({ - fetcher: CommentRepository.getComments, - params: { - referenceId: post.postId, - referenceType: 'post', - limit: 5, - includeDeleted: true, - }, - placement: 'comment' as Amity.AdPlacement, - pageSize: 5, - getItemId: (item) => item.commentId, - }); - - useIntersectionObserver({ - ref: intersectionRef, - onIntersect: () => { - if (hasMore && isLoading === false) { - loadMore(); - } - }, - }); - - useUserSubscription({ - userId: post.targetId, - level: SubscriptionLevels.COMMENT, - shouldSubscribe: post.targetType === 'user', - }); - - useCommunitySubscription({ - communityId: post.targetId, - level: SubscriptionLevels.COMMENT, - shouldSubscribe: post.targetType === 'community', - }); - - return ( -
- {items.map((item) => { - return isAmityAd(item) ? ( - - ) : ( - onClickReply?.(comment)} - componentId={componentId} - postTargetId={post.targetId} - postTargetType={post.targetType} - /> - ); - })} - {/* TODO: add this button when implement desktop view */} - {/*
- View all comments... -
*/} - {!isLoading && ( -
- )} -
- ); -}; diff --git a/src/v4/social/components/PostCommentList/index.ts b/src/v4/social/components/PostCommentList/index.ts deleted file mode 100644 index 646fb933..00000000 --- a/src/v4/social/components/PostCommentList/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { PostCommentList } from './PostCommentList'; diff --git a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.module.css b/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.module.css deleted file mode 100644 index 2b4a017b..00000000 --- a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.mentionTextInput_item { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: 12.5rem; - overflow-y: scroll; -} - -.mentionTextInput_item::-webkit-scrollbar { - display: none; -} diff --git a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.tsx b/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.tsx deleted file mode 100644 index b747ca97..00000000 --- a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionInput.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import styles from './PostCommentMentionInput.module.css'; -import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; -import { - LexicalTypeaheadMenuPlugin, - MenuOption, - MenuTextMatch, -} from '@lexical/react/LexicalTypeaheadMenuPlugin'; -import { TextNode } from 'lexical'; -import React, { RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import ReactDOM from 'react-dom'; -import { $createMentionNode } from '../../internal-components/MentionTextInput/MentionNodes'; -import { CommunityMember } from '../../internal-components/CommunityMember/CommunityMember'; - -const MAX_LENGTH = 5000; - -const PUNCTUATION = '\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%\'"~=<>_:;'; -const NAME = '\\b[A-Z][^\\s' + PUNCTUATION + ']'; - -const DocumentMentionsRegex = { - NAME, - PUNCTUATION, -}; - -const PUNC = DocumentMentionsRegex.PUNCTUATION; - -const TRIGGERS = ['@'].join(''); - -// Chars we expect to see in a mention (non-space, non-punctuation). -const VALID_CHARS = '[^' + TRIGGERS + PUNC + '\\s]'; - -// Non-standard series of chars. Each series must be preceded and followed by -// a valid char. -const VALID_JOINS = - '(?:' + - '\\.[ |$]|' + // E.g. "r. " in "Mr. Smith" - ' |' + // E.g. " " in "Josh Duck" - '[' + - PUNC + - ']|' + // E.g. "-' in "Salier-Hellendag" - ')'; - -const LENGTH_LIMIT = 75; - -const AtSignMentionsRegex = new RegExp( - '(^|\\s|\\()(' + - '[' + - TRIGGERS + - ']' + - '((?:' + - VALID_CHARS + - VALID_JOINS + - '){0,' + - LENGTH_LIMIT + - '})' + - ')$', -); - -// 50 is the longest alias length limit. -const ALIAS_LENGTH_LIMIT = 50; - -// Regex used to match alias. -const AtSignMentionsRegexAliasRegex = new RegExp( - '(^|\\s|\\()(' + - '[' + - TRIGGERS + - ']' + - '((?:' + - VALID_CHARS + - '){0,' + - ALIAS_LENGTH_LIMIT + - '})' + - ')$', -); - -function checkForAtSignMentions(text: string, minMatchLength: number): MenuTextMatch | null { - let match = AtSignMentionsRegex.exec(text); - - if (match === null) { - match = AtSignMentionsRegexAliasRegex.exec(text); - } - if (match !== null) { - // The strategy ignores leading whitespace but we need to know it's - // length to add it to the leadOffset - const maybeLeadingWhitespace = match[1]; - - const matchingString = match[3]; - if (matchingString.length >= minMatchLength) { - return { - leadOffset: match.index + maybeLeadingWhitespace.length, - matchingString, - replaceableString: match[2], - }; - } - } - return null; -} - -function getPossibleQueryMatch(text: string): MenuTextMatch | null { - return checkForAtSignMentions(text, 1); -} - -export class MentionTypeaheadOption extends MenuOption { - user: Amity.User; - - constructor(user: Amity.User) { - super(user.userId); - this.user = user; - } -} - -export const PostCommentMentionInput = ({ - mentionUsers, - offsetBottom = 0, - onQueryChange, -}: { - mentionUsers: Amity.User[]; - offsetBottom?: number; - onQueryChange: (query: string) => void; -}) => { - const mentionTextInputItemRef = useRef(null); - return ( -
-
- -
- ); -}; - -type MentionProps = { - anchorRef: RefObject; - mentionUsers: Amity.User[]; - offsetBottom?: number; - onQueryChange: (queryString: string) => void; -}; - -function Mention({ anchorRef, mentionUsers, offsetBottom = 0, onQueryChange }: MentionProps) { - const [editor] = useLexicalComposerContext(); - - const [queryString, setQueryString] = useState(null); - - useEffect(() => { - queryString && onQueryChange(queryString); - }, [queryString]); - - const options = useMemo( - () => mentionUsers.map((user) => new MentionTypeaheadOption(user)), - [mentionUsers], - ); - - const onSelectOption = useCallback( - ( - selectedOption: MentionTypeaheadOption, - nodeToReplace: TextNode | null, - closeMenu: () => void, - ) => { - editor.update(() => { - const mentionNode = $createMentionNode({ - mentionName: selectedOption.key, - displayName: selectedOption.user.displayName, - userId: selectedOption.user.userId, - }); - if (nodeToReplace) { - nodeToReplace.replace(mentionNode); - } - mentionNode.select(); - closeMenu(); - }); - }, - [editor], - ); - - const checkForMentionMatch = useCallback( - (text: string) => { - return getPossibleQueryMatch(text); - }, - [editor], - ); - - return ( - - anchorRef.current && options.length - ? ReactDOM.createPortal( -
- {options.map((option, i: number) => ( - { - setHighlightedIndex(i); - selectOptionAndCleanUp(option); - }} - onMouseEnter={() => { - setHighlightedIndex(i); - }} - key={option.key} - option={option} - /> - ))} -
, - anchorRef.current, - ) - : null - } - /> - ); -} diff --git a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionNode.tsx b/src/v4/social/components/PostCommentMentionInput/PostCommentMentionNode.tsx deleted file mode 100644 index 64a89d86..00000000 --- a/src/v4/social/components/PostCommentMentionInput/PostCommentMentionNode.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import type { Spread } from 'lexical'; - -import { - DOMConversionMap, - DOMConversionOutput, - DOMExportOutput, - EditorConfig, - LexicalNode, - NodeKey, - SerializedTextNode, - TextNode, -} from 'lexical'; - -export type SerializedMentionNode = Spread< - { - mentionName: string; - displayName?: string; - userId?: string; - userInternalId?: string; - userPublicId?: string; - type: 'mention'; - version: 1; - }, - SerializedTextNode ->; - -function convertMentionElement(domNode: HTMLElement): DOMConversionOutput | null { - const textContent = domNode.textContent; - - if (textContent !== null) { - const node = $createMentionNode({ mentionName: textContent }); - return { - node, - }; - } - - return null; -} - -const mentionStyle = `color: var(--asc-color-primary-default)`; - -export class MentionNode extends TextNode { - __mention: string; - __displayName: string | undefined; - __userId: string | undefined; - __userInternalId: string | undefined; - __userPublicId: string | undefined; - - static getType(): string { - return 'mention'; - } - - static clone(node: MentionNode): MentionNode { - return new MentionNode({ - mentionName: node.__mention, - displayName: node.__displayName, - userId: node.__userId, - userInternalId: node.__userInternalId, - userPublicId: node.__userPublicId, - text: node.__text, - key: node.__key, - }); - } - static importJSON(serializedNode: SerializedMentionNode): MentionNode { - const node = $createMentionNode({ - mentionName: serializedNode.mentionName, - displayName: serializedNode.displayName, - userId: serializedNode.userId, - userInternalId: serializedNode.userInternalId, - userPublicId: serializedNode.userPublicId, - }); - node.setTextContent(serializedNode.text); - node.setFormat(serializedNode.format); - node.setDetail(serializedNode.detail); - node.setMode(serializedNode.mode); - node.setStyle(serializedNode.style); - return node; - } - - constructor({ - mentionName, - displayName, - userId, - userInternalId, - userPublicId, - text, - key, - }: { - mentionName: string; - text?: string; - key?: NodeKey; - displayName?: string; - userId?: string; - userInternalId?: string; - userPublicId?: string; - }) { - super(text ?? mentionName, key); - this.__mention = mentionName; - this.__displayName = displayName; - this.__userId = userId; - this.__userInternalId = userInternalId; - this.__userPublicId = userPublicId; - } - - exportJSON(): SerializedMentionNode { - return { - ...super.exportJSON(), - mentionName: this.__mention, - displayName: this.__displayName, - userId: this.__userId, - userInternalId: this.__userInternalId, - userPublicId: this.__userPublicId, - type: 'mention', - version: 1, - }; - } - - createDOM(config: EditorConfig): HTMLElement { - const dom = super.createDOM(config); - dom.style.cssText = mentionStyle; //class name css - dom.className = 'mention'; //create css - return dom; - } - - exportDOM(): DOMExportOutput { - const element = document.createElement('span'); - element.setAttribute('data-lexical-mention', 'true'); - element.textContent = this.__text; - return { element }; - } - - isSegmented(): false { - return false; - } - - static importDOM(): DOMConversionMap | null { - return { - span: (domNode: HTMLElement) => { - if (!domNode.hasAttribute('data-lexical-mention')) { - return null; - } - return { - conversion: convertMentionElement, - priority: 1, - }; - }, - }; - } - - isTextEntity(): true { - return true; - } - - isToken(): true { - return true; - } - - canInsertTextBefore(): boolean { - return false; - } - - canInsertTextAfter(): boolean { - return false; - } -} - -export function $createMentionNode({ - mentionName, - displayName, - userId, - userInternalId, - userPublicId, -}: { - mentionName: string; - displayName?: string; - userId?: string; - userInternalId?: string; - userPublicId?: string; -}): MentionNode { - const mentionNode = new MentionNode({ - mentionName: `@${mentionName}`, - displayName: displayName, - userId: userId, - userInternalId: userInternalId, - userPublicId: userPublicId, - }) - .setMode('segmented') - .toggleDirectionless(); - return mentionNode; -} - -export function $isMentionNode(node: LexicalNode | null | undefined): node is MentionNode { - return node instanceof MentionNode; -} diff --git a/src/v4/social/components/PostCommentMentionInput/PostMentionUser.module.css b/src/v4/social/components/PostCommentMentionInput/PostMentionUser.module.css deleted file mode 100644 index 2167f73f..00000000 --- a/src/v4/social/components/PostCommentMentionInput/PostMentionUser.module.css +++ /dev/null @@ -1,27 +0,0 @@ -.communityMember__item { - width: 100%; - display: flex; - align-items: center; - padding: 0.5rem 1rem; - background-color: var(--asc-color-background-default); - color: var(--asc-color-base-default); -} - -.communityMember__item:focus { - background-color: var(--asc-color-base-shade4); -} - -.communityMember__avatar { - width: 2.5rem; - height: 2.5rem; -} - -.communityMember__displayName { - margin-left: 0.5rem; - font-size: 1rem; - display: block; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - color: var(--asc-color-base-default); -} diff --git a/src/v4/social/components/PostCommentMentionInput/PostMentionUser.tsx b/src/v4/social/components/PostCommentMentionInput/PostMentionUser.tsx deleted file mode 100644 index 2925cf29..00000000 --- a/src/v4/social/components/PostCommentMentionInput/PostMentionUser.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import styles from './PostMentionUser.module.css'; -import { UserAvatar } from '~/v4/social/internal-components/UserAvatar/UserAvatar'; -import { MentionTypeaheadOption } from './PostCommentMentionInput'; - -interface PostMentionUserProps { - isSelected: boolean; - onClick: () => void; - onMouseEnter: () => void; - option: MentionTypeaheadOption; -} - -export function PostMentionUser({ - isSelected, - onClick, - onMouseEnter, - option, -}: PostMentionUserProps) { - let className = 'item'; - if (isSelected) { - className += ' selected'; - } - - return ( -
-
-
- -
-

{option.user.displayName}

-
-
- ); -} diff --git a/src/v4/social/components/PostCommentMentionInput/index.ts b/src/v4/social/components/PostCommentMentionInput/index.ts deleted file mode 100644 index 485bb672..00000000 --- a/src/v4/social/components/PostCommentMentionInput/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { PostCommentMentionInput } from './PostCommentMentionInput'; diff --git a/src/v4/social/components/PostReplyComment/PostReplyComment.module.css b/src/v4/social/components/PostReplyComment/PostReplyComment.module.css deleted file mode 100644 index 1b4c2f03..00000000 --- a/src/v4/social/components/PostReplyComment/PostReplyComment.module.css +++ /dev/null @@ -1,197 +0,0 @@ -.postReplyComment { - width: 100%; - display: grid; - grid-template-columns: min-content 1fr; - gap: 0.5rem; -} - -.postReplyComment__avatar { - margin-right: 0.75rem; - display: inline-block; -} - -.postReplyComment__details { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.postReplyComment__content { - display: flex; - flex-direction: column; - gap: 0.25rem; - justify-content: center; - align-items: start; - background-color: var(--asc-color-base-shade4); - border-radius: 0 0.75rem 0.75rem; - padding: 0.75rem; - max-width: max-content; -} - -.postReplyComment__content__username { - color: var(--asc-color-base-default); -} - -.postReplyComment__content__text { - color: var(--asc-color-base-default); -} - -.postReplyComment__secondRow { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; -} - -.postReplyComment__secondRow__leftPane { - display: flex; - gap: 0.75rem; - align-items: center; -} - -.postReplyComment__secondRow__rightPane { - display: flex; - gap: 0.25rem; - align-items: center; -} - -.postReplyComment__secondRow__rightPane__like { - width: 1.25rem; - height: 1.25rem; -} - -.postReplyComment__secondRow__like { - cursor: pointer; - color: var(--asc-color-base-shade2); -} - -.postReplyComment__secondRow__like[data-is-liked='true'] { - color: var(--asc-color-primary-default); -} - -.postReplyComment__secondRow__reply { - color: var(--asc-color-base-shade2); -} - -.postReplyComment__secondRow__actionButton { - fill: var(--asc-color-secondary-shade2); - cursor: pointer; - width: 1.25rem; - height: 1.25rem; -} - -.postReplyComment__viewReply_button { - display: flex; - padding: 0.3125rem 0.75rem 0.3125rem 0.5rem; - cursor: pointer; - align-items: flex-start; - gap: 0.25rem; - background: var(--asc-color-background-default); - border: 1px solid var(--asc-color-base-shade4); - border-radius: 0.25rem; - width: max-content; -} - -.postReplyComment__viewReply_icon { - color: var(--asc-color-secondary-shade1); - width: 1rem; - height: 1rem; -} - -.postReplyComment__viewReply_text { - color: var(--asc-color-secondary-shade1); -} - -.postReplyComment__actionButton { - display: flex; - gap: 0.75rem; - padding: 1rem 0; - align-items: center; - cursor: pointer; -} - -.postReplyComment__actionButton__icon { - color: var(--asc-color-base-default); - width: 1.5rem; - height: 1.5rem; -} - -.postReplyComment__actionButton__text { - color: var(--asc-color-base-default); -} - -.postReplyComment__deleteComment_container { - display: flex; - padding: 0.31rem 0.5rem; - gap: 0.25rem; - background-color: var(--asc-color-secondary-shade4); - border-radius: var(--asc-border-radius-sm); - width: max-content; - - /* justify-content: center; */ - align-items: center; - margin-bottom: var(--asc-spacing-s2); -} - -.postReplyComment__deleteComment_icon { - width: 1rem; - height: 1rem; - color: var(--asc-color-secondary-shade2); -} - -.postReplyComment__deleteComment_text { - color: var(--asc-color-secondary-shade2); -} - -.postReplyComment__edit { - display: flex; - gap: 0.5rem; -} - -.postReplyComment__edit__inputWrap { - width: 100%; -} - -.postReplyComment__edit__input { - display: flex; - height: 7.5rem; - padding: 0.75rem; - flex-direction: column; - align-items: flex-start; - gap: 0.25rem; - align-self: stretch; - background-color: var(--asc-color-base-shade4); - width: 100%; - border-radius: 0 0.75rem 0.75rem; -} - -.postReplyComment__edit__buttonWrap { - display: flex; - gap: var(--asc-spacing-s1); - justify-content: flex-end; - margin-top: var(--asc-spacing-s1); -} - -.postReplyComment__edit__button { - padding: 0.375rem 0.75rem; - cursor: pointer; -} - -.postReplyComment__edit__cancelButton { - color: var(--asc-color-secondary-shade1); - border-radius: var(--asc-border-radius-sm); - border: 1px solid var(--asc-color-secondary-shade1); - background: var(--asc-color-background-default); -} - -.postReplyComment__edit__saveButton { - color: var(--asc-color-white); - border-radius: var(--asc-border-radius-sm); - background: var(--asc-color-primary-default); -} - -.postReplyComment__secondRow__timestamp { - display: flex; - color: var(--asc-color-base-shade2); - white-space: pre; -} diff --git a/src/v4/social/components/PostReplyComment/PostReplyComment.tsx b/src/v4/social/components/PostReplyComment/PostReplyComment.tsx deleted file mode 100644 index 902c83bb..00000000 --- a/src/v4/social/components/PostReplyComment/PostReplyComment.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import { CommentRepository, ReactionRepository } from '@amityco/ts-sdk'; -import clsx from 'clsx'; -import millify from 'millify'; -import React, { useCallback, useState } from 'react'; -import EllipsisH from '~/icons/EllipsisH'; -import { BottomSheet, Typography } from '~/v4/core/components/index'; -import useCommentSubscription from '~/v4/core/hooks/subscriptions/useCommentSubscription'; -import { useAmityComponent } from '~/v4/core/hooks/uikit/index'; -import { useConfirmContext } from '~/v4/core/providers/ConfirmProvider'; -import { Mentionees } from '~/v4/helpers/utils'; -import { LIKE_REACTION_KEY } from '../../constants/reactions'; -import { EditCancelButton } from '../../elements/EditCancelButton/EditCancelButton'; -import { SaveButton } from '../../elements/index'; -import { ModeratorBadge } from '../../elements/ModeratorBadge/ModeratorBadge'; -import Like from '../../elements/ReactionButton/Like'; -import { Timestamp } from '../../elements/Timestamp/Timestamp'; -import { MinusCircleIcon } from '../../icons/index'; -import { TextWithMention } from '../../internal-components/TextWithMention/TextWithMention'; -import { UserAvatar } from '../../internal-components/UserAvatar/UserAvatar'; -import { CommentOptions } from '../CommentOptions/CommentOptions'; -import { CreateCommentParams } from '../PostCommentComposer/PostCommentComposer'; -import { PostCommentInput } from '../PostCommentComposer/PostCommentInput'; -import styles from './PostReplyComment.module.css'; - -type PostReplyCommentProps = { - pageId?: string; - postTargetId: string; - postTargetType: Amity.PostTargetType; - comment: Amity.Comment; -}; - -const PostReplyComment = ({ - pageId = '*', - postTargetId, - postTargetType, - comment, -}: PostReplyCommentProps) => { - const componentId = 'post_comment'; - const { confirm } = useConfirmContext(); - const { accessibilityId, config, defaultConfig, isExcluded, uiReference, themeStyles } = - useAmityComponent({ - pageId, - componentId, - }); - - const [bottomSheetOpen, setBottomSheetOpen] = useState(false); - const [isEditing, setIsEditing] = useState(false); - const [commentData, setCommentData] = useState(); - - const isLiked = (comment.myReactions || []).some((reaction) => reaction === 'like'); - - const toggleBottomSheet = () => setBottomSheetOpen((prev) => !prev); - - const deleteComment = async () => - comment.commentId && CommentRepository.deleteComment(comment.commentId); - - const handleEditComment = () => { - setIsEditing(true); - }; - - const handleDeleteComment = () => { - confirm({ - pageId, - componentId, - title: 'Delete reply', - content: 'This reply will be permanently removed.', - cancelText: 'Cancel', - okText: 'Delete', - onOk: deleteComment, - }); - }; - - const handleLike = async () => { - if (!comment) return; - - if (!isLiked) { - await ReactionRepository.addReaction('comment', comment?.commentId, LIKE_REACTION_KEY); - } else { - await ReactionRepository.removeReaction('comment', comment?.commentId, LIKE_REACTION_KEY); - } - }; - - const handleSaveComment = useCallback(async () => { - if (!commentData || !comment.commentId) return; - - await CommentRepository.updateComment(comment.commentId, { - data: commentData.data, - mentionees: commentData.mentionees as Amity.UserMention[], - metadata: commentData.metadata, - }); - - setIsEditing(false); - }, [commentData]); - - useCommentSubscription({ - commentId: comment.commentId, - }); - - if (isExcluded) return null; - - return ( - <> - {comment.isDeleted ? ( -
- - - This reply has been deleted - -
- ) : isEditing ? ( -
- -
-
- { - setCommentData(value); - }} - /> -
-
- { - setIsEditing(false); - }} - /> - -
-
-
- ) : ( -
- -
-
- - {comment.creator?.displayName} - - - - - -
-
-
- - - {comment.createdAt !== comment.editedAt && ' (edited)'} - -
- - {isLiked ? 'Liked' : 'Like'} - -
- setBottomSheetOpen(true)} - /> -
- {comment.reactionsCount > 0 && ( -
- {millify(comment.reactionsCount)} - -
- )} -
-
-
- )} - - - - - ); -}; - -export default PostReplyComment; diff --git a/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.module.css b/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.module.css deleted file mode 100644 index 207117e6..00000000 --- a/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.module.css +++ /dev/null @@ -1,21 +0,0 @@ -.postReplyCommentList__viewReply_button { - display: flex; - padding: 0.3125rem 0.75rem 0.3125rem 0.5rem; - cursor: pointer; - align-items: flex-start; - gap: 0.25rem; - background: var(--asc-color-background-default); - border: 1px solid var(--asc-color-base-shade4); - border-radius: 0.25rem; - width: max-content; -} - -.postReplyCommentList__viewReply_icon { - color: var(--asc-color-secondary-shade1); - width: 1rem; - height: 1rem; -} - -.postReplyCommentList__viewReply_text { - color: var(--asc-color-secondary-shade1); -} diff --git a/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.tsx b/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.tsx deleted file mode 100644 index c14fda53..00000000 --- a/src/v4/social/components/PostReplyCommentList/PostReplyCommentList.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react'; -import { Typography } from '~/v4/core/components/index'; -import ReplyComment from '~/v4/icons/ReplyComment'; -import useCommentsCollection from '../../hooks/collections/useCommentsCollection'; -import PostReplyComment from '../PostReplyComment/PostReplyComment'; -import styles from './PostReplyCommentList.module.css'; - -interface PostReplyCommentProps { - postTargetType: Amity.PostTargetType; - postTargetId: string; - referenceId: string; - parentId: string; -} - -export const PostReplyCommentList = ({ - referenceId, - postTargetId, - postTargetType, - parentId, -}: PostReplyCommentProps) => { - const { comments, hasMore, loadMore } = useCommentsCollection({ - referenceId: referenceId, - referenceType: 'post', - parentId: parentId, - limit: 5, - shouldCall: true, - includeDeleted: true, - }); - - const handleClickLoadMore = () => { - loadMore(); - }; - - return ( -
- {comments.map((comment) => { - return ( - - ); - })} - {hasMore && ( -
- - - View more replies - -
- )} -
- ); -}; diff --git a/src/v4/social/components/ReactionList/styles.module.css b/src/v4/social/components/ReactionList/styles.module.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/v4/social/components/StoryTab/StoryRing.module.css b/src/v4/social/components/StoryTab/StoryRing.module.css deleted file mode 100644 index dc031eac..00000000 --- a/src/v4/social/components/StoryTab/StoryRing.module.css +++ /dev/null @@ -1,25 +0,0 @@ -.emptyStateRing { - stroke: var(--asc-color-base-shade4); - stroke-width: 2; - fill: none; -} - -.errorRing { - stroke: var(--asc-color-alert); -} - -.uploadingProgressRing { - stroke-dasharray: 339; - stroke-dashoffset: 339; - transform: rotate(-90deg); - animation: progress 2s linear infinite; -} - -@keyframes progress { - 0% { - stroke-dashoffset: 339; - } - 100% { - stroke-dashoffset: 0; - } -} \ No newline at end of file diff --git a/src/v4/social/components/StoryTab/StoryRing.tsx b/src/v4/social/components/StoryTab/StoryRing.tsx deleted file mode 100644 index c99a69c5..00000000 --- a/src/v4/social/components/StoryTab/StoryRing.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import React from 'react'; -import styles from './StoryRing.module.css'; -import { useCustomization } from '~/v4/core/providers/CustomizationProvider'; - -interface StoryRingProps extends React.SVGProps { - pageId?: '*'; - componentId?: 'story_tab_component'; - hasUnseen?: boolean; - uploading?: boolean; - isErrored?: boolean; - size?: number; -} - -const EmptyStateRingSvg = ({ - pageId, - componentId, - elementId, - size, -}: { - pageId: string; - componentId: string; - elementId: string; - size: number; -}) => { - const { getConfig } = useCustomization(); - const elementConfig = getConfig(`${pageId}/${componentId}/${elementId}`); - return ( - - - - - - - - - - ); -}; - -const HasSeenRingSvg = ({ - pageId, - componentId, - elementId, - size, -}: { - pageId: string; - componentId: string; - elementId: string; - size: number; -}) => { - const { getConfig } = useCustomization(); - const elementConfig = getConfig(`${pageId}/${componentId}/${elementId}`); - return ( - - - - - - - - - - ); -}; - -const UploadingRingSvg = ({ - pageId, - componentId, - elementId, - size, -}: { - pageId: string; - componentId: string; - elementId: string; - size: number; -}) => { - const { getConfig } = useCustomization(); - const elementConfig = getConfig(`${pageId}/${componentId}/${elementId}`); - - return ( - - - - - - - - - - ); -}; - -const StoryRing = ({ - pageId = '*', - componentId = 'story_tab_component', - hasUnseen = false, - uploading = false, - isErrored = false, - size = 64, - ...props -}: StoryRingProps) => { - const elementId = 'story_ring'; - const { isExcluded } = useCustomization(); - const isElementExcluded = isExcluded(`${pageId}/${componentId}/${elementId}`); - - if (isElementExcluded) return null; - if (isErrored) { - return ( - - - - ); - } - - if (uploading) { - return ( - - ); - } - - if (hasUnseen) { - return ( - - ); - } - - return ( - - ); -}; - -export default StoryRing; diff --git a/src/v4/social/components/ViewStoryPage/ViewStoryPage.module.css b/src/v4/social/components/ViewStoryPage/ViewStoryPage.module.css deleted file mode 100644 index ee1d203d..00000000 --- a/src/v4/social/components/ViewStoryPage/ViewStoryPage.module.css +++ /dev/null @@ -1,356 +0,0 @@ -.storyWrapper { - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - margin: 2rem; - gap: 1rem; - background-color: var(--color-black); - } - - .mobileSheet { - margin: 0 auto; - width: 100%; - } - - .mobileSheet .reactModalSheetContent { - position: relative; - padding: 0rem 1rem; - } - - .replyingBlock { - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1rem; - background-color: var(--color-gray-light); - } - - .storyDisabledCommentComposerBarContainer { - display: flex; - justify-content: center; - align-items: center; - gap: 0.5rem; - padding: 0.625rem 1rem; - border-top: 1px solid var(--color-gray-lighter); - color: var(--color-base-shade2); - font-family: var(--typography-body-font-family); - font-size: var(--typography-body-font-size); - font-weight: var(--typography-body-font-weight); - line-height: var(--typography-body-line-height); - } - - .storyCommentComposerBar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.75rem; - background-color: var(--color-black); - color: var(--color-white); - } - - .mobileSheetContent { - position: relative; - padding: 0rem 1rem; - } - - .mobileSheetScroller { - height: calc(100% - 4.5rem); - } - - .mobileSheetComposeBarContainer { - position: absolute; - bottom: 0; - width: 100%; - z-index: 99999; - } - - .mobileActionSheetContent { - padding: 1rem; - } - - .closeButton { - color: var(--color-white); - cursor: pointer; - } - - .verifiedBadge { - color: var(--color-white); - } - - .dotsButton { - cursor: pointer; - color: var(--color-white); - } - - .viewCountIcon { - color: var(--color-gray-shade3); - } - - .storyContainer { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - } - - .viewStoryInfoContainer { - display: flex; - flex-direction: column; - justify-content: flex-start; - width: 100%; - } - - .storyTabBarContainer { - display: flex; - flex-direction: column; - align-items: center; - padding: 0.5rem; - height: 5rem; - } - - .viewStoryCompostBarContainer { - width: 100%; - display: flex; - position: absolute; - justify-content: space-between; - align-items: center; - height: 3.5rem; - padding: 0.75rem; - background-color: var(--color-black); - bottom: 0; - } - - .viewStoryCompostBarViewIconContainer { - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-white); - gap: 0.25rem; - } - - .viewStoryCompostBarEngagementContainer { - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-white); - gap: 0.75rem; - } - - .viewStoryCompostBarEngagementIconContainer { - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-white); - gap: 0.25rem; - border-radius: 50%; - padding: 0.5rem 0.625rem; - background-color: var(--color-base-default); - } - - .storyContentContainer { - display: flex; - flex-direction: column; - align-items: center; - padding: 0.5rem; - height: 5rem; - } - - .viewStoryContainer { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - } - - .viewStoryContent { - position: relative; - width: 23.438rem; - height: 40.875rem; - display: flex; - flex-direction: column; - overflow: hidden; - z-index: 2; - } - - .viewStoryOverlay { - position: absolute; - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(0, 0, 0, 0.16) 55.05%, rgba(255, 255, 255, 0) 96.52%); - z-index: 3; - } - - .viewStoryHeaderContainer { - z-index: 2; - position: absolute; - width: 100%; - display: flex; - justify-content: space-between; - align-items: center; - flex-direction: column; - padding: 1.5rem 1rem 0.625rem 1rem; - gap: 0.5rem; - } - - .avatarContainer { - position: relative; - display: flex; - justify-content: center; - align-items: center; - width: 2.5rem; - height: 2.5rem; - overflow: hidden; - } - - .avatar { - width: 2.5rem; - height: 2.5rem; - border-radius: 50%; - } - - .viewStoryHeaderListActionsContainer { - display: flex; - gap: 1.25rem; - justify-content: flex-end; - align-items: center; - } - - .viewStoryHeadingInfoContainer { - display: flex; - justify-content: space-between; - width: 100%; - gap: 0.75rem; - align-items: center; - } - - .viewStoryHeading { - display: flex; - gap: 0.25rem; - color: var(--color-white); - font-size: 0.938rem; - font-style: normal; - font-weight: 600; - line-height: 1.25rem; - letter-spacing: -0.24px; - margin-right: 0.25rem; - align-items: center; - } - - .viewStorySubheading { - display: inline-flex; - gap: 0.25rem; - margin-bottom: 0.25rem; - color: var(--color-white); - font-size: 0.813rem; - font-style: normal; - font-weight: 400; - line-height: 1.25rem; - letter-spacing: -0.1px; - } - - .viewStoryImageContainer { - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - } - - .viewStoryImageContent { - flex: 1; - width: 100%; - height: 100%; - object-fit: cover; - } - - .viewStoryVideoContent { - flex: 1; - width: 100%; - height: 100%; - } - - .viewStoryContentContainer { - flex: 1; - width: 100%; - height: 100%; - } - - .tabBarContainer { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1rem; - height: 5rem; - } - - .flexContainer { - display: flex; - flex-direction: column; - min-height: 100%; - } - - .actionList { - list-style: none; - } - - .actionItem { - margin-bottom: 0.75rem; - } - - .actionButton { - border: none; - width: 100%; - display: flex; - align-items: center; - gap: 0.5rem; - background-color: transparent; - cursor: pointer; - justify-content: flex-start; - } - - .deleteIcon { - width: 1.5rem; - height: 1.5rem; - color: var(--color-base-default); - } - - .mobileSheetHeader { - text-align: center; - border-bottom: 1px solid var(--color-gray-lighter); - padding-bottom: 0.5rem; - color: var(--color-base-default); - font-family: var(--typography-title-font-family); - font-size: var(--typography-title-font-size); - font-weight: var(--typography-title-font-weight); - line-height: var(--typography-title-line-height); - } - - .storyActionItem { - display: flex; - justify-content: flex-start; - align-items: center; - gap: 0.5rem; - width: 100%; - } - - .storyActionItemText { - color: var(--color-base-main); - font-family: var(--typography-body-bold-font-family); - font-size: var(--typography-body-bold-font-size); - font-weight: var(--typography-body-bold-font-weight); - line-height: var(--typography-body-bold-line-height); - } - - .storyArrowButton{ - cursor: pointer; - border: none; - background-color: transparent; - } - - .hiddenInput { - display: none; - } - diff --git a/src/v4/social/constants/permissions.ts b/src/v4/social/constants/permissions.ts index 9edb4f26..a0b0f6b4 100644 --- a/src/v4/social/constants/permissions.ts +++ b/src/v4/social/constants/permissions.ts @@ -35,4 +35,5 @@ export enum Permissions { EditCommunityCategoryPermission = 'EDIT_COMMUNITY_CATEGORY', DeleteCommunityCategoryPermission = 'DELETE_COMMUNITY_CATEGORY', ManageStoryPermission = 'MANAGE_COMMUNITY_STORY', + CreatePivillegedPostPermission = 'CREATE_PRIVILEGED_POST', } diff --git a/src/v4/social/elements/CreateNewPostButton/CreateNewPostButton.tsx b/src/v4/social/elements/CreateNewPostButton/CreateNewPostButton.tsx index ed28d427..31b25a1e 100644 --- a/src/v4/social/elements/CreateNewPostButton/CreateNewPostButton.tsx +++ b/src/v4/social/elements/CreateNewPostButton/CreateNewPostButton.tsx @@ -7,7 +7,7 @@ interface CreateNewPostButtonProps { pageId: string; componentId?: string; isValid: boolean; - onSubmit: () => void; + onSubmit?: () => void; } export function CreateNewPostButton({ diff --git a/src/v4/social/elements/PostTextField/PostTextField.tsx b/src/v4/social/elements/PostTextField/PostTextField.tsx index 25ee78ed..315603c5 100644 --- a/src/v4/social/elements/PostTextField/PostTextField.tsx +++ b/src/v4/social/elements/PostTextField/PostTextField.tsx @@ -211,6 +211,8 @@ export const PostTextField = ({ {options.map((option, i: number) => { return ( { setHighlightedIndex(i); diff --git a/src/v4/social/elements/ShareStoryButton/ShareStoryButton.tsx b/src/v4/social/elements/ShareStoryButton/ShareStoryButton.tsx index 8a43ff4c..9feb99ec 100644 --- a/src/v4/social/elements/ShareStoryButton/ShareStoryButton.tsx +++ b/src/v4/social/elements/ShareStoryButton/ShareStoryButton.tsx @@ -5,6 +5,7 @@ import { useAmityElement } from '~/v4/core/hooks/uikit'; import styles from './ShareStoryButton.module.css'; import { CommunityAvatar } from '~/v4/social/elements/CommunityAvatar'; +import { Button } from '~/v4/core/natives/Button'; const ArrowRightIcon = (props: React.SVGProps) => { return ( @@ -47,11 +48,10 @@ export const ShareStoryButton = ({ if (isExcluded) return null; return ( - + ); }; diff --git a/src/v4/social/hooks/collections/useCommunityMembersCollection.tsx b/src/v4/social/hooks/collections/useCommunityMembersCollection.tsx deleted file mode 100644 index be566897..00000000 --- a/src/v4/social/hooks/collections/useCommunityMembersCollection.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { CommunityRepository } from '@amityco/ts-sdk'; -import useLiveCollection from '~/core/hooks/useLiveCollection'; - -export default function useCommunityMembersCollection(communityId?: string, limit: number = 5) { - const { items, ...rest } = useLiveCollection({ - fetcher: CommunityRepository.Membership.getMembers, - params: { communityId: communityId as string, limit, memberships: ['member'] }, - shouldCall: () => !!communityId, - }); - - return { - members: items, - ...rest, - }; -} diff --git a/src/v4/social/hooks/collections/useGlobalStoryTargets.tsx b/src/v4/social/hooks/collections/useGlobalStoryTargets.tsx deleted file mode 100644 index 127de2c3..00000000 --- a/src/v4/social/hooks/collections/useGlobalStoryTargets.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { StoryRepository } from '@amityco/ts-sdk'; -import useLiveCollection from '~/core/hooks/useLiveCollection'; - -export const useGlobalStoryTargets = ( - params: Amity.LiveCollectionParams, -) => { - const { items, hasMore, loadMore, ...rest } = useLiveCollection({ - fetcher: StoryRepository.getGlobalStoryTargets, - params, - shouldCall: () => true, - }); - - const loadMoreStories = () => { - if (hasMore) { - loadMore(); - } - }; - - return { - stories: items, - hasMore, - loadMoreStories, - ...rest, - }; -}; diff --git a/src/v4/social/hooks/collections/useReactionsCollection.tsx b/src/v4/social/hooks/collections/useReactionsCollection.tsx deleted file mode 100644 index e58c66f9..00000000 --- a/src/v4/social/hooks/collections/useReactionsCollection.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { ReactionRepository } from '@amityco/ts-sdk'; - -import useLiveCollection from '~/core/hooks/useLiveCollection'; - -type UseReactionsCollectionParams = Parameters[0]; - -export const useReactionsCollection = (params: UseReactionsCollectionParams) => { - const { items, ...rest } = useLiveCollection({ - fetcher: ReactionRepository.getReactions, - params, - shouldCall: () => !!params.referenceId && !!params.referenceType, - }); - - return { - reactions: items, - ...rest, - }; -}; diff --git a/src/v4/social/hooks/useCommentFlaggedByMe.tsx b/src/v4/social/hooks/useCommentFlaggedByMe.tsx deleted file mode 100644 index f318ebd3..00000000 --- a/src/v4/social/hooks/useCommentFlaggedByMe.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { CommentRepository } from '@amityco/ts-sdk'; -import { useQuery } from '@tanstack/react-query'; -import React, { useEffect, useState } from 'react'; -import { FormattedMessage } from 'react-intl'; -import { useNotifications } from '~/v4/core/providers/NotificationProvider'; - -export const useCommentFlaggedByMe = (commentId?: string) => { - const notification = useNotifications(); - const [isFlaggedByMe, setIsFlaggedByMe] = useState(false); - - const { data, isLoading, refetch } = useQuery({ - queryKey: ['asc-uikit', 'CommentRepository', 'isCommentFlaggedByMe', commentId], - queryFn: () => { - return CommentRepository.isCommentFlaggedByMe(commentId as string); - }, - enabled: commentId != null, - }); - - useEffect(() => { - if (data != null) { - setIsFlaggedByMe(data); - } - }, [data]); - - const flagComment = async () => { - if (commentId == null) return; - try { - setIsFlaggedByMe(true); - await CommentRepository.flagComment(commentId); - } catch (_error) { - setIsFlaggedByMe(false); - } finally { - refetch(); - } - }; - - const unflagComment = async () => { - if (commentId == null) return; - try { - setIsFlaggedByMe(false); - await CommentRepository.unflagComment(commentId); - } catch (_error) { - setIsFlaggedByMe(true); - } finally { - refetch(); - } - }; - - const toggleFlagComment = async () => { - if (commentId == null) return; - if (isFlaggedByMe) { - await unflagComment(); - notification.success({ - content: , - }); - } else { - await flagComment(); - notification.success({ - content: , - }); - } - }; - - return { - isLoading, - isFlaggedByMe, - flagComment, - unflagComment, - toggleFlagComment, - }; -}; diff --git a/src/v4/social/hooks/useGetStoryByStoryId.tsx b/src/v4/social/hooks/useGetStoryByStoryId.tsx deleted file mode 100644 index 403a6b91..00000000 --- a/src/v4/social/hooks/useGetStoryByStoryId.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { StoryRepository } from '@amityco/ts-sdk'; - -import useLiveObject from '~/core/hooks/useLiveObject'; - -const useGetStoryByStoryId = (storyId: string | undefined) => { - const story = useLiveObject({ - fetcher: StoryRepository.getStoryByStoryId, - params: storyId, - shouldCall: () => !!storyId, - }); - - return story; -}; - -export default useGetStoryByStoryId; diff --git a/src/v4/social/hooks/useVisibilitySensor.tsx b/src/v4/social/hooks/useVisibilitySensor.ts similarity index 100% rename from src/v4/social/hooks/useVisibilitySensor.tsx rename to src/v4/social/hooks/useVisibilitySensor.ts diff --git a/src/v4/social/internal-components/CreatePost/CreatePost.tsx b/src/v4/social/internal-components/CreatePost/CreatePost.tsx index fcb9d1dc..f8f2f79a 100644 --- a/src/v4/social/internal-components/CreatePost/CreatePost.tsx +++ b/src/v4/social/internal-components/CreatePost/CreatePost.tsx @@ -300,7 +300,6 @@ export function CreatePost({ community, targetType, targetId }: AmityPostCompose 0 || postImages.length > 0 || postVideos.length > 0} />
@@ -349,6 +348,7 @@ export function CreatePost({ community, targetType, targetId }: AmityPostCompose } as React.CSSProperties } className={styles.mentionTextInput_item} + data-qa-anchor={`${pageId}/mention_text_input_options`} />
diff --git a/src/v4/social/internal-components/Lexical/MentionItem.tsx b/src/v4/social/internal-components/Lexical/MentionItem.tsx index 9cd28181..ec76ba63 100644 --- a/src/v4/social/internal-components/Lexical/MentionItem.tsx +++ b/src/v4/social/internal-components/Lexical/MentionItem.tsx @@ -33,6 +33,7 @@ export function MentionItem({ key={option.key} tabIndex={-1} data-is-selected={isSelected} + data-qa-ancgor={`${pageId}/${componentId}/mention_item`} className={styles.userMentionItem__item} ref={option.setRefElement} role="option" diff --git a/src/v4/social/internal-components/MentionTextInput/MentionTextInput.tsx b/src/v4/social/internal-components/MentionTextInput/MentionTextInput.tsx index 0cd34870..d5e65f60 100644 --- a/src/v4/social/internal-components/MentionTextInput/MentionTextInput.tsx +++ b/src/v4/social/internal-components/MentionTextInput/MentionTextInput.tsx @@ -231,6 +231,7 @@ function Mention({
{options.map((option, i: number) => ( { - return ( -
{ - AmityPostTargetSelectionPage?.goToPostComposerPage?.({ - targetId: community.communityId, - targetType: 'community', - mode: Mode.CREATE, - community: community, - }); - }} - key={community.communityId} - className={styles.selectPostTargetPage__timeline} - > -
- -
- -
- {community.isOfficial && } - {!community.isPublic && } + const renderCommunity = communities + .filter((community) => canCreatePostCommunity(client, community)) + .map((community) => { + return ( +
{ + AmityPostTargetSelectionPage?.goToPostComposerPage?.({ + targetId: community.communityId, + targetType: 'community', + mode: Mode.CREATE, + community: community, + }); + }} + key={community.communityId} + className={styles.selectPostTargetPage__timeline} + > +
+ +
+ +
+ {community.isOfficial && } + {!community.isPublic && } +
-
- ); - }); + ); + }); return (
diff --git a/src/v4/social/pages/StoryPage/CommunityFeedStory.tsx b/src/v4/social/pages/StoryPage/CommunityFeedStory.tsx index 52b393f9..25dd39f9 100644 --- a/src/v4/social/pages/StoryPage/CommunityFeedStory.tsx +++ b/src/v4/social/pages/StoryPage/CommunityFeedStory.tsx @@ -70,7 +70,7 @@ export const CommunityFeedStory = ({ const dragEventTarget = useRef(new EventTarget()); const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); - const { stories } = useGetActiveStoriesByTarget({ + const { stories: storiesData } = useGetActiveStoriesByTarget({ targetId: communityId, targetType: 'community', options: { @@ -79,6 +79,22 @@ export const CommunityFeedStory = ({ }, }); + const stories = storiesData.reduce( + (acc: (Amity.Ad | Amity.Story)[], current: Amity.Ad | Amity.Story) => { + const isDuplicate = acc.find((item) => { + if (isStory(item) && isStory(current)) { + return item.storyId === current.storyId; + } + return false; + }); + if (!isDuplicate) { + acc.push(current); + } + return acc; + }, + [], + ); + const communityFeedRenderers = useMemo( () => renderers.map(({ renderer, tester }) => { diff --git a/src/v4/social/utils/index.ts b/src/v4/social/utils/index.ts index 0aadd9aa..d57d4c17 100644 --- a/src/v4/social/utils/index.ts +++ b/src/v4/social/utils/index.ts @@ -210,3 +210,22 @@ export function formatTimeAgo(dateString: string | Date | undefined) { return `${hours}h`; } } + +export function canCreatePostCommunity( + client: Amity.Client | null | undefined, + community: Amity.Community, +) { + if (!client) { + return false; + } + + const communityPermission = client + .hasPermission(Permissions.CreatePivillegedPostPermission) + .community(community.communityId); + + if (communityPermission || community.postSetting !== 'ONLY_ADMIN_CAN_POST') { + return true; + } + + return false; +}