this repo has no description
0
fork

Configure Feed

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

Private notes

+243 -4
+1
src/app.css
··· 1438 1438 display: inline-block; 1439 1439 margin: 4px; 1440 1440 align-self: center; 1441 + text-align: center; 1441 1442 1442 1443 &.clickable { 1443 1444 cursor: pointer;
+99 -1
src/components/account-info.css
··· 165 165 animation: fade-in 0.3s both ease-in-out 0.2s; 166 166 } 167 167 168 + .private-note-tag { 169 + z-index: 1; 170 + appearance: none; 171 + display: inline-block; 172 + color: var(--private-note-text-color); 173 + background-color: var(--private-note-bg-color); 174 + border: 1px solid var(--private-note-border-color); 175 + padding: 4px; 176 + line-height: normal; 177 + font-size: smaller; 178 + border-radius: 0; 179 + align-self: center !important; 180 + /* clip a dog ear on top right */ 181 + clip-path: polygon(0 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 0 100%); 182 + /* 4x4px square on top right */ 183 + background-size: 4px 4px; 184 + background-repeat: no-repeat; 185 + background-position: top right; 186 + background-image: linear-gradient( 187 + to bottom, 188 + var(--private-note-border-color), 189 + var(--private-note-border-color) 190 + ); 191 + transition: transform 0.15s ease-in-out; 192 + 193 + span { 194 + color: inherit; 195 + opacity: 0.75; 196 + text-overflow: ellipsis; 197 + overflow: hidden; 198 + display: -webkit-box; 199 + display: box; 200 + -webkit-box-orient: vertical; 201 + box-orient: vertical; 202 + -webkit-line-clamp: 2; 203 + line-clamp: 2; 204 + text-align: left; 205 + } 206 + 207 + &:hover:not(:active) { 208 + filter: none !important; 209 + transform: rotate(-0.5deg) scale(1.05); 210 + 211 + span { 212 + opacity: 1; 213 + } 214 + } 215 + } 216 + .account-container .private-note { 217 + font-size: 90%; 218 + color: var(--text-insignificant-color); 219 + text-overflow: ellipsis; 220 + overflow: hidden; 221 + white-space: nowrap; 222 + padding: 12px; 223 + background-color: var(--bg-faded-color); 224 + display: flex; 225 + gap: 0.5em; 226 + align-items: center; 227 + 228 + b { 229 + font-size: 90%; 230 + text-transform: uppercase; 231 + } 232 + p { 233 + margin: 0; 234 + padding: 0; 235 + } 236 + } 237 + 168 238 .account-container .note { 169 239 font-size: 95%; 170 240 line-height: 1.4; ··· 228 298 align-items: center; 229 299 } 230 300 .account-container .actions button { 231 - align-self: flex-end; 301 + /* align-self: flex-end; */ 232 302 } 233 303 .account-container .actions .buttons { 234 304 display: flex; 305 + align-items: center; 235 306 } 236 307 237 308 .account-container .account-metadata-box { ··· 571 642 drop-shadow(8px 0 8px var(--header-color-4, --bg-color)); 572 643 } 573 644 } 645 + 646 + #private-note-container { 647 + textarea { 648 + margin-top: 8px; 649 + width: 100%; 650 + resize: vertical; 651 + height: 33vh; 652 + min-height: 25vh; 653 + max-height: 50vh; 654 + color: var(--private-note-text-color); 655 + background-color: var(--private-note-bg-color); 656 + border: 1px solid var(--private-note-border-color); 657 + box-shadow: 0 2px 8px var(--drop-shadow-color); 658 + border-radius: 0; 659 + padding: 16px; 660 + } 661 + 662 + footer { 663 + display: flex; 664 + justify-content: space-between; 665 + padding: 8px 0; 666 + 667 + * { 668 + vertical-align: middle; 669 + } 670 + } 671 + }
+139 -3
src/components/account-info.jsx
··· 772 772 requested, 773 773 domainBlocking, 774 774 endorsed, 775 + note: privateNote, 775 776 } = relationship || {}; 776 777 777 778 const [currentInfo, setCurrentInfo] = useState(null); ··· 853 854 854 855 const [showTranslatedBio, setShowTranslatedBio] = useState(false); 855 856 const [showAddRemoveLists, setShowAddRemoveLists] = useState(false); 857 + const [showPrivateNoteModal, setShowPrivateNoteModal] = useState(false); 856 858 857 859 return ( 858 860 <> ··· 863 865 ) : !!lastStatusAt ? ( 864 866 <small class="insignificant"> 865 867 Last post:{' '} 866 - {niceDateTime(lastStatusAt, { 867 - hideTime: true, 868 - })} 868 + <span class="ib"> 869 + {niceDateTime(lastStatusAt, { 870 + hideTime: true, 871 + })} 872 + </span> 869 873 </small> 870 874 ) : ( 871 875 <span /> ··· 874 878 {blocking && <span class="tag danger">Blocked</span>} 875 879 </span>{' '} 876 880 <span class="buttons"> 881 + {!!privateNote && ( 882 + <button 883 + type="button" 884 + class="private-note-tag" 885 + title="Private note" 886 + onClick={() => { 887 + setShowPrivateNoteModal(true); 888 + }} 889 + dir="auto" 890 + > 891 + <span>{privateNote}</span> 892 + </button> 893 + )} 877 894 <Menu 878 895 instanceRef={menuInstanceRef} 879 896 portal={{ ··· 926 943 > 927 944 <Icon icon="translate" /> 928 945 <span>Translate bio</span> 946 + </MenuItem> 947 + <MenuItem 948 + onClick={() => { 949 + setShowPrivateNoteModal(true); 950 + }} 951 + > 952 + <Icon icon="pencil" /> 953 + <span> 954 + {privateNote ? 'Edit private note' : 'Add private note'} 955 + </span> 929 956 </MenuItem> 930 957 {/* Add/remove from lists is only possible if following the account */} 931 958 {following && ( ··· 1237 1264 /> 1238 1265 </Modal> 1239 1266 )} 1267 + {!!showPrivateNoteModal && ( 1268 + <Modal 1269 + class="light" 1270 + onClose={() => { 1271 + setShowPrivateNoteModal(false); 1272 + }} 1273 + > 1274 + <PrivateNoteSheet 1275 + account={info} 1276 + note={privateNote} 1277 + onRelationshipChange={(relationship) => { 1278 + setRelationship(relationship); 1279 + // onRelationshipChange({ relationship, currentID: accountID.current }); 1280 + }} 1281 + onClose={() => setShowPrivateNoteModal(false)} 1282 + /> 1283 + </Modal> 1284 + )} 1240 1285 </> 1241 1286 ); 1242 1287 } ··· 1430 1475 /> 1431 1476 </Modal> 1432 1477 )} 1478 + </div> 1479 + ); 1480 + } 1481 + 1482 + function PrivateNoteSheet({ 1483 + account, 1484 + note: initialNote, 1485 + onRelationshipChange = () => {}, 1486 + onClose = () => {}, 1487 + }) { 1488 + const { masto } = api(); 1489 + const [uiState, setUIState] = useState('default'); 1490 + const textareaRef = useRef(null); 1491 + 1492 + useEffect(() => { 1493 + let timer; 1494 + if (textareaRef.current && !initialNote) { 1495 + timer = setTimeout(() => { 1496 + textareaRef.current.focus?.(); 1497 + }, 100); 1498 + } 1499 + return () => { 1500 + clearTimeout(timer); 1501 + }; 1502 + }, []); 1503 + 1504 + return ( 1505 + <div class="sheet" id="private-note-container"> 1506 + {!!onClose && ( 1507 + <button type="button" class="sheet-close" onClick={onClose}> 1508 + <Icon icon="x" /> 1509 + </button> 1510 + )} 1511 + <header> 1512 + <b>Private note for @{account?.acct}</b> 1513 + </header> 1514 + <main> 1515 + <form 1516 + onSubmit={(e) => { 1517 + e.preventDefault(); 1518 + const formData = new FormData(e.target); 1519 + const note = formData.get('note'); 1520 + if (note?.trim() !== initialNote?.trim()) { 1521 + setUIState('loading'); 1522 + (async () => { 1523 + try { 1524 + const newRelationship = await masto.v1.accounts 1525 + .$select(account?.id) 1526 + .note.create({ 1527 + comment: note, 1528 + }); 1529 + console.log('updated relationship', newRelationship); 1530 + setUIState('default'); 1531 + onRelationshipChange(newRelationship); 1532 + onClose(); 1533 + } catch (e) { 1534 + console.error(e); 1535 + setUIState('error'); 1536 + alert(e?.message || 'Unable to update private note.'); 1537 + } 1538 + })(); 1539 + } 1540 + }} 1541 + > 1542 + <textarea 1543 + ref={textareaRef} 1544 + name="note" 1545 + disabled={uiState === 'loading'} 1546 + > 1547 + {initialNote} 1548 + </textarea> 1549 + <footer> 1550 + <button 1551 + type="button" 1552 + class="light" 1553 + disabled={uiState === 'loading'} 1554 + onClick={() => { 1555 + onClose?.(); 1556 + }} 1557 + > 1558 + Cancel 1559 + </button> 1560 + <span> 1561 + <Loader abrupt hidden={uiState !== 'loading'} /> 1562 + <button disabled={uiState === 'loading'} type="submit"> 1563 + Save &amp; close 1564 + </button> 1565 + </span> 1566 + </footer> 1567 + </form> 1568 + </main> 1433 1569 </div> 1434 1570 ); 1435 1571 }
+4
src/index.css
··· 62 62 --close-button-bg-active-color: rgba(0, 0, 0, 0.2); 63 63 --close-button-color: rgba(0, 0, 0, 0.5); 64 64 --close-button-hover-color: rgba(0, 0, 0, 1); 65 + --private-note-text-color: var(--text-color); 66 + --private-note-bg-color: color-mix(in srgb, yellow 20%, var(--bg-color)); 67 + --private-note-border-color: rgba(0, 0, 0, 0.2); 65 68 66 69 /* Video colors won't change based on color scheme */ 67 70 --media-fg-color: #f0f2f5; ··· 111 114 --close-button-bg-active-color: rgba(255, 255, 255, 0.15); 112 115 --close-button-color: rgba(255, 255, 255, 0.5); 113 116 --close-button-hover-color: rgba(255, 255, 255, 1); 117 + --private-note-border-color: rgba(255, 255, 255, 0.2); 114 118 } 115 119 } 116 120