diff --git a/.gitignore b/.gitignore index 66445bcf1..c2c6233cb 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ .env.development.local .env.test.local .env.production.local +.env.staging .env npm-debug.log* @@ -29,3 +30,5 @@ yarn-error.log* faker/custom-extended-schemas/ src/config/apollo-client/customClientTypeDefs.ts + +caddy/certificate/root.crt diff --git a/CHANGELOG.md b/CHANGELOG.md index 99fb36b0e..00653702f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,381 @@ +## [0.5.1](https://github.com/geyserfund/geyser-app/compare/v0.2.0...v0.5.1) (2023-08-30) + + +### Features + +* add caching google fonts to workbox runtimecaching ([0d6bdd9](https://github.com/geyserfund/geyser-app/commit/0d6bdd9297f8a0e4ed570264bb83612f8a2e2488)) +* add CONTRIBUTING document ([#1053](https://github.com/geyserfund/geyser-app/issues/1053)) ([1b5b6d7](https://github.com/geyserfund/geyser-app/commit/1b5b6d7db47fac047ac980f7170000305d493718)) +* add controls to video player ([#1003](https://github.com/geyserfund/geyser-app/issues/1003)) ([79882f2](https://github.com/geyserfund/geyser-app/commit/79882f29c449d76253a4e280950a4e0bff93e461)) +* add delete project feature ([#931](https://github.com/geyserfund/geyser-app/issues/931)) ([778181d](https://github.com/geyserfund/geyser-app/commit/778181d6fca98722513b326cb8f9541c74c18e49)) +* add delete user profile ([0f2de29](https://github.com/geyserfund/geyser-app/commit/0f2de29156d38006ef74250f12b9b1adef2328fb)) +* add finishing touches and glow to about page ([94c9aa0](https://github.com/geyserfund/geyser-app/commit/94c9aa06bcc7ce61190adf18794fde925c8c5845)) +* add github action for tests ([837c943](https://github.com/geyserfund/geyser-app/commit/837c943a4f42f4c9e55cf77d25c369d2ccd32490)) +* add OTP after login and before project creation ([8854cea](https://github.com/geyserfund/geyser-app/commit/8854ceabb676708f422cdebe267c04d74c8c0bab)) +* add package.json ([c05c533](https://github.com/geyserfund/geyser-app/commit/c05c533da812a32c2800966ac7168ad274d291c0)) +* add scripts for trusting caddy local CA ([0c082d5](https://github.com/geyserfund/geyser-app/commit/0c082d5722e8c51b0476e373cbcb5284fc654424)) +* add tooltip in project navigation ([#938](https://github.com/geyserfund/geyser-app/issues/938)) ([0977c9a](https://github.com/geyserfund/geyser-app/commit/0977c9a57b3fa8b36a6b0000d48df174598ba782)) +* add translation files for 7 other languages ([5ad0a14](https://github.com/geyserfund/geyser-app/commit/5ad0a141f0e9ec8e97e31a8c821ab1efcac1f7e3)) +* add translation to activity brief ([f88d748](https://github.com/geyserfund/geyser-app/commit/f88d74852b80c295a60313136010c8488427e892)) +* add translation to logout and nodata component ([c8e46c9](https://github.com/geyserfund/geyser-app/commit/c8e46c919aea0f1e1f58fff12ae4f9042d8a5e1d)) +* add translation to other components in landing page ([aa1a51b](https://github.com/geyserfund/geyser-app/commit/aa1a51b0d2f8fa8b757ad039587a61a5238f735f)) +* add translation to some more components ([ad9ce60](https://github.com/geyserfund/geyser-app/commit/ad9ce605fb85216fa5c5869353792c0851b562b8)) +* add translation to tab bar ([642c1a4](https://github.com/geyserfund/geyser-app/commit/642c1a412e48870c43fe504b96ad7256d889ebae)) +* add translations ([b33e868](https://github.com/geyserfund/geyser-app/commit/b33e868dd8c0d8a4971d22abc136367615552b2f)) +* add translations for badges and auth modals ([0dbdefa](https://github.com/geyserfund/geyser-app/commit/0dbdefa6cc4630c7a852be0ac273d538fc61b600)) +* add translations for entry ([62ad804](https://github.com/geyserfund/geyser-app/commit/62ad804734c9e0b3dc22556fce234346167b75eb)) +* add translations for landing page banner and filters ([e871861](https://github.com/geyserfund/geyser-app/commit/e871861caaa9c9fba9aed39e2b0f2f5f97285e83)) +* add translations to auth modal, topnavbar/menu ([339cec0](https://github.com/geyserfund/geyser-app/commit/339cec05d3dc0f4459dc554f3681d27f1ab4922e)) +* add translations to profile page & remove unnecessary files ([5e8b524](https://github.com/geyserfund/geyser-app/commit/5e8b524c0b0c2639d98b2a59b13ed725a04185ce)) +* add translations to project activity panel ([0365316](https://github.com/geyserfund/geyser-app/commit/0365316ae075fd4789c8c5c02db55bb49df863fa)) +* add translations to project activity panel ([c19ccb5](https://github.com/geyserfund/geyser-app/commit/c19ccb5fa0c2a5552d24a1d5c7e718fca93bfd58)) +* add translations to project creation ([69ae4ad](https://github.com/geyserfund/geyser-app/commit/69ae4ada697fb206831e1a0804170ca3c80bc17d)) +* add translations to project dashboard ([20bcd7a](https://github.com/geyserfund/geyser-app/commit/20bcd7a2226630ceee3796b47937ce98e5c49601)) +* add translations to project page & main screen of activity panel ([de61b40](https://github.com/geyserfund/geyser-app/commit/de61b406dab277f9f910eeeda0181fa2f7044306)) +* configure i18next and create ui for language selection ([2f59628](https://github.com/geyserfund/geyser-app/commit/2f596285ba5bf9ef25d8214c6ebf3cb6acd4378d)) +* contribution milestone circular progress ([#967](https://github.com/geyserfund/geyser-app/issues/967)) ([cab79d7](https://github.com/geyserfund/geyser-app/commit/cab79d79c29db0dd6687d5ca40ef2a78e38d9dd1)) +* create about page, WIP ([9491bfc](https://github.com/geyserfund/geyser-app/commit/9491bfc152c64071fc9677aca6212ce1e909f9e6)) +* create button below the left sidebar ([#966](https://github.com/geyserfund/geyser-app/issues/966)) ([0efb53c](https://github.com/geyserfund/geyser-app/commit/0efb53cf64b918d918010390c5c1c80137775b1e)) +* finish login e2e test ([2fe4fe9](https://github.com/geyserfund/geyser-app/commit/2fe4fe904c21a51555e88f14e9c5b9b02879c4ad)) +* hide keyboard on search + improve filters dependencies ([#978](https://github.com/geyserfund/geyser-app/issues/978)) ([12b93c7](https://github.com/geyserfund/geyser-app/commit/12b93c7e8c3ee6f470db3e73e41f222850c4416a)) +* improve back button style and secondary buttons bg ([#1004](https://github.com/geyserfund/geyser-app/issues/1004)) ([b275164](https://github.com/geyserfund/geyser-app/commit/b275164ca263188dced642310b9268deb5978255)) +* install vite plugin for pwa and configure ([9c0c0dd](https://github.com/geyserfund/geyser-app/commit/9c0c0dd2c7bc7971bc5107f858fe8ff84632165c)) +* login with email ([2b540c9](https://github.com/geyserfund/geyser-app/commit/2b540c9269d6ca4a216e910b9997ba287a149e7e)) +* login with email with OTP ([f9251ca](https://github.com/geyserfund/geyser-app/commit/f9251ca84a5b1b20ad2be034543479a31121b402)) +* make rewards selectable only ([#987](https://github.com/geyserfund/geyser-app/issues/987)) ([231ad3b](https://github.com/geyserfund/geyser-app/commit/231ad3b6053665445174ed7469e95b9d55e9c29f)) +* mobile navigation update ([#944](https://github.com/geyserfund/geyser-app/issues/944)) ([1b26a9b](https://github.com/geyserfund/geyser-app/commit/1b26a9bc253224b5b081c3c7bef900d5d078feaa)) +* project layout updates ([#950](https://github.com/geyserfund/geyser-app/issues/950)) ([ddd25ee](https://github.com/geyserfund/geyser-app/commit/ddd25ee0d10a805d9a5e5224819dcf26c8a469c0)) +* remove canvas from project page ([#1001](https://github.com/geyserfund/geyser-app/issues/1001)) ([1bef81f](https://github.com/geyserfund/geyser-app/commit/1bef81fece1133bb99e773ecb58f5a0992ffd961)) +* remove default image from project header ([6042f22](https://github.com/geyserfund/geyser-app/commit/6042f229c0ecc6bee0318a7fca7f40638c7bc113)) +* remove default image from project header ([#1007](https://github.com/geyserfund/geyser-app/issues/1007)) ([06e874f](https://github.com/geyserfund/geyser-app/commit/06e874f8d99c0e503d3115f30d3dfb3bd76c5f99)) +* show different qrs for onchain and lightning ([ccb9e62](https://github.com/geyserfund/geyser-app/commit/ccb9e620fad13201507ac860ff85afc977fa6844)) +* supporters list and modal ([#1006](https://github.com/geyserfund/geyser-app/issues/1006)) ([91f6724](https://github.com/geyserfund/geyser-app/commit/91f672493a5d6240f9183ddcc46c90a58e0c0024)) +* update featured project ([8de0c8a](https://github.com/geyserfund/geyser-app/commit/8de0c8a1174c6e1717f5ea0414f51cc344dff0b7)) +* update language list ([0b30b8f](https://github.com/geyserfund/geyser-app/commit/0b30b8fb21037fc4294d02c743a77a22677578ac)) +* updated funding flow ([#1023](https://github.com/geyserfund/geyser-app/issues/1023)) ([2d00660](https://github.com/geyserfund/geyser-app/commit/2d0066016ce96ea9a083bcfd477f0ed60e00752b)) +* use OTP to update wallet ([80d5f6c](https://github.com/geyserfund/geyser-app/commit/80d5f6cea05dc7f942954d15dd2304611f88b994)) +* use videos as artifacts in gh actions ([1020fe8](https://github.com/geyserfund/geyser-app/commit/1020fe82b11b5a74b8dc2fdb4f7ca91cb94e3d87)) +* use videos as artifacts in gh actions ([8d90d54](https://github.com/geyserfund/geyser-app/commit/8d90d54aa1ea9407a2c03af31cab611cc1e5d7db)) +* use videos as artifacts in gh actions ([1b9b591](https://github.com/geyserfund/geyser-app/commit/1b9b5919f05ef10b38c7de7680423473f214c08d)) +* video as header ([#969](https://github.com/geyserfund/geyser-app/issues/969)) ([cd143ef](https://github.com/geyserfund/geyser-app/commit/cd143ef7648edd4effb693bba34928c83f39ee3a)) + + +### Bug Fixes + +* a plus icon next to the project create icon ([988a109](https://github.com/geyserfund/geyser-app/commit/988a1093ae3efebf52f1f0e02cc732ad1fea7742)) +* activity feed refreshes on unfollow project ([10945ef](https://github.com/geyserfund/geyser-app/commit/10945ef2053993a3547e901d27661cebaa72799f)) +* add a top navbar menu button to install geyser ([bc88673](https://github.com/geyserfund/geyser-app/commit/bc88673517e4b751c0a509ee6a9bacc5a994990f)) +* add all of the texts in the about page to translations ([bbd5ecf](https://github.com/geyserfund/geyser-app/commit/bbd5ecf1be2fc82368d3508860e711dfe01c7dde)) +* add all reference codes to dashboard ([#936](https://github.com/geyserfund/geyser-app/issues/936)) ([cbf234f](https://github.com/geyserfund/geyser-app/commit/cbf234f3a18c82ad1dff8093cd2ea5e4c496297f)) +* add all reference codes to dashboard ([#937](https://github.com/geyserfund/geyser-app/issues/937)) ([d9474c5](https://github.com/geyserfund/geyser-app/commit/d9474c5f536229d045bd9e6476644cee1d6111d3)) +* add arabic to i18n config ([e7dae94](https://github.com/geyserfund/geyser-app/commit/e7dae94f1454e7085c19b79a684f2db9cb454faf)) +* add background to downloadable component ([bff67f9](https://github.com/geyserfund/geyser-app/commit/bff67f97e84e3f64f0102e9c007dba5487f1e19c)) +* add blink and fix sponsor image for darkmode ([1eb24a8](https://github.com/geyserfund/geyser-app/commit/1eb24a8bee03b1258c435457733559f40fcf2546)) +* add board members ([abb2f28](https://github.com/geyserfund/geyser-app/commit/abb2f285d18b597b1658783393508b2e74f8df47)) +* add caching for dependencies CICD ([e809e4e](https://github.com/geyserfund/geyser-app/commit/e809e4e729923e291efaa307eb1d9350a222fd61)) +* add changelog and version update ([3f6aba1](https://github.com/geyserfund/geyser-app/commit/3f6aba1bf3c5131cc90a0d54100a10f0cc5c3712)) +* add checks for entry to not be 0 ([f9448cd](https://github.com/geyserfund/geyser-app/commit/f9448cd998d124451e867a19cbe20c31411ee02c)) +* add comma formatting ([e15e4b5](https://github.com/geyserfund/geyser-app/commit/e15e4b5a89de2c29b1041402a0201d5e0ba96a8f)) +* add deployment.md content ([bf56018](https://github.com/geyserfund/geyser-app/commit/bf560184562ae56a698f484eb9d45f74715fc69c)) +* add dividers to landing page default view ([d0415ba](https://github.com/geyserfund/geyser-app/commit/d0415baa0e6351a20af7a1304d3397d4074fb09c)) +* add edit raw feature to markdown editor ([01bf036](https://github.com/geyserfund/geyser-app/commit/01bf036f26791c080b7476d3e5338f034c4f01f2)) +* add elipsis to language button ([39b6d2d](https://github.com/geyserfund/geyser-app/commit/39b6d2df6ed9ad9450f25ebe92bc88452fc82ac0)) +* add empty spanish translations ([5ec1776](https://github.com/geyserfund/geyser-app/commit/5ec1776d00e29f443f526907f64b9eaa99e50563)) +* add error handling around twttr widgets ([0c4ef54](https://github.com/geyserfund/geyser-app/commit/0c4ef54e4668c24ae4e0302ba7542b5c4d0af178)) +* add funding amount exception ([48f1ee9](https://github.com/geyserfund/geyser-app/commit/48f1ee9e10af1b9c615df2fe825d1dbfed365c86)) +* add language file for arabic language ([51982b8](https://github.com/geyserfund/geyser-app/commit/51982b8f63871979c903de32ccedf2b97f1ef458)) +* add link to find out more on connect node modal ([#982](https://github.com/geyserfund/geyser-app/issues/982)) ([ff05787](https://github.com/geyserfund/geyser-app/commit/ff05787ed16618dbe80b809fed045ced7bdde1cf)) +* add loader till the success component is loaded ([aa3889c](https://github.com/geyserfund/geyser-app/commit/aa3889c21a1e42ea0984087ea74d3b611c216972)) +* add login in public comment section ([07b5d21](https://github.com/geyserfund/geyser-app/commit/07b5d211447533628f07088d16315132df65d7e3)) +* add missing translations ([55a226f](https://github.com/geyserfund/geyser-app/commit/55a226f32a8d1410be08115dda29e6841d15dc43)) +* add missing translations ([f57d13c](https://github.com/geyserfund/geyser-app/commit/f57d13c10ce85f465cf96632cfb2e132d9991695)) +* add missing translations ([ed4fda1](https://github.com/geyserfund/geyser-app/commit/ed4fda1d3a3c59fa7968684d6ec3c5c1361859e3)) +* add missing translations ([b417d2c](https://github.com/geyserfund/geyser-app/commit/b417d2c380df251c27f0e18e55bd8488738fee71)) +* add missing translations in badges page ([ca32433](https://github.com/geyserfund/geyser-app/commit/ca32433df0cc18b69ea8d4043ab95aebf0beec27)) +* add missing type ([#946](https://github.com/geyserfund/geyser-app/issues/946)) ([a9ef595](https://github.com/geyserfund/geyser-app/commit/a9ef5950061ca39ebcd9fcaf963ca299ffd8f239)) +* add more pwa icons ([01145a5](https://github.com/geyserfund/geyser-app/commit/01145a51f75ba9a66abfc4d44591dfaf247052c5)) +* add new script for upstream running, dev-stage ([5723eb2](https://github.com/geyserfund/geyser-app/commit/5723eb27559d2152c22954a2579ba607b64e648e)) +* add number of retires to 2 ([4fc2a1c](https://github.com/geyserfund/geyser-app/commit/4fc2a1c86bb38d0284dc69430f8b361cb8284a2f)) +* add onclick for table button ([f96c827](https://github.com/geyserfund/geyser-app/commit/f96c82761e369086b717a6aa5c2378fd8be1b1f0)) +* add padding ([#961](https://github.com/geyserfund/geyser-app/issues/961)) ([10e9579](https://github.com/geyserfund/geyser-app/commit/10e95796326338c15a9ac7ce08b3e1ff96ec8cc8)) +* add padding to the contributors component ([3cebdb0](https://github.com/geyserfund/geyser-app/commit/3cebdb0479f86c925e7982d0143540dafb86ad1b)) +* add pwa icons ([03f9afc](https://github.com/geyserfund/geyser-app/commit/03f9afcf59508b56e3d38d6c5b7fd14f5e446810)) +* add request a language link ([d229c49](https://github.com/geyserfund/geyser-app/commit/d229c49c8891131b1e555446640cca44a12d2fbf)) +* add separate mask icons ([07e224d](https://github.com/geyserfund/geyser-app/commit/07e224d2ea7232be8dd8b50dea686d95b983676d)) +* add skeleton to contribution and leaderboard list ([9ed0214](https://github.com/geyserfund/geyser-app/commit/9ed0214ca1dae540c6091cf9bb1eaee26d2ab539)) +* add sticktotop back to activity panel tabs ([dc51006](https://github.com/geyserfund/geyser-app/commit/dc51006750cb77cb6299863a3d16a889d426e2d2)) +* add stuff to readme.md about dev:stage ([4cfa6ea](https://github.com/geyserfund/geyser-app/commit/4cfa6ea1c7c5de5ef921d26c4de6e6fc3d789b9c)) +* add the new tag to the list ([94bb75d](https://github.com/geyserfund/geyser-app/commit/94bb75d4c7d8e5d7a723cff9a1ef0ffdaf7384b0)) +* add the plus icon ([5abcff4](https://github.com/geyserfund/geyser-app/commit/5abcff43ef14488b4c08f14100765391ab427119)) +* add tooltip when delete profile button is disabled ([40dbfae](https://github.com/geyserfund/geyser-app/commit/40dbfae900f7e2cefad204dd89fbf75ddbbc8d05)) +* add twitter embed inside markdown ([d4628d5](https://github.com/geyserfund/geyser-app/commit/d4628d5e1452613f5f7039935a78a1aa81e1eb19)) +* add update email feature ([02cf41f](https://github.com/geyserfund/geyser-app/commit/02cf41f28538d63175d25725f5a5c7eee7cbf593)) +* adding more to translations and testing ([f984b36](https://github.com/geyserfund/geyser-app/commit/f984b36d97f323b6f7c58aecb1d1740a36bf4bc1)) +* alignment of edit button ([9ba9250](https://github.com/geyserfund/geyser-app/commit/9ba9250e082ae6dfe13faf0d7204049efb17b5f3)) +* allow save only on form dirty ([3e0da2c](https://github.com/geyserfund/geyser-app/commit/3e0da2c730b71fa7a28338abeecd1acbd5b839ce)) +* allow users to edit email if unverified ([115a1cd](https://github.com/geyserfund/geyser-app/commit/115a1cd2e60ebfb43840dcd0baad0418d960ca35)) +* allow value to be set to 0 ([1cfb1ec](https://github.com/geyserfund/geyser-app/commit/1cfb1ec18c3640d19f6c4af896e9957444d678c9)) +* apollo type error ([8056250](https://github.com/geyserfund/geyser-app/commit/80562500fa167b8925c271839c8da4ac7779405d)) +* apply retry logic on all refresh token errors ([5de8c5d](https://github.com/geyserfund/geyser-app/commit/5de8c5d21566d5d642dfa2be02dbd720e79ba8af)) +* ask email for every reward ([61a0463](https://github.com/geyserfund/geyser-app/commit/61a0463dd416eec30430374259f6e6b5f343c65e)) +* ask email for every reward ([#1035](https://github.com/geyserfund/geyser-app/issues/1035)) ([62e3ba9](https://github.com/geyserfund/geyser-app/commit/62e3ba940063610babad229c2840dd2b79e99e55)) +* bitcoin display logic from sats ([a533a76](https://github.com/geyserfund/geyser-app/commit/a533a765336262b35b2176ed1091497cd6cfab3d)) +* build error ([5cf5f6e](https://github.com/geyserfund/geyser-app/commit/5cf5f6e1cd063431abe4d0dc31970934e272282f)) +* can't scroll down in this activity panel in mobile ([de33a55](https://github.com/geyserfund/geyser-app/commit/de33a5592ee1e736a7fc0395dbcea03e410e832a)) +* change contribute icon to lightning icon, resolves GEY-3322 ([b81c308](https://github.com/geyserfund/geyser-app/commit/b81c3084dbee38de87171ab2ef3fb82e91391009)) +* change icon layout ([59d15bf](https://github.com/geyserfund/geyser-app/commit/59d15bf899761e30a6a985e7096f4c42ed5a006b)) +* change webln to signmessage for lnauth ([88c8c52](https://github.com/geyserfund/geyser-app/commit/88c8c529284698459099a5fe2bfcaf88dab9c304)) +* check mark color, resolves GEY-3041 ([9aafbad](https://github.com/geyserfund/geyser-app/commit/9aafbad4b24bc9b3870bb12239cc11ee57c17ae2)) +* checking for fix ([298b9ed](https://github.com/geyserfund/geyser-app/commit/298b9ed4afa97b2ff1673dff8a0f06834eb93ff6)) +* chore cleanup ([01e92d9](https://github.com/geyserfund/geyser-app/commit/01e92d919175dedef44c576c674591febdc0e2fb)) +* cleanup runtime caching config ([ebf9ef5](https://github.com/geyserfund/geyser-app/commit/ebf9ef5ecca79b8b46551fc373ad09dd096e04e4)) +* clear reward add/edit form on close ([8f27217](https://github.com/geyserfund/geyser-app/commit/8f27217f7cbefba5ba13e83a6f1a80cb23517318)) +* close modal on language select ([8b74544](https://github.com/geyserfund/geyser-app/commit/8b7454445e7b86b51e4d027b6eb8c3ece1c31d9d)) +* close tooltip after 1.5 seconds ([4730721](https://github.com/geyserfund/geyser-app/commit/4730721b7343988b5e11c55de365e9a7120ffe47)) +* configure workbox to skip waiting ([63c3450](https://github.com/geyserfund/geyser-app/commit/63c3450a4dd3f4a9a372b928e97dd29a2c7ee5c6)) +* convert cents to dollars before conversion ([4a71a43](https://github.com/geyserfund/geyser-app/commit/4a71a43ea827c6d954191af4eaceb6a8fe5b30dc)) +* copies in grants ([e94b3e8](https://github.com/geyserfund/geyser-app/commit/e94b3e8207af09c39208900b8ec4c772193d681e)) +* correct copy, resolves GEY-2654 ([91ff415](https://github.com/geyserfund/geyser-app/commit/91ff4151ccf524f44795994d6294d5a91a393023)) +* create delete reward mutation and implement ([426986c](https://github.com/geyserfund/geyser-app/commit/426986cb957585142e9d472aa0f29eeb221beeaa)) +* create different fragment and order by createdAt ([c2164de](https://github.com/geyserfund/geyser-app/commit/c2164de9f7e5beca39013363688a540ea52085a1)) +* create hook to handle subscription ([815c113](https://github.com/geyserfund/geyser-app/commit/815c11311d463c5d43a8cbb6007301231b2b84d1)) +* create webln auth fix ([3cf6c86](https://github.com/geyserfund/geyser-app/commit/3cf6c860284a259c51ce691f09f39bdf1abf420f)) +* dashboard fixes mobile ([e430f3d](https://github.com/geyserfund/geyser-app/commit/e430f3de1e39257c2225b9f76cdb400c256f12cf)) +* deprecate media field from project ([4fabe6e](https://github.com/geyserfund/geyser-app/commit/4fabe6e993e7c9358f4b4f1ba47400a2b4b19b88)) +* disable button when lighting address is null ([16209b5](https://github.com/geyserfund/geyser-app/commit/16209b5d264c2efa11be2ce3ecbd14ec29fcad9e)) +* disable languages for this push ([76f3873](https://github.com/geyserfund/geyser-app/commit/76f3873f8f9d73877573b2e24215fb026201921c)) +* do not replace uuid if null ([55168c7](https://github.com/geyserfund/geyser-app/commit/55168c7f0df551f4804416c0ee82ce78a587d4e1)) +* do not replace uuid if null ([61006ea](https://github.com/geyserfund/geyser-app/commit/61006eafed32437b39738e2bc2f676efd4a46995)) +* don't show connected accounts ([4443f12](https://github.com/geyserfund/geyser-app/commit/4443f120372561dce46b0907189b49f568f1bd28)) +* don't throw error when webln fails ([fd82a23](https://github.com/geyserfund/geyser-app/commit/fd82a23083ea1d583eff11fbddbff7e1ab28e767)) +* dont show tag that has less than 3 projects ([2a0a99e](https://github.com/geyserfund/geyser-app/commit/2a0a99e2bee1e635f39ef5e81de7ca7efc9bad54)) +* e2e test ([8d80a41](https://github.com/geyserfund/geyser-app/commit/8d80a4167e5e11c5a418084f8f316f35f94c04a0)) +* enable arabic and portuguese ([f4639d8](https://github.com/geyserfund/geyser-app/commit/f4639d898a0bd6e2e1b1899181f319cc68437997)) +* error of

with

([4c6d46c](https://github.com/geyserfund/geyser-app/commit/4c6d46cc957f6771e1c1af31b54665aa6a3de8eb)) +* fetch and view board members ([fad2357](https://github.com/geyserfund/geyser-app/commit/fad23572c90b3919a5bda308f93b107bd1160811)) +* final chnage to delete user profile tooltip ([631ac9c](https://github.com/geyserfund/geyser-app/commit/631ac9c88814797c52518a9ec2654e92b6a30c8c)) +* final OTP fixes ([cc75bcf](https://github.com/geyserfund/geyser-app/commit/cc75bcf98cfd26fbf3bb89e3efb03bc462677aec)) +* finalize funding success ([418355c](https://github.com/geyserfund/geyser-app/commit/418355cc0de89984c378ebb4250b77c46919740c)) +* finalize table feature for story markdown editor and viewer ([350a9d2](https://github.com/geyserfund/geyser-app/commit/350a9d2d1e254ff8f7c5c303c6ce4dc2a965e66a)) +* finalize the update service worker and app ([fbb3fc9](https://github.com/geyserfund/geyser-app/commit/fbb3fc9f1aed98f0aa2ecea14b8b8f0e99d3458e)) +* finalize video fixes and sanitize html ([bc25d9b](https://github.com/geyserfund/geyser-app/commit/bc25d9b7976e13c5b7e35164e3e4c796e868d846)) +* finalized icons ([27f928e](https://github.com/geyserfund/geyser-app/commit/27f928ebffb5458442ab4cc8b400a8e22b396785)) +* finishing touches ([ca2905b](https://github.com/geyserfund/geyser-app/commit/ca2905bdadee0502c1c6efaf193b68deae468040)) +* fix build ([b47ad13](https://github.com/geyserfund/geyser-app/commit/b47ad131cd24445b0b17a386841303983dcaa124)) +* fix grid wrapper to allow fetching more ([0471914](https://github.com/geyserfund/geyser-app/commit/0471914850d118b3aa91f575517090b2bcc197be)) +* fix missing change ([05984a7](https://github.com/geyserfund/geyser-app/commit/05984a70015005f2095ad6d8cbae4238fa2e9d5d)) +* fix mobile sort logic ([00325c9](https://github.com/geyserfund/geyser-app/commit/00325c98cf43c84ddd784d40163ede73649c5a3f)) +* fix otp copy when wallet update and add back button ([c33f6fc](https://github.com/geyserfund/geyser-app/commit/c33f6fc94f2d0d677bcae646502aaa12e13370ba)) +* fix project title elipsis and project image size ([88f14a0](https://github.com/geyserfund/geyser-app/commit/88f14a02de542548ac6bb1cb71f4622392affd5d)) +* fixes based on linear issues ([84e9704](https://github.com/geyserfund/geyser-app/commit/84e970481a41c7b957e05988b4291774ae430e2c)) +* follow button in mobile ([c00921a](https://github.com/geyserfund/geyser-app/commit/c00921a0a5041c2602bfc0dd6779eb8194bef83f)) +* force refresh to close on confirm ([ae53ab4](https://github.com/geyserfund/geyser-app/commit/ae53ab4158466c22e24bc884f88d2aada4d637a3)) +* gif search and refactor gif modal component to be resuable ([2be775e](https://github.com/geyserfund/geyser-app/commit/2be775e9d1016497bfebde675429cba3a79aac69)) +* go back in history when back in entry ([fb11f58](https://github.com/geyserfund/geyser-app/commit/fb11f589185ffd0a2f3126f418b0cfb5f9870294)) +* grant 2 page had active label ([8e3b462](https://github.com/geyserfund/geyser-app/commit/8e3b462470169bb385291109efdbdcb862b4873a)) +* have language button, show the current language ([b86031e](https://github.com/geyserfund/geyser-app/commit/b86031e5db95be717faf13ae02c5706c9472e2f8)) +* have loading before image is loaded ([4d27b3c](https://github.com/geyserfund/geyser-app/commit/4d27b3cf33562e14d082455ae295d9da36f8e4f0)) +* have nextStage call inside invoiceID match condition ([5a49f8f](https://github.com/geyserfund/geyser-app/commit/5a49f8fb792208c2d8874cfedda17802fb9eb1fa)) +* header title fix ([ae33f9e](https://github.com/geyserfund/geyser-app/commit/ae33f9e366ddba349b62b29efb0fa9e0c902baea)) +* header title fix ([92af1df](https://github.com/geyserfund/geyser-app/commit/92af1df6ceb0cfe05b52ff6f54441d1033c9f069)) +* hit the logout request on expired refresh token and retry on stale refresh token ([8c6a740](https://github.com/geyserfund/geyser-app/commit/8c6a7408314540605bcf271089a2b9d33c7d5f0b)) +* hotfix for cross button in success page ([ca200ff](https://github.com/geyserfund/geyser-app/commit/ca200ffd0bfa7aa32e246bcc48590d8f8d4808a8)) +* icons ([34ba389](https://github.com/geyserfund/geyser-app/commit/34ba38970a4323ce4a1601b79bee67116cda9e90)) +* image upload lasting too long when image upload has failed GEY-2823 ([6841675](https://github.com/geyserfund/geyser-app/commit/6841675d53fbd82c35ffb4131e3038fa62872acf)) +* image url validation ([#1000](https://github.com/geyserfund/geyser-app/issues/1000)) ([36079c9](https://github.com/geyserfund/geyser-app/commit/36079c949e1943eb58de9412c91f2603ba4cc915)) +* in progress ([fbd1df9](https://github.com/geyserfund/geyser-app/commit/fbd1df95180b1270da114aa20d8ab373ce424f23)) +* input toggle button size increase ([2031078](https://github.com/geyserfund/geyser-app/commit/2031078b09b328e856ad753ebf74217688e0892e)) +* insert hardbreak after images and videos ([3b02573](https://github.com/geyserfund/geyser-app/commit/3b02573f534cc2882479f774c2f667d48056498a)) +* issues with markdown and add multi line feature ([e46b51b](https://github.com/geyserfund/geyser-app/commit/e46b51bcff6fc908d263cd2f43f15214ef784603)) +* keyboard collapse on return ([d2f8cc7](https://github.com/geyserfund/geyser-app/commit/d2f8cc7c65955591d10fbbb9993d0f4135b702f6)) +* layout of distribution chart ([5840dfb](https://github.com/geyserfund/geyser-app/commit/5840dfb717eaf435589f4b8498e36d6fe530f69f)) +* layout so that the top sticks ([2373216](https://github.com/geyserfund/geyser-app/commit/2373216cf6e76dd53dfc38dc937849b3e7050d7a)) +* lightning login issue & webln triiger issue ([d8b0915](https://github.com/geyserfund/geyser-app/commit/d8b09155693421605cbd9ab327262c26f725e5ce)) +* lint ([59ed6c4](https://github.com/geyserfund/geyser-app/commit/59ed6c42a676131a54d4aa929ddb26df7171acda)) +* load supporters separately, resolves GEY-2938 ([b928fda](https://github.com/geyserfund/geyser-app/commit/b928fda93dda095cf7acfbe1df4ac49a362773e3)) +* log and check login with lightining ([d10c5df](https://github.com/geyserfund/geyser-app/commit/d10c5df49fd432ea0bba32a9f3cf96261a0c4e54)) +* log error ([20cced2](https://github.com/geyserfund/geyser-app/commit/20cced2b034f26ab4c2b4451bdc21422458cc2fc)) +* made fixes based on linear comment ([a53ffe8](https://github.com/geyserfund/geyser-app/commit/a53ffe855055c3301f0aca6c476a3691be0db08b)) +* make bottom nav in mobile appear at once ([#964](https://github.com/geyserfund/geyser-app/issues/964)) ([2d388a6](https://github.com/geyserfund/geyser-app/commit/2d388a60dca6bbabf6ad3da47a7f99b9cd57034f)) +* make changes for grant -5, resolves GEY-2560 ([4c02281](https://github.com/geyserfund/geyser-app/commit/4c0228195c1b49455b1c3ee88ea22930ec683b31)) +* make create project expiresAt null instead of empty string when ongoing is selected ([#939](https://github.com/geyserfund/geyser-app/issues/939)) ([001c75d](https://github.com/geyserfund/geyser-app/commit/001c75d8543190019ed57128e4e97052e627187a)) +* make fixes to OTP popup, resolves GEY-2991 ([41e503f](https://github.com/geyserfund/geyser-app/commit/41e503ff35e85edbdf18b8ab63aa34a5c299aa7e)) +* make icons align better in project nav ([#942](https://github.com/geyserfund/geyser-app/issues/942)) ([6841951](https://github.com/geyserfund/geyser-app/commit/684195154910a9170996e2898f1097abd9441b20)) +* make mobile -success screen scrollable ([05e2c7c](https://github.com/geyserfund/geyser-app/commit/05e2c7c71cf329037a2c7870b7558fc958919b7a)) +* make new lines not possible in project objective ([#940](https://github.com/geyserfund/geyser-app/issues/940)) ([20ab335](https://github.com/geyserfund/geyser-app/commit/20ab3351257965b6a69998d6367383d043acafa4)) +* make qr code bigger and square ([b6a4232](https://github.com/geyserfund/geyser-app/commit/b6a42326ccb47ba38dc9da06f90962c59f7d7820)) +* make qr logo smaller ([#1045](https://github.com/geyserfund/geyser-app/issues/1045)) ([d6bbdfd](https://github.com/geyserfund/geyser-app/commit/d6bbdfd75facc6b48187ba37df5793d6147cf300)) +* make qr more responsive ([0eaa3aa](https://github.com/geyserfund/geyser-app/commit/0eaa3aa4684794f88f1fd3cceec212f0d8792dec)) +* make styles consistent in project settings ([#955](https://github.com/geyserfund/geyser-app/issues/955)) ([349c499](https://github.com/geyserfund/geyser-app/commit/349c499f35dab434a28164d22ef0d9d370965951)) +* make success image component static to theme ([e248e56](https://github.com/geyserfund/geyser-app/commit/e248e5635cab5b37ba453526b488c18370e52e90)) +* make sure the button is not clickable when authToken get failed ([92715bd](https://github.com/geyserfund/geyser-app/commit/92715bd4bafe13f7108f4876565c471e6ca898d4)) +* make youtube iframe height bigger ([#959](https://github.com/geyserfund/geyser-app/issues/959)) ([0b721a2](https://github.com/geyserfund/geyser-app/commit/0b721a219fa8bc49ac0914a37ed9d3d6d0197ba5)) +* map issue ([8a1223e](https://github.com/geyserfund/geyser-app/commit/8a1223ed3a21e271a8c2889c2d37419eaefc51ac)) +* mapping ([3680226](https://github.com/geyserfund/geyser-app/commit/368022653604e4325b730a304f564600e5a13e9f)) +* markdown table in WIP ([664859c](https://github.com/geyserfund/geyser-app/commit/664859cec824e0fd6135be776b7e7d5aca62ae18)) +* merge updates ([9685166](https://github.com/geyserfund/geyser-app/commit/968516660f4ce14b8def1e860e947bea98a131d1)) +* minor fix ([c677a01](https://github.com/geyserfund/geyser-app/commit/c677a01a7e725ac2c2e389ca8f9a43318a7ade95)) +* minor height adjustment ([a128a01](https://github.com/geyserfund/geyser-app/commit/a128a010eb2a4f76da488811e171e91bd8cb166a)) +* minor improvements ([1595383](https://github.com/geyserfund/geyser-app/commit/1595383e1353d74246b57942d97fe9ba0b4aa6d2)) +* minor improvements based on comments ([4b74973](https://github.com/geyserfund/geyser-app/commit/4b74973d6c6adc31d7e46209655c7f6675ea9adc)) +* minor style fix ([8c6b2c0](https://github.com/geyserfund/geyser-app/commit/8c6b2c005227ff28e0bde6d260c0e2f3672224a6)) +* minor translation update ([b183c7a](https://github.com/geyserfund/geyser-app/commit/b183c7af6376b4ca1209962146ff8bc4bddbdace)) +* minor update in grant page project lists ([9bff44f](https://github.com/geyserfund/geyser-app/commit/9bff44f0c3a018a8f5a806a4bea4bdabb8a02c95)) +* missing change ([7086437](https://github.com/geyserfund/geyser-app/commit/7086437697dcac1f53da957c327d9a9bfab170b9)) +* missing change ([5ef59dd](https://github.com/geyserfund/geyser-app/commit/5ef59dd947f2df2bb4b04054d91caa772e39d1d4)) +* mobile nav styling ([#958](https://github.com/geyserfund/geyser-app/issues/958)) ([fa3ca95](https://github.com/geyserfund/geyser-app/commit/fa3ca95cb44ead2d7cca4eec2d753fbd72983d37)) +* mobile view for default view ([e00e1dd](https://github.com/geyserfund/geyser-app/commit/e00e1ddcc514fd23e8ab9c349c8e749a5eee9bbe)) +* move all manifest configuration insige vitaPWA manifest ([b75f338](https://github.com/geyserfund/geyser-app/commit/b75f338a5f5bd79ae3a335a11507be298427a83c)) +* no key for mapped jsx ([aa020e1](https://github.com/geyserfund/geyser-app/commit/aa020e1856de238c41e563ab1586119358cbb1e9)) +* no reference code ([3d0b7f7](https://github.com/geyserfund/geyser-app/commit/3d0b7f7a4a6bbe4442b793757258142cf18e77f4)) +* objective textarea fix + tooltip placement ([#948](https://github.com/geyserfund/geyser-app/issues/948)) ([53ec9b4](https://github.com/geyserfund/geyser-app/commit/53ec9b47a21c63282257c3e4e852e893abe1553c)) +* only add languages with above 70% translation ([93f29f2](https://github.com/geyserfund/geyser-app/commit/93f29f200da4b503dd4e73843e183524fdf461db)) +* only show projects with length 3 ([f1dde51](https://github.com/geyserfund/geyser-app/commit/f1dde5199906bb06ef87a8eee02c0964f4007731)) +* only use light mode view for lnurlpay qr code ([255e05b](https://github.com/geyserfund/geyser-app/commit/255e05bc9326907209c63ad3f07e8d09d12df305)) +* prevent follow and unfollow when state already the same ([#983](https://github.com/geyserfund/geyser-app/issues/983)) ([4527bb6](https://github.com/geyserfund/geyser-app/commit/4527bb6f294290573e810d55d13fcb607a9f8f9c)) +* prevent query by name when name is less than 3 characters ([#981](https://github.com/geyserfund/geyser-app/issues/981)) ([043ab7f](https://github.com/geyserfund/geyser-app/commit/043ab7f58bfdbab8621cdef10f52f272cd6b88d3)) +* project card fixes ([#1012](https://github.com/geyserfund/geyser-app/issues/1012)) ([a8e548b](https://github.com/geyserfund/geyser-app/commit/a8e548b1ed28c8e5c5239d84e638b3c2d7f96434)) +* project cards ([#1011](https://github.com/geyserfund/geyser-app/issues/1011)) ([4793176](https://github.com/geyserfund/geyser-app/commit/4793176e631a0c36d39fa5471e9acb275b7536a7)) +* project entry card follow and sats icon fix ([#963](https://github.com/geyserfund/geyser-app/issues/963)) ([c345cb2](https://github.com/geyserfund/geyser-app/commit/c345cb2516f18f3b3d10092f418ad75bfce0e0fe)) +* project layout cleanup ([4e280ab](https://github.com/geyserfund/geyser-app/commit/4e280abfb243cba59e255cfad92dd646b52f6862)) +* projects in Profile show from oldest to newest ([75d3c9c](https://github.com/geyserfund/geyser-app/commit/75d3c9c544b2388463d2823cccf8a18865138e5d)) +* pwa options ([9ddaef3](https://github.com/geyserfund/geyser-app/commit/9ddaef389cc3d538e713d5addcc0e5502ea301b7)) +* qr code fixes ([f2d7b30](https://github.com/geyserfund/geyser-app/commit/f2d7b30b8f23929a346a2c9dbde1481d2d7b0435)) +* qr code flickering issue ([5cff146](https://github.com/geyserfund/geyser-app/commit/5cff146ad061ef54cd2d70afdfd5a9e7152fbe9f)) +* qr code update ([934de8d](https://github.com/geyserfund/geyser-app/commit/934de8d960ad70f56226a4316c7937b2053f1c52)) +* re-enable languages for staging ([979c68f](https://github.com/geyserfund/geyser-app/commit/979c68fb69a5ae3ebd96175af8867e0f50857b18)) +* reconnection for subscriptions ([d100627](https://github.com/geyserfund/geyser-app/commit/d1006276f528b1914a745b0bd604595fb7716584)) +* refactor activity panel WIP ([03c77b1](https://github.com/geyserfund/geyser-app/commit/03c77b11a5c045b6e0a234ef6dcfe5eb27d01d55)) +* refactor all of the screen in activity panel ([c10867b](https://github.com/geyserfund/geyser-app/commit/c10867b2e1a3db462902f6b9d20bb83d8008b14d)) +* remove disabled logic for translations and add spanish back ([e1172c0](https://github.com/geyserfund/geyser-app/commit/e1172c095545794d64d0187e1ead99dc159f3d62)) +* remove draft status before status loaded ([#970](https://github.com/geyserfund/geyser-app/issues/970)) ([a0bb076](https://github.com/geyserfund/geyser-app/commit/a0bb0763df5951ec8f3f3b5375177ff350cecc22)) +* remove economics tag ([4b7e36e](https://github.com/geyserfund/geyser-app/commit/4b7e36e80724b4dfba31923dcac317275554653d)) +* remove Email button from connectedAccounts in profile, resolves GEY-2676 ([cf76cd0](https://github.com/geyserfund/geyser-app/commit/cf76cd05c6cf8f76eabf6ab7e15eaaaed73ce573)) +* remove empty translations ([0d08166](https://github.com/geyserfund/geyser-app/commit/0d08166972f9f71d0b1ab16945da405e5c1fd32d)) +* remove launched label ([#980](https://github.com/geyserfund/geyser-app/issues/980)) ([6ff9d15](https://github.com/geyserfund/geyser-app/commit/6ff9d15be5f481b03af2993d64538a3ebf876632)) +* remove login with email for now ([02eb57f](https://github.com/geyserfund/geyser-app/commit/02eb57f664ffcb19ff8cf9f3a259ed6affe7a59b)) +* remove nostr from mobile login ([512c9ac](https://github.com/geyserfund/geyser-app/commit/512c9ac56ae54437ec72013ce2e48a5ee3b8af7b)) +* remove shadow ([ad42b17](https://github.com/geyserfund/geyser-app/commit/ad42b170cefe5295d3d299b3904b60f27ad6aa62)) +* remove shop from the list of tags ([1313cc2](https://github.com/geyserfund/geyser-app/commit/1313cc2cb1bd7782f21326971c318f2133229e1b)) +* remove status active when search is active ([0022ce5](https://github.com/geyserfund/geyser-app/commit/0022ce5fbd75e14caa7a50e3e9623bc3a57b2268)) +* remove supports section when no funders ([a57fa67](https://github.com/geyserfund/geyser-app/commit/a57fa6731fbb863a9c27e8d45fe1ddb61c2232eb)) +* remove tags and funding tx count ([eaf97a6](https://github.com/geyserfund/geyser-app/commit/eaf97a6006bd483ae91bf858f709759aa2532e66)) +* remove tooltip in language button ([6899cb6](https://github.com/geyserfund/geyser-app/commit/6899cb64e9e7ed06fb1e6f86bcb0bef5182f435c)) +* remove unhandled rejection error from bitcoin api ([569f1c2](https://github.com/geyserfund/geyser-app/commit/569f1c221c1a00b2122f4f3768d9a08bee108a2e)) +* remove unused fields ([280da9a](https://github.com/geyserfund/geyser-app/commit/280da9a3ebb107012298aaa0b22568a2c8412eb6)) +* remove verify email prompt ([a0c423e](https://github.com/geyserfund/geyser-app/commit/a0c423e487b965a085d60e228699604a35f293fd)) +* remove worth of votes in mobile, resolves GEY-3016 ([d8af2ff](https://github.com/geyserfund/geyser-app/commit/d8af2ffca1f2805a3e9b27cac75c24266f346416)) +* replace copies ([6e3bb11](https://github.com/geyserfund/geyser-app/commit/6e3bb1188c1de8ea0286634222d7ae3becfe39ae)) +* responsive project headers ([e1fc57d](https://github.com/geyserfund/geyser-app/commit/e1fc57d87ce1d2c1a65d5bdce7852da6923caa8d)) +* responsive project headers ([043bc4e](https://github.com/geyserfund/geyser-app/commit/043bc4e6aa73f115917c7f2e5aaf6e518429b4d3)) +* retry the graphql operation if the error is expired_refresh_token ([0155e67](https://github.com/geyserfund/geyser-app/commit/0155e679dbd5e36682f629db124937eb0a108bcd)) +* revert back to default null for project context ([dfb6590](https://github.com/geyserfund/geyser-app/commit/dfb6590c1a891b920a3dd3abe66d49a8c820ec0d)) +* revert unwanted change ([#954](https://github.com/geyserfund/geyser-app/issues/954)) ([1bb00c4](https://github.com/geyserfund/geyser-app/commit/1bb00c47d4ac5fd0d7c2a20d84353d14901b0a4a)) +* safari issues ([d859356](https://github.com/geyserfund/geyser-app/commit/d85935604598a3127c4f4440cd1499f08b5d464e)) +* same behavior towards tabs ([d8e6aa2](https://github.com/geyserfund/geyser-app/commit/d8e6aa2fe57830bb399e8b6a1155b1e2b8c55967)) +* show less than one for dollar ([b77339c](https://github.com/geyserfund/geyser-app/commit/b77339c9c5f5e4a2623323ce1123ee43cfb17e91)) +* show max 3 entries in project page ([d9b03ec](https://github.com/geyserfund/geyser-app/commit/d9b03ecb4f3789c53a9ac98292d43c99c6e1db73)) +* show the default order ([bd6a643](https://github.com/geyserfund/geyser-app/commit/bd6a643eafaaa673f29aedc80ba3e0c23f4864ec)) +* skelton width, resolves GEY-2878 ([5c21fe5](https://github.com/geyserfund/geyser-app/commit/5c21fe5aff3864ad3e2c95cabc0b12cf1fc3cdb6)) +* skip pagination when search is active ([f13b074](https://github.com/geyserfund/geyser-app/commit/f13b074518732d96f775244da302c581254c5beb)) +* sort projects in project followed ([6b4c728](https://github.com/geyserfund/geyser-app/commit/6b4c728aa509b31c2352a13364ca46e7f6eba62e)) +* staging fixes ([2b0066e](https://github.com/geyserfund/geyser-app/commit/2b0066edc717acd622118fd6c54834dafb29693b)) +* staging fixes + delete unused components ([7bf28ab](https://github.com/geyserfund/geyser-app/commit/7bf28ab3568e47ed81b72cb3a870201cc2d15f47)) +* staging style fixes ([#1027](https://github.com/geyserfund/geyser-app/issues/1027)) ([4bbcaf7](https://github.com/geyserfund/geyser-app/commit/4bbcaf7dde84931d9c1948d474405fa0eb63f775)) +* staging style fixes ([#1028](https://github.com/geyserfund/geyser-app/issues/1028)) ([c6989f6](https://github.com/geyserfund/geyser-app/commit/c6989f6ebcdfc0064636dadb7a52b5ed6f0c32fd)) +* staging style fixes ([#947](https://github.com/geyserfund/geyser-app/issues/947)) ([959d1c5](https://github.com/geyserfund/geyser-app/commit/959d1c52d1dc4c1a57679166da70579d65fbd246)) +* start webln flow when login with lightning qr is displayed ([39143c5](https://github.com/geyserfund/geyser-app/commit/39143c56cff745f44959e3d897d1ce1195ccd6f9)) +* sticky markdown toolbar fix + geyser topbar logo ([#934](https://github.com/geyserfund/geyser-app/issues/934)) ([f097a65](https://github.com/geyserfund/geyser-app/commit/f097a656ad0a3b144255912589ea09c0e640a507)) +* style fixes staging ([#986](https://github.com/geyserfund/geyser-app/issues/986)) ([df21fbe](https://github.com/geyserfund/geyser-app/commit/df21fbe49692b38129b5d429ea248efd1b38c282)) +* supporters update, resolves GEY-3109 ([88d0e31](https://github.com/geyserfund/geyser-app/commit/88d0e3188f3422ad49f1e1657171fc23a1d9f22a)) +* supporters widget fixes ([#1010](https://github.com/geyserfund/geyser-app/issues/1010)) ([bc9e2cb](https://github.com/geyserfund/geyser-app/commit/bc9e2cbaef548af681eafc4b5fa99646ae49f0e7)) +* table fix WIP ([86c35d0](https://github.com/geyserfund/geyser-app/commit/86c35d01b1360b361e44499a2d5d49129a8a5c37)) +* temp stuff to check ([dde3281](https://github.com/geyserfund/geyser-app/commit/dde3281f1e9cad331c0d4a188c928182f25f7feb)) +* testing changes for PWA ([f424ce9](https://github.com/geyserfund/geyser-app/commit/f424ce971d768217428d96ebd448d3ac7aa6d557)) +* testing more icons ([bbeb329](https://github.com/geyserfund/geyser-app/commit/bbeb329b0e3b49946ea0257bd221f6f4230722d1)) +* testing poeditor ([e0d2db1](https://github.com/geyserfund/geyser-app/commit/e0d2db121ca3b75b09dd70b3f0c186acec3160ee)) +* translation tooltip ([99638e3](https://github.com/geyserfund/geyser-app/commit/99638e3632a9904dee50d3340daf94bd677b4467)) +* type issue ([2857ac7](https://github.com/geyserfund/geyser-app/commit/2857ac7feb091cc702a95175b7b1b017d47eff65)) +* typo ([7ded5fc](https://github.com/geyserfund/geyser-app/commit/7ded5fcdee4c7aabac6107d04dbd168be59ecc3b)) +* typo and translation label, resolves GEY-2894 ([051d592](https://github.com/geyserfund/geyser-app/commit/051d5922f0f7e621f36f8fe3afecc096a06b9827)) +* udpate icons ([14acfd2](https://github.com/geyserfund/geyser-app/commit/14acfd2028d9c4789cc6b755de38b42b59433923)) +* update -BR to Portuguese, update flag for it and arabic ([a9a11ff](https://github.com/geyserfund/geyser-app/commit/a9a11ffee6a867daaabc6f45401a4b1575a1049f)) +* update app name and intall button style ([d23c16f](https://github.com/geyserfund/geyser-app/commit/d23c16febfeda74c1a604484a793bf6a23cbd412)) +* update button to include currency conversion ([d3e9f50](https://github.com/geyserfund/geyser-app/commit/d3e9f50a3608a629860fd5a2b5ca4c15dfe11860)) +* update changelog and package version ([9478d01](https://github.com/geyserfund/geyser-app/commit/9478d01ce748f7fbfc0e4b8fbfbe6c031494bf39)) +* update changelog and package.json ([03babae](https://github.com/geyserfund/geyser-app/commit/03babae7a49174ec966e55f962e012d99fb5bd20)) +* update circle progress colors so that they are more contrasting ([a967c97](https://github.com/geyserfund/geyser-app/commit/a967c97d22810f477ac2ebda80c337fd6c1d0215)) +* update contribution view to not have lines in between ([60c1edc](https://github.com/geyserfund/geyser-app/commit/60c1edc79f5e92f9f2f40132948f03bf918d2811)) +* update copy to mention look in spam folder ([6fb1c68](https://github.com/geyserfund/geyser-app/commit/6fb1c68c804cce1102cbaafcca1ce58d84ecc668)) +* update description length to 8k ([87f597c](https://github.com/geyserfund/geyser-app/commit/87f597c54d14421c087a1e52694f74b4d4418539)) +* update featured project ([9280202](https://github.com/geyserfund/geyser-app/commit/9280202259e23b4b5730d3a6f8188295716eddf4)) +* update featured project to bitcoindocjennareid ([9fb3c59](https://github.com/geyserfund/geyser-app/commit/9fb3c59cbbbb224043d5cbac99e877304c2e159e)) +* update featured project to bitcoinmatatutours ([ed398f5](https://github.com/geyserfund/geyser-app/commit/ed398f5573c7d97a545c0a0640050cf1bcd2a817)) +* update featured project to maxisclub ([c46c438](https://github.com/geyserfund/geyser-app/commit/c46c438839018211e16e126015ff737771a1cf02)) +* update featured project to miprimerbitcoin ([eb0063b](https://github.com/geyserfund/geyser-app/commit/eb0063b6ce669e6f270d4ad33876bd4cac5cf78a)) +* update featured project to nostrparty ([0ae04de](https://github.com/geyserfund/geyser-app/commit/0ae04dece1055160c9fcf099fed0c501f80db2ce)) +* update featured project to thebatlightningatm ([f1426a8](https://github.com/geyserfund/geyser-app/commit/f1426a8280f5cc76f6e87e7668f6249cd9635c05)) +* update featured project to theprogressivebitcoiner ([1159b8f](https://github.com/geyserfund/geyser-app/commit/1159b8f47db8591eee72ed7a1bc464b1247794d1)) +* update fetch-api to handle failed cases with localstorage and backup ([465b9ad](https://github.com/geyserfund/geyser-app/commit/465b9ad4414e7ffcf339ccf80c93c5ca57c75cba)) +* update geyser grants gaq url ([70b6473](https://github.com/geyserfund/geyser-app/commit/70b647338042e18ff6e828840ea951212a73ab08)) +* update gif and search gif to the latest version ([409cb96](https://github.com/geyserfund/geyser-app/commit/409cb9676164f8d153415aa4285696d04603ec54)) +* update grant application details url ([74a665a](https://github.com/geyserfund/geyser-app/commit/74a665a96d950145b644c072a48d47d653b655ec)) +* update grant apply and grant contribute section to be dynamic to grant title ([e27fd07](https://github.com/geyserfund/geyser-app/commit/e27fd0705aa7563271956d4ee1b05cc20abe863b)) +* update grants copy ([5bedb59](https://github.com/geyserfund/geyser-app/commit/5bedb5956850bf7e75b0043e1bfce06ec00159bd)) +* update grants page and project view ([a8ea147](https://github.com/geyserfund/geyser-app/commit/a8ea147f84665ea87c0427a75bc090334c70ec22)) +* update icon, add update modal and service worker updater ([71d5d5b](https://github.com/geyserfund/geyser-app/commit/71d5d5b6d121f69f3dce6fd699d210f5c9dfa22d)) +* update icons ([b4d02f6](https://github.com/geyserfund/geyser-app/commit/b4d02f66de8caa1ba993acc5177f51501b150389)) +* update icons ([d22d661](https://github.com/geyserfund/geyser-app/commit/d22d6619ffdb78726cf03e116b32d4fcdaf217d3)) +* update icons and other fixes ([9f526ae](https://github.com/geyserfund/geyser-app/commit/9f526ae560ee8346c0ac3bfec432e162d3648512)) +* update icons to better quality ([9eb009c](https://github.com/geyserfund/geyser-app/commit/9eb009ccd5110aaad8772331bfa9d91a4673640a)) +* update image to be more crispy ([ed33ed9](https://github.com/geyserfund/geyser-app/commit/ed33ed9b43d759d34432613150478f61b95af8cb)) +* update landing page tags order ([279843b](https://github.com/geyserfund/geyser-app/commit/279843b357464f28511f90cebd5106ca92b5c953)) +* update landing project pages ([cde8ea1](https://github.com/geyserfund/geyser-app/commit/cde8ea1f6ebc51a160bb8318069f8b6f4bcbb0cf)) +* update language modal ([b2edf38](https://github.com/geyserfund/geyser-app/commit/b2edf3816a208629247fe36262a4156cc87b30a6)) +* update launch project icons ([c34ec36](https://github.com/geyserfund/geyser-app/commit/c34ec36c56e5685d27d1d951b3060f704e4977e1)) +* update launch rocket image ([6171bbf](https://github.com/geyserfund/geyser-app/commit/6171bbf1bec11508d991b18f145172f77a4ce058)) +* update layout for profile pages ([d90c933](https://github.com/geyserfund/geyser-app/commit/d90c933e2639960b76d012b3f25a6a9a56344279)) +* update lighting address to lighting invoice ([d22db34](https://github.com/geyserfund/geyser-app/commit/d22db3454f26b198308ec99a9011a2c4d67466ce)) +* update nostr faq copy ([7b84128](https://github.com/geyserfund/geyser-app/commit/7b8412815a926f71d96002641fa9bb4af075d230)) +* update project header text variants ([75b735e](https://github.com/geyserfund/geyser-app/commit/75b735ef21944cc961fe68db36a9298357418fab)) +* update project header text variants ([5be9706](https://github.com/geyserfund/geyser-app/commit/5be9706126454002cf87c7a8f89e6ef7d9fa05f2)) +* update pwa icons ([537bc40](https://github.com/geyserfund/geyser-app/commit/537bc402b75c63137633378c3ee8c1fe262239bf)) +* update routes to reload and increase pre-cache file limit ro add all files to pre-cache ([cb1cf7d](https://github.com/geyserfund/geyser-app/commit/cb1cf7d886d9f1c34b944268081c7cd36175db88)) +* update runtimecaching config ([3fad5a7](https://github.com/geyserfund/geyser-app/commit/3fad5a711936e0fee11519a624dc1c48fc553d16)) +* update sponsors logos to be compatible with dark mode ([e7c4ae2](https://github.com/geyserfund/geyser-app/commit/e7c4ae288624d54767f4b3c0b3d19c291f9f9866)) +* update text ([9e311bd](https://github.com/geyserfund/geyser-app/commit/9e311bd7adaa816bce53689daf3f98a96b95df02)) +* update the input component ([6650811](https://github.com/geyserfund/geyser-app/commit/6650811b3d2522f1f8adf84c40adabd23be38b74)) +* update to retry on fail ([70b440e](https://github.com/geyserfund/geyser-app/commit/70b440e8e9369c7c7e0d27f1e82d60fa9934feeb)) +* update tooltip copy ([b4d3c10](https://github.com/geyserfund/geyser-app/commit/b4d3c10a6b6bf12637a2d445331895bfb9c5739a)) +* update tweetid extraction and copy updates ([5b5d0c6](https://github.com/geyserfund/geyser-app/commit/5b5d0c64675f799ea2c8f2f7efb510313ce2c82f)) +* update types ([b12b54f](https://github.com/geyserfund/geyser-app/commit/b12b54fc76dfbeca29ce5aa2cd14fd110931d5b3)) +* update UI for app update message ([4b05bcb](https://github.com/geyserfund/geyser-app/commit/4b05bcbca90912a16794ee9327d63ed55bce772d)) +* update validation to counter edge cases ([026926b](https://github.com/geyserfund/geyser-app/commit/026926b900792c21e7e2bf5a70724f56dae99a3b)) +* update version and changelog ([d691350](https://github.com/geyserfund/geyser-app/commit/d6913500a56299dd84cdaee73666abe1fd8a5fa9)) +* update version and changelog ([066e01d](https://github.com/geyserfund/geyser-app/commit/066e01df8b32602eaf4af98fd24e96d0c3f4a62e)) +* updates to PWA for app installabitlity ([e5ee516](https://github.com/geyserfund/geyser-app/commit/e5ee5167da020c9f28a88389e58a964c73719fc7)) +* upgrade apollo client to prevent bug ([#941](https://github.com/geyserfund/geyser-app/issues/941)) ([1079b98](https://github.com/geyserfund/geyser-app/commit/1079b985baf322b68551dc66c870d5b26a3dc273)) +* use a tag instead of js trigger for twitter login ([2dcf1be](https://github.com/geyserfund/geyser-app/commit/2dcf1bea601acc01f5499bd3da13a9f049d7324b)) +* use bitstamp and bitfinex as btcrate sources ([ed19c30](https://github.com/geyserfund/geyser-app/commit/ed19c30eed3d5b38afaf2e5b188952f07cd554cf)) +* use component height instead of static ([43b194b](https://github.com/geyserfund/geyser-app/commit/43b194b3cc9d858c1f441fc4b26a83e2adf6644a)) +* use funding status updated subscription for funding tx update ([84ed7a7](https://github.com/geyserfund/geyser-app/commit/84ed7a7644e42c016627026339c43340aa86942c)) +* use generated hooks and fix activity subscription name duplication ([b09f3b5](https://github.com/geyserfund/geyser-app/commit/b09f3b5b869b6a155b522e5520662db4cb16ec9f)) +* use getalby lnurl method ([2161d76](https://github.com/geyserfund/geyser-app/commit/2161d763b2c8931ed476a8af1cc513ff8f5d2c59)) +* use Login instead of Connect for signin button ([b7c5af4](https://github.com/geyserfund/geyser-app/commit/b7c5af49db3a2e2bda809c4352beacbda09eeb30)) +* use of subscription variables ([a15e3f8](https://github.com/geyserfund/geyser-app/commit/a15e3f8a43abf06155e734d28aa511b704316c09)) +* use retry link to retry requests on stale refresh token ([057da61](https://github.com/geyserfund/geyser-app/commit/057da61f12d2495a9f362327e6c3b0168795eb6e)) +* use row count and column count constants instead of array constant ([74a7cbf](https://github.com/geyserfund/geyser-app/commit/74a7cbfe1742e728173afc154659f39ac47ac19c)) +* use solid toasts for better compatibility with darkmode ([2074340](https://github.com/geyserfund/geyser-app/commit/207434020b2ff33a9d140a5b5b9e9a04bbb489ab)) +* use subscription on contribution list in activity panel ([7944a26](https://github.com/geyserfund/geyser-app/commit/7944a26db5102b1ad0e84adfbb5bcac35804fd1b)) +* use tab for going to the next place instead of indenting ([f722a94](https://github.com/geyserfund/geyser-app/commit/f722a94118bdb3f2fda6ecd4045a33643e3d911b)) +* use the whole balance summary unit as a button ([6b7c122](https://github.com/geyserfund/geyser-app/commit/6b7c122b85ef3885df9031e280efbdfc05f4b0cd)) +* use translation where text is for mobile top bar ([9059974](https://github.com/geyserfund/geyser-app/commit/905997460d81f7e7248abf9847bf441b9265a3ae)) +* use unControlled component for filter search ([48f46a8](https://github.com/geyserfund/geyser-app/commit/48f46a80974f7726ad71651d5f51fcb51ada10f0)) +* validate entry.id before publishing ([5354b8e](https://github.com/geyserfund/geyser-app/commit/5354b8e97c7e5968496f144f54f270bb446bf1ac)) +* view project button, resolves GEY-3015 ([71bf04f](https://github.com/geyserfund/geyser-app/commit/71bf04f8b08305ec18b425b82bf7537ae4fea7b9)) +* wait for 500ms and make another request incase of expired refresh token error ([3636bc8](https://github.com/geyserfund/geyser-app/commit/3636bc850a50b66473b06dc6446f3b35f91a566f)) +* wait for lesser time on staging and increase bottom navbar padding ([204f23d](https://github.com/geyserfund/geyser-app/commit/204f23d28bb5ed4727cf0241aa9996c2acf567f6)) +* we don't load all supporters ([05dc515](https://github.com/geyserfund/geyser-app/commit/05dc51582eb46ec588b683fd8bf3e5e02805d893)) + ## [0.5.0](https://github.com/geyserfund/geyser-app/compare/v0.4.1...v0.5.0) (2023-08-16) diff --git a/README.md b/README.md index d8136ed7e..988cee57c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The app requires some environment variables to be set. We provide an `example.en cp .env.example .env ``` -From there, populate the new file with the correct values. You have two development environment options: +From there, populate the new file with the correct values. You have three development environment options, detailed below. It is recommended to use the staging API for most development tasks. #### Option A: use the staging API @@ -49,16 +49,29 @@ REACT_APP_API_ENDPOINT=https://api.dev.geyser.fund APOLLO_KEY= ``` -[Contact us](email:admin@geyser.fund) if you don't have an `APOLLO_KEY` yet. +[Contact us](email:stelios@geyser.fund) if you don't have an `APOLLO_KEY` yet. + +#### Option C: use both local server and staging API interchangably + +Many at times we prefer using staging API while sometimes we prefer the local server. In such cases we can setup to use them interchangably. + +1. Create the normal `.env` file, which contains the values for local server. This would be used when we command `yarn dev`. +2. Create a new file `.env.staging` this would have the values to use the staging API, and use the command `yarn dev:stage` to use the staging server env values. ### Hosts Configuration +#### Staging API + In order for the requests to go through to the staging backend API, you will need to add the following line to your `/etc/hosts` file: ```shell 127.0.0.1 staging.geyser.fund ``` +This makes sure that you are able to make requests to the staging API from your local development environment with encountering CORS errors. + +#### GraphQL Faker + If running against the GraphQL Faker server, you'll also need these in the same `/etc/hosts` file: ```shell @@ -94,6 +107,18 @@ or docker-compose logs -f geyser-app ``` +### Trusting Caddy Local CA Certificate + +We are using Caddy as a reverse proxy to serve the local development app over HTTPS. This means that you will need to trust the Caddy Local CA Certificate in order to avoid any `ERR_CERT_AUTHORITY_INVALID` errors in your browser. + +To do so, you can run the following command from the project root directory **after starting the app and caddy server**: + +```shell +sudo yarn caddy:trust-ca +``` + +This command will add the Caddy Local CA Certificate to your system's list of trusted certificates (only works on MacOS for now). It needs sudo rights for that. + ### Opening in the Browser With Docker running, navigate to the URL that's appropriate for the development-environment configuration in your `.env` file: diff --git a/caddy/Caddyfile b/caddy/Caddyfile index 437e3bd47..d8ef2104d 100644 --- a/caddy/Caddyfile +++ b/caddy/Caddyfile @@ -13,6 +13,7 @@ api.dev.geyser.fund { reverse_proxy graphql-faker:9002 } +# Local deployment with staging api staging.geyser.fund { tls internal reverse_proxy geyser-app-standalone:3000 diff --git a/docker-compose.yaml b/docker-compose.yaml index 0113bcbe1..05c2217d0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,6 +6,8 @@ services: context: . target: base command: sh -c "RUN_DOCKER=true && yarn install && yarn dev" + depends_on: + - caddy working_dir: /usr/app image: geyser-app env_file: .env diff --git a/index.html b/index.html index a266caab3..d224a7670 100644 --- a/index.html +++ b/index.html @@ -42,6 +42,22 @@ a.appendChild(r); })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); +

diff --git a/package.json b/package.json index ddc9da014..804277271 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,10 @@ { "name": "geyser-app", "private": true, - "version": "0.5.0", + "version": "0.5.1", "scripts": { "dev": "vite", + "dev:stage": "vite --mode staging", "build": "tsc && vite build", "preview": "vite preview --port 3000", "test:e2e": "yarn cypress run --e2e", @@ -17,6 +18,7 @@ "graph:fetch": "run(){ rover graph fetch geyser-graph@$1 > ./schema.graphql; }; run", "graph:generate": "run(){ yarn graph:fetch $1 && graphql-codegen --config codegen.ts && rm schema.graphql && yarn graph:format; }; run", "graph:generate:staging": "yarn graph:generate staging", + "caddy:trust-ca": "bash ./scripts/trust-caddy-cert.sh", "changelog": "yarn conventional-changelog -p conventionalcommits -i CHANGELOG.md -s" }, "dependencies": { @@ -31,6 +33,7 @@ "@hookform/resolvers": "^3.1.0", "@loadable/component": "^5.15.3", "@react-hookz/web": "^23.0.0", + "@remirror/extension-node-formatting": "^2.0.13", "@remirror/pm": "^2.0.5", "@remirror/react": "^2.0.28", "@remirror/react-components": "^2.1.12", @@ -40,6 +43,7 @@ "bech32": "^2.0.0", "buffer": "^6.0.3", "classnames": "^2.3.2", + "dompurify": "^3.0.5", "dotenv": "^16.0.3", "express": "^4.18.2", "framer-motion": "^8.5.2", @@ -96,6 +100,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.4.3", + "@types/dompurify": "^3.0.2", "@types/loadable__component": "^5.13.4", "@types/luxon": "^3.2.0", "@types/node": "^18.11.18", diff --git a/public/icons/120.png b/public/icons/120.png new file mode 100644 index 000000000..b490f0541 Binary files /dev/null and b/public/icons/120.png differ diff --git a/public/icons/128-padded.png b/public/icons/128-padded.png deleted file mode 100644 index 95969ee07..000000000 Binary files a/public/icons/128-padded.png and /dev/null differ diff --git a/public/icons/16.png b/public/icons/16.png deleted file mode 100644 index 079c6735b..000000000 Binary files a/public/icons/16.png and /dev/null differ diff --git a/public/icons/180-padded.png b/public/icons/180-padded.png new file mode 100644 index 000000000..7c87651a5 Binary files /dev/null and b/public/icons/180-padded.png differ diff --git a/public/icons/180.png b/public/icons/180.png deleted file mode 100644 index 41c974b34..000000000 Binary files a/public/icons/180.png and /dev/null differ diff --git a/public/icons/192-maskable.png b/public/icons/192-maskable.png index 75a3fa79a..3d8b72db0 100644 Binary files a/public/icons/192-maskable.png and b/public/icons/192-maskable.png differ diff --git a/public/icons/192.png b/public/icons/192.png index e0b48982b..047c36d1c 100644 Binary files a/public/icons/192.png and b/public/icons/192.png differ diff --git a/public/icons/32.png b/public/icons/32.png deleted file mode 100644 index fd18ac910..000000000 Binary files a/public/icons/32.png and /dev/null differ diff --git a/public/icons/512-maskable.png b/public/icons/512-maskable.png index 0b8152c56..961199389 100644 Binary files a/public/icons/512-maskable.png and b/public/icons/512-maskable.png differ diff --git a/public/icons/512-padded.png b/public/icons/512-padded.png index 87f5a69a7..7edba1ee7 100644 Binary files a/public/icons/512-padded.png and b/public/icons/512-padded.png differ diff --git a/public/icons/60.png b/public/icons/60.png new file mode 100644 index 000000000..2dec1f687 Binary files /dev/null and b/public/icons/60.png differ diff --git a/scripts/trust-caddy-cert.sh b/scripts/trust-caddy-cert.sh new file mode 100755 index 000000000..9bcab6dfb --- /dev/null +++ b/scripts/trust-caddy-cert.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +if security find-certificate -c "Caddy Local Authority" -p >> /dev/null; then + echo 'Caddy Local Authority is trusted.' +else + echo 'Adding Caddy Local Authority to KeyChain.' + mkdir -p ./caddy/certificate/ + CERT_FILE=./caddy/certificate/root.crt + docker exec geyser-caddy-standalone cat /data/caddy/pki/authorities/local/root.crt > $CERT_FILE + security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $CERT_FILE +fi; diff --git a/src/components/molecules/AuthModal.tsx b/src/components/molecules/AuthModal.tsx index 89e64071d..03832fa91 100644 --- a/src/components/molecules/AuthModal.tsx +++ b/src/components/molecules/AuthModal.tsx @@ -16,7 +16,7 @@ import { useAuthContext } from '../../context' import { ConnectWithLightning } from '../../pages/auth/ConnectWithLightning' import { ConnectWithNostr } from '../../pages/auth/ConnectWithNostr' import { ConnectWithTwitter } from '../../pages/auth/ConnectWithTwitter' -import { hasNostrAccount, hasTwitterAccount } from '../../utils' +import { hasNostrAccount, hasTwitterAccount, useMobileMode } from '../../utils' import { Caption } from '../typography' import { ButtonComponent } from '../ui' @@ -67,6 +67,7 @@ const ConnectAccounts = ({ export const AuthModal = (authModalProps: IAuthModal) => { const { t } = useTranslation() + const isMobile = useMobileMode() const { isOpen, onClose, @@ -124,7 +125,7 @@ export const AuthModal = (authModalProps: IAuthModal) => { )} diff --git a/src/components/molecules/DonationInput.tsx b/src/components/molecules/DonationInput.tsx index d25692b39..5fdf6aaed 100644 --- a/src/components/molecules/DonationInput.tsx +++ b/src/components/molecules/DonationInput.tsx @@ -103,6 +103,8 @@ export const DonationInput = ({ const val = Number(value) if (!val) { + setDollar(0) + setSatoshi(0) return } @@ -135,7 +137,6 @@ export const DonationInput = ({ } const fontSize = { base: 'sm', md: 'md', lg: 'sm', xl: 'md' } - return ( @@ -224,8 +225,13 @@ export const DonationInput = ({ > {isSatoshi ? ( <> - - {commaFormatted(dollar) || 0} + + {dollar > 0 + ? `$${commaFormatted(dollar)}` + : satoshi > 0 + ? '< $1' + : '$0'} + ) : ( <> diff --git a/src/components/nav/NavBarLogo.tsx b/src/components/nav/NavBarLogo.tsx index 5b1231e36..6914cd601 100644 --- a/src/components/nav/NavBarLogo.tsx +++ b/src/components/nav/NavBarLogo.tsx @@ -29,13 +29,13 @@ export const NavBarLogo = ({ {useFullOne ? ( ) : ( )} diff --git a/src/components/nav/bottomNav/LandingNavBar.tsx b/src/components/nav/bottomNav/LandingNavBar.tsx index 483fe3183..d23589333 100644 --- a/src/components/nav/bottomNav/LandingNavBar.tsx +++ b/src/components/nav/bottomNav/LandingNavBar.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import { Link, matchPath, matchRoutes, useLocation } from 'react-router-dom' import { getPath } from '../../../constants' +import { BottomNavContainerCommonStyles } from '../../../constants/styles' import { FeedNavIcon, GrantsNavIcon, @@ -79,18 +80,10 @@ export const LandingNavBar = () => { <> {LandingNavItems.map(({ name, path, Icon }) => { const isActive = Boolean(matchPath(path, location.pathname)) diff --git a/src/config/apollo-client/apolloClient.ts b/src/config/apollo-client/apolloClient.ts index e8ce358dc..53916e075 100644 --- a/src/config/apollo-client/apolloClient.ts +++ b/src/config/apollo-client/apolloClient.ts @@ -39,9 +39,60 @@ const httpLink = createHttpLink({ const prefix = __development__ ? 'ws' : 'wss' +let restartRequestedBeforeConnected = false +let gracefullyRestart = () => { + restartRequestedBeforeConnected = true +} + +let activeSocket: WebSocket | null = null +let timedOut = 0 + +const closeSocket = (socket: WebSocket | null) => { + if (socket?.readyState === WebSocket?.OPEN) { + socket?.close(4408, 'Request Timeout') + } +} + const wsLink = new GraphQLWsLink( createClient({ url: `${prefix}://${API_SERVICE_ENDPOINT.split('//')[1]}/graphql`, + retryAttempts: Infinity, + shouldRetry: () => true, + keepAlive: 10000, + on: { + error() { + if (activeSocket) { + closeSocket(activeSocket) + } + }, + connected(socket: any) { + activeSocket = socket // save the active socket for later use + // restart by closing the socket which will trigger a silent reconnect + gracefullyRestart = () => { + closeSocket(socket) + } + + // if any restarts were missed during the connection + // phase, restart and reset the request + if (restartRequestedBeforeConnected) { + restartRequestedBeforeConnected = false + gracefullyRestart() + } + }, + ping(received) { + if (!received) { + // sent + timedOut = setTimeout(() => { + closeSocket(activeSocket) + }, 5000) + } // wait 5 seconds for the pong and then close the connection + }, + pong(received) { + if (received) { + clearTimeout(timedOut) + } // pong is received, clear connection close timeout + }, + }, }), ) diff --git a/src/config/theme/popOverTheme.ts b/src/config/theme/popOverTheme.ts new file mode 100644 index 000000000..384782aa4 --- /dev/null +++ b/src/config/theme/popOverTheme.ts @@ -0,0 +1,14 @@ +import { popoverAnatomy } from '@chakra-ui/anatomy' +import { createMultiStyleConfigHelpers } from '@chakra-ui/react' + +const { definePartsStyle, defineMultiStyleConfig } = + createMultiStyleConfigHelpers(popoverAnatomy.keys) + +const baseStyle = definePartsStyle({ + body: { + bg: 'neutral.0', + borderRadius: '8px', + }, +}) + +export const popOverTheme = defineMultiStyleConfig({ baseStyle }) diff --git a/src/config/theme/theme.ts b/src/config/theme/theme.ts index ea0c72f58..8d105c9f6 100644 --- a/src/config/theme/theme.ts +++ b/src/config/theme/theme.ts @@ -5,6 +5,7 @@ import { alertTheme } from './alertTheme' import { drawerTheme } from './drawerTheme' import { menuTheme } from './menuTheme' import { modalTheme } from './modalTheme' +import { popOverTheme } from './popOverTheme' export const theme = { initialColorMode: 'system', @@ -247,6 +248,7 @@ export const theme = { Menu: menuTheme, Modal: modalTheme, Drawer: drawerTheme, + Popover: popOverTheme, Input: { defaultProps: { focusBorderColor: 'primary.400', diff --git a/src/constants/components/id.ts b/src/constants/components/id.ts index cd9fc495c..ed3be575c 100644 --- a/src/constants/components/id.ts +++ b/src/constants/components/id.ts @@ -22,6 +22,11 @@ export const ID = { contribution: 'project-activity-list-container', leaderboard: 'project-leaderboard-list-container', }, + story: { + markdown: { + container: 'project-story-markdown-container', + }, + }, }, profile: { tabs: 'user-profile-tab-container', diff --git a/src/constants/platform/url.ts b/src/constants/platform/url.ts index 27f2e0568..0d7c0980b 100644 --- a/src/constants/platform/url.ts +++ b/src/constants/platform/url.ts @@ -45,23 +45,38 @@ export const ProjectMediaUrl = export const BotTwitterUrl = 'https://twitter.com/geyserfunders' +// LAUNCH PROJECT URLS + export const LaunchImageUrl = 'https://storage.googleapis.com/geyser-projects-media/app/launch.png' export const LaunchProjectRocketUrl = 'https://storage.googleapis.com/geyser-projects-media/app/create-project-rocket.png' +export const LaunchProjectRocketAIUrl = + 'https://storage.googleapis.com/geyser-projects-media/app/launch/launch-rocket-ai.png' + +export const LaunchProjectCoinsUrl = + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-coins.webp' export const LaunchProjectEntryUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-entry.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-entry.webp' export const LaunchProjectFeesUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-fees.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-fees.webp' export const LaunchProjectGiftUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-gift.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-gift.webp' export const LaunchProjectKeyUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-key.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-key.webp' export const LaunchProjectLightningUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-lightning.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-lightning.webp' +export const LaunchProjectPounchUrl = + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-pouch.webp' +export const LaunchProjectSearchUrl = + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-search.webp' +export const LaunchProjectWalletUrl = + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-wallet.webp' export const LaunchProjectWorldUrl = - 'https://storage.googleapis.com/geyser-projects-media/app/create-project-world.png' + 'https://storage.googleapis.com/geyser-projects-media/app/launch/create-project-world.webp' + +// =============================== export const GeyserLignteningNodeUrl = 'https://amboss.space/node/0272e8731c6feda7fb7e2b8dbe0fbf1322f9e3b60cc2727f4ee4ca0f820b9cd169' @@ -180,7 +195,7 @@ export const LogoNameDark = // Geyser Notion Links export const GrantsFAQUrl = - 'https://geyser.notion.site/About-Geyser-Grants-fad8a130545d4597a3750a17a7ce301f' + 'https://geyser.notion.site/About-Geyser-Grants-925d6b2adc1a4043b70d2835ecfebdde?pvs=4' export const LearnAboutCrowdfundingUrl = 'https://geyser.notion.site/Crowdfunding-Resources-134d19c1214741a7bae5d0bf9b8c8463' export const GeyserProhibitedItemsUrl = diff --git a/src/constants/styles/BottomNav.ts b/src/constants/styles/BottomNav.ts new file mode 100644 index 000000000..b4ca7ab94 --- /dev/null +++ b/src/constants/styles/BottomNav.ts @@ -0,0 +1,11 @@ +export const BottomNavContainerCommonStyles = { + height: '70px', + paddingBottom: '12px', + backgroundColor: 'neutral.50', + width: '100%', + bottom: '0px', + borderTop: '2px solid', + borderTopColor: 'neutral.200', + justifyContent: 'center', + alignItems: 'center', +} diff --git a/src/constants/styles/index.ts b/src/constants/styles/index.ts new file mode 100644 index 000000000..4d0c06a55 --- /dev/null +++ b/src/constants/styles/index.ts @@ -0,0 +1 @@ +export * from './BottomNav' diff --git a/src/forms/components/TableCellMenuComponent.tsx b/src/forms/components/TableCellMenuComponent.tsx new file mode 100644 index 000000000..a7b350324 --- /dev/null +++ b/src/forms/components/TableCellMenuComponent.tsx @@ -0,0 +1,69 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + IconButton, + Menu, + MenuButton, + MenuItem, + MenuItemProps, + MenuList, + VStack, +} from '@chakra-ui/react' +import { useCommands } from '@remirror/react' +import { useTranslation } from 'react-i18next' + +export const TableCellMenuComponent = () => { + const { t } = useTranslation() + const commands = useCommands() + + return ( + + } + border="1px solid" + borderRadius="4px" + borderColor="neutral.200" + _hover={{ color: 'primary.400', borderColor: 'primary.400' }} + /> + + commands.addTableRowBefore()}> + {t('Add row above')} + + commands.addTableRowAfter()}> + {t('Add row below')} + + commands.addTableColumnBefore()}> + {t('Add column left')} + + commands.addTableColumnAfter()}> + {t('Add column right')} + + commands.deleteTableColumn()}> + {t('Remove column')} + + commands.deleteTableRow()}> + {t('Remove row')} + + + + ) +} + +const ModifiedMenuItem = (props: MenuItemProps) => { + return ( + + ) +} diff --git a/src/forms/markdown/MarkdownField.tsx b/src/forms/markdown/MarkdownField.tsx index 7fb638939..1c5460198 100644 --- a/src/forms/markdown/MarkdownField.tsx +++ b/src/forms/markdown/MarkdownField.tsx @@ -1,10 +1,25 @@ +/* eslint-disable react-hooks/rules-of-hooks */ import { Box, Button, HStack, Text } from '@chakra-ui/react' -import { EditorComponent, Remirror, useRemirror } from '@remirror/react' +import { + EditorComponent, + Remirror, + TableComponents, + useCommands, + useKeymap, + useRemirror, +} from '@remirror/react' import { ForwardedRef, useCallback } from 'react' import { Control } from 'react-hook-form' import { useTranslation } from 'react-i18next' import { BsGear } from 'react-icons/bs' -import { InvalidContentHandler } from 'remirror' +import { + AnyExtension, + ExtensionPriority, + findParentNodeOfType, + getCursor, + InvalidContentHandler, + KeyBindingProps, +} from 'remirror' import { BlockquoteExtension, BoldExtension, @@ -17,6 +32,7 @@ import { ItalicExtension, LinkExtension, MarkdownExtension, + NodeFormattingExtension, OrderedListExtension, PlaceholderExtension, TableExtension, @@ -29,10 +45,14 @@ import TurndownService from 'turndown' import { useSignedUpload } from '../../hooks' import { useMobileMode } from '../../utils' import { ReactHookTextArea } from '../components/ReactHookTextArea' -import { PreviewRenderer } from './helpers/PreviewRenderer' -import { SaveModule } from './helpers/SaveModule' -import { StyleProvider } from './helpers/StyleProvider' -import { imageHandler } from './helpers/typeMaps' +import { TableCellMenuComponent } from '../components/TableCellMenuComponent' +import { + FrameHandler, + imageHandler, + PreviewRenderer, + SaveModule, + StyleProvider, +} from './helpers' import { MarkdownToolbar } from './MarkdownToolbar' const turndownService = new TurndownService() @@ -69,7 +89,6 @@ export const MarkdownField = ({ }: Props) => { const { t } = useTranslation() const isMobile = useMobileMode() - const onError: InvalidContentHandler = useCallback( ({ json, invalidContent, transformers }) => { // Automatically remove all invalid nodes and marks. @@ -80,8 +99,8 @@ export const MarkdownField = ({ const { uploadFile } = useSignedUpload() - const extensions = useCallback( - () => [ + const extensions = useCallback<() => AnyExtension[]>(() => { + const exts = [ new PlaceholderExtension({ placeholder }), new LinkExtension({ autoLink: true, @@ -92,7 +111,6 @@ export const MarkdownField = ({ }), new MarkdownExtension({ copyAsMarkdown: true, - htmlToMarkdown: (html) => turndownService.turndown(html), }), new BoldExtension(), new UnderlineExtension(), @@ -101,9 +119,22 @@ export const MarkdownField = ({ new BlockquoteExtension(), new OrderedListExtension(), new CodeExtension(), - new IframeExtension(), + new IframeExtension({ + enableResizing: false, + extraAttributes: { + width: '100%', + scolling: 'no', + style: { + default: JSON.stringify({ width: '100%', height: '400px' }), + parseDOM: (domNode) => domNode.getAttribute('style'), + toDOM: (attrs) => ['style', (attrs.style as string) || ''], + }, + }, + }), new HardBreakExtension(), - new TableExtension(), + new TableExtension({ + resizable: false, + }), new TrailingNodeExtension(), new BulletListExtension(), new TextExtension(), @@ -119,9 +150,14 @@ export const MarkdownField = ({ }, enableResizing: false, }), - ], - [placeholder, uploadFile], - ) + ] as AnyExtension[] + + if (!preview) { + exts.push(new NodeFormattingExtension()) + } + + return exts + }, [placeholder, uploadFile]) const { manager } = useRemirror({ extensions, @@ -130,19 +166,49 @@ export const MarkdownField = ({ react: { nodeViewComponents: { image: imageHandler, - paragraph: ({ forwardRef }: { forwardRef: ForwardedRef }) => ( - - ), bulletList: ({ forwardRef }: { forwardRef: ForwardedRef }) => ( ), orderedList: ({ forwardRef }: { forwardRef: ForwardedRef }) => ( ), + iframe: (props: any) => FrameHandler(props), }, }, }) + const hooks = [ + () => { + const { selectText } = useCommands() + + useKeymap( + 'Tab', + (params: KeyBindingProps) => { + const nodeMatch = findParentNodeOfType({ + types: ['tableCell', 'tableHeaderCell'], + selection: params.tr.selection, + }) + + if (!nodeMatch) { + return false + } + + const position = getCursor(params.state.selection) + + const newPosition = position?.after() + + if (newPosition) { + selectText(newPosition) + return true + } + + return false + }, + ExtensionPriority.Highest, + ) + }, + ] + if (preview) { return ( @@ -160,11 +226,13 @@ export const MarkdownField = ({ autoFocus={autoFocus} manager={manager} initialContent={initialContent?.()} + hooks={hooks} > + diff --git a/src/forms/markdown/MarkdownToolbar.tsx b/src/forms/markdown/MarkdownToolbar.tsx index 6028fc1d2..72694708d 100644 --- a/src/forms/markdown/MarkdownToolbar.tsx +++ b/src/forms/markdown/MarkdownToolbar.tsx @@ -4,6 +4,7 @@ import { ToolbarBlocks } from './toolbar/ToolbarBlocks' import { ToolbarCommon } from './toolbar/ToolbarCommon' import { ToolbarHeading } from './toolbar/ToolbarHeading' import { ToolbarMedia } from './toolbar/ToolbarMedia' +import { ToolbarTable } from './toolbar/ToolbarTable' export const MarkdownToolbar = ({ isDisabled }: { isDisabled?: boolean }) => { return ( @@ -12,6 +13,7 @@ export const MarkdownToolbar = ({ isDisabled }: { isDisabled?: boolean }) => { + ) } diff --git a/src/forms/markdown/commands/ImageCommand.tsx b/src/forms/markdown/commands/ImageCommand.tsx index d179b40ee..0c5e5314e 100644 --- a/src/forms/markdown/commands/ImageCommand.tsx +++ b/src/forms/markdown/commands/ImageCommand.tsx @@ -9,10 +9,15 @@ export const ImageCommand = ({ isDisabled }: { isDisabled?: boolean }) => { const commands = useCommands() const modal = useInsertLinkModal(({ url, label }: MarkdownImage) => { + if (!commands.insertImage) return + commands.insertHardBreak() commands.insertImage({ src: url, alt: label || 'image', }) + + commands.insertHardBreak() + modal.onClose() }) diff --git a/src/forms/markdown/commands/LinkCommand.tsx b/src/forms/markdown/commands/LinkCommand.tsx index 0578ec1fa..e1779a8c8 100644 --- a/src/forms/markdown/commands/LinkCommand.tsx +++ b/src/forms/markdown/commands/LinkCommand.tsx @@ -12,6 +12,7 @@ export const LinkCommand = ({ isDisabled }: { isDisabled?: boolean }) => { const commands = useCommands() const modal = useInsertLinkModal(({ url, label }: MarkdownLink) => { + if (!commands.insertMarkdown) return commands.insertMarkdown(`[${label || url}](${url})`) modal.onClose() }) diff --git a/src/forms/markdown/commands/TableCommand.tsx b/src/forms/markdown/commands/TableCommand.tsx new file mode 100644 index 000000000..b6e6ef03c --- /dev/null +++ b/src/forms/markdown/commands/TableCommand.tsx @@ -0,0 +1,111 @@ +import { + Box, + HStack, + Popover, + PopoverArrow, + PopoverBody, + PopoverContent, + PopoverTrigger, + useDisclosure, + VStack, +} from '@chakra-ui/react' +import { useCommands } from '@remirror/react' +import { useState } from 'react' +import { BsTable } from 'react-icons/bs' + +import { MonoBody2 } from '../../../components/typography' +import { useDebounce } from '../../../hooks' +import { ToolbarCommandButton } from './ToolbarCommandButton' + +interface TableCommandProps { + isDisabled?: boolean +} + +const TABLE_ROW_COUNT = 5 +const TABLE_COLUMN_COUNT = 5 + +const tableBoxes = Array.from({ length: TABLE_ROW_COUNT }, (_, i) => + Array.from({ length: TABLE_COLUMN_COUNT }, (_, j) => `${i + 1}${j + 1}`), +) + +export const TableCommand = ({ isDisabled }: TableCommandProps) => { + const { isOpen, onOpen, onClose } = useDisclosure() + const commands = useCommands() + + const debouncedIsOpen = useDebounce(isOpen, 200) + + const [currentPosition, setCurrentPosition] = useState({ i: 0, j: 0 }) + + const handleTableCreate = ({ i, j }: { i: number; j: number }) => { + if (!commands.createTable) return + commands.createTable({ + rowsCount: i + 1, + columnsCount: j + 1, + }) + onClose() + } + + return ( + <> + + + + + + + + + + + + {tableBoxes.map((row, i) => ( + + {row.map((_, j) => ( + setCurrentPosition({ i, j })} + onClick={() => handleTableCreate({ i, j })} + > + + + ))} + + ))} + + {`${currentPosition.i + 1}X${ + currentPosition.j + 1 + }`} + + + + + + ) +} diff --git a/src/forms/markdown/commands/TweetCommand.tsx b/src/forms/markdown/commands/TweetCommand.tsx new file mode 100644 index 000000000..5c63e3ace --- /dev/null +++ b/src/forms/markdown/commands/TweetCommand.tsx @@ -0,0 +1,99 @@ +import { Box } from '@chakra-ui/react' +import { useCommands } from '@remirror/react' +import { useTranslation } from 'react-i18next' +import { BsTwitter } from 'react-icons/bs' + +import { useDarkMode, useNotification } from '../../../utils' +import { TwitterRegex } from '../../validations/twitter' +import { + InsertTwitterModal, + MarkdownTwitter, + useInsertTwitterModal, +} from '../modals/InsertTwitterModal' +import { ToolbarCommandButton } from './ToolbarCommandButton' + +export const TweetCommand = ({ isDisabled }: { isDisabled?: boolean }) => { + const { t } = useTranslation() + const commands = useCommands() + const isDarkMode = useDarkMode() + const { toast } = useNotification() + + const modal = useInsertTwitterModal(async ({ url }: MarkdownTwitter) => { + commands.insertHardBreak() + + const tweetId = getTweetIdFromUrl(url) + + if (!tweetId) { + toast({ + status: 'error', + title: 'Invalid tweet URL', + description: 'Please try again', + }) + return + } + + try { + const value = await twttr.widgets.createTweet( + tweetId, + document.getElementById('tweet-container'), + { + width: '350px', + theme: isDarkMode ? 'dark' : 'light', + }, + ) + + commands.insertHtml(value.innerHTML, {}) + commands.insertHardBreak() + + const element = document.getElementById('tweet-container') + if (element) { + element.innerHTML = '' + } + } catch { + toast({ + status: 'error', + title: 'Failed to insert tweet', + description: 'Please try again', + }) + } + + modal.onClose() + }) + + return ( + <> + modal.onOpen()} + isDisabled={isDisabled} + > + + + {modal.isOpen ? : null} + + + ) +} + +const getTweetIdFromUrl = (url: string) => { + const match = url.match(TwitterRegex) + + if (match && match.length >= 3) { + const tweetId = match[2] + return tweetId + } + + return '' +} diff --git a/src/forms/markdown/commands/VideoCommand.tsx b/src/forms/markdown/commands/VideoCommand.tsx index b4043ed56..c2ab9d47e 100644 --- a/src/forms/markdown/commands/VideoCommand.tsx +++ b/src/forms/markdown/commands/VideoCommand.tsx @@ -12,7 +12,10 @@ export const VideoCommand = ({ isDisabled }: { isDisabled?: boolean }) => { const commands = useCommands() const modal = useInsertVideoModal(({ url }: MarkdownVideo) => { + if (!commands.addYouTubeVideo) return + commands.insertHardBreak() commands.addYouTubeVideo({ video: url }) + commands.insertHardBreak() modal.onClose() }) diff --git a/src/forms/markdown/commands/useToolbarCommand.ts b/src/forms/markdown/commands/useToolbarCommand.ts index da8bf540b..cb13b0952 100644 --- a/src/forms/markdown/commands/useToolbarCommand.ts +++ b/src/forms/markdown/commands/useToolbarCommand.ts @@ -11,7 +11,7 @@ export const useToolbarCommand = (name: string, cmd: string) => { (attrs?: any) => { if (command) { command(attrs) - commands.focus() + commands.focus?.() } }, [command, commands], diff --git a/src/forms/markdown/helpers/PreviewRenderer.tsx b/src/forms/markdown/helpers/PreviewRenderer.tsx index 7c63c17df..faf689bfd 100644 --- a/src/forms/markdown/helpers/PreviewRenderer.tsx +++ b/src/forms/markdown/helpers/PreviewRenderer.tsx @@ -1,4 +1,5 @@ import { RemirrorRenderer } from '@remirror/react' +import DOMPurify from 'dompurify' import { getRemirrorJSON, RemirrorContentType, RemirrorManager } from 'remirror' import { markMap, typeMap } from './typeMaps' @@ -10,16 +11,31 @@ export const PreviewRenderer = ({ manager: RemirrorManager content?: RemirrorContentType }) => { + const newContent = FormatWhiteSpaceForMarkDownString( + content?.toString() || '', + ) + return ( ) } + +export const matchMarkDownSpecialKeysAtLineEnd = + /(?))\n(?!.*(\*|_|#|-|\[|>|\n\||\||`|[0-9]+(\.|\))))/g + +export const FormatWhiteSpaceForMarkDownString = (value: string): string => { + const adjustForLineChange = value + ? value.replaceAll(matchMarkDownSpecialKeysAtLineEnd, '
') + : '' + + return DOMPurify.sanitize(adjustForLineChange, { ADD_TAGS: ['iframe'] }) +} diff --git a/src/forms/markdown/helpers/SaveModule.tsx b/src/forms/markdown/helpers/SaveModule.tsx index 56832388b..265dea021 100644 --- a/src/forms/markdown/helpers/SaveModule.tsx +++ b/src/forms/markdown/helpers/SaveModule.tsx @@ -2,6 +2,8 @@ import { useDebouncedCallback } from '@react-hookz/web' import { useHelpers, useRemirrorContext } from '@remirror/react' import { Control, useController, useFormContext } from 'react-hook-form' +import { htmlToMarkdown } from './htmlToMarkdown' + export function SaveModule(props: { control?: Control; name?: string }) { const { field: { onChange }, @@ -11,11 +13,14 @@ export function SaveModule(props: { control?: Control; name?: string }) { }) const { trigger } = useFormContext() - const { getMarkdown } = useHelpers() + const { getHTML } = useHelpers() const changeCallback = useDebouncedCallback( - (ctx) => { - onChange(getMarkdown(ctx.state)) + async (ctx) => { + const html = getHTML(ctx.state) + const newHTML = html.replaceAll('

', '
') + const newMarkdown = htmlToMarkdown(newHTML) + onChange(newMarkdown) trigger(props.name ?? 'content') }, [], diff --git a/src/forms/markdown/helpers/StyleProvider.tsx b/src/forms/markdown/helpers/StyleProvider.tsx index e65cbea7d..843e3768a 100644 --- a/src/forms/markdown/helpers/StyleProvider.tsx +++ b/src/forms/markdown/helpers/StyleProvider.tsx @@ -1,19 +1,33 @@ import { Box, BoxProps, styled } from '@chakra-ui/react' import { ThemeProvider } from '@remirror/react-components' import { AllStyledComponent } from '@remirror/styles/emotion' -import { useMemo } from 'react' +import { captureException } from '@sentry/react' +import { useEffect, useMemo } from 'react' import { RemirrorThemeType } from 'remirror' +import { ID } from '../../../constants' import { useCustomTheme } from '../../../utils' +import { tableCellStyles } from './typeMaps' const Container = styled(Box, { baseStyle: { '& p, & iframe, & h1, & h2, & h3, & h4, & h5': { mt: 4, }, + '& table': { + '& p': { + margin: '0px', + }, + ...tableCellStyles, + }, '& iframe': { minHeight: '28em', }, + '& div.remirror-iframe-custom': { + width: '100% !important', + height: 'auto !important', + marginBottom: '20px', + }, '& a': { textDecoration: 'underline', }, @@ -50,8 +64,19 @@ export const StyleProvider = ({ [colors], ) + useEffect(() => { + twttr.widgets + .load(document.getElementById(ID.project.story.markdown.container)) + .catch((e: any) => + captureException(e, { + tags: { area: 'twitter-widgets' }, + }), + ) + }, []) + return ( n.nodeName === 'TH') && + childNodes.some((n) => Boolean(n.textContent)) + ) +} + +/** + * Controller cells are generated by the React Tables extension, and provide Node Views for adding/removing columns and rows + * + * However they should not be included in markdown output. + */ +function isControllerHeadingCell(cell: unknown): cell is HTMLTableCellElement { + return isElementDomNode(cell) && cell.matches('th[data-controller-cell]') +} + +/** + * A tableRow is a controller heading row if: + * - the parent is a THEAD + * - or if its the first child of the TABLE or the first TBODY (possibly + * following a blank THEAD) + * - and every cell is a controller cell + */ +function isControllerHeadingRow( + tableRow: Node, +): tableRow is HTMLTableRowElement { + const { parentNode } = tableRow + + if (!isElementDomNode(parentNode)) { + return false + } + + if (parentNode.nodeName !== 'TABLE' && !isFirstTbody(parentNode)) { + return false + } + + const childNodes = [...tableRow.childNodes] + return childNodes.every((n) => isControllerHeadingCell(n)) +} + +/** + * Check whether this is the first `tbody` in the table. + */ +function isFirstTbody(element: Node): element is HTMLTableSectionElement { + if (element.nodeName !== 'TBODY') { + return false + } + + const { previousSibling } = element + + if (!previousSibling) { + return true + } + + return ( + isElementDomNode(previousSibling) && + previousSibling.nodeName === 'THEAD' && + !previousSibling.textContent?.trim() + ) +} + +/** + * Markdown does not support nested tables, check if current table has a table ancestor node + */ +function isNestedTable(element: HTMLElement): boolean { + const currentTable = element.closest('table') + + if (!currentTable) { + return false + } + + const { parentNode } = currentTable + + if (!parentNode) { + return true + } + + return Boolean((parentNode as HTMLElement).closest('table')) +} + +/** + * Create a cell from the table. + */ +function cell(content: string, node: Node) { + const childNodes = [] + + for (const n of node.parentNode?.childNodes ?? []) { + if (isControllerHeadingCell(n)) { + continue + } + + childNodes.push(n) + } + + const index = childNodes.indexOf(node as ChildNode) + const prefix = index === 0 ? '| ' : ' ' + + return `${prefix + content.trim()} |` +} + +/** + * Create the turndown service which will be used to convert html to markdown. + * + * This supports html by default. + */ +const turndownService = new TurndownService({ + codeBlockStyle: 'fenced', + headingStyle: 'atx', +}) + .keep(['iframe']) + .addRule('taskListItems', { + filter: (node) => + node.nodeName === 'LI' && node.hasAttribute('data-task-list-item'), + replacement(content, node) { + const isChecked = (node as HTMLElement).hasAttribute('data-checked') + return `- ${isChecked ? '[x]' : '[ ]'} ${content.trimStart()}` + }, + }) + .addRule('tableCell', { + filter: ['th', 'td'], + replacement(content, node) { + if (isControllerHeadingCell(node)) { + return '' + } + + return cell(content, node as ChildNode) + }, + }) + .addRule('tableRow', { + filter: 'tr', + replacement(content, node) { + let borderCells = '' + const alignMap = { left: ':--', right: '--:', center: ':-:' } + + // Get child nodes ignoring controller cells + const childNodes = [...node.childNodes].filter( + (n) => !isControllerHeadingCell(n), + ) + + if (isHeadingRow(node)) { + for (const childNode of childNodes) { + if (!isElementDomNode(childNode)) { + // This should never happen. + continue + } + + let border = '---' + const align = ( + childNode.getAttribute('align') ?? '' + ).toLowerCase() as keyof typeof alignMap + + if (align) { + border = alignMap[align] || border + } + + borderCells += cell(border, childNode) + } + } + + return `\n${content}${borderCells ? `\n${borderCells}` : ''}` + }, + }) + .addRule('table', { + // Only convert tables with a heading row. Tables with no heading row are kept + // using `keep` (see below). + filter(node) { + if (node.nodeName !== 'TABLE') { + return false + } + + if (isNestedTable(node)) { + return false + } + + const rows = [...(node as HTMLTableElement).rows].filter( + (r) => + // Remove controller rows + !isControllerHeadingRow(r), + ) + if (rows[0]) return isHeadingRow(rows[0]) + return false + }, + + replacement(content) { + // Ensure there are no blank lines + content = content.replace('\n\n', '\n') + return `\n\n${content}\n\n` + }, + }) + .addRule('tableSection', { + filter: ['thead', 'tbody', 'tfoot'], + replacement(content) { + return content + }, + }) + .keep( + (node) => + node.nodeName === 'TABLE' && + !isHeadingRow((node as HTMLTableElement).rows[0] as any), + ) + .keep((node) => node.nodeName === 'TABLE' && isNestedTable(node)) + .addRule('strikethrough', { + filter: ['del', 's', 'strike' as 'del'], + replacement(content) { + return `~${content}~` + }, + }) + + // Add improved code block support from html. + .addRule('fencedCodeBlock', { + filter: (node, options) => + Boolean( + options.codeBlockStyle === 'fenced' && + node.nodeName === 'PRE' && + node.firstChild && + node.firstChild.nodeName === 'CODE', + ), + + replacement(_, node, options) { + invariant(isElementDomNode(node.firstChild), { + code: ErrorConstant.EXTENSION, + message: `Invalid node \`${node.firstChild?.nodeName}\` encountered for codeblock when converting html to markdown.`, + }) + + const className = node.firstChild.getAttribute('class') ?? '' + const language = + className.match(/(?:lang|language)-(\S+)/)?.[1] ?? + node.firstChild.getAttribute('data-code-block-language') ?? + '' + + return `\n\n${options.fence}${language}\n${node.firstChild.textContent}\n${options.fence}\n\n` + }, + }) diff --git a/src/forms/markdown/helpers/index.ts b/src/forms/markdown/helpers/index.ts new file mode 100644 index 000000000..1b42a768f --- /dev/null +++ b/src/forms/markdown/helpers/index.ts @@ -0,0 +1,5 @@ +export * from './htmlToMarkdown' +export * from './PreviewRenderer' +export * from './SaveModule' +export * from './StyleProvider' +export * from './typeMaps' diff --git a/src/forms/markdown/helpers/typeMaps.tsx b/src/forms/markdown/helpers/typeMaps.tsx index cc6d199a6..99d4d7e41 100644 --- a/src/forms/markdown/helpers/typeMaps.tsx +++ b/src/forms/markdown/helpers/typeMaps.tsx @@ -1,15 +1,22 @@ import { + Box, Divider, + HStack, Image, ListItem, ListProps, OrderedList, + Table, + Tbody, + Td, + Th, + Thead, + Tr, UnorderedList, } from '@chakra-ui/react' import { Callout, CodeBlock, - createIFrameHandler, createLinkHandler, Doc, Heading, @@ -34,6 +41,100 @@ export const listItemHandler = ({ children }: ListProps) => { return {children} } +export const tableCellStyles = { + '& th, & td': { + padding: '3px 8px', + border: '1px solid', + borderColor: 'neutral.200', + height: '30px', + }, +} + +export const tableHandler = (props: any) => { + const hasHeader = + props?.children[0]?.props?.json?.content[0]?.type === 'tableHeaderCell' + + return ( + + {hasHeader && {props.children[0]}} + + { + + {props.children.map((child: any, index: number) => { + if (hasHeader && index === 0) { + return null + } + + return child + })} + + } +
+ ) +} + +export const FrameHandler = (props: any) => { + const colorMode = localStorage.getItem('chakra-ui-color-mode') + + const newSrc = `${props.node.attrs.src}`.replace( + /theme=dark|theme=light/, + `theme=${colorMode || 'light'}`, + ) + + const splitValues = + `${props.node.attrs.style}` + .replaceAll(/"|\{|\}/g, '') + .replaceAll(',', ';') + .split(';') || [] + + const newStyle = {} as { [key: string]: string | number } + + splitValues.map((acc: any) => { + const [key, value] = acc.split(':') + if (key && value) { + newStyle[key.trim()] = value.trim() + } + }) + + const isTwitter = newSrc.toLowerCase().includes('twitter') + + return ( + + +