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;
margin: 4px;
align-self: center;
text-align: center;
&.clickable {
cursor: pointer;

View file

@ -165,6 +165,76 @@
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 {
font-size: 95%;
line-height: 1.4;
@ -228,10 +298,11 @@
align-items: center;
}
.account-container .actions button {
align-self: flex-end;
/* align-self: flex-end; */
}
.account-container .actions .buttons {
display: flex;
align-items: center;
}
.account-container .account-metadata-box {
@ -571,3 +642,30 @@
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,
domainBlocking,
endorsed,
note: privateNote,
} = relationship || {};
const [currentInfo, setCurrentInfo] = useState(null);
@ -853,6 +854,7 @@ function RelatedActions({
const [showTranslatedBio, setShowTranslatedBio] = useState(false);
const [showAddRemoveLists, setShowAddRemoveLists] = useState(false);
const [showPrivateNoteModal, setShowPrivateNoteModal] = useState(false);
return (
<>
@ -863,9 +865,11 @@ function RelatedActions({
) : !!lastStatusAt ? (
<small class="insignificant">
Last post:{' '}
<span class="ib">
{niceDateTime(lastStatusAt, {
hideTime: true,
})}
</span>
</small>
) : (
<span />
@ -874,6 +878,19 @@ function RelatedActions({
{blocking && <span class="tag danger">Blocked</span>}
</span>{' '}
<span class="buttons">
{!!privateNote && (
<button
type="button"
class="private-note-tag"
title="Private note"
onClick={() => {
setShowPrivateNoteModal(true);
}}
dir="auto"
>
<span>{privateNote}</span>
</button>
)}
<Menu
instanceRef={menuInstanceRef}
portal={{
@ -927,6 +944,16 @@ function RelatedActions({
<Icon icon="translate" />
<span>Translate bio</span>
</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 */}
{following && (
<MenuItem
@ -1237,6 +1264,24 @@ function RelatedActions({
/>
</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;

View file

@ -62,6 +62,9 @@
--close-button-bg-active-color: rgba(0, 0, 0, 0.2);
--close-button-color: rgba(0, 0, 0, 0.5);
--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 */
--media-fg-color: #f0f2f5;
@ -111,6 +114,7 @@
--close-button-bg-active-color: rgba(255, 255, 255, 0.15);
--close-button-color: rgba(255, 255, 255, 0.5);
--close-button-hover-color: rgba(255, 255, 255, 1);
--private-note-border-color: rgba(255, 255, 255, 0.2);
}
}