2025-03-05 12:01:48 +01:00
|
|
|
import { create } from 'zustand';
|
|
|
|
|
import useSelectedTextStore from './use-selected-text-store';
|
|
|
|
|
|
|
|
|
|
interface ReplyModalState {
|
|
|
|
|
showReplyModal: boolean;
|
2026-02-23 19:33:59 +08:00
|
|
|
/** True when opened via "Post a Reply" footer button — textarea should be empty, no quote. */
|
|
|
|
|
openEmpty: boolean;
|
2025-03-05 12:01:48 +01:00
|
|
|
activeCid: string | null;
|
2025-12-28 11:53:02 +01:00
|
|
|
parentNumber: number | null;
|
2025-12-28 22:16:38 +01:00
|
|
|
threadNumber: number | null;
|
2025-03-05 12:01:48 +01:00
|
|
|
threadCid: string | null;
|
|
|
|
|
subplebbitAddress: string | null;
|
|
|
|
|
scrollY: number;
|
2026-02-10 14:57:47 +08:00
|
|
|
quoteInsertRequestId: number;
|
|
|
|
|
quoteInsertNumber: number | null;
|
2026-02-10 15:51:58 +08:00
|
|
|
quoteInsertSelectedText: string | null;
|
2025-03-05 12:01:48 +01:00
|
|
|
closeModal: () => void;
|
2025-12-28 22:16:38 +01:00
|
|
|
openReplyModal: (parentCid: string, parentNumber: number | undefined, postCid: string, threadNumber: number | undefined, subplebbitAddress: string) => void;
|
2026-02-23 16:47:51 +08:00
|
|
|
/** Open reply modal with empty textarea, no prefilled quote. Use for "Post a Reply" footer button. */
|
|
|
|
|
openReplyModalEmpty: (postCid: string, threadNumber: number | undefined, subplebbitAddress: string) => void;
|
2025-03-05 12:01:48 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-10 15:51:58 +08:00
|
|
|
const getQuotedSelection = () => {
|
|
|
|
|
const text = document.getSelection()?.toString();
|
|
|
|
|
if (!text) return '';
|
|
|
|
|
|
|
|
|
|
// Keep each selected line as 5chan greentext and normalize newlines.
|
|
|
|
|
const normalizedText = text.replace(/\r\n/g, '\n').replace(/\n+$/g, '');
|
|
|
|
|
|
|
|
|
|
if (!normalizedText) return '';
|
|
|
|
|
|
|
|
|
|
return normalizedText
|
|
|
|
|
.split('\n')
|
|
|
|
|
.map((line) => `>${line}`)
|
|
|
|
|
.join('\n');
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-05 12:01:48 +01:00
|
|
|
const useReplyModalStore = create<ReplyModalState>((set, get) => ({
|
|
|
|
|
showReplyModal: false,
|
2026-02-23 19:33:59 +08:00
|
|
|
openEmpty: false,
|
2025-03-05 12:01:48 +01:00
|
|
|
activeCid: null,
|
2025-12-28 11:53:02 +01:00
|
|
|
parentNumber: null,
|
2025-12-28 22:16:38 +01:00
|
|
|
threadNumber: null,
|
2025-03-05 12:01:48 +01:00
|
|
|
threadCid: null,
|
|
|
|
|
subplebbitAddress: null,
|
|
|
|
|
scrollY: 0,
|
2026-02-10 14:57:47 +08:00
|
|
|
quoteInsertRequestId: 0,
|
|
|
|
|
quoteInsertNumber: null,
|
2026-02-10 15:51:58 +08:00
|
|
|
quoteInsertSelectedText: null,
|
2025-03-05 12:01:48 +01:00
|
|
|
|
|
|
|
|
closeModal: () => {
|
|
|
|
|
// Reset selected text if you're using that store
|
|
|
|
|
useSelectedTextStore.getState().resetSelectedText();
|
|
|
|
|
set({
|
|
|
|
|
showReplyModal: false,
|
2026-02-23 19:33:59 +08:00
|
|
|
openEmpty: false,
|
2025-03-05 12:01:48 +01:00
|
|
|
activeCid: null,
|
2025-12-28 11:53:02 +01:00
|
|
|
parentNumber: null,
|
2025-12-28 22:16:38 +01:00
|
|
|
threadNumber: null,
|
2026-02-10 14:57:47 +08:00
|
|
|
quoteInsertNumber: null,
|
2026-02-10 15:51:58 +08:00
|
|
|
quoteInsertSelectedText: null,
|
2025-03-05 12:01:48 +01:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-28 22:16:38 +01:00
|
|
|
openReplyModal: (parentCid, parentNumber, postCid, threadNumber, subplebbitAddress) => {
|
2026-02-10 15:51:58 +08:00
|
|
|
const quotedSelection = getQuotedSelection();
|
|
|
|
|
|
2026-02-10 14:57:47 +08:00
|
|
|
// If the reply modal is already open, insert this quote in the current textarea at caret.
|
|
|
|
|
if (get().showReplyModal) {
|
|
|
|
|
set((state) => ({
|
|
|
|
|
quoteInsertRequestId: state.quoteInsertRequestId + 1,
|
|
|
|
|
quoteInsertNumber: parentNumber ?? null,
|
2026-02-10 15:51:58 +08:00
|
|
|
quoteInsertSelectedText: quotedSelection || null,
|
2026-02-10 14:57:47 +08:00
|
|
|
}));
|
2025-11-08 17:00:28 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-10 15:51:58 +08:00
|
|
|
if (quotedSelection) {
|
|
|
|
|
useSelectedTextStore.getState().setSelectedText(`${quotedSelection}\n`);
|
2025-03-05 12:01:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle mobile scrollY
|
|
|
|
|
const isMobile = window.innerWidth <= 768; // Simple check, adjust as needed
|
|
|
|
|
const scrollY = isMobile ? window.scrollY : 0;
|
|
|
|
|
|
|
|
|
|
set({
|
2026-02-23 19:33:59 +08:00
|
|
|
openEmpty: false,
|
2026-02-11 18:15:06 +08:00
|
|
|
activeCid: postCid,
|
2025-12-28 11:53:02 +01:00
|
|
|
parentNumber: parentNumber ?? null,
|
2025-12-28 22:16:38 +01:00
|
|
|
threadNumber: threadNumber ?? null,
|
2025-03-05 12:01:48 +01:00
|
|
|
threadCid: postCid,
|
|
|
|
|
showReplyModal: true,
|
|
|
|
|
subplebbitAddress,
|
|
|
|
|
scrollY,
|
|
|
|
|
});
|
|
|
|
|
},
|
2026-02-23 16:47:51 +08:00
|
|
|
|
|
|
|
|
openReplyModalEmpty: (postCid, threadNumber, subplebbitAddress) => {
|
|
|
|
|
useSelectedTextStore.getState().resetSelectedText();
|
|
|
|
|
const isMobile = window.innerWidth <= 768;
|
|
|
|
|
const scrollY = isMobile ? window.scrollY : 0;
|
|
|
|
|
set({
|
2026-02-23 19:33:59 +08:00
|
|
|
openEmpty: true,
|
2026-02-23 16:47:51 +08:00
|
|
|
activeCid: postCid,
|
|
|
|
|
parentNumber: null,
|
|
|
|
|
threadNumber: threadNumber ?? null,
|
|
|
|
|
threadCid: postCid,
|
|
|
|
|
showReplyModal: true,
|
|
|
|
|
subplebbitAddress,
|
|
|
|
|
scrollY,
|
|
|
|
|
quoteInsertNumber: null,
|
|
|
|
|
quoteInsertSelectedText: null,
|
|
|
|
|
});
|
|
|
|
|
},
|
2025-03-05 12:01:48 +01:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
export default useReplyModalStore;
|