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 (
+
+ )
+}
+
+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 (
+