this repo has no description
0
fork

Configure Feed

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

Merge pull request #266 from cheeaun/main

Update from main

authored by

Chee Aun and committed by
GitHub
bf6ee572 7b049385

+259 -32
+12 -1
.github/workflows/prodtag.yml
··· 1 - name: Auto-create tag on every push to `production` 1 + name: Auto-create tag/release on every push to `production` 2 2 3 3 on: 4 4 push: ··· 8 8 jobs: 9 9 tag: 10 10 runs-on: ubuntu-latest 11 + permissions: 12 + contents: write 11 13 steps: 12 14 - uses: actions/checkout@v4 13 15 with: 14 16 ref: production 15 17 - run: git tag "`date +%Y.%m.%d`.`git rev-parse --short HEAD`" $(git rev-parse HEAD) 16 18 - run: git push --tags 19 + - uses: actions/setup-node@v3 20 + with: 21 + node-version: 18 22 + - run: npm ci && npm run build 23 + - run: cd dist && zip -r ../phanpy-dist.zip . && cd .. 24 + - uses: softprops/action-gh-release@v1 25 + with: 26 + generate_release_notes: true 27 + files: phanpy-dist.zip
-26
.github/workflows/tagrelease.yml
··· 1 - name: Create Release on every tag push in `production` 2 - 3 - on: 4 - push: 5 - tags: 6 - - '*' 7 - workflow_dispatch: 8 - 9 - jobs: 10 - release: 11 - runs-on: ubuntu-latest 12 - permissions: 13 - contents: write 14 - steps: 15 - - uses: actions/checkout@v4 16 - with: 17 - ref: production 18 - - uses: actions/setup-node@v3 19 - with: 20 - node-version: 18 21 - - run: npm ci && npm run build 22 - - run: cd dist && zip -r ../phanpy-dist.zip . && cd .. 23 - - uses: softprops/action-gh-release@v1 24 - with: 25 - generate_release_notes: true 26 - files: phanpy-dist.zip
+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;
+100 -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 + overflow-wrap: anywhere; 193 + 194 + span { 195 + color: inherit; 196 + opacity: 0.75; 197 + text-overflow: ellipsis; 198 + overflow: hidden; 199 + display: -webkit-box; 200 + display: box; 201 + -webkit-box-orient: vertical; 202 + box-orient: vertical; 203 + -webkit-line-clamp: 2; 204 + line-clamp: 2; 205 + text-align: left; 206 + } 207 + 208 + &:hover:not(:active) { 209 + filter: none !important; 210 + transform: rotate(-0.5deg) scale(1.05); 211 + 212 + span { 213 + opacity: 1; 214 + } 215 + } 216 + } 217 + .account-container .private-note { 218 + font-size: 90%; 219 + color: var(--text-insignificant-color); 220 + text-overflow: ellipsis; 221 + overflow: hidden; 222 + white-space: nowrap; 223 + padding: 12px; 224 + background-color: var(--bg-faded-color); 225 + display: flex; 226 + gap: 0.5em; 227 + align-items: center; 228 + 229 + b { 230 + font-size: 90%; 231 + text-transform: uppercase; 232 + } 233 + p { 234 + margin: 0; 235 + padding: 0; 236 + } 237 + } 238 + 168 239 .account-container .note { 169 240 font-size: 95%; 170 241 line-height: 1.4; ··· 228 299 align-items: center; 229 300 } 230 301 .account-container .actions button { 231 - align-self: flex-end; 302 + /* align-self: flex-end; */ 232 303 } 233 304 .account-container .actions .buttons { 234 305 display: flex; 306 + align-items: center; 235 307 } 236 308 237 309 .account-container .account-metadata-box { ··· 571 643 drop-shadow(8px 0 8px var(--header-color-4, --bg-color)); 572 644 } 573 645 } 646 + 647 + #private-note-container { 648 + textarea { 649 + margin-top: 8px; 650 + width: 100%; 651 + resize: vertical; 652 + height: 33vh; 653 + min-height: 25vh; 654 + max-height: 50vh; 655 + color: var(--private-note-text-color); 656 + background-color: var(--private-note-bg-color); 657 + border: 1px solid var(--private-note-border-color); 658 + box-shadow: 0 2px 8px var(--drop-shadow-color); 659 + border-radius: 0; 660 + padding: 16px; 661 + } 662 + 663 + footer { 664 + display: flex; 665 + justify-content: space-between; 666 + padding: 8px 0; 667 + 668 + * { 669 + vertical-align: middle; 670 + } 671 + } 672 + }
+142 -4
src/components/account-info.jsx
··· 643 643 > 644 644 <div> 645 645 {postingStats.daysSinceLastPost < 365 646 - ? `Last ${postingStats.total} posts in the past 646 + ? `Last ${postingStats.total} post${ 647 + postingStats.total > 1 ? 's' : '' 648 + } in the past 647 649 ${postingStats.daysSinceLastPost} day${ 648 650 postingStats.daysSinceLastPost > 1 ? 's' : '' 649 651 }` ··· 770 772 requested, 771 773 domainBlocking, 772 774 endorsed, 775 + note: privateNote, 773 776 } = relationship || {}; 774 777 775 778 const [currentInfo, setCurrentInfo] = useState(null); ··· 851 854 852 855 const [showTranslatedBio, setShowTranslatedBio] = useState(false); 853 856 const [showAddRemoveLists, setShowAddRemoveLists] = useState(false); 857 + const [showPrivateNoteModal, setShowPrivateNoteModal] = useState(false); 854 858 855 859 return ( 856 860 <> ··· 861 865 ) : !!lastStatusAt ? ( 862 866 <small class="insignificant"> 863 867 Last post:{' '} 864 - {niceDateTime(lastStatusAt, { 865 - hideTime: true, 866 - })} 868 + <span class="ib"> 869 + {niceDateTime(lastStatusAt, { 870 + hideTime: true, 871 + })} 872 + </span> 867 873 </small> 868 874 ) : ( 869 875 <span /> ··· 872 878 {blocking && <span class="tag danger">Blocked</span>} 873 879 </span>{' '} 874 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 + )} 875 894 <Menu 876 895 instanceRef={menuInstanceRef} 877 896 portal={{ ··· 924 943 > 925 944 <Icon icon="translate" /> 926 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> 927 956 </MenuItem> 928 957 {/* Add/remove from lists is only possible if following the account */} 929 958 {following && ( ··· 1235 1264 /> 1236 1265 </Modal> 1237 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 + )} 1238 1285 </> 1239 1286 ); 1240 1287 } ··· 1428 1475 /> 1429 1476 </Modal> 1430 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> 1431 1569 </div> 1432 1570 ); 1433 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