package com.vgmlr.wedge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Undo
import androidx.compose.material.icons.automirrored.outlined.ExitToApp
import androidx.compose.material.icons.automirrored.outlined.Sort
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditorTopBar(
menuExpanded: Boolean,
onMenuExpandedChange: (Boolean) -> Unit,
showCopyDot: Boolean,
showPasteDot: Boolean,
undoEnabled: Boolean,
onCopy: () -> Unit,
onPaste: () -> Unit,
onUndo: () -> Unit,
onSelectAll: () -> Unit,
onSort: () -> Unit,
onToggleCalc: () -> Unit,
showCalc: Boolean,
onShowData: () -> Unit,
onExport: () -> Unit,
onSettings: () -> Unit,
onShowVersion: () -> Unit,
isEncrypted: Boolean,
onSecurityAction: () -> Unit,
// onSync: () -> Unit
) {
TopAppBar(
title = { },
colors = TopAppBarDefaults.topAppBarColors(containerColor = colorResource(id = R.color.primary_color)),
actions = {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("wedge", color = colorResource(id = R.color.title_color), fontSize = 18.sp)
Spacer(Modifier.width(10.dp))
IconButton(
onClick = onUndo,
enabled = undoEnabled
) {
Icon(
Icons.AutoMirrored.Filled.Undo,
contentDescription = "Undo",
tint = if (undoEnabled) colorResource(id = R.color.title_color) else colorResource(id = R.color.title_color).copy(alpha = 0.3f)
)
}
IconButton(onClick = onCopy) {
Box {
Icon(Icons.Outlined.ContentCopy, "Copy", tint = colorResource(id = R.color.title_color))
if (showCopyDot) {
Box(
modifier = Modifier
.size(6.dp)
.align(Alignment.TopEnd)
.background(
colorResource(id = R.color.title_color),
shape = androidx.compose.foundation.shape.CircleShape
)
)
}
}
}
IconButton(onClick = onPaste) {
Box {
Icon(Icons.Outlined.ContentPaste, "Paste", tint = colorResource(id = R.color.title_color))
if (showPasteDot) {
Box(
modifier = Modifier
.size(6.dp)
.align(Alignment.TopEnd)
.background(
colorResource(id = R.color.title_color),
shape = androidx.compose.foundation.shape.CircleShape
)
)
}
}
}
IconButton(onClick = onSort) {
Box {
Icon(Icons.AutoMirrored.Outlined.Sort, "Sort", tint = colorResource(id = R.color.title_color))
}
}
Box {
IconButton(onClick = { onMenuExpandedChange(true) }) {
Icon(Icons.Default.MoreVert, null, tint = colorResource(id = R.color.title_color))
}
DropdownMenu(
expanded = menuExpanded,
onDismissRequest = { onMenuExpandedChange(false) },
modifier = Modifier
.background(colorResource(id = R.color.menu_bg_color))
.padding(horizontal = 6.dp)
) {
DropdownMenuItem(
text = { Text("Select All", color = colorResource(id = R.color.menu_color)) },
onClick = onSelectAll,
leadingIcon = { Icon(Icons.Outlined.SelectAll, null, tint = colorResource(id = R.color.menu_color)) }
)
HorizontalDivider(
modifier = Modifier.padding(vertical = 8.dp),
color = colorResource(id = R.color.hr_color).copy(0.4f),
thickness = 1.dp
)
DropdownMenuItem(
text = { Text(if (isEncrypted) "Decrypt" else "Encrypt", color = colorResource(id = R.color.menu_color)) },
onClick = onSecurityAction,
leadingIcon = {
Icon(
if (isEncrypted) Icons.Outlined.LockOpen else Icons.Outlined.Lock,
null,
tint = colorResource(id = R.color.menu_color)
)
}
)
DropdownMenuItem(
text = { Text("Sync", color = colorResource(id = R.color.menu_color)) },
onClick = onSettings,
leadingIcon = { Icon(Icons.Outlined.Loop, null, tint = colorResource(id = R.color.menu_color)) }
)
DropdownMenuItem(
text = { Text("Export", color = colorResource(id = R.color.menu_color)) },
onClick = onExport,
leadingIcon = { Icon(Icons.AutoMirrored.Outlined.ExitToApp, null, tint = colorResource(id = R.color.menu_color)) }
)
HorizontalDivider(
modifier = Modifier.padding(vertical = 8.dp),
color = colorResource(id = R.color.hr_color).copy(0.4f),
thickness = 1.dp
)
DropdownMenuItem(
text = { Text("Data", color = colorResource(id = R.color.menu_color)) },
onClick = onShowData,
leadingIcon = { Icon(Icons.Outlined.DataArray, null, tint = colorResource(id = R.color.menu_color)) }
)
DropdownMenuItem(
text = { Text("Settings", color = colorResource(id = R.color.menu_color)) },
onClick = onSettings,
leadingIcon = { Icon(Icons.Outlined.Settings, null, tint = colorResource(id = R.color.menu_color)) }
)
DropdownMenuItem(
text = { Text("Version", color = colorResource(id = R.color.menu_color)) },
onClick = onShowVersion,
leadingIcon = { Icon(Icons.Outlined.History, null, tint = colorResource(id = R.color.menu_color)) }
)
}
}
}
}
)
}
@Composable
fun CalculatorOverlay(
calcValue: String,
onCalcValueChange: (String) -> Unit,
onDismiss: () -> Unit,
focusRequester: FocusRequester
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
.background(colorResource(id = R.color.calc_bg_color))
) {
IconButton(
onClick = { if (calcValue.isEmpty()) onDismiss() else onCalcValueChange("") },
modifier = Modifier.align(Alignment.CenterStart)
) { Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.4f)) }
BasicTextField(
value = calcValue,
onValueChange = { onCalcValueChange(if (it.endsWith("=")) WedgeCalculator.doCalc(it.dropLast(1)) else it) },
modifier = Modifier
.fillMaxWidth()
.padding(start = 48.dp, end = 22.dp)
.align(Alignment.Center)
.focusRequester(focusRequester),
textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 19.sp, textAlign = TextAlign.End, fontFamily = FontFamily.Monospace),
cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { onCalcValueChange(WedgeCalculator.doCalc(calcValue)) }),
singleLine = true,
decorationBox = { inner ->
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
if (calcValue.isEmpty()) Text("0", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.6f), fontSize = 19.sp, textAlign = TextAlign.End, fontFamily = FontFamily.Monospace))
inner()
}
}
)
}
}
@Composable
fun EncryptionOverlay(
passPhrase: String,
onPassPhraseChange: (String) -> Unit,
onAction: () -> Unit,
onDismiss: () -> Unit,
focusRequester: FocusRequester,
isDecrypt: Boolean = false
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
.background(colorResource(id = R.color.calc_bg_color))
) {
IconButton(
onClick = onAction,
enabled = passPhrase.isNotEmpty(),
modifier = Modifier.align(Alignment.CenterStart)
) {
Icon(
if (isDecrypt) Icons.Outlined.LockOpen else Icons.Outlined.Lock,
contentDescription = null,
modifier = Modifier.padding(start = 3.dp),
tint = if (passPhrase.isNotEmpty()) colorResource(id = R.color.calc_color) else colorResource(id = R.color.calc_color).copy(alpha = 0.4f)
)
}
BasicTextField(
value = passPhrase,
onValueChange = onPassPhraseChange,
modifier = Modifier
.fillMaxWidth()
.padding(start = 58.dp, end = 48.dp)
.align(Alignment.Center)
.focusRequester(focusRequester),
textStyle = TextStyle(
colorResource(id = R.color.calc_color),
fontSize = 16.sp,
textAlign = TextAlign.Start,
fontFamily = FontFamily.Monospace
),
cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done,
keyboardType = KeyboardType.Password
),
keyboardActions = KeyboardActions(onDone = { if(passPhrase.isNotEmpty()) onAction() }),
singleLine = true,
decorationBox = { inner ->
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterStart) {
if (passPhrase.isEmpty()) Text(
if (isDecrypt) "Pass Phrase" else "Pass Phrase",
style = TextStyle(
colorResource(id = R.color.calc_color).copy(alpha = 0.6f),
fontSize = 16.sp,
textAlign = TextAlign.Start,
fontFamily = FontFamily.Monospace
)
)
inner()
}
}
)
IconButton(
onClick = onDismiss,
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 3.dp),
) { Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.4f)) }
}
}
@Composable
fun CalendarOverlay(
daySelected: String,
onDaySelectedChange: (String) -> Unit,
timeValue: String,
onTimeValueChange: (String) -> Unit,
textValue: String,
onTextValueChange: (String) -> Unit,
onDismiss: () -> Unit,
onEnterPressed: () -> Unit,
focusRequester: FocusRequester
) {
val focusManager = LocalFocusManager.current
Box(
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
.background(colorResource(id = R.color.calc_bg_color))
) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(start = 8.dp, end = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(7.dp)
) {
BasicTextField(
value = daySelected,
onValueChange = onDaySelectedChange,
modifier = Modifier
.width(40.dp)
.padding(end = 4.dp),
textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.End),
cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
singleLine = true,
decorationBox = { inner ->
Box(contentAlignment = Alignment.CenterEnd) {
if (daySelected.isEmpty()) Text("Date", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, textAlign = TextAlign.End))
inner()
}
}
)
BasicTextField(
value = timeValue,
onValueChange = { if (it.length <= 5) onTimeValueChange(it) },
modifier = Modifier
.width(65.dp)
.background(
Color.White.copy(alpha = 0.05f),
androidx.compose.foundation.shape.RoundedCornerShape(4.dp)
)
.padding(8.dp)
.focusRequester(focusRequester)
.onPreviewKeyEvent { keyEvent ->
if (keyEvent.key == Key.Enter || keyEvent.key == Key.NumPadEnter) {
focusManager.moveFocus(FocusDirection.Next)
true
} else {
false
}
},
textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.Center),
cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(
onNext = { focusManager.moveFocus(FocusDirection.Next) }
),
decorationBox = { inner ->
Box(contentAlignment = Alignment.Center) {
if (timeValue.isEmpty()) Text("HHMM", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.Center))
inner()
}
}
)
BasicTextField(
value = textValue,
onValueChange = onTextValueChange,
modifier = Modifier
.weight(1f)
.background(
Color.White.copy(alpha = 0.05f),
androidx.compose.foundation.shape.RoundedCornerShape(4.dp)
)
.padding(8.dp),
textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace),
cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
singleLine = true,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { onEnterPressed() }),
decorationBox = { inner ->
Box(contentAlignment = Alignment.CenterStart) {
if (textValue.isEmpty()) Text("Event", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, fontFamily = FontFamily.Monospace))
inner()
}
}
)
IconButton(
onClick = onDismiss,
modifier = Modifier.size(36.dp)
) {
Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.6f))
}
}
}
}