From 8b7a4e72af051e684d3b40fa4e36426a3da7860a Mon Sep 17 00:00:00 2001 From: Nutomic Date: Wed, 2 Oct 2024 14:37:41 +0200 Subject: [PATCH] Post scheduling (#2693) * Post scheduling Adds simple input for scheduling a post x minutes in the future. Do you want to pull in a date picker library for this? See https://github.com/LemmyNet/lemmy/pull/5025 * lint * add date picker * Adding i18n, and fixing some fields (#2694) * fix edits * cleanup --------- Co-authored-by: Dessalines --- src/shared/components/post/post-form.tsx | 43 ++++++++++++++++++++- src/shared/components/post/post-listing.tsx | 10 ++++- src/shared/utils/helpers/get-unix-time.ts | 26 ++++++++++++- src/shared/utils/helpers/index.ts | 2 - 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/shared/components/post/post-form.tsx b/src/shared/components/post/post-form.tsx index 6d227382..9a658d73 100644 --- a/src/shared/components/post/post-form.tsx +++ b/src/shared/components/post/post-form.tsx @@ -48,6 +48,11 @@ import { isBrowser } from "@utils/browser"; import isMagnetLink, { extractMagnetLinkDownloadName, } from "@utils/media/is-magnet-link"; +import { + getUnixTimeLemmy, + getUnixTime, + unixTimeToLocalDateStr, +} from "@utils/helpers/get-unix-time"; const MAX_POST_TITLE_LENGTH = 200; @@ -88,6 +93,8 @@ interface PostFormState { honeypot?: string; custom_thumbnail?: string; alt_text?: string; + // Javascript treats this field as a string, that can't have timezone info. + scheduled_publish_time?: string; }; suggestedPostsRes: RequestState; metadataRes: RequestState; @@ -112,6 +119,7 @@ function handlePostSubmit(i: PostForm, event: any) { const pForm = i.state.form; const pv = i.props.post_view; + const scheduled_publish_time = getUnixTimeLemmy(pForm.scheduled_publish_time); if (pv) { i.props.onEdit?.( @@ -124,6 +132,7 @@ function handlePostSubmit(i: PostForm, event: any) { language_id: pForm.language_id, custom_thumbnail: pForm.custom_thumbnail, alt_text: pForm.alt_text, + scheduled_publish_time, }, () => { i.setState({ bypassNavWarning: true }); @@ -141,6 +150,7 @@ function handlePostSubmit(i: PostForm, event: any) { honeypot: pForm.honeypot, custom_thumbnail: pForm.custom_thumbnail, alt_text: pForm.alt_text, + scheduled_publish_time, }, () => { i.setState({ bypassNavWarning: true }); @@ -202,6 +212,18 @@ function handlePostNsfwChange(i: PostForm, event: any) { ); } +function handlePostScheduleChange(i: PostForm, event: any) { + const scheduled_publish_time = event.target.value; + + i.setState(prev => ({ + ...prev, + form: { + ...prev.form, + scheduled_publish_time, + }, + })); +} + function handleHoneyPotChange(i: PostForm, event: any) { i.setState(s => ((s.form.honeypot = event.target.value), s)); } @@ -317,9 +339,10 @@ export class PostForm extends Component { this.updateUrl = this.updateUrl.bind(this); const { post_view, selectedCommunityChoice, params } = this.props; - // Means its an edit if (post_view) { + const unix = getUnixTime(post_view.post.scheduled_publish_time); + var scheduled_publish_time = unixTimeToLocalDateStr(unix); this.state = { ...this.state, form: { @@ -331,6 +354,7 @@ export class PostForm extends Component { language_id: post_view.post.language_id, custom_thumbnail: post_view.post.thumbnail_url, alt_text: post_view.post.alt_text, + scheduled_publish_time, }, }; } else if (selectedCommunityChoice) { @@ -684,6 +708,23 @@ export class PostForm extends Component { )} + +
+ +
+ +
+
+ { createdLine() { const pv = this.postView; - return (
@@ -459,6 +458,13 @@ export class PostListing extends Component { } )}{" "} + {pv.post.scheduled_publish_time && ( + + {I18NextService.i18n.t("publish_in_time", { + time: formatPastDate(pv.post.scheduled_publish_time), + })} + + )}{" "} ยท
); diff --git a/src/shared/utils/helpers/get-unix-time.ts b/src/shared/utils/helpers/get-unix-time.ts index ec9d0191..ae8a8aa8 100644 --- a/src/shared/utils/helpers/get-unix-time.ts +++ b/src/shared/utils/helpers/get-unix-time.ts @@ -1,3 +1,27 @@ -export default function getUnixTime(text?: string): number | undefined { +/** + * Converts timestamp string to unix timestamp in seconds, as used by Lemmy API + */ +export function getUnixTimeLemmy(text?: string): number | undefined { return text ? new Date(text).getTime() / 1000 : undefined; } +/** + * Converts timestamp string to unix timestamp in millis, as used by Javascript + */ +export function getUnixTime(text?: string): number | undefined { + return text ? new Date(text).getTime() : undefined; +} + +/** + * This converts a unix time to a local date string, + * popping to tho nearest minute, and removing the Z for + * javascript fields. + */ +export function unixTimeToLocalDateStr(unixTime?: number): string | undefined { + return unixTime + ? convertUTCDateToLocalDate(new Date(unixTime)).toISOString().slice(0, -8) + : undefined; +} + +function convertUTCDateToLocalDate(date: Date): Date { + return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000); +} diff --git a/src/shared/utils/helpers/index.ts b/src/shared/utils/helpers/index.ts index f50c10c9..6108bac3 100644 --- a/src/shared/utils/helpers/index.ts +++ b/src/shared/utils/helpers/index.ts @@ -11,7 +11,6 @@ import getQueryParams from "./get-query-params"; import getQueryString from "./get-query-string"; import getRandomCharFromAlphabet from "./get-random-char-from-alphabet"; import getRandomFromList from "./get-random-from-list"; -import getUnixTime from "./get-unix-time"; import { groupBy } from "./group-by"; import hostname from "./hostname"; import hsl from "./hsl"; @@ -43,7 +42,6 @@ export { getQueryString, getRandomCharFromAlphabet, getRandomFromList, - getUnixTime, groupBy, hostname, hsl,