Skip to content
This repository has been archived by the owner on Sep 6, 2024. It is now read-only.

Commit

Permalink
add profile note feature
Browse files Browse the repository at this point in the history
  • Loading branch information
sir.kokabi committed Jun 28, 2024
1 parent af07db7 commit 4492974
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 2 deletions.
100 changes: 100 additions & 0 deletions src/contents/ProfileNote.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import cssText from "data-text:~contents/styles.css";
import type { PlasmoCSConfig, PlasmoGetInlineAnchor } from "plasmo";
import React, { useState, useEffect, useCallback } from "react";
import * as utils from "~utils";

export const config: PlasmoCSConfig = {
matches: ["https://twitter.com/*", "https://x.com/*"]
};

export const getInlineAnchor: PlasmoGetInlineAnchor = () =>
document.querySelector(`div[data-testid='UserName'] > div > div`);

export const getStyle = () => {
const style = document.createElement("style");
style.textContent = cssText;
return style;
};

const ProfileNote = () => {
const [note, setNote] = useState("");
const [originalNote, setOriginalNote] = useState("");
const [isPersian, setIsPersian] = useState(false);
const [showToast, setShowToast] = useState(false);
const [remainingLength, setRemainingLength] = useState(120);
const username = window.location.toString().split('/').pop();

useEffect(() => {
utils.getProfileNote(username).then((value) => {
if (value !== undefined) {
setNote(value);
setOriginalNote(value);
setIsPersian(utils.isPersian(value));
setRemainingLength(120 - value.length);
}
});
}, [username]);

const saveNote = useCallback(async () => {
if (note.trim() === '') await utils.deleteProfileNote(username);
else {
utils.saveProfileNote(username, note)
}
setShowToast(true);
setOriginalNote(note);
setTimeout(() => {
setShowToast(false);
}, 800);

}, [note, username]);

const handleChange = (e) => {
const newNote = e.target.value;
setNote(newNote);
setIsPersian(utils.isPersian(newNote));
setRemainingLength(120 - newNote.length);
};

const handleKeyDown = (e) => {
if (e.key === "Enter") {
e.preventDefault();
saveNote();
}
};

const isNoteChanged = note !== originalNote;

return (
<div className="relative w-full">
<textarea
className="w-full shadow-[0px_2px_3px_-1px_rgba(0,0,0,0.1),0px_1px_0px_0px_rgba(25,28,33,0.02),0px_0px_0px_1px_rgba(25,28,33,0.08)] p-3 rounded-md mt-2"
style={{ direction: isPersian ? "rtl" : "ltr", border: "none" }}
value={note}
maxLength={120}
onChange={handleChange}
onKeyDown={handleKeyDown}
placeholder="Add a short note"
/>
{isNoteChanged && (
<>
<button
className={`mt-2 px-4 py-1 bg-[#299cee] text-white rounded ${isPersian ? 'mr-auto' : 'ml-auto'} block`}
onClick={saveNote}
>
Save
</button>
<div className={`absolute bottom-2 ${isPersian ? 'right-2' : 'left-2'} text-xs px-2 py-1`}>
{remainingLength}
</div>
</>
)}
{showToast && (
<div className={`absolute bottom-2 ${isPersian ? 'left-2' : 'right-2'} text-xs px-2 py-1`}>
Saved
</div>
)}
</div>
);
};

export default ProfileNote;
45 changes: 45 additions & 0 deletions src/contents/ProfileNoteAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import cssText from "data-text:~contents/styles.css";
import type { PlasmoCSConfig, PlasmoGetInlineAnchorList } from "plasmo";
import React, { useState, useEffect, useCallback } from "react";
import * as utils from "~utils";

export const config: PlasmoCSConfig = {
matches: ["https://twitter.com/*", "https://x.com/*"]
};

export const getInlineAnchorList: PlasmoGetInlineAnchorList = () =>
document.querySelectorAll(`div[data-testid="User-Name"]`);

export const getStyle = () => {
const style = document.createElement("style");
style.textContent = cssText;
return style;
};

const truncateString = (str = '', maxLength = 50) =>
str.length > maxLength ? `${str.slice(0, maxLength)}…` : str;

const ProfileNoteAlert = ({anchor}) => {
const [note, setNote] = useState("");
const [isPersian, setIsPersian] = useState(false);

const username = anchor.element.querySelector('div[data-testid="User-Name"] > div:nth-child(2) > div > div').textContent.replace("@","");

useEffect(() => {
utils.getProfileNote(username).then((value) => {
if (typeof value === 'string' && value.trim() !== ''){
setNote(value);
setIsPersian(utils.isPersian(value))
}
});
}, [anchor]);


return (
<span title={note} style={{ direction: isPersian ? "rtl" : "ltr", border: "none" }} className="font-bold text-sm">
{truncateString(note, 50)}
</span>
);
};

export default ProfileNoteAlert;
9 changes: 9 additions & 0 deletions src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import { Storage } from "@plasmohq/storage";

const storage = new Storage();

export const readStorage = async (key:string)=>{
return storage.get(key);
}

export const deleteStorageKey = async (key:string)=>{
await storage.remove(key);
}


export const readStorageAsBoolean = async (key:string)=>{
const value = await storage.get(key);
return value=="true";
Expand Down
21 changes: 19 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import persianRex from "persian-rex"
import rtl from "rtl-detect"
import Virastar from "virastar"

import { readStorageAsList } from "./storage"
import { readStorageAsList, readStorage, writeStorage, deleteStorageKey } from "./storage"

var virastar = new Virastar({ cleanup_begin_and_end: false })

Expand All @@ -20,6 +20,7 @@ function cleanupText(text) {
}

function isPersian(text) {
if (!text) return false;
var totalCharacters = text.length

var persianCharacters = 0
Expand Down Expand Up @@ -97,6 +98,19 @@ async function hasMuttedText(tweetText) {
})
}

async function getProfileNote(username) {
const profileNote = await readStorage(username)
return profileNote
}

async function saveProfileNote(username, note) {
await writeStorage(username, note)
}

async function deleteProfileNote(username) {
await deleteStorageKey(username)
}

function evaluateXpath(xpath) {
return document.evaluate(
xpath,
Expand Down Expand Up @@ -198,5 +212,8 @@ export {
evaluateXpath,
bgColorForCurrentTheme,
getCurrentTheme,
getSimplifiedVersion
getSimplifiedVersion,
getProfileNote,
saveProfileNote,
deleteProfileNote
}

0 comments on commit 4492974

Please sign in to comment.