Add local iOS release pipeline, fix shortcuts, and improve invoice UX.

Enable App Store builds without EAS, iOS 18 App Intents plugins, and signing
fixes for distribution export. Add mobile invoice PDF preview, compact line
items, and more reliable shortcut deep-link handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-23 01:08:20 -04:00
parent 06bc91ac13
commit 355b14faef
35 changed files with 1915 additions and 502 deletions
+92
View File
@@ -0,0 +1,92 @@
import { Ionicons } from "@expo/vector-icons";
import { Pressable, StyleSheet, TextInput, View, type StyleProp, type ViewStyle } from "react-native";
import { fonts, radii } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
type CompactStepperInputProps = {
value: string;
onChangeText: (value: string) => void;
step?: number;
min?: number;
style?: StyleProp<ViewStyle>;
};
export function CompactStepperInput({
value,
onChangeText,
step = 0.25,
min = 0,
style,
}: CompactStepperInputProps) {
const { colors } = useAppTheme();
function adjust(delta: number) {
const current = Number.parseFloat(value) || 0;
const next = Math.max(min, Math.round((current + delta) * 100) / 100);
onChangeText(Number.isInteger(next) ? String(next) : String(next));
}
return (
<View
style={[
styles.field,
{ borderColor: colors.border, backgroundColor: colors.cardGlass },
style,
]}
>
<Pressable
accessibilityRole="button"
accessibilityLabel="Decrease hours"
hitSlop={4}
onPress={() => adjust(-step)}
style={({ pressed }) => [styles.stepButton, pressed && styles.pressed]}
>
<Ionicons name="remove" size={14} color={colors.foreground} />
</Pressable>
<TextInput
value={value}
onChangeText={onChangeText}
keyboardType="decimal-pad"
placeholder="0"
placeholderTextColor={colors.mutedForeground}
style={[styles.input, { color: colors.foreground }]}
/>
<Pressable
accessibilityRole="button"
accessibilityLabel="Increase hours"
hitSlop={4}
onPress={() => adjust(step)}
style={({ pressed }) => [styles.stepButton, pressed && styles.pressed]}
>
<Ionicons name="add" size={14} color={colors.foreground} />
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
field: {
minHeight: 36,
borderWidth: 1,
borderRadius: radii.md,
flexDirection: "row",
alignItems: "center",
},
stepButton: {
width: 28,
height: 36,
alignItems: "center",
justifyContent: "center",
},
pressed: {
opacity: 0.65,
},
input: {
flex: 1,
textAlign: "center",
fontSize: 13,
fontFamily: fonts.bodyMedium,
paddingVertical: 4,
},
});