Private notes

This commit is contained in:
Lim Chee Aun 2023-10-17 20:20:26 +08:00
parent 1b0a77dfae
commit 8ae9131543
4 changed files with 243 additions and 4 deletions

View file

@ -1438,6 +1438,7 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
display: inline-block; display: inline-block;
margin: 4px; margin: 4px;
align-self: center; align-self: center;
text-align: center;
&.clickable { &.clickable {
cursor: pointer; cursor: pointer;

View file

@ -165,6 +165,76 @@
animation: fade-in 0.3s both ease-in-out 0.2s; animation: fade-in 0.3s both ease-in-out 0.2s;
} }
.private-note-tag {
z-index: 1;
appearance: none;
display: inline-block;
color: var(--private-note-text-color);
background-color: var(--private-note-bg-color);
border: 1px solid var(--private-note-border-color);
padding: 4px;
line-height: normal;
font-size: smaller;
border-radius: 0;
align-self: center !important;
/* clip a dog ear on top right */
clip-path: polygon(0 0, calc(100% - 4px) 0, 100% 4px, 100% 100%, 0 100%);
/* 4x4px square on top right */
background-size: 4px 4px;
background-repeat: no-repeat;
background-position: top right;
background-image: linear-gradient(
to bottom,
var(--private-note-border-color),
var(--private-note-border-color)
);
transition: transform 0.15s ease-in-out;
span {
color: inherit;
opacity: 0.75;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
display: box;
-webkit-box-orient: vertical;
box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
text-align: left;
}
&:hover:not(:active) {
filter: none !important;
transform: rotate(-0.5deg) scale(1.05);
span {
opacity: 1;
}
}
}
.account-container .private-note {
font-size: 90%;
color: var(--text-insignificant-color);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding: 12px;
background-color: var(--bg-faded-color);
display: flex;
gap: 0.5em;
align-items: center;
b {
font-size: 90%;
text-transform: uppercase;
}
p {
margin: 0;
padding: 0;
}
}
.account-container .note { .account-container .note {
font-size: 95%; font-size: 95%;
line-height: 1.4; line-height: 1.4;
@ -228,10 +298,11 @@
align-items: center; align-items: center;
} }
.account-container .actions button { .account-container .actions button {
align-self: flex-end; /* align-self: flex-end; */
} }
.account-container .actions .buttons { .account-container .actions .buttons {
display: flex; display: flex;
align-items: center;
} }
.account-container .account-metadata-box { .account-container .account-metadata-box {
@ -571,3 +642,30 @@
drop-shadow(8px 0 8px var(--header-color-4, --bg-color)); drop-shadow(8px 0 8px var(--header-color-4, --bg-color));
} }
} }
#private-note-container {
textarea {
margin-top: 8px;
width: 100%;
resize: vertical;
height: 33vh;
min-height: 25vh;
max-height: 50vh;
color: var(--private-note-text-color);
background-color: var(--private-note-bg-color);
border: 1px solid var(--private-note-border-color);
box-shadow: 0 2px 8px var(--drop-shadow-color);
border-radius: 0;
padding: 16px;
}
footer {
display: flex;
justify-content: space-between;
padding: 8px 0;
* {
vertical-align: middle;
}
}
}

View file

@ -772,6 +772,7 @@ function RelatedActions({
requested, requested,
domainBlocking, domainBlocking,
endorsed, endorsed,
note: privateNote,
} = relationship || {}; } = relationship || {};
const [currentInfo, setCurrentInfo] = useState(null); const [currentInfo, setCurrentInfo] = useState(null);
@ -853,6 +854,7 @@ function RelatedActions({
const [showTranslatedBio, setShowTranslatedBio] = useState(false); const [showTranslatedBio, setShowTranslatedBio] = useState(false);
const [showAddRemoveLists, setShowAddRemoveLists] = useState(false); const [showAddRemoveLists, setShowAddRemoveLists] = useState(false);
const [showPrivateNoteModal, setShowPrivateNoteModal] = useState(false);
return ( return (
<> <>
@ -863,9 +865,11 @@ function RelatedActions({
) : !!lastStatusAt ? ( ) : !!lastStatusAt ? (
<small class="insignificant"> <small class="insignificant">
Last post:{' '} Last post:{' '}
<span class="ib">
{niceDateTime(lastStatusAt, { {niceDateTime(lastStatusAt, {
hideTime: true, hideTime: true,
})} })}
</span>
</small> </small>
) : ( ) : (
<span /> <span />
@ -874,6 +878,19 @@ function RelatedActions({
{blocking && <span class="tag danger">Blocked</span>} {blocking && <span class="tag danger">Blocked</span>}
</span>{' '} </span>{' '}
<span class="buttons"> <span class="buttons">
{!!privateNote && (
<button
type="button"
class="private-note-tag"
title="Private note"
onClick={() => {
setShowPrivateNoteModal(true);
}}
dir="auto"
>
<span>{privateNote}</span>
</button>
)}
<Menu <Menu
instanceRef={menuInstanceRef} instanceRef={menuInstanceRef}
portal={{ portal={{
@ -927,6 +944,16 @@ function RelatedActions({
<Icon icon="translate" /> <Icon icon="translate" />
<span>Translate bio</span> <span>Translate bio</span>
</MenuItem> </MenuItem>
<MenuItem
onClick={() => {
setShowPrivateNoteModal(true);
}}
>
<Icon icon="pencil" />
<span>
{privateNote ? 'Edit private note' : 'Add private note'}
</span>
</MenuItem>
{/* Add/remove from lists is only possible if following the account */} {/* Add/remove from lists is only possible if following the account */}
{following && ( {following && (
<MenuItem <MenuItem
@ -1237,6 +1264,24 @@ function RelatedActions({
/> />
</Modal> </Modal>
)} )}
{!!showPrivateNoteModal && (
<Modal
class="light"
onClose={() => {
setShowPrivateNoteModal(false);
}}
>
<PrivateNoteSheet
account={info}
note={privateNote}
onRelationshipChange={(relationship) => {
setRelationship(relationship);
// onRelationshipChange({ relationship, currentID: accountID.current });
}}
onClose={() => setShowPrivateNoteModal(false)}
/>
</Modal>
)}
</> </>
); );
} }
@ -1434,4 +1479,95 @@ function AddRemoveListsSheet({ accountID, onClose }) {
); );
} }
function PrivateNoteSheet({
account,
note: initialNote,
onRelationshipChange = () => {},
onClose = () => {},
}) {
const { masto } = api();
const [uiState, setUIState] = useState('default');
const textareaRef = useRef(null);
useEffect(() => {
let timer;
if (textareaRef.current && !initialNote) {
timer = setTimeout(() => {
textareaRef.current.focus?.();
}, 100);
}
return () => {
clearTimeout(timer);
};
}, []);
return (
<div class="sheet" id="private-note-container">
{!!onClose && (
<button type="button" class="sheet-close" onClick={onClose}>
<Icon icon="x" />
</button>
)}
<header>
<b>Private note for @{account?.acct}</b>
</header>
<main>
<form
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.target);
const note = formData.get('note');
if (note?.trim() !== initialNote?.trim()) {
setUIState('loading');
(async () => {
try {
const newRelationship = await masto.v1.accounts
.$select(account?.id)
.note.create({
comment: note,
});
console.log('updated relationship', newRelationship);
setUIState('default');
onRelationshipChange(newRelationship);
onClose();
} catch (e) {
console.error(e);
setUIState('error');
alert(e?.message || 'Unable to update private note.');
}
})();
}
}}
>
<textarea
ref={textareaRef}
name="note"
disabled={uiState === 'loading'}
>
{initialNote}
</textarea>
<footer>
<button
type="button"
class="light"
disabled={uiState === 'loading'}
onClick={() => {
onClose?.();
}}
>
Cancel
</button>
<span>
<Loader abrupt hidden={uiState !== 'loading'} />
<button disabled={uiState === 'loading'} type="submit">
Save &amp; close
</button>
</span>
</footer>
</form>
</main>
</div>
);
}
export default AccountInfo; export default AccountInfo;

View file

@ -62,6 +62,9 @@
--close-button-bg-active-color: rgba(0, 0, 0, 0.2); --close-button-bg-active-color: rgba(0, 0, 0, 0.2);
--close-button-color: rgba(0, 0, 0, 0.5); --close-button-color: rgba(0, 0, 0, 0.5);
--close-button-hover-color: rgba(0, 0, 0, 1); --close-button-hover-color: rgba(0, 0, 0, 1);
--private-note-text-color: var(--text-color);
--private-note-bg-color: color-mix(in srgb, yellow 20%, var(--bg-color));
--private-note-border-color: rgba(0, 0, 0, 0.2);
/* Video colors won't change based on color scheme */ /* Video colors won't change based on color scheme */
--media-fg-color: #f0f2f5; --media-fg-color: #f0f2f5;
@ -111,6 +114,7 @@
--close-button-bg-active-color: rgba(255, 255, 255, 0.15); --close-button-bg-active-color: rgba(255, 255, 255, 0.15);
--close-button-color: rgba(255, 255, 255, 0.5); --close-button-color: rgba(255, 255, 255, 0.5);
--close-button-hover-color: rgba(255, 255, 255, 1); --close-button-hover-color: rgba(255, 255, 255, 1);
--private-note-border-color: rgba(255, 255, 255, 0.2);
} }
} }