+
Post History for {platform}
+ {isLoadingHistory &&
Loading...
}
+ {!isLoadingHistory && postHistory.length === 0 &&
No posts found in history.
}
+ {!isLoadingHistory && postHistory.length > 0 && (
+
+ {postHistory.map(post => (
+
+
+
{stripHtml(post.content)}
+
📅 {formatScheduledTime(post.created_at)}
+
+ ❤️ {post.favourites_count}
+ 🔄 {post.reblogs_count}
+
+ {post.media_attachments?.length > 0 && (
+
+ {post.media_attachments.map((media, idx) => (
+

+ ))}
+
+ )}
+
+ View on Mastodon →
+
+
+
+ ))}
- ))}
+ )}
- {isLiveJournal ? (
-
-
-
Character Limits
-
- - Subject: 255 characters
- - Content: 60,000 characters
- - Tags: Unlimited (comma-separated)
-
+
+
+ {platform}-Specific Details
+
+
+ - Max characters: {charLimit}
+ - Supports hashtags: Yes
+ - Image support: Yes
+ - Alt text support: Yes (up to 1500 characters)
+ - Recommended dimensions: 1200x675 px
+ - Max image size: 5MB
+
+
+
Confirmation Preferences
+
+
+
+
+ )}
+
+
setModalOpen(false)}
+ title={modalConfig.title}
+ message={modalConfig.message}
+ onConfirm={modalConfig.onConfirm}
+ confirmText={modalConfig.confirmText}
+ confirmColor={modalConfig.confirmColor}
+ showDontShowAgain={modalConfig.showDontShowAgain}
+ onDontShowAgainChange={() => handleDontShowAgainChange(modalConfig.preferenceKey)}
+ />
+
+ setPreviewOpen(false)} size="lg" centered>
+ setPreviewOpen(false)}>Post Preview
+
+ {previewData && (
+
+
+

+
+
Your Account
+
+ {previewData.scheduledTime
+ ? `Scheduled for ${formatScheduledTime(previewData.scheduledTime)}`
+ : 'Posting now'}
+
+
-
Security Options
-
- -
- Public: Visible to everyone
-
- -
- Private: Only visible to you
-
- -
- Friends Only: Visible to your friends list
-
-
+ {previewData.content}
+
+ {previewData.image && (
+
+

+ {previewData.altText && (
+
+ Alt text: {previewData.altText}
+
+ )}
+
+ )}
+ {previewData.crossPostTo.length > 0 && (
+
+ 📤 Will also be selected for:{' '}
+ {previewData.crossPostTo.join(', ')}
+
+ )}
+
+ Character count: {previewData.content.length} / {charLimit}
+ )}
+
+
+
+ {previewData?.scheduledTime ? (
+
) : (
- Platform details here
+
)}
-
- )}
+
+
);
}
diff --git a/src/components/Announcements/SocialMediaComposer.module.css b/src/components/Announcements/SocialMediaComposer.module.css
new file mode 100644
index 0000000000..ace613aced
--- /dev/null
+++ b/src/components/Announcements/SocialMediaComposer.module.css
@@ -0,0 +1,719 @@
+/* Social Media Composer - LIGHT MODE BY DEFAULT */
+
+/* Main Container - WHITE background in light mode */
+.social-media-composer {
+ padding: 1.5rem;
+ background: #ffffff;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.platform-title {
+ font-size: 1.5rem;
+ font-weight: 600;
+ margin-bottom: 1rem;
+ color: #333333;
+ text-transform: capitalize;
+}
+
+/* Tabs */
+.tabs-container {
+ display: flex;
+ gap: 0.5rem;
+ margin-bottom: 1.5rem;
+ border-bottom: 2px solid #e0e0e0;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.tab-button {
+ padding: 0.75rem 1rem;
+ background: transparent;
+ border: none;
+ border-bottom: 3px solid transparent;
+ cursor: pointer;
+ font-size: 0.95rem;
+ font-weight: 500;
+ color: #666666;
+ transition: all 0.2s;
+ white-space: nowrap;
+ min-width: 120px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.tab-button:hover {
+ color: #007bff;
+ background: #f0f8ff;
+}
+
+.tab-button.active {
+ color: #007bff;
+ border-bottom-color: #007bff;
+ background: #f0f8ff;
+}
+
+/* Composer Content */
+.composer-content {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+/* TEXTAREA - BLACK TEXT ON WHITE BACKGROUND */
+.post-textarea {
+ width: 100%;
+ min-height: 150px;
+ padding: 12px;
+ border: 1px solid #cccccc;
+ border-radius: 6px;
+ font-family: inherit;
+ font-size: 1rem;
+ resize: vertical;
+ background: #ffffff;
+ color: #000000;
+ /* BLACK TEXT */
+ box-sizing: border-box;
+}
+
+.post-textarea:focus {
+ outline: none;
+ border-color: #007bff;
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
+}
+
+.post-textarea::placeholder {
+ color: #999999;
+}
+
+/* Upload Section */
+.upload-section {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.section-label {
+ font-weight: 500;
+ font-size: 0.9rem;
+ color: #333333;
+}
+
+.file-input {
+ padding: 0.5rem;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+ background: #ffffff;
+ color: #333333;
+ cursor: pointer;
+}
+
+.image-preview-container {
+ position: relative;
+ display: inline-block;
+ margin-top: 0.5rem;
+}
+
+.image-preview {
+ max-width: 300px;
+ max-height: 300px;
+ border-radius: 8px;
+ border: 2px solid #e0e0e0;
+}
+
+.remove-image-btn {
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ background: #dc3545;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 30px;
+ height: 30px;
+ cursor: pointer;
+ font-size: 1.2rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ transition: background 0.2s;
+}
+
+.remove-image-btn:hover {
+ background: #c82333;
+}
+
+/* ALT TEXT INPUT - BLACK TEXT ON WHITE */
+.alt-text-section {
+ margin-top: 1rem;
+}
+
+.alt-text-input {
+ width: 100%;
+ padding: 8px 12px;
+ border-radius: 4px;
+ border: 1px solid #cccccc;
+ background: #ffffff;
+ color: #000000;
+ /* BLACK TEXT */
+ font-family: inherit;
+ font-size: 0.9rem;
+ box-sizing: border-box;
+}
+
+.alt-text-input:focus {
+ outline: none;
+ border-color: #007bff;
+}
+
+.alt-text-input::placeholder {
+ color: #999999;
+}
+
+/* Schedule Section */
+.schedule-section {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.datetime-inputs {
+ display: flex;
+ gap: 1rem;
+}
+
+.datetime-input {
+ flex: 1;
+ padding: 0.5rem;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+ font-family: inherit;
+ background: #ffffff;
+ color: #000000;
+ /* BLACK TEXT */
+}
+
+.datetime-input:focus {
+ outline: none;
+ border-color: #007bff;
+}
+
+/* Action Buttons */
+.action-buttons {
+ display: flex;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+ margin-top: 1rem;
+}
+
+.btn {
+ padding: 0.6rem 1.2rem;
+ border: none;
+ border-radius: 4px;
+ font-size: 0.95rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.btn:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.btn-primary {
+ background: #007bff;
+ color: white;
+}
+
+.btn-primary:hover:not(:disabled) {
+ background: #0056b3;
+}
+
+.btn-success {
+ background: #28a745;
+ color: white;
+}
+
+.btn-success:hover:not(:disabled) {
+ background: #218838;
+}
+
+.btn-info {
+ background: #17a2b8;
+ color: white;
+}
+
+.btn-info:hover:not(:disabled) {
+ background: #138496;
+}
+
+.btn-secondary {
+ background: #6c757d;
+ color: white;
+}
+
+.btn-secondary:hover:not(:disabled) {
+ background: #5a6268;
+}
+
+/* Cross-posting */
+.crosspost-container {
+ position: relative;
+}
+
+.crosspost-dropdown {
+ position: absolute;
+ bottom: calc(100% + 8px);
+ left: 0;
+ background: #ffffff;
+ border: 1px solid #cccccc;
+ border-radius: 6px;
+ padding: 1rem;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ z-index: 1000;
+ min-width: 200px;
+}
+
+.crosspost-option {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem;
+ cursor: pointer;
+ color: #333333;
+}
+
+.crosspost-option:hover {
+ background: #f0f8ff;
+}
+
+.crosspost-option input[type="checkbox"] {
+ width: 16px;
+ height: 16px;
+ cursor: pointer;
+}
+
+.crosspost-note {
+ margin-top: 0.5rem;
+ padding-top: 0.5rem;
+ border-top: 1px solid #e0e0e0;
+ font-size: 0.75rem;
+ color: #666666;
+}
+
+/* Edit Banner */
+.edit-banner {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.75rem 1rem;
+ background: #fff3cd;
+ border: 1px solid #ffc107;
+ border-radius: 6px;
+ margin-bottom: 1rem;
+ font-weight: 500;
+ color: #856404;
+}
+
+.btn-cancel-edit {
+ background: #6c757d;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 4px 12px;
+ cursor: pointer;
+ font-size: 0.875rem;
+ transition: background 0.2s;
+}
+
+.btn-cancel-edit:hover {
+ background: #5a6268;
+}
+
+/* Scheduled & History Content - WHITE BACKGROUND */
+.scheduled-content,
+.history-content,
+.details-content {
+ padding: 1rem;
+ background: #ffffff;
+ color: #333333;
+}
+
+.scheduled-content h4,
+.history-content h4 {
+ margin-bottom: 1rem;
+ color: #333333;
+}
+
+.posts-list {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.post-card {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1rem;
+ background: #f8f9fa;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+}
+
+.post-card-content {
+ flex: 1;
+}
+
+.post-text {
+ color: #333333;
+ margin-bottom: 0.5rem;
+ line-height: 1.5;
+}
+
+.post-meta {
+ font-size: 0.85rem;
+ color: #666666;
+ margin-bottom: 0.5rem;
+}
+
+.post-thumbnail {
+ max-width: 200px;
+ max-height: 150px;
+ border-radius: 6px;
+ margin-top: 0.5rem;
+}
+
+.post-card-actions {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.action-btn {
+ width: 36px;
+ height: 36px;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 1rem;
+ transition: all 0.2s;
+ color: white;
+}
+
+.action-btn.success {
+ background: #28a745;
+}
+
+.action-btn.success:hover {
+ background: #218838;
+}
+
+.action-btn.danger {
+ background: #dc3545;
+}
+
+.action-btn.danger:hover {
+ background: #c82333;
+}
+
+.action-btn.edit {
+ background: #17a2b8;
+}
+
+.action-btn.edit:hover {
+ background: #138496;
+}
+
+/* Post Card Full (History) */
+.post-card-full {
+ width: 100%;
+}
+
+.post-stats {
+ display: flex;
+ gap: 1rem;
+ margin: 0.5rem 0;
+ font-size: 0.9rem;
+ color: #666666;
+}
+
+.post-media {
+ display: flex;
+ gap: 0.5rem;
+ margin-top: 0.5rem;
+}
+
+.post-link {
+ display: inline-block;
+ margin-top: 0.5rem;
+ color: #007bff;
+ text-decoration: none;
+ font-size: 0.9rem;
+}
+
+.post-link:hover {
+ text-decoration: underline;
+}
+
+/* Details Content */
+.details-content {
+ color: #333333;
+}
+
+.details-content ul {
+ padding-left: 1.5rem;
+ line-height: 1.8;
+ color: #333333;
+}
+
+.details-content strong {
+ color: #333333;
+}
+
+/* Preview Modal Content */
+.preview-container {
+ padding: 1rem;
+ background: #ffffff;
+}
+
+.preview-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 1rem;
+}
+
+.preview-content {
+ padding: 1rem;
+ background: #f8f9fa;
+ border: 1px solid #e0e0e0;
+ border-radius: 6px;
+ white-space: pre-wrap;
+ line-height: 1.6;
+ color: #333333;
+}
+
+/* Mobile Responsiveness */
+@media (max-width: 768px) {
+ .tabs-container {
+ overflow-x: auto;
+ }
+
+ .tab-button {
+ min-width: 90px;
+ font-size: 0.85rem;
+ }
+
+ .action-buttons {
+ flex-direction: column;
+ }
+
+ .btn {
+ width: 100%;
+ }
+
+ .datetime-inputs {
+ flex-direction: column;
+ }
+
+ .post-card {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .post-card-actions {
+ width: 100%;
+ justify-content: flex-end;
+ margin-top: 0.5rem;
+ }
+
+ .post-thumbnail {
+ max-width: 150px;
+ max-height: 100px;
+ }
+
+ .crosspost-dropdown {
+ left: 50%;
+ transform: translateX(-50%);
+ width: 90%;
+ }
+
+ .edit-banner {
+ flex-direction: column;
+ gap: 0.5rem;
+ align-items: flex-start;
+ }
+
+ .btn-cancel-edit {
+ align-self: flex-end;
+ }
+}
+
+@media (max-width: 480px) {
+ .social-media-composer {
+ padding: 1rem;
+ }
+
+ .tab-button {
+ padding: 0.5rem 0.75rem;
+ min-width: 80px;
+ }
+
+ .post-textarea {
+ min-height: 120px;
+ }
+
+ .image-preview {
+ max-width: 100%;
+ }
+
+ .post-thumbnail {
+ max-width: 80px;
+ max-height: 80px;
+ }
+}
+
+/* ====================================
+ DARK MODE - ONLY IN DARK MODE
+ ==================================== */
+@media (prefers-color-scheme: dark) {
+ .social-media-composer {
+ background: #1e1e1e;
+ }
+
+ .platform-title {
+ color: #e0e0e0;
+ }
+
+ .tabs-container {
+ border-bottom-color: #444444;
+ }
+
+ .tab-button {
+ color: #a0a0a0;
+ }
+
+ .tab-button:hover {
+ color: #4da6ff;
+ background: #2a2a2a;
+ }
+
+ .tab-button.active {
+ color: #4da6ff;
+ border-bottom-color: #4da6ff;
+ background: #2a2a2a;
+ }
+
+ .post-textarea {
+ background: #2a2a2a;
+ border-color: #444444;
+ color: #e0e0e0;
+ }
+
+ .post-textarea::placeholder {
+ color: #666666;
+ }
+
+ .section-label {
+ color: #e0e0e0;
+ }
+
+ .file-input {
+ background: #2a2a2a;
+ border-color: #444444;
+ color: #e0e0e0;
+ }
+
+ .alt-text-input {
+ background: #2a2a2a;
+ border-color: #444444;
+ color: #e0e0e0;
+ }
+
+ .alt-text-input::placeholder {
+ color: #666666;
+ }
+
+ .datetime-input {
+ background: #2a2a2a;
+ border-color: #444444;
+ color: #e0e0e0;
+ }
+
+ .crosspost-dropdown {
+ background: #2a2a2a;
+ border-color: #444444;
+ }
+
+ .crosspost-option {
+ color: #e0e0e0;
+ }
+
+ .crosspost-option:hover {
+ background: #333333;
+ }
+
+ .crosspost-note {
+ color: #a0a0a0;
+ border-top-color: #444444;
+ }
+
+ .edit-banner {
+ background: #664d03;
+ border-color: #856404;
+ color: #ffc107;
+ }
+
+ .scheduled-content,
+ .history-content,
+ .details-content {
+ background: #1e1e1e;
+ color: #e0e0e0;
+ }
+
+ .scheduled-content h4,
+ .history-content h4 {
+ color: #e0e0e0;
+ }
+
+ .post-card {
+ background: #2a2a2a;
+ border-color: #444444;
+ }
+
+ .post-text {
+ color: #e0e0e0;
+ }
+
+ .post-meta {
+ color: #a0a0a0;
+ }
+
+ .post-stats {
+ color: #a0a0a0;
+ }
+
+ .details-content {
+ color: #e0e0e0;
+ }
+
+ .details-content ul {
+ color: #e0e0e0;
+ }
+
+ .details-content strong {
+ color: #e0e0e0;
+ }
+
+ .preview-container {
+ background: #1e1e1e;
+ }
+
+ .preview-content {
+ background: #2a2a2a;
+ border-color: #444444;
+ color: #e0e0e0;
+ }
+}
diff --git a/vite.config.js b/vite.config.js
index 8f188e3e10..e876ca690d 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -10,7 +10,15 @@ export default defineConfig(({ mode }) => {
'~': resolve('src/'),
},
},
- // https://stackoverflow.com/a/77824845
+ server: {
+ proxy: {
+ '/api': {
+ target: 'http://localhost:4500',
+ changeOrigin: true,
+ secure: false,
+ },
+ },
+ },
define: {
...Object.keys(env).reduce((prev, key) => {
const sanitizedKey = key.replace(/[^a-zA-Z0-9_]/g, '_');
@@ -23,13 +31,5 @@ export default defineConfig(({ mode }) => {
outDir: 'build',
},
plugins: [react()],
- server: {
- proxy: {
- '/api': {
- target: 'http://localhost:4500',
- changeOrigin: true,
- },
- },
- },
};
});
diff --git a/yarn.lock b/yarn.lock
index 03ce3bdad7..25350acb6b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7799,15 +7799,10 @@ jest-message-util@30.2.0:
resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz"
integrity sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==
dependencies:
- "@babel/code-frame" "^7.27.1"
- "@jest/types" "30.2.0"
- "@types/stack-utils" "^2.0.3"
+ "@jest/get-type" "30.1.0"
chalk "^4.1.2"
- graceful-fs "^4.2.11"
- micromatch "^4.0.8"
- pretty-format "30.2.0"
- slash "^3.0.0"
- stack-utils "^2.0.6"
+ jest-diff "30.1.1"
+ pretty-format "30.0.5"
jest-mock@^29.7.0:
version "29.7.0"