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,
 | 
			
		||||
  ThreeP as ThreePIcon,
 | 
			
		||||
  ListAlt as ListAltIcon,
 | 
			
		||||
  Visibility,
 | 
			
		||||
  Translate,
 | 
			
		||||
} from "@suid/icons-material";
 | 
			
		||||
import type { Account } from "../accounts/stores";
 | 
			
		||||
import tootComposers from "./TootComposer.module.css";
 | 
			
		||||
import { makeEventListener } from "@solid-primitives/event-listener";
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -154,17 +159,19 @@ const TootVisibilityPickerDialog: Component<{
 | 
			
		|||
const ReplyEditor: Component<{
 | 
			
		||||
  profile: Account;
 | 
			
		||||
  replyToDisplayName: string;
 | 
			
		||||
  isTyping?: boolean
 | 
			
		||||
  onTypingChange: (value: boolean) => void
 | 
			
		||||
  isTyping?: boolean;
 | 
			
		||||
  onTypingChange: (value: boolean) => void;
 | 
			
		||||
}> = (props) => {
 | 
			
		||||
  let inputRef: HTMLTextAreaElement;
 | 
			
		||||
  const buttonId = createUniqueId();
 | 
			
		||||
  const menuId = createUniqueId();
 | 
			
		||||
 | 
			
		||||
  const typing = () => props.isTyping
 | 
			
		||||
  const setTyping = (v: boolean) => props.onTypingChange(v)
 | 
			
		||||
  const typing = () => props.isTyping;
 | 
			
		||||
  const setTyping = (v: boolean) => props.onTypingChange(v);
 | 
			
		||||
  const [visibility, setVisibility] = createSignal<TootVisibility>("public");
 | 
			
		||||
  const [permPicker, setPermPicker] = createSignal(false);
 | 
			
		||||
  const [language, setLanguage] = createSignal(useLanguage()().split("-")[0]);
 | 
			
		||||
  const [langPickerOpen, setLangPickerOpen] = createSignal(false);
 | 
			
		||||
 | 
			
		||||
  onMount(() => {
 | 
			
		||||
    makeEventListener(inputRef, "focus", () => setTyping(true));
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +225,13 @@ const ReplyEditor: Component<{
 | 
			
		|||
          "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}>
 | 
			
		||||
          <Visibility sx={{ marginTop: "-0.15em", marginRight: "0.25em" }} />
 | 
			
		||||
          {visibilityText()}
 | 
			
		||||
          <ArrowDropDown sx={{ marginTop: "-0.25em" }} />
 | 
			
		||||
        </Button>
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +243,17 @@ const ReplyEditor: Component<{
 | 
			
		|||
        visibility={visibility()}
 | 
			
		||||
        onVisibilityChange={setVisibility}
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
      <BottomSheet
 | 
			
		||||
        open={langPickerOpen()}
 | 
			
		||||
        onClose={() => setLangPickerOpen(false)}
 | 
			
		||||
      >
 | 
			
		||||
        <ChooseTootLang
 | 
			
		||||
          code={language()}
 | 
			
		||||
          onCodeChange={setLanguage}
 | 
			
		||||
          onClose={[setLangPickerOpen, false]}
 | 
			
		||||
        />
 | 
			
		||||
      </BottomSheet>
 | 
			
		||||
    </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