ReplyEditor: added language picker
This commit is contained in:
		
							parent
							
								
									a1a587a77f
								
							
						
					
					
						commit
						4cf065fe1f
					
				
					 4 changed files with 120 additions and 4 deletions
				
			
		
							
								
								
									
										86
									
								
								src/timelines/ChooseTootLang.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/timelines/ChooseTootLang.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,86 @@
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  For,
 | 
				
			||||||
 | 
					  onMount,
 | 
				
			||||||
 | 
					  type Component,
 | 
				
			||||||
 | 
					  type JSX,
 | 
				
			||||||
 | 
					} from "solid-js";
 | 
				
			||||||
 | 
					import Scaffold from "../material/Scaffold";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  AppBar,
 | 
				
			||||||
 | 
					  IconButton,
 | 
				
			||||||
 | 
					  List,
 | 
				
			||||||
 | 
					  ListItemButton,
 | 
				
			||||||
 | 
					  ListItemSecondaryAction,
 | 
				
			||||||
 | 
					  ListItemText,
 | 
				
			||||||
 | 
					  Radio,
 | 
				
			||||||
 | 
					  Toolbar,
 | 
				
			||||||
 | 
					} from "@suid/material";
 | 
				
			||||||
 | 
					import { Close as CloseIcon } from "@suid/icons-material";
 | 
				
			||||||
 | 
					import iso639_1 from "iso-639-1";
 | 
				
			||||||
 | 
					import { createTranslator } from "../platform/i18n";
 | 
				
			||||||
 | 
					import { Title } from "../material/typography";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ChooseTootLangProps = {
 | 
				
			||||||
 | 
					  code: string;
 | 
				
			||||||
 | 
					  onCodeChange: (ncode?: string) => void;
 | 
				
			||||||
 | 
					  onClose?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ChooseTootLang: Component<ChooseTootLangProps> = (props) => {
 | 
				
			||||||
 | 
					  let listRef: HTMLUListElement;
 | 
				
			||||||
 | 
					  const [t] = createTranslator(
 | 
				
			||||||
 | 
					    (code) =>
 | 
				
			||||||
 | 
					      import(`./i18n/${code}.json`) as Promise<{
 | 
				
			||||||
 | 
					        default: Record<string, string | undefined>;
 | 
				
			||||||
 | 
					      }>,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMount(() => {
 | 
				
			||||||
 | 
					    const code = props.code;
 | 
				
			||||||
 | 
					    const el = listRef.querySelector(`[data-langcode="${code}"]`);
 | 
				
			||||||
 | 
					    if (el) {
 | 
				
			||||||
 | 
					      el.scrollIntoView({ behavior: "auto" });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Scaffold
 | 
				
			||||||
 | 
					      topbar={
 | 
				
			||||||
 | 
					        <AppBar position="static">
 | 
				
			||||||
 | 
					          <Toolbar
 | 
				
			||||||
 | 
					            variant="dense"
 | 
				
			||||||
 | 
					            sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <IconButton color="inherit" onClick={props.onClose} disableRipple>
 | 
				
			||||||
 | 
					              <CloseIcon />
 | 
				
			||||||
 | 
					            </IconButton>
 | 
				
			||||||
 | 
					            <Title>{t("Choose Language")}</Title>
 | 
				
			||||||
 | 
					          </Toolbar>
 | 
				
			||||||
 | 
					        </AppBar>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <List
 | 
				
			||||||
 | 
					        ref={listRef!}
 | 
				
			||||||
 | 
					        sx={{
 | 
				
			||||||
 | 
					          paddingBottom: "var(--safe-area-inset-bottom, 0)",
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <For each={iso639_1.getAllCodes()}>
 | 
				
			||||||
 | 
					          {(code) => (
 | 
				
			||||||
 | 
					            <ListItemButton
 | 
				
			||||||
 | 
					              data-langcode={code}
 | 
				
			||||||
 | 
					              onClick={() => props.onCodeChange(code)}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <ListItemText>{iso639_1.getNativeName(code)}</ListItemText>
 | 
				
			||||||
 | 
					              <ListItemSecondaryAction>
 | 
				
			||||||
 | 
					                <Radio checked={props.code == code}></Radio>
 | 
				
			||||||
 | 
					              </ListItemSecondaryAction>
 | 
				
			||||||
 | 
					            </ListItemButton>
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					        </For>
 | 
				
			||||||
 | 
					      </List>
 | 
				
			||||||
 | 
					    </Scaffold>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ChooseTootLang;
 | 
				
			||||||
| 
						 | 
					@ -27,11 +27,16 @@ import {
 | 
				
			||||||
  People as PeopleIcon,
 | 
					  People as PeopleIcon,
 | 
				
			||||||
  ThreeP as ThreePIcon,
 | 
					  ThreeP as ThreePIcon,
 | 
				
			||||||
  ListAlt as ListAltIcon,
 | 
					  ListAlt as ListAltIcon,
 | 
				
			||||||
 | 
					  Visibility,
 | 
				
			||||||
 | 
					  Translate,
 | 
				
			||||||
} from "@suid/icons-material";
 | 
					} from "@suid/icons-material";
 | 
				
			||||||
import type { Account } from "../accounts/stores";
 | 
					import type { Account } from "../accounts/stores";
 | 
				
			||||||
import tootComposers from "./TootComposer.module.css";
 | 
					import tootComposers from "./TootComposer.module.css";
 | 
				
			||||||
import { makeEventListener } from "@solid-primitives/event-listener";
 | 
					import { makeEventListener } from "@solid-primitives/event-listener";
 | 
				
			||||||
import BottomSheet from "../material/BottomSheet";
 | 
					import BottomSheet from "../material/BottomSheet";
 | 
				
			||||||
 | 
					import { useLanguage } from "../platform/i18n";
 | 
				
			||||||
 | 
					import iso639_1 from "iso-639-1";
 | 
				
			||||||
 | 
					import ChooseTootLang from "./ChooseTootLang";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TootVisibility = "public" | "unlisted" | "private" | "direct";
 | 
					type TootVisibility = "public" | "unlisted" | "private" | "direct";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,17 +159,19 @@ const TootVisibilityPickerDialog: Component<{
 | 
				
			||||||
const ReplyEditor: Component<{
 | 
					const ReplyEditor: Component<{
 | 
				
			||||||
  profile: Account;
 | 
					  profile: Account;
 | 
				
			||||||
  replyToDisplayName: string;
 | 
					  replyToDisplayName: string;
 | 
				
			||||||
  isTyping?: boolean
 | 
					  isTyping?: boolean;
 | 
				
			||||||
  onTypingChange: (value: boolean) => void
 | 
					  onTypingChange: (value: boolean) => void;
 | 
				
			||||||
}> = (props) => {
 | 
					}> = (props) => {
 | 
				
			||||||
  let inputRef: HTMLTextAreaElement;
 | 
					  let inputRef: HTMLTextAreaElement;
 | 
				
			||||||
  const buttonId = createUniqueId();
 | 
					  const buttonId = createUniqueId();
 | 
				
			||||||
  const menuId = createUniqueId();
 | 
					  const menuId = createUniqueId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const typing = () => props.isTyping
 | 
					  const typing = () => props.isTyping;
 | 
				
			||||||
  const setTyping = (v: boolean) => props.onTypingChange(v)
 | 
					  const setTyping = (v: boolean) => props.onTypingChange(v);
 | 
				
			||||||
  const [visibility, setVisibility] = createSignal<TootVisibility>("public");
 | 
					  const [visibility, setVisibility] = createSignal<TootVisibility>("public");
 | 
				
			||||||
  const [permPicker, setPermPicker] = createSignal(false);
 | 
					  const [permPicker, setPermPicker] = createSignal(false);
 | 
				
			||||||
 | 
					  const [language, setLanguage] = createSignal(useLanguage()().split("-")[0]);
 | 
				
			||||||
 | 
					  const [langPickerOpen, setLangPickerOpen] = createSignal(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onMount(() => {
 | 
					  onMount(() => {
 | 
				
			||||||
    makeEventListener(inputRef, "focus", () => setTyping(true));
 | 
					    makeEventListener(inputRef, "focus", () => setTyping(true));
 | 
				
			||||||
| 
						 | 
					@ -218,7 +225,13 @@ const ReplyEditor: Component<{
 | 
				
			||||||
          "margin-top": "8px",
 | 
					          "margin-top": "8px",
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
 | 
					        <Button onClick={[setLangPickerOpen, true]}>
 | 
				
			||||||
 | 
					          <Translate sx={{ marginTop: "-0.25em", marginRight: "0.25em" }} />
 | 
				
			||||||
 | 
					          {iso639_1.getNativeName(language())}
 | 
				
			||||||
 | 
					          <ArrowDropDown sx={{ marginTop: "-0.25em" }} />
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
        <Button onClick={[setPermPicker, true]} id={buttonId}>
 | 
					        <Button onClick={[setPermPicker, true]} id={buttonId}>
 | 
				
			||||||
 | 
					          <Visibility sx={{ marginTop: "-0.15em", marginRight: "0.25em" }} />
 | 
				
			||||||
          {visibilityText()}
 | 
					          {visibilityText()}
 | 
				
			||||||
          <ArrowDropDown sx={{ marginTop: "-0.25em" }} />
 | 
					          <ArrowDropDown sx={{ marginTop: "-0.25em" }} />
 | 
				
			||||||
        </Button>
 | 
					        </Button>
 | 
				
			||||||
| 
						 | 
					@ -230,6 +243,17 @@ const ReplyEditor: Component<{
 | 
				
			||||||
        visibility={visibility()}
 | 
					        visibility={visibility()}
 | 
				
			||||||
        onVisibilityChange={setVisibility}
 | 
					        onVisibilityChange={setVisibility}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <BottomSheet
 | 
				
			||||||
 | 
					        open={langPickerOpen()}
 | 
				
			||||||
 | 
					        onClose={() => setLangPickerOpen(false)}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <ChooseTootLang
 | 
				
			||||||
 | 
					          code={language()}
 | 
				
			||||||
 | 
					          onCodeChange={setLanguage}
 | 
				
			||||||
 | 
					          onClose={[setLangPickerOpen, false]}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </BottomSheet>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/timelines/i18n/en.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/timelines/i18n/en.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Choose Language": "Choose Language"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/timelines/i18n/zh-Hans.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/timelines/i18n/zh-Hans.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Choose Language": "选择语言"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue