Skip to content

Instantly share code, notes, and snippets.

@DerGoogler
Last active September 3, 2024 20:33
Show Gist options
  • Select an option

  • Save DerGoogler/c24015d1a310809ab882a7d7f23ddd62 to your computer and use it in GitHub Desktop.

Select an option

Save DerGoogler/c24015d1a310809ab882a7d7f23ddd62 to your computer and use it in GitHub Desktop.

Revisions

  1. DerGoogler revised this gist Sep 3, 2024. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@
    `fallbackwidth` and `fallbackheight` are empty when you run the config in the browser

    > [!NOTE]
    > The current version is messy.
    ![image](https://gist.github.com/user-attachments/assets/c45b27c9-98dd-4f02-9edd-0aa24537b4d7)
  2. DerGoogler created this gist Sep 3, 2024.
    3 changes: 3 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    `fallbackwidth` and `fallbackheight` are empty when you run the config in the browser

    ![image](https://gist.github.com/user-attachments/assets/c45b27c9-98dd-4f02-9edd-0aa24537b4d7)
    391 changes: 391 additions & 0 deletions index.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,391 @@
    import { Page, Toolbar, CodeBlock } from "@mmrl/ui";
    import { useActivity, useConfig } from "@mmrl/hooks";
    import { withRequireNewVersion } from "@mmrl/hoc";
    import { ConfigProvider } from "@mmrl/providers";
    import {
    List,
    ListItem,
    ListItemButton,
    ListItemText,
    ListSubheader,
    DialogTitle,
    Dialog,
    ListItemIcon,
    Switch,
    Checkbox,
    Button,
    Divider,
    TextField,
    DialogActions
    } from "@mui/material";
    import { Check } from "@mui/icons-material"


    const screen_dims = Shell.cmd("wm size").result()
    const width_height = Shell.cmd(`${screen_dims} | tr -s ' ' ':' | cut -d':' -f3`).result()
    const width = Shell.cmd(`${width_height} | cut -d'x' -f1`).result()
    const height = Shell.cmd(`${width_height} | cut -d'x' -f2`).result()

    const initialConfig = {
    background: "transparent",
    colors: true,
    wordwrap: true, // assuming true since it's present
    logcatlevels: {
    V: true,
    D: true,
    I: true,
    W: true,
    E: true,
    F: true,
    S: true,
    },
    logcatbuffers: {
    M: true,
    S: true,
    R: true,
    E: true,
    C: true,
    },
    logcatformat: 'threadtime',
    dmesg: true,
    lines: '80',
    save: true,
    fallbackwidth: width,
    fallbackheight: height,
    }
    const backgroundsList = [
    {
    name: "Default",
    value: " "
    },
    {
    name: "Transparent",
    value: "transparent"
    },
    {
    name: "Dark",
    value: "dark"
    },
    ]

    const logcatFormatsList = [
    {
    name: "Brief",
    value: "brief"
    },
    {
    name: "Process",
    value: "process"
    },
    {
    name: "Tag",
    value: "tag"
    },
    {
    name: "Thread",
    value: "thread"
    },
    {
    name: "Time",
    value: "time"
    },
    {
    name: "Thread time",
    value: "threadtime"
    }
    ]

    const logcatBuffersList = [
    {
    name: "Main",
    value: "M"
    },
    {
    name: "System",
    value: "S"
    },
    {
    name: "Radio",
    value: "R"
    },
    {
    name: "Events",
    value: "E"
    },
    {
    name: "Crash",
    value: "C"
    },
    ]

    const logcatLevelsList = [
    {
    name: "Verbose",
    value: "V"
    },
    {
    name: "Debug",
    value: "D"
    },
    {
    name: "Info",
    value: "I"
    },
    {
    name: "Warning",
    value: "W"
    },
    {
    name: "Error",
    value: "E"
    },
    {
    name: "Fatal",
    value: "F"
    },
    {
    name: "Silent",
    value: "S"
    },
    ]

    const RenderToolbar = () => {
    const { context } = useActivity()

    return (
    <Toolbar modifier="noshadow">
    <Toolbar.Left>
    <Toolbar.BackButton onClick={context.popPage} />
    </Toolbar.Left>
    <Toolbar.Center>
    Liveboot Magisk
    </Toolbar.Center>
    </Toolbar>
    )
    }

    function ListItemSelectDialog(props) {
    const [config, setConfig] = useConfig();
    const [open, setOpen] = React.useState(false);
    const { conf, primary, secondary, items } = props;

    const handleClickOpen = () => {
    setOpen(true);
    };

    const handleClose = () => {
    setOpen(false)
    setConfig(conf, items[0].value)
    };

    const handleListItemClick = (value) => {
    setOpen(false)
    setConfig(conf, value);
    };

    return (
    <>
    <ListItemButton onClick={handleClickOpen}>
    <ListItemText primary={primary} secondary={secondary} />
    </ListItemButton>
    <Dialog fullWidth onClose={handleClose} open={open}>
    <DialogTitle>{primary}</DialogTitle>
    <List sx={{ pt: 0 }}>
    {items.map((item) => (
    <ListItem disablePadding key={item.value}>
    <ListItemButton onClick={() => handleListItemClick(item.value)}>
    <ListItemText primary={item.name} />
    {item.value === config[conf] && (
    <ListItemIcon>
    <Check />
    </ListItemIcon>
    )}
    </ListItemButton>
    </ListItem>
    ))}
    </List>
    </Dialog>
    </>
    );
    }

    const ListItemCheckboxDialog = (props) => {
    const [config, setConfig] = useConfig();
    const [open, setOpen] = React.useState(false);

    const { conf, primary, secondary, items } = props;

    const handleClickOpen = () => {
    setOpen(true);
    };

    const handleClose = () => {
    setOpen(false)
    };

    const handleToggle = (e, item) => {
    setConfig(conf, (prev) => {
    return Object.assign(prev, {
    [item.value]: e.target.checked
    })
    });
    };

    return (
    <>
    <ListItemButton onClick={handleClickOpen}>
    <ListItemText primary={primary} secondary={secondary} />
    </ListItemButton>
    <Dialog fullWidth open={open} onClose={handleClose}>
    <DialogTitle>{props.primary}</DialogTitle>

    <List>
    {items.map((item) => (
    <ListItem key={item.value}>
    <ListItemIcon>
    <Checkbox
    edge="start"
    checked={config[conf][item.value]}
    onChange={(e) => handleToggle(e, item)}


    />
    </ListItemIcon>
    <ListItemText primary={item.name} secondary={item.desc} />
    </ListItem>
    ))}
    </List>
    <DialogActions>
    <Button onClick={handleClose} color="primary">
    Close
    </Button>

    </DialogActions>
    </Dialog>
    </>
    )
    }

    const ListItemSwitch = (props) => {
    const [config, setConfig] = useConfig();
    return (
    <ListItem>
    <ListItemText primary={props.primary} secondary={props.secondary} />
    <Switch checked={config[props.conf]} onChange={(e) => setConfig(props.conf, e.target.checked)} />
    </ListItem>
    )
    }

    const App = () => {
    const [config, setConfig] = useConfig();

    const logcatbuffers = React.useMemo(() => Object.entries(config.logcatbuffers).map((buf) => {
    const key = buf[0]
    const value = buf[1]
    if (value) return key
    }).join(""), [config])

    const logcatlevels = React.useMemo(() => Object.entries(config.logcatlevels).map((lvl) => {
    const key = lvl[0]
    const value = lvl[1]
    if (value) return key
    }).join(""), [config])

    const commandString = React.useMemo(() => {
    let command = "";

    if (config.background) command += `${config.background} `;
    if (config.colors) {
    command += "colors ";
    } else {
    command += "logcatnocolors ";
    }
    if (config.wordwrap) command += "wordwrap ";
    if (config.save) command += "save ";

    if (logcatlevels.length !== 0) {
    command += `logcatlevels=${logcatlevels} `;
    }

    if (logcatbuffers.length !== 0) {
    command += `logcatbuffers=${logcatbuffers} `;
    }

    command += `logcatformat=${config.logcatformat} `;

    if (config.dmesg) {
    command += `dmesg=0-99 `;
    } else {
    command += `dmesg=0--1 `;
    }

    command += `lines=${config.lines} `;
    command += `fallbackwidth=${config.fallbackwidth} `;
    command += `fallbackheight=${config.fallbackheight}`;

    const parsedCommand = command.trim()

    SuFile.write("/data/adb/liveboot.args.txt", parsedCommand)

    return parsedCommand;
    }, [config])

    const findBackground = React.useMemo(() => backgroundsList.find((t) => t.value === config.background), [config.background])
    const findLogcatFormat = React.useMemo(() => logcatFormatsList.find((t) => t.value === config.logcatformat), [config.logcatformat])
    const findLogcatBuffers = React.useMemo(() => logcatBuffersList.filter((buf) => logcatbuffers.includes(buf.value)).map((n) => n.name), [config.logcatbuffers])
    const findLogcatLevels = React.useMemo(() => logcatLevelsList.filter((lvl) => logcatlevels.includes(lvl.value)).map((n) => n.name), [config.logcatlevels])

    return (
    <Page sx={{ p: 2 }} renderToolbar={RenderToolbar}>

    <CodeBlock lang="">{`liveboot ${commandString}`}</CodeBlock>

    <List subheader={<ListSubheader>Logcat appearence</ListSubheader>}>
    <ListItemSwitch conf="wordwrap" primary="Word wrap" />
    <ListItemSwitch conf="colors" primary="Colorful logs" />
    <ListItemSelectDialog conf="background" primary="Background" secondary={findBackground.name} items={backgroundsList} />
    </List>

    <Divider />

    <List subheader={<ListSubheader>Settings</ListSubheader>}>
    <ListItemSelectDialog conf="logcatformat" primary="Logcat format" secondary={findLogcatFormat.name} items={logcatFormatsList} />
    <ListItemCheckboxDialog conf="logcatbuffers" primary="Logcat buffers" secondary={findLogcatBuffers.join(", ")} items={logcatBuffersList} />
    <ListItemCheckboxDialog conf="logcatlevels" primary="Logcat levels" secondary={findLogcatLevels.join(", ")} items={logcatLevelsList} />
    </List>

    <Divider />

    <List subheader={<ListSubheader>Other</ListSubheader>}>
    <ListItemSwitch conf="save" primary="Save logs" />
    <ListItemSwitch conf="dmesg" primary="DMESG" />
    <TextField
    sx={{ m: 1, width: "calc(100% - 16px)" }}
    type="number"
    label="Lines"
    variant="outlined"
    value={config.lines}
    onInput={(e) => {
    e.target.value = Math.max(0, parseInt(e.target.value)).toString().slice(0, 5)
    }}
    onChange={(e) => setConfig("lines", e.target.value)} />
    </List>

    </Page>
    )
    }

    export default withRequireNewVersion({
    versionCode: 32325,
    component: () => {
    return (
    <ConfigProvider
    loadFromFile="/data/adb/liveboot.config.json"
    initialConfig={initialConfig}
    loader="json"
    >
    <App />
    </ConfigProvider>
    );
    },
    });