a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Feature/watermark (#93)

* added the watermark

* add watermark to mobile view as well

* added a checkbox to theme setter

* icon based watermark

* made it work for mobile

* changed color of checked box in theme settings

* removed an underline in link on hover

* wire up toggle for leaflet watermark

---------

Co-authored-by: celine <celine@hyperlink.academy>

authored by

Jared Pereira
celine
and committed by
GitHub
f1b266cd 3bf2228f

+150 -12
+15 -6
actions/createNewLeaflet.ts
··· 57 57 // And add it to that permission set 58 58 .values({ set: entity_set.id, id: v7() }) 59 59 .returning(); 60 - await tx.insert(facts).values({ 61 - id: v7(), 62 - entity: root_entity.id, 63 - attribute: "root/page", 64 - data: sql`${{ type: "ordered-reference", value: first_page.id, position: "a0" }}`, 65 - }); 60 + await tx.insert(facts).values([ 61 + { 62 + id: v7(), 63 + entity: root_entity.id, 64 + attribute: "root/page", 65 + data: sql`${{ type: "ordered-reference", value: first_page.id, position: "a0" }}`, 66 + }, 67 + //Set theme/page-leaflet-watermark to true by default for new leaflets 68 + { 69 + id: v7(), 70 + entity: root_entity.id, 71 + attribute: "theme/page-leaflet-watermark", 72 + data: sql`${{ type: "boolean", value: true }}`, 73 + }, 74 + ]); 66 75 67 76 if (pageType === "canvas") { 68 77 await tx.insert(facts).values([
+57
components/Icons.tsx
··· 390 390 ); 391 391 }; 392 392 393 + export const LogoSmall = ( 394 + props: Props & { fillColor?: string; strokeColor: string }, 395 + ) => { 396 + return ( 397 + <svg 398 + width="24" 399 + height="24" 400 + viewBox="0 0 24 24" 401 + fill="none" 402 + xmlns="http://www.w3.org/2000/svg" 403 + {...props} 404 + > 405 + <path 406 + fillRule="evenodd" 407 + clipRule="evenodd" 408 + d="M2.32215 16.4108C1.57824 17.6533 0.898485 19.0047 0.309311 20.4716C-0.150671 21.6168 0.404821 22.9181 1.55002 23.378C2.69523 23.838 3.99649 23.2825 4.45647 22.1373C4.57293 21.8474 4.68516 21.5618 4.79357 21.2859L4.79458 21.2833C5.20745 20.2328 5.56352 19.3338 5.99429 18.5241C6.47944 18.4978 7.03415 18.4938 7.65963 18.4902L7.73825 18.4898C8.87897 18.4835 10.2533 18.476 11.4384 18.2361C12.6242 17.9961 14.0917 17.4287 14.7404 15.909C14.916 15.4976 15.0941 14.8903 14.9382 14.2734C14.985 14.2734 15.0329 14.2734 15.0821 14.2734C15.1084 14.2734 15.1353 14.2734 15.1626 14.2734C15.7884 14.2738 16.6691 14.2744 17.4563 14.0603C18.3749 13.8104 19.3408 13.2187 19.7646 11.9723C19.9177 11.5219 19.946 11.0489 19.8139 10.6019C19.8544 10.5948 19.8959 10.5875 19.9385 10.58C19.959 10.5764 19.9798 10.5728 20.0009 10.5691C20.5388 10.4751 21.2588 10.3493 21.8739 10.1191C22.4722 9.89531 23.4554 9.39523 23.75 8.24915C23.9179 7.5959 23.9003 6.90435 23.5231 6.2798C23.3663 6.02011 23.1667 5.81564 22.9897 5.66485C23.1546 5.45852 23.3642 5.17147 23.5087 4.85478C23.7592 4.30533 23.8884 3.49804 23.3759 2.70818C22.7942 1.81172 21.7967 1.65512 21.3033 1.61454C20.7902 1.57235 20.2386 1.61742 19.8422 1.65324C19.7884 1.52139 19.7143 1.38273 19.6118 1.24589C19.0616 0.511039 18.208 0.449277 17.7276 0.462196C16.757 0.488299 15.9979 0.918975 15.4491 1.36566C15.1611 1.6001 14.9015 1.86418 14.6773 2.11348C14.2327 1.65325 13.6218 1.42654 13.0163 1.33322C11.8407 1.15205 10.8811 1.94149 10.2041 2.8079C9.36031 3.8879 8.79706 5.14254 8.05202 6.28553C7.78598 6.11247 7.37758 5.92468 6.87391 5.94808C6.04405 5.98662 5.45234 6.54928 5.09562 6.93422C4.47486 7.60409 4.09699 8.64071 3.82812 9.54678C3.53705 10.5277 3.28551 11.6885 3.04921 12.838C2.90284 13.5499 2.87051 13.8888 3.01223 15.1868C2.57773 15.8871 2.66239 15.7879 2.32215 16.4108Z" 409 + fill={props.strokeColor} 410 + /> 411 + <path 412 + fillRule="evenodd" 413 + clipRule="evenodd" 414 + d="M7.40173 7.68265C7.64462 7.89605 7.92928 8.14615 8.54339 7.93249C8.94492 7.79279 9.46383 6.88268 10.0428 5.86718C10.8892 4.38281 11.8639 2.67329 12.788 2.81571C13.9026 2.9875 13.834 3.60458 13.7812 4.0792C13.7442 4.41212 13.715 4.67494 14.1074 4.66485C14.5071 4.65457 14.896 4.18484 15.3474 3.63974C15.971 2.88678 16.7136 1.99 17.768 1.96164C18.5115 1.94165 18.4998 2.26202 18.4879 2.58691C18.4803 2.79457 18.4726 3.00408 18.662 3.12774C18.8486 3.24955 19.3179 3.20699 19.8573 3.15805C20.7221 3.0796 21.7673 2.98479 22.1177 3.52468C22.4257 3.99932 22.0333 4.47107 21.6572 4.92323C21.3386 5.30622 21.0317 5.67516 21.172 6.0199C21.2865 6.30118 21.5215 6.45965 21.7518 6.61499C22.1286 6.86906 22.4929 7.11477 22.2973 7.87571C22.0905 8.68031 20.8462 8.89822 19.6799 9.10247C18.7028 9.27359 17.7804 9.43512 17.5686 9.92398C17.4357 10.2306 17.6561 10.3734 17.9031 10.5333C18.1982 10.7245 18.5312 10.9402 18.3445 11.4894C17.908 12.7733 16.4503 12.7733 15.0822 12.7734C13.9079 12.7734 12.7997 12.7734 12.4599 13.5853C12.2637 14.0541 12.5606 14.1368 12.8864 14.2276C13.2852 14.3388 13.7272 14.462 13.3609 15.3201C12.66 16.9622 10.0451 16.9768 7.6513 16.9903C6.77358 16.9952 5.92559 16.9999 5.21259 17.0847C5.1312 17.0944 5.05901 17.1411 5.01636 17.2111C4.36027 18.2876 3.89495 19.4717 3.3986 20.7347C3.28956 21.0122 3.17903 21.2935 3.06464 21.5782C2.91343 21.9547 2.48566 22.1373 2.10919 21.9861C1.73272 21.8349 1.55011 21.4071 1.70132 21.0307C2.26451 19.6285 2.91425 18.3391 3.6247 17.1555C4.78415 15.0203 7.06972 12.4007 9.48667 10.4328C11.6372 8.64231 13.6909 7.30217 16.081 6.28526C16.3802 6.15796 16.2914 5.80807 15.9791 5.89834C13.8592 6.51095 11.9852 7.72607 10.0428 8.95064C7.93016 10.2825 6.15972 12.0837 5.07026 13.3932C4.87817 13.6241 4.45809 13.4342 4.51857 13.14C4.99173 10.8384 5.48007 8.72627 6.19593 7.95378C6.87557 7.22037 7.10812 7.42469 7.40173 7.68265Z" 415 + fill={props.fillColor ? props.fillColor : "currentColor"} 416 + /> 417 + </svg> 418 + ); 419 + }; 420 + 393 421 export const PaintSmall = (props: Props) => { 394 422 return ( 395 423 <svg ··· 581 609 viewBox="0 0 12 12" 582 610 fill="none" 583 611 xmlns="http://www.w3.org/2000/svg" 612 + {...props} 584 613 > 585 614 <path 586 615 fillRule="evenodd" ··· 626 655 clipRule="evenodd" 627 656 d="M13.8372 4.31196C14.3059 3.84333 14.3059 3.08353 13.8372 2.6149C13.3686 2.14627 12.6088 2.14627 12.1402 2.6149L8.18872 6.56637L4.23725 2.6149C3.76862 2.14627 3.00882 2.14627 2.54019 2.6149C2.07156 3.08353 2.07156 3.84333 2.54019 4.31196L6.49166 8.26343L2.54019 12.2149C2.07156 12.6835 2.07156 13.4433 2.54019 13.912C3.00882 14.3806 3.76862 14.3806 4.23725 13.912L8.18872 9.96048L12.1402 13.912C12.6088 14.3806 13.3686 14.3806 13.8372 13.912C14.3059 13.4433 14.3059 12.6835 13.8372 12.2149L9.88578 8.26343L13.8372 4.31196Z" 628 657 fill="currentColor" 658 + /> 659 + </svg> 660 + ); 661 + }; 662 + 663 + export const LogoTiny = ( 664 + props: Props & { fillColor: string; strokeColor: string }, 665 + ) => { 666 + return ( 667 + <svg 668 + width="16" 669 + height="16" 670 + viewBox="0 0 16 16" 671 + fill="none" 672 + xmlns="http://www.w3.org/2000/svg" 673 + {...props} 674 + > 675 + <path 676 + fillRule="evenodd" 677 + clipRule="evenodd" 678 + d="M1.54814 10.9405C1.0522 11.7689 0.599031 12.6698 0.206248 13.6477C-0.100407 14.4112 0.269922 15.2787 1.03339 15.5854C1.79686 15.892 2.66437 15.5217 2.97102 14.7582C3.04866 14.5649 3.12348 14.3745 3.19575 14.1906L3.19643 14.1889C3.47167 13.4885 3.70905 12.8892 3.99623 12.3494C4.31967 12.3319 4.68947 12.3292 5.10646 12.3268L5.15887 12.3265C5.91935 12.3224 6.83557 12.3173 7.62565 12.1574C8.41619 11.9974 9.39452 11.6191 9.82699 10.606C9.94405 10.3317 10.0628 9.92687 9.95882 9.51563C9.99002 9.51559 10.022 9.51558 10.0548 9.51558C10.0723 9.51558 10.0902 9.5156 10.1085 9.51561C10.5257 9.51589 11.1128 9.51628 11.6376 9.37351C12.25 9.20692 12.8939 8.81245 13.1764 7.9815C13.2785 7.68126 13.2974 7.36594 13.2093 7.06794C13.2363 7.06317 13.264 7.05831 13.2924 7.05333C13.3061 7.05094 13.3199 7.04852 13.334 7.04606C13.6926 6.98339 14.1726 6.8995 14.5826 6.74609C14.9815 6.59687 15.637 6.26348 15.8334 5.49943C15.9453 5.06394 15.9336 4.6029 15.6821 4.18653C15.5775 4.01341 15.4445 3.87709 15.3265 3.77657C15.4364 3.63901 15.5762 3.44765 15.6725 3.23652C15.8395 2.87022 15.9257 2.33203 15.584 1.80545C15.1962 1.20781 14.5312 1.10341 14.2022 1.07636C13.8601 1.04823 13.4924 1.07828 13.2282 1.10216C13.1923 1.01426 13.1429 0.921818 13.0746 0.83059C12.7078 0.340692 12.1387 0.299518 11.8185 0.308131C11.1714 0.325533 10.6653 0.61265 10.2994 0.910443C10.1074 1.06673 9.93438 1.24279 9.78489 1.40899C9.48851 1.10217 9.08126 0.951024 8.6776 0.888814C7.89387 0.768032 7.25409 1.29433 6.8028 1.87193C6.24025 2.59193 5.86475 3.42836 5.36805 4.19036C5.19069 4.07498 4.91843 3.94979 4.58264 3.96538C4.02941 3.99108 3.63493 4.36619 3.39712 4.62281C2.98328 5.06939 2.73137 5.76047 2.55212 6.36452C2.35807 7.01847 2.19038 7.79233 2.03285 8.55864C1.93527 9.03328 1.91371 9.25921 2.00819 10.1245C1.71853 10.5914 1.77497 10.5253 1.54814 10.9405Z" 679 + fill={props.strokeColor} 680 + /> 681 + <path 682 + fillRule="evenodd" 683 + clipRule="evenodd" 684 + d="M4.93445 5.12177C5.09637 5.26404 5.28615 5.43077 5.69555 5.28833C5.96324 5.1952 6.30918 4.58845 6.69518 3.91146C7.2594 2.92188 7.90919 1.7822 8.52526 1.87714C9.26838 1.99167 9.22264 2.40306 9.18745 2.71947C9.16277 2.94142 9.14329 3.11663 9.40488 3.1099C9.67134 3.10305 9.93066 2.7899 10.2316 2.4265C10.6473 1.92453 11.1423 1.32667 11.8453 1.30777C12.341 1.29444 12.3331 1.50802 12.3252 1.72461C12.3201 1.86305 12.315 2.00273 12.4413 2.08516C12.5657 2.16637 12.8785 2.138 13.2382 2.10537C13.8147 2.05307 14.5115 1.98986 14.7451 2.34979C14.9504 2.66622 14.6888 2.98072 14.4381 3.28216C14.2257 3.53748 14.0211 3.78344 14.1146 4.01327C14.191 4.20079 14.3476 4.30644 14.5012 4.41C14.7523 4.57938 14.9952 4.74318 14.8648 5.25048C14.727 5.78688 13.8974 5.93215 13.1199 6.06832C12.4685 6.1824 11.8536 6.29008 11.7123 6.61599C11.6238 6.8204 11.7707 6.91558 11.9353 7.02222C12.1321 7.14967 12.3541 7.29348 12.2296 7.65961C11.9386 8.51555 10.9668 8.51557 10.0547 8.51558C9.2719 8.51559 8.53306 8.51561 8.30654 9.05688C8.17575 9.3694 8.37369 9.42457 8.59088 9.4851C8.85674 9.5592 9.15143 9.64133 8.90725 10.2134C8.43997 11.3081 6.69669 11.3179 5.10083 11.3268C4.51568 11.3301 3.95036 11.3333 3.47502 11.3898C3.42076 11.3962 3.37264 11.4274 3.3442 11.474C2.90681 12.1917 2.59659 12.9811 2.2657 13.8231C2.193 14.0081 2.11931 14.1956 2.04305 14.3855C1.94225 14.6365 1.65707 14.7582 1.40608 14.6574C1.1551 14.5566 1.03336 14.2714 1.13417 14.0204C1.50964 13.0857 1.94279 12.2261 2.41642 11.437C3.18939 10.0135 4.71311 8.26715 6.3244 6.95517C7.75809 5.76154 9.12719 4.86812 10.7207 4.19018C10.9201 4.10531 10.8609 3.87205 10.6527 3.93223C9.23943 4.34064 7.99012 5.15072 6.69518 5.9671C5.28673 6.85503 4.10644 8.05578 3.38013 8.92879C3.25207 9.08272 2.97202 8.95614 3.01234 8.76C3.32778 7.22563 3.65334 5.81751 4.13058 5.30252C4.58367 4.81359 4.73871 4.9498 4.93445 5.12177Z" 685 + fill={props.fillColor} 629 686 /> 630 687 </svg> 631 688 );
+3 -2
components/MobileFooter.tsx
··· 8 8 import { useEntitySetContext } from "./EntitySetProvider"; 9 9 import { HelpPopover } from "./HelpPopover"; 10 10 import { CreateNewLeafletButton } from "app/home/CreateNewButton"; 11 + import { Watermark } from "./Watermark"; 11 12 12 13 export function MobileFooter(props: { entityID: string }) { 13 14 let focusedBlock = useUIState((s) => s.focusedEntity); ··· 40 41 </div> 41 42 </div> 42 43 ) : ( 43 - <div className="pb-2 px-2 z-10"> 44 - <HomeButton /> 44 + <div className="pb-2 px-2 z-10 place-self-end"> 45 + <Watermark mobile /> 45 46 </div> 46 47 )} 47 48 </Media>
+5 -2
components/Pages/index.tsx
··· 1 1 "use client"; 2 + 2 3 import { useEffect, useState } from "react"; 3 4 import { useUIState } from "src/useUIState"; 4 5 import { useEntitySetContext } from "../EntitySetProvider"; ··· 32 33 import { PageThemeSetter } from "../ThemeManager/PageThemeSetter"; 33 34 import { CardThemeProvider } from "../ThemeManager/ThemeProvider"; 34 35 import { PageShareMenu } from "./PageShareMenu"; 36 + import { Watermark } from "components/Watermark"; 35 37 36 38 export function Pages(props: { rootPage: string }) { 37 39 let rootPage = useEntity(props.rootPage, "root/page")[0]; ··· 57 59 }} 58 60 > 59 61 <Media mobile={false} className="h-full"> 60 - <div className="flex flex-col h-full justify-between mr-4 mt-1"> 62 + <div className="flex flex-col h-full justify-between mt-1"> 61 63 {entity_set.permissions.write ? ( 62 - <div className="flex flex-col justify-center gap-2 "> 64 + <div className="flex flex-col justify-center gap-2 mr-4"> 63 65 <ShareOptions rootEntity={props.rootPage} /> 64 66 <LeafletOptions entityID={props.rootPage} /> 65 67 <CreateNewLeafletButton /> ··· 73 75 <HomeButton />{" "} 74 76 </div> 75 77 )} 78 + <Watermark /> 76 79 </div> 77 80 </Media> 78 81 </div>
+37 -2
components/ThemeManager/ThemeSetter.tsx
··· 19 19 import { useEffect, useMemo, useState } from "react"; 20 20 import { 21 21 BlockImageSmall, 22 + CheckboxChecked, 23 + CheckboxEmpty, 22 24 CloseContrastSmall, 23 25 PaintSmall, 24 26 PopoverArrow, ··· 170 172 ? "cover" 171 173 : `calc(${leafletBGRepeat.data.value}px / 2 )`, 172 174 }} 173 - className={`bg-bg-leaflet mx-2 p-3 mb-3 flex flex-col rounded-md border border-border ${props.home ? "" : "pb-0"}`} 175 + className={`bg-bg-leaflet mx-2 p-3 mb-2 flex flex-col rounded-md border border-border ${props.home ? "" : "pb-0"}`} 174 176 > 175 177 <div className={`flex flex-col z-10 mt-4 -mb-[6px] `}> 176 178 <div ··· 284 286 </> 285 287 )} 286 288 </div> 289 + <WatermarkSetter entityID={props.entityID} /> 287 290 </div> 288 291 <Popover.Arrow asChild width={16} height={8} viewBox="0 0 16 8"> 289 292 <PopoverArrow ··· 297 300 </> 298 301 ); 299 302 }; 300 - 303 + function WatermarkSetter(props: { entityID: string }) { 304 + let { rep } = useReplicache(); 305 + let checked = useEntity(props.entityID, "theme/page-leaflet-watermark"); 306 + return ( 307 + <label className="px-3 pb-3 flex gap-2 items-start cursor-pointer"> 308 + <input 309 + type="checkbox" 310 + checked={!!checked?.data.value} 311 + className="hidden" 312 + onChange={(e) => { 313 + rep?.mutate.assertFact({ 314 + entity: props.entityID, 315 + attribute: "theme/page-leaflet-watermark", 316 + data: { type: "boolean", value: e.currentTarget.checked }, 317 + }); 318 + }} 319 + /> 320 + {!checked?.data.value ? ( 321 + <CheckboxEmpty className="shrink-0 mt-1 text-[#595959]" /> 322 + ) : ( 323 + <CheckboxChecked className="shrink-0 mt-1 text-[#595959]" /> 324 + )} 325 + <div className="flex flex-col gap-0"> 326 + <div className="text-sm font-bold text-[#595959]"> 327 + Show Leaflet Watermark 328 + </div> 329 + <div className="text-sm text-[#969696]"> 330 + If you like using Leaflet, consider helping us spread the word! 331 + </div> 332 + </div> 333 + </label> 334 + ); 335 + } 301 336 let thumbStyle = 302 337 "w-4 h-4 rounded-full border-2 border-white shadow-[0_0_0_1px_#8C8C8C,_inset_0_0_0_1px_#8C8C8C]"; 303 338
+29
components/Watermark.tsx
··· 1 + import Link from "next/link"; 2 + import { LogoSmall, LogoTiny } from "./Icons"; 3 + import { theme } from "tailwind.config"; 4 + import { useEntity, useReplicache } from "src/replicache"; 5 + 6 + export const Watermark = (props: { mobile?: boolean }) => { 7 + let { rootEntity } = useReplicache(); 8 + let showWatermark = useEntity(rootEntity, "theme/page-leaflet-watermark"); 9 + if (!showWatermark?.data.value) return null; 10 + return ( 11 + <Link href="/" className="hover:no-underline"> 12 + <div className="sm:mb-2 sm:mr-4 group/watermark flex sm:flex-col gap-2 items-center justify-center "> 13 + <div 14 + className="hidden group-hover/watermark:block sm:rotate-180 sm:py-1 sm:px-0 px-1 w-max rounded-md h-fit whitespace-nowrap text-sm text-tertiary" 15 + style={{ 16 + writingMode: !props.mobile ? "vertical-lr" : "horizontal-tb", 17 + backgroundColor: "rgba(var(--bg-page), 0.6)", 18 + }} 19 + > 20 + made using <span className="text-accent-1">Leaflet</span> 21 + </div> 22 + <LogoSmall 23 + strokeColor={theme.colors["bg-page"]} 24 + className="text-tertiary group-hover/watermark:text-accent-1" 25 + /> 26 + </div> 27 + </Link> 28 + ); 29 + };
+4
src/replicache/attributes.ts
··· 112 112 } as const; 113 113 114 114 export const ThemeAttributes = { 115 + "theme/page-leaflet-watermark": { 116 + type: "boolean", 117 + cardinality: "one", 118 + }, 115 119 "theme/page-background": { 116 120 type: "color", 117 121 cardinality: "one",