Fix: navbar being weird when in logs/settings menu

This commit is contained in:
appelmoesgg
2025-10-04 22:47:05 +02:00
parent 4c5276c2b2
commit ded6da019c
11 changed files with 158 additions and 100 deletions

View File

@@ -211,74 +211,82 @@ class Navigation(
val itemCount = selectedRoutes.size.coerceAtLeast(1)
val density = androidx.compose.ui.platform.LocalDensity.current
val selectedIndex = remember(currentRoute, selectedRoutes) {
selectedRoutes.indexOf(currentRoute).coerceAtLeast(0)
val index = selectedRoutes.indexOf(currentRoute)
if (index >= 0) index else null
}
val itemWidthPx = remember(barWidthPx, itemCount) { if (itemCount > 0) barWidthPx / itemCount else 0f }
val offsetAnim = remember { Animatable(0f) }
var lastSelectedIndex by remember { mutableStateOf(selectedIndex) }
LaunchedEffect(itemWidthPx) {
if (itemWidthPx > 0f) {
offsetAnim.snapTo(selectedIndex * itemWidthPx)
}
}
LaunchedEffect(selectedIndex, itemWidthPx) {
if (itemWidthPx <= 0f) return@LaunchedEffect
val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val damping = when {
dist >= 3 -> 0.65f
dist == 2 -> 0.75f
else -> 0.90f
}
val stiffness = Spring.StiffnessMediumLow
offsetAnim.animateTo(
targetValue = selectedIndex * itemWidthPx,
animationSpec = spring(dampingRatio = damping, stiffness = stiffness)
)
lastSelectedIndex = selectedIndex
}
val horizontalInset = 8.dp
val indicatorWidth = with(density) { itemWidthPx.toDp() } - horizontalInset * 2
Box(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned { barWidthPx = it.size.width.toFloat() }
) {
val motionProgress = remember { Animatable(1f) }
LaunchedEffect(selectedIndex) {
motionProgress.snapTo(0f)
val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val dur = when {
dist >= 3 -> 440
dist == 2 -> 380
else -> 320
selectedIndex?.let {
val itemWidthPx =
remember(barWidthPx, itemCount) { if (itemCount > 0) barWidthPx / itemCount else 0f }
val offsetAnim = remember { Animatable(0f) }
var lastSelectedIndex by remember { mutableStateOf(selectedIndex) }
LaunchedEffect(itemWidthPx) {
if (itemWidthPx > 0f) {
offsetAnim.snapTo(selectedIndex * itemWidthPx)
}
motionProgress.animateTo(1f, animationSpec = tween(durationMillis = dur, easing = FastOutSlowInEasing))
}
val pulse = sin(PI * motionProgress.value).toFloat()
val distForScale = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val scaleXBase = 0.18f
val scaleXExtra = 0.06f
val scaleYBase = 0.06f
val scaleYExtra = 0.02f
val mult = (distForScale - 1).coerceAtLeast(0)
val scaleXAnim = 1f + (scaleXBase + scaleXExtra * mult) * pulse
val scaleYAnim = 1f - (scaleYBase + scaleYExtra * mult) * pulse
if (barWidthPx > 0f && itemCount > 0) {
val offsetX = with(density) { offsetAnim.value.toDp() } + horizontalInset
Box(
modifier = Modifier
.fillMaxHeight()
.width(indicatorWidth.coerceAtLeast(0.dp))
.offset(x = offsetX)
.padding(vertical = 8.dp)
.graphicsLayer { scaleX = scaleXAnim; scaleY = scaleYAnim }
.clip(RoundedCornerShape(14.dp))
.background(MaterialTheme.colorScheme.primary.copy(alpha = 0.10f))
.border(
BorderStroke(1.dp, MaterialTheme.colorScheme.primary.copy(alpha = 0.30f)),
RoundedCornerShape(14.dp)
)
LaunchedEffect(selectedIndex, itemWidthPx) {
if (itemWidthPx <= 0f) return@LaunchedEffect
val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val damping = when {
dist >= 3 -> 0.65f
dist == 2 -> 0.75f
else -> 0.90f
}
val stiffness = Spring.StiffnessMediumLow
offsetAnim.animateTo(
targetValue = selectedIndex * itemWidthPx,
animationSpec = spring(dampingRatio = damping, stiffness = stiffness)
)
lastSelectedIndex = selectedIndex
}
val horizontalInset = 8.dp
val indicatorWidth = with(density) { itemWidthPx.toDp() } - horizontalInset * 2
Box(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned { barWidthPx = it.size.width.toFloat() }
) {
val motionProgress = remember { Animatable(1f) }
LaunchedEffect(selectedIndex) {
motionProgress.snapTo(0f)
val dist = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val dur = when {
dist >= 3 -> 440
dist == 2 -> 380
else -> 320
}
motionProgress.animateTo(
1f,
animationSpec = tween(durationMillis = dur, easing = FastOutSlowInEasing)
)
}
val pulse = sin(PI * motionProgress.value).toFloat()
val distForScale = kotlin.math.abs(selectedIndex - lastSelectedIndex).coerceAtLeast(1)
val scaleXBase = 0.18f
val scaleXExtra = 0.06f
val scaleYBase = 0.06f
val scaleYExtra = 0.02f
val mult = (distForScale - 1).coerceAtLeast(0)
val scaleXAnim = 1f + (scaleXBase + scaleXExtra * mult) * pulse
val scaleYAnim = 1f - (scaleYBase + scaleYExtra * mult) * pulse
if (barWidthPx > 0f && itemCount > 0) {
val offsetX = with(density) { offsetAnim.value.toDp() } + horizontalInset
Box(
modifier = Modifier
.fillMaxHeight()
.width(indicatorWidth.coerceAtLeast(0.dp))
.offset(x = offsetX)
.padding(vertical = 8.dp)
.graphicsLayer { scaleX = scaleXAnim; scaleY = scaleYAnim }
.clip(RoundedCornerShape(14.dp))
.background(MaterialTheme.colorScheme.primary.copy(alpha = 0.10f))
.border(
BorderStroke(1.dp, MaterialTheme.colorScheme.primary.copy(alpha = 0.30f)),
RoundedCornerShape(14.dp)
)
)
}
}
}
NavigationBar(

View File

@@ -4,9 +4,9 @@
"requires": true,
"packages": {
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -18,7 +18,7 @@ and limitations under the License.
// src/compiler/corePublic.ts
var versionMajorMinor = "5.9";
var version = "5.9.2";
var version = "5.9.3";
// src/compiler/core.ts
var emptyArray = [];
@@ -20254,10 +20254,22 @@ function createParenthesizerRules(factory2) {
}
return parenthesizerRule;
}
function mixingBinaryOperatorsRequiresParentheses(a, b) {
if (a === 61 /* QuestionQuestionToken */) {
return b === 56 /* AmpersandAmpersandToken */ || b === 57 /* BarBarToken */;
}
if (b === 61 /* QuestionQuestionToken */) {
return a === 56 /* AmpersandAmpersandToken */ || a === 57 /* BarBarToken */;
}
return false;
}
function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) {
const emittedOperand = skipPartiallyEmittedExpressions(operand);
if (isBinaryExpression(emittedOperand) && mixingBinaryOperatorsRequiresParentheses(binaryOperator, emittedOperand.operatorToken.kind)) {
return true;
}
const binaryOperatorPrecedence = getOperatorPrecedence(227 /* BinaryExpression */, binaryOperator);
const binaryOperatorAssociativity = getOperatorAssociativity(227 /* BinaryExpression */, binaryOperator);
const emittedOperand = skipPartiallyEmittedExpressions(operand);
if (!isLeftSideOfBinary && operand.kind === 220 /* ArrowFunction */ && binaryOperatorPrecedence > 3 /* Assignment */) {
return true;
}
@@ -53296,7 +53308,22 @@ function createTypeChecker(host) {
function getPropertyNameNodeForSymbol(symbol, context) {
const hashPrivateName = getClonedHashPrivateName(symbol);
if (hashPrivateName) {
return hashPrivateName;
const shouldEmitErroneousFieldName = !!context.tracker.reportPrivateInBaseOfClassExpression && context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */;
if (!shouldEmitErroneousFieldName) {
return hashPrivateName;
} else {
let rawName2 = unescapeLeadingUnderscores(symbol.escapedName);
rawName2 = rawName2.replace(/__#\d+@#/g, "__#private@#");
return createPropertyNameNodeForIdentifierOrLiteral(
rawName2,
getEmitScriptTarget(compilerOptions),
/*singleQuote*/
false,
/*stringNamed*/
true,
!!(symbol.flags & 8192 /* Method */)
);
}
}
const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed);
const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed);
@@ -124188,10 +124215,9 @@ function createProgram(_rootNamesOrOptions, _options, _host, _oldProgram, _confi
}
const getCommonSourceDirectory3 = memoize(() => getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames()));
commandLine.fileNames.forEach((fileName) => {
if (isDeclarationFileName(fileName)) return;
const path = toPath3(fileName);
let outputDts;
if (!fileExtensionIs(fileName, ".json" /* Json */)) {
if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, ".json" /* Json */)) {
if (!commandLine.options.outFile) {
outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory3);
mapOutputFileToResolvedRef.set(toPath3(outputDts), { resolvedRef, source: fileName });

View File

@@ -374,6 +374,8 @@ interface Float16ArrayConstructor {
new (length?: number): Float16Array<ArrayBuffer>;
new (array: ArrayLike<number> | Iterable<number>): Float16Array<ArrayBuffer>;
new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(buffer: TArrayBuffer, byteOffset?: number, length?: number): Float16Array<TArrayBuffer>;
new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float16Array<ArrayBuffer>;
new (array: ArrayLike<number> | ArrayBuffer): Float16Array<ArrayBuffer>;
/**
* The size in bytes of each element in the array.

View File

@@ -5907,7 +5907,6 @@ declare namespace ts {
*/
interface SourceFileLike {
readonly text: string;
languageVariant?: LanguageVariant;
}
interface SourceFileLike {
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;

View File

@@ -2285,7 +2285,7 @@ module.exports = __toCommonJS(typescript_exports);
// src/compiler/corePublic.ts
var versionMajorMinor = "5.9";
var version = "5.9.2";
var version = "5.9.3";
var Comparison = /* @__PURE__ */ ((Comparison3) => {
Comparison3[Comparison3["LessThan"] = -1] = "LessThan";
Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo";
@@ -6790,10 +6790,10 @@ var ScriptTarget = /* @__PURE__ */ ((ScriptTarget12) => {
ScriptTarget12[ScriptTarget12["Latest"] = 99 /* ESNext */] = "Latest";
return ScriptTarget12;
})(ScriptTarget || {});
var LanguageVariant = /* @__PURE__ */ ((LanguageVariant3) => {
LanguageVariant3[LanguageVariant3["Standard"] = 0] = "Standard";
LanguageVariant3[LanguageVariant3["JSX"] = 1] = "JSX";
return LanguageVariant3;
var LanguageVariant = /* @__PURE__ */ ((LanguageVariant4) => {
LanguageVariant4[LanguageVariant4["Standard"] = 0] = "Standard";
LanguageVariant4[LanguageVariant4["JSX"] = 1] = "JSX";
return LanguageVariant4;
})(LanguageVariant || {});
var WatchDirectoryFlags = /* @__PURE__ */ ((WatchDirectoryFlags3) => {
WatchDirectoryFlags3[WatchDirectoryFlags3["None"] = 0] = "None";
@@ -24351,10 +24351,22 @@ function createParenthesizerRules(factory2) {
}
return parenthesizerRule;
}
function mixingBinaryOperatorsRequiresParentheses(a, b) {
if (a === 61 /* QuestionQuestionToken */) {
return b === 56 /* AmpersandAmpersandToken */ || b === 57 /* BarBarToken */;
}
if (b === 61 /* QuestionQuestionToken */) {
return a === 56 /* AmpersandAmpersandToken */ || a === 57 /* BarBarToken */;
}
return false;
}
function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) {
const emittedOperand = skipPartiallyEmittedExpressions(operand);
if (isBinaryExpression(emittedOperand) && mixingBinaryOperatorsRequiresParentheses(binaryOperator, emittedOperand.operatorToken.kind)) {
return true;
}
const binaryOperatorPrecedence = getOperatorPrecedence(227 /* BinaryExpression */, binaryOperator);
const binaryOperatorAssociativity = getOperatorAssociativity(227 /* BinaryExpression */, binaryOperator);
const emittedOperand = skipPartiallyEmittedExpressions(operand);
if (!isLeftSideOfBinary && operand.kind === 220 /* ArrowFunction */ && binaryOperatorPrecedence > 3 /* Assignment */) {
return true;
}
@@ -57907,7 +57919,22 @@ function createTypeChecker(host) {
function getPropertyNameNodeForSymbol(symbol, context) {
const hashPrivateName = getClonedHashPrivateName(symbol);
if (hashPrivateName) {
return hashPrivateName;
const shouldEmitErroneousFieldName = !!context.tracker.reportPrivateInBaseOfClassExpression && context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */;
if (!shouldEmitErroneousFieldName) {
return hashPrivateName;
} else {
let rawName2 = unescapeLeadingUnderscores(symbol.escapedName);
rawName2 = rawName2.replace(/__#\d+@#/g, "__#private@#");
return createPropertyNameNodeForIdentifierOrLiteral(
rawName2,
getEmitScriptTarget(compilerOptions),
/*singleQuote*/
false,
/*stringNamed*/
true,
!!(symbol.flags & 8192 /* Method */)
);
}
}
const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed);
const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed);
@@ -129038,10 +129065,9 @@ function createProgram(_rootNamesOrOptions, _options, _host, _oldProgram, _confi
}
const getCommonSourceDirectory3 = memoize(() => getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames()));
commandLine.fileNames.forEach((fileName) => {
if (isDeclarationFileName(fileName)) return;
const path = toPath3(fileName);
let outputDts;
if (!fileExtensionIs(fileName, ".json" /* Json */)) {
if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, ".json" /* Json */)) {
if (!commandLine.options.outFile) {
outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory3);
mapOutputFileToResolvedRef.set(toPath3(outputDts), { resolvedRef, source: fileName });
@@ -140403,7 +140429,7 @@ function isInsideJsxElementOrAttribute(sourceFile, position) {
if (token && token.kind === 20 /* CloseBraceToken */ && token.parent.kind === 295 /* JsxExpression */) {
return true;
}
if (token.kind === 31 /* LessThanSlashToken */ && token.parent.kind === 288 /* JsxClosingElement */) {
if (token.kind === 30 /* LessThanToken */ && token.parent.kind === 288 /* JsxClosingElement */) {
return true;
}
return false;
@@ -140431,7 +140457,7 @@ function isInJSXText(sourceFile, position) {
function isInsideJsxElement(sourceFile, position) {
function isInsideJsxElementTraversal(node) {
while (node) {
if (node.kind >= 286 /* JsxSelfClosingElement */ && node.kind <= 295 /* JsxExpression */ || node.kind === 12 /* JsxText */ || node.kind === 30 /* LessThanToken */ || node.kind === 32 /* GreaterThanToken */ || node.kind === 80 /* Identifier */ || node.kind === 20 /* CloseBraceToken */ || node.kind === 19 /* OpenBraceToken */ || node.kind === 44 /* SlashToken */ || node.kind === 31 /* LessThanSlashToken */) {
if (node.kind >= 286 /* JsxSelfClosingElement */ && node.kind <= 295 /* JsxExpression */ || node.kind === 12 /* JsxText */ || node.kind === 30 /* LessThanToken */ || node.kind === 32 /* GreaterThanToken */ || node.kind === 80 /* Identifier */ || node.kind === 20 /* CloseBraceToken */ || node.kind === 19 /* OpenBraceToken */ || node.kind === 44 /* SlashToken */) {
node = node.parent;
} else if (node.kind === 285 /* JsxElement */) {
if (position > node.getStart(sourceFile)) return true;
@@ -151873,9 +151899,7 @@ function createChildren(node, sourceFile) {
});
return children;
}
const languageVariant = (sourceFile == null ? void 0 : sourceFile.languageVariant) ?? 0 /* Standard */;
scanner.setText((sourceFile || node.getSourceFile()).text);
scanner.setLanguageVariant(languageVariant);
let pos = node.pos;
const processNode = (child) => {
addSyntheticNodes(children, pos, child.pos, node);
@@ -151892,7 +151916,6 @@ function createChildren(node, sourceFile) {
node.forEachChild(processNode, processNodes);
addSyntheticNodes(children, pos, node.end, node);
scanner.setText(void 0);
scanner.setLanguageVariant(0 /* Standard */);
return children;
}
function addSyntheticNodes(nodes, pos, end, parent2) {
@@ -167606,7 +167629,7 @@ function getJsxClosingTagCompletion(location, sourceFile) {
switch (node.kind) {
case 288 /* JsxClosingElement */:
return true;
case 31 /* LessThanSlashToken */:
case 44 /* SlashToken */:
case 32 /* GreaterThanToken */:
case 80 /* Identifier */:
case 212 /* PropertyAccessExpression */:
@@ -168942,7 +168965,7 @@ function getCompletionData(program, log, sourceFile, compilerOptions, position,
location = currentToken;
}
break;
case 31 /* LessThanSlashToken */:
case 44 /* SlashToken */:
if (currentToken.parent.kind === 286 /* JsxSelfClosingElement */) {
location = currentToken;
}
@@ -168951,7 +168974,7 @@ function getCompletionData(program, log, sourceFile, compilerOptions, position,
}
switch (parent2.kind) {
case 288 /* JsxClosingElement */:
if (contextToken.kind === 31 /* LessThanSlashToken */) {
if (contextToken.kind === 44 /* SlashToken */) {
isStartingCloseTag = true;
location = contextToken;
}
@@ -170572,7 +170595,7 @@ function isValidTrigger(sourceFile, triggerCharacter, contextToken, position) {
case "<":
return !!contextToken && contextToken.kind === 30 /* LessThanToken */ && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
case "/":
return !!contextToken && (isStringLiteralLike(contextToken) ? !!tryGetImportFromModuleSpecifier(contextToken) : contextToken.kind === 31 /* LessThanSlashToken */ && isJsxClosingElement(contextToken.parent));
return !!contextToken && (isStringLiteralLike(contextToken) ? !!tryGetImportFromModuleSpecifier(contextToken) : contextToken.kind === 44 /* SlashToken */ && isJsxClosingElement(contextToken.parent));
case " ":
return !!contextToken && isImportKeyword(contextToken) && contextToken.parent.kind === 308 /* SourceFile */;
default:

View File

@@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "https://www.typescriptlang.org/",
"version": "5.9.2",
"version": "5.9.3",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [
@@ -116,5 +116,5 @@
"node": "20.1.0",
"npm": "8.19.4"
},
"gitHead": "5be33469d551655d878876faa9e30aa3b49f8ee9"
"gitHead": "c63de15a992d37f0d6cec03ac7631872838602cb"
}

View File

@@ -5,13 +5,13 @@
"packages": {
"": {
"dependencies": {
"typescript": "^5.9.2"
"typescript": "^5.9.3"
}
},
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -1,5 +1,5 @@
{
"dependencies": {
"typescript": "^5.9.2"
"typescript": "^5.9.3"
}
}

View File

@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xms4G -Xmx4G -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xms12G -Xmx12G -Dfile.encoding=UTF-8
org.gradle.parallel=true
android.useAndroidX=true
kotlin.code.style=official

View File

@@ -674,7 +674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "PurrfectSnap"
name = "snapenhance"
version = "0.1.0"
dependencies = [
"android-ndk",