Skip to content

Instantly share code, notes, and snippets.

@DerGoogler
Last active September 3, 2024 20:33
Show Gist options
  • Save DerGoogler/c24015d1a310809ab882a7d7f23ddd62 to your computer and use it in GitHub Desktop.
Save DerGoogler/c24015d1a310809ab882a7d7f23ddd62 to your computer and use it in GitHub Desktop.
ModConf prototype for the livebootmagisk module

fallbackwidth and fallbackheight are empty when you run the config in the browser

Note

The current version is messy.

image

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>
);
},
});
@symbuzzer
Copy link

@DerGoogler Isn't it possible to get the fallbackwidth and fallbackheight values ​​of the device with this code? Or at least run the shell command and use its output?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment