| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | /* | 
					
						
							|  |  |  | 	GoToSocial | 
					
						
							|  |  |  | 	Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | 	it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | 	the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | 	(at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | 	GNU Affero General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const React = require("react"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { useRoute, Link, Redirect } = require("wouter"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 16:00:23 +01:00
										 |  |  | const { CategorySelect } = require("../category-select"); | 
					
						
							|  |  |  | const { useComboBoxInput, useFileInput } = require("../../../components/form"); | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 16:00:23 +01:00
										 |  |  | const query = require("../../../lib/query"); | 
					
						
							|  |  |  | const FakeToot = require("../../../components/fake-toot"); | 
					
						
							|  |  |  | const Loading = require("../../../components/loading"); | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 16:00:23 +01:00
										 |  |  | const base = "/settings/custom-emoji/local"; | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | module.exports = function EmojiDetailRoute() { | 
					
						
							|  |  |  | 	let [_match, params] = useRoute(`${base}/:emojiId`); | 
					
						
							|  |  |  | 	if (params?.emojiId == undefined) { | 
					
						
							|  |  |  | 		return <Redirect to={base}/>; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return ( | 
					
						
							|  |  |  | 			<div className="emoji-detail"> | 
					
						
							|  |  |  | 				<Link to={base}><a>< go back</a></Link> | 
					
						
							|  |  |  | 				<EmojiDetailData emojiId={params.emojiId}/> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function EmojiDetailData({emojiId}) { | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	const {currentData: emoji, isLoading, error} = query.useGetEmojiQuery(emojiId); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 	if (error) { | 
					
						
							|  |  |  | 		return ( | 
					
						
							|  |  |  | 			<div className="error accent"> | 
					
						
							|  |  |  | 				{error.status}: {error.data.error} | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} else if (isLoading) { | 
					
						
							| 
									
										
										
										
											2022-12-11 16:00:23 +01:00
										 |  |  | 		return ( | 
					
						
							|  |  |  | 			<div> | 
					
						
							|  |  |  | 				<Loading/> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		return <EmojiDetail emoji={emoji}/>; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | function EmojiDetail({emoji}) { | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 	const [modifyEmoji, modifyResult] = query.useEditEmojiMutation(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const [isNewCategory, setIsNewCategory] = React.useState(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const [categoryState, _resetCategory, { category }] = useComboBoxInput("category", {defaultValue: emoji.category}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const [onFileChange, _resetFile, { image, imageURL, imageInfo }] = useFileInput("image", { | 
					
						
							|  |  |  | 		withPreview: true, | 
					
						
							|  |  |  | 		maxSize: 50 * 1024 | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function modifyCategory() { | 
					
						
							|  |  |  | 		modifyEmoji({id: emoji.id, category: category.trim()}); | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 	function modifyImage() { | 
					
						
							|  |  |  | 		modifyEmoji({id: emoji.id, image: image}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	React.useEffect(() => { | 
					
						
							| 
									
										
										
										
											2022-11-25 16:37:57 +01:00
										 |  |  | 		if (category != emoji.category && !categoryState.open && !isNewCategory && category.trim().length > 0) { | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 			console.log("updating to", category); | 
					
						
							|  |  |  | 			modifyEmoji({id: emoji.id, category: category.trim()}); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}, [isNewCategory, category, categoryState.open, emoji.category, emoji.id, modifyEmoji]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	return ( | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 		<> | 
					
						
							|  |  |  | 			<div className="emoji-header"> | 
					
						
							|  |  |  | 				<img src={emoji.url} alt={emoji.shortcode} title={emoji.shortcode}/> | 
					
						
							|  |  |  | 				<div> | 
					
						
							|  |  |  | 					<h2>{emoji.shortcode}</h2> | 
					
						
							|  |  |  | 					<DeleteButton id={emoji.id}/> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<div className="left-border"> | 
					
						
							|  |  |  | 				<h2>Modify this emoji {modifyResult.isLoading && "(processing..)"}</h2> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				{modifyResult.error && <div className="error"> | 
					
						
							|  |  |  | 					{modifyResult.error.status}: {modifyResult.error.data.error} | 
					
						
							|  |  |  | 				</div>} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				<div className="update-category"> | 
					
						
							|  |  |  | 					<CategorySelect | 
					
						
							|  |  |  | 						value={category} | 
					
						
							|  |  |  | 						categoryState={categoryState} | 
					
						
							|  |  |  | 						setIsNew={setIsNewCategory} | 
					
						
							|  |  |  | 					> | 
					
						
							|  |  |  | 						<button style={{visibility: (isNewCategory ? "initial" : "hidden")}} onClick={modifyCategory}> | 
					
						
							|  |  |  | 							Create | 
					
						
							|  |  |  | 						</button> | 
					
						
							|  |  |  | 					</CategorySelect> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				<div className="update-image"> | 
					
						
							|  |  |  | 					<b>Image</b> | 
					
						
							|  |  |  | 					<div className="form-field file"> | 
					
						
							|  |  |  | 						<label className="file-input button" htmlFor="image"> | 
					
						
							|  |  |  | 							Browse | 
					
						
							|  |  |  | 						</label> | 
					
						
							|  |  |  | 						{imageInfo} | 
					
						
							|  |  |  | 						<input | 
					
						
							|  |  |  | 							className="hidden" | 
					
						
							|  |  |  | 							type="file" | 
					
						
							|  |  |  | 							id="image" | 
					
						
							|  |  |  | 							name="Image" | 
					
						
							|  |  |  | 							accept="image/png,image/gif" | 
					
						
							|  |  |  | 							onChange={onFileChange} | 
					
						
							|  |  |  | 						/> | 
					
						
							|  |  |  | 					</div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					<button onClick={modifyImage} disabled={image == undefined}>Replace image</button> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					<FakeToot> | 
					
						
							|  |  |  | 						Look at this new custom emoji <img | 
					
						
							|  |  |  | 							className="emoji" | 
					
						
							|  |  |  | 							src={imageURL ?? emoji.url} | 
					
						
							|  |  |  | 							title={`:${emoji.shortcode}:`} | 
					
						
							|  |  |  | 							alt={emoji.shortcode} | 
					
						
							|  |  |  | 						/> isn't it cool? | 
					
						
							|  |  |  | 					</FakeToot> | 
					
						
							|  |  |  | 				</div> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		</> | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function DeleteButton({id}) { | 
					
						
							|  |  |  | 	// TODO: confirmation dialog?
 | 
					
						
							|  |  |  | 	const [deleteEmoji, deleteResult] = query.useDeleteEmojiMutation(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 	let text = "Delete"; | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	if (deleteResult.isLoading) { | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 		text = "Deleting..."; | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (deleteResult.isSuccess) { | 
					
						
							|  |  |  | 		return <Redirect to={base}/>; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ( | 
					
						
							| 
									
										
										
										
											2022-11-25 15:49:48 +01:00
										 |  |  | 		<button className="danger" onClick={() => deleteEmoji(id)} disabled={deleteResult.isLoading}>{text}</button> | 
					
						
							| 
									
										
										
										
											2022-11-08 17:51:44 +01:00
										 |  |  | 	); | 
					
						
							|  |  |  | } |