From 2dab52c1b44fc615df7421db8ea264a486a030d9 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Tue, 20 Jan 2026 21:25:13 +0100 Subject: [PATCH] Update mobile app to use generic item type icons (#1465) --- .../app/vaultstore/models/ItemTypeIcons.kt | 95 +++++++++ apps/mobile-app/components/items/ItemIcon.tsx | 195 +++--------------- .../items/ItemTypeIconComponents.tsx | 82 ++++++++ .../ios/AliasVault.xcodeproj/project.pbxproj | 2 +- .../ios/VaultModels/ItemTypeIcons.swift | 79 +++++++ .../ios/VaultUI/Components/ItemLogoView.swift | 100 ++++----- .../ios/VaultUI/Components/ItemTypeIcon.swift | 159 -------------- .../utils/dist/core/models/icons/index.d.ts | 64 ++++++ .../utils/dist/core/models/icons/index.js | 82 ++++++++ 9 files changed, 479 insertions(+), 379 deletions(-) create mode 100644 apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/ItemTypeIcons.kt create mode 100644 apps/mobile-app/components/items/ItemTypeIconComponents.tsx create mode 100644 apps/mobile-app/ios/VaultModels/ItemTypeIcons.swift delete mode 100644 apps/mobile-app/ios/VaultUI/Components/ItemTypeIcon.swift create mode 100644 apps/mobile-app/utils/dist/core/models/icons/index.d.ts create mode 100644 apps/mobile-app/utils/dist/core/models/icons/index.js diff --git a/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/ItemTypeIcons.kt b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/ItemTypeIcons.kt new file mode 100644 index 000000000..ca55311c8 --- /dev/null +++ b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/ItemTypeIcons.kt @@ -0,0 +1,95 @@ +// +// This file is auto-generated from core/models/src/icons/ItemTypeIcons.ts +// Do not edit this file directly. Run 'npm run generate:models' to regenerate. +@file:Suppress("MaxLineLength") + +package net.aliasvault.app.vaultstore.models + +/** + * Centralized SVG icon definitions for item types. + * Single source of truth for all item type icons across platforms. + */ +object ItemTypeIcons { + /** + * Placeholder icon SVG. + */ + val PLACEHOLDER = """ + + + + + + + + """.trimIndent() + + /** + * Note icon SVG. + */ + val NOTE = """ + + + + + + + + """.trimIndent() + + /** + * CreditCard icon SVG. + */ + val CREDIT_CARD = """ + + + + + + + """.trimIndent() + + /** + * Visa icon SVG. + */ + val VISA = """ + + + + + """.trimIndent() + + /** + * Mastercard icon SVG. + */ + val MASTERCARD = """ + + + + + + + """.trimIndent() + + /** + * Amex icon SVG. + */ + val AMEX = """ + + + AMEX + + """.trimIndent() + + /** + * Discover icon SVG. + */ + val DISCOVER = """ + + + + + + + + """.trimIndent() +} diff --git a/apps/mobile-app/components/items/ItemIcon.tsx b/apps/mobile-app/components/items/ItemIcon.tsx index 08b897a4e..2c305f21e 100644 --- a/apps/mobile-app/components/items/ItemIcon.tsx +++ b/apps/mobile-app/components/items/ItemIcon.tsx @@ -1,14 +1,24 @@ import { Buffer } from 'buffer'; import { Image, ImageStyle, StyleSheet, View } from 'react-native'; -import Svg, { Circle, Path, Rect, Text as SvgText } from 'react-native-svg'; import { SvgUri } from 'react-native-svg'; import type { Item } from '@/utils/dist/core/models/vault'; -import { ItemTypes, FieldKey } from '@/utils/dist/core/models/vault'; +import { + ItemTypes, + FieldKey, +} from '@/utils/dist/core/models/vault'; import servicePlaceholder from '@/assets/images/service-placeholder.webp'; +// Import centralized icon components (auto-generated from core/models/src/icons/ItemTypeIcons.ts) +import { + iconComponents, + PlaceholderIcon, + NoteIcon, + type IconKey, +} from './ItemTypeIconComponents'; + /** * Item icon props - supports both legacy logo-only mode and new item-based mode. */ @@ -21,179 +31,27 @@ type ItemIconProps = { }; /** - * Credit card brand type + * Detect credit card brand from card number using BIN prefixes. */ -type CardBrand = 'visa' | 'mastercard' | 'amex' | 'discover' | 'generic'; +const detectCardBrand = (cardNumber: string | undefined): IconKey => { + if (!cardNumber) return 'CreditCard'; -/** - * Detect credit card brand from card number using industry-standard prefixes - * @param cardNumber - The card number to detect brand from - * @returns The detected card brand - */ -const detectCardBrand = (cardNumber: string | undefined): CardBrand => { - if (!cardNumber) { - return 'generic'; - } - - // Remove spaces and dashes const cleaned = cardNumber.replace(/[\s-]/g, ''); + if (!/^\d{4,}/.test(cleaned)) return 'CreditCard'; - // Must be mostly numeric - if (!/^\d{4,}/.test(cleaned)) { - return 'generic'; - } + if (/^4/.test(cleaned)) return 'Visa'; + if (/^5[1-5]/.test(cleaned) || /^2[2-7]/.test(cleaned)) return 'Mastercard'; + if (/^3[47]/.test(cleaned)) return 'Amex'; + if (/^6(?:011|22|4[4-9]|5)/.test(cleaned)) return 'Discover'; - // Visa: starts with 4 - if (/^4/.test(cleaned)) { - return 'visa'; - } - - // Mastercard: starts with 51-55 or 2221-2720 - if (/^5[1-5]/.test(cleaned) || /^2[2-7]/.test(cleaned)) { - return 'mastercard'; - } - - // Amex: starts with 34 or 37 - if (/^3[47]/.test(cleaned)) { - return 'amex'; - } - - // Discover: starts with 6011, 622, 644-649, 65 - if (/^6(?:011|22|4[4-9]|5)/.test(cleaned)) { - return 'discover'; - } - - return 'generic'; + return 'CreditCard'; }; /** - * Generic credit card icon in AliasVault style + * Get the appropriate icon component for a card number. */ -const CreditCardIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - - - -); - -/** - * Visa card icon in AliasVault style - */ -const VisaIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - -); - -/** - * Mastercard icon in AliasVault style - */ -const MastercardIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - - - -); - -/** - * Amex card icon in AliasVault style - */ -const AmexIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - AMEX - - -); - -/** - * Discover card icon in AliasVault style - */ -const DiscoverIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - - - - -); - -/** - * Note/document icon in AliasVault style - */ -const NoteIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - - - - - - -); - -/** - * Placeholder icon for Login/Alias items - traditional key design with outline style - */ -const PlaceholderIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }) => ( - - {/* Key bow (circular head) - positioned top-left */} - - {/* Key hole in bow */} - - {/* Key shaft - diagonal */} - - {/* Key teeth - perpendicular to shaft */} - - - -); - -/** - * Get the appropriate icon component based on card brand - */ -const getCardIcon = (brand: CardBrand) => { - switch (brand) { - case 'visa': - return VisaIcon; - case 'mastercard': - return MastercardIcon; - case 'amex': - return AmexIcon; - case 'discover': - return DiscoverIcon; - default: - return CreditCardIcon; - } +const getCardIconComponent = (cardNumber: string | undefined) => { + return iconComponents[detectCardBrand(cardNumber)]; }; /** @@ -221,8 +79,7 @@ export function ItemIcon({ logo, item, style }: ItemIconProps) : React.ReactNode ? (Array.isArray(cardNumberField.Value) ? cardNumberField.Value[0] : cardNumberField.Value) : undefined; - const brand = detectCardBrand(cardNumber); - const CardIcon = getCardIcon(brand); + const CardIcon = getCardIconComponent(cardNumber); return ( @@ -418,4 +275,4 @@ const styles = StyleSheet.create({ borderRadius: 4, overflow: 'hidden', }, -}); \ No newline at end of file +}); diff --git a/apps/mobile-app/components/items/ItemTypeIconComponents.tsx b/apps/mobile-app/components/items/ItemTypeIconComponents.tsx new file mode 100644 index 000000000..330af6e90 --- /dev/null +++ b/apps/mobile-app/components/items/ItemTypeIconComponents.tsx @@ -0,0 +1,82 @@ +// +// This file is auto-generated from core/models/src/icons/ItemTypeIcons.ts +// Do not edit this file directly. Run 'npm run generate:models' to regenerate. + +import React from 'react'; +import Svg, { Circle, Path, Rect, Text as SvgText } from 'react-native-svg'; + +export const PlaceholderIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + + + + +); + +export const NoteIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + + + + +); + +export const CreditCardIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + + + +); + +export const VisaIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + +); + +export const MastercardIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + + + +); + +export const AmexIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + AMEX + +); + +export const DiscoverIcon = ({ width = 32, height = 32 }: { width?: number; height?: number }): React.ReactElement => ( + + + + + + + +); +/** + * Map of icon key to React Native SVG component. + */ +export const iconComponents = { + Placeholder: PlaceholderIcon, + Note: NoteIcon, + CreditCard: CreditCardIcon, + Visa: VisaIcon, + Mastercard: MastercardIcon, + Amex: AmexIcon, + Discover: DiscoverIcon, +}; + +export type IconKey = keyof typeof iconComponents; diff --git a/apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj b/apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj index 8b37a5687..47180dca3 100644 --- a/apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj +++ b/apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ diff --git a/apps/mobile-app/ios/VaultModels/ItemTypeIcons.swift b/apps/mobile-app/ios/VaultModels/ItemTypeIcons.swift new file mode 100644 index 000000000..063980144 --- /dev/null +++ b/apps/mobile-app/ios/VaultModels/ItemTypeIcons.swift @@ -0,0 +1,79 @@ +// +// This file is auto-generated from core/models/src/icons/ItemTypeIcons.ts +// Do not edit this file directly. Run 'npm run generate:models' to regenerate. +// swiftlint:disable line_length + +import Foundation + +/// Centralized SVG icon definitions for item types. +/// Single source of truth for all item type icons across platforms. +public struct ItemTypeIcons { + /// Placeholder icon SVG. + public static let placeholder = """ + + + + + + + +""" + + /// Note icon SVG. + public static let note = """ + + + + + + + +""" + + /// CreditCard icon SVG. + public static let creditCard = """ + + + + + + +""" + + /// Visa icon SVG. + public static let visa = """ + + + + +""" + + /// Mastercard icon SVG. + public static let mastercard = """ + + + + + + +""" + + /// Amex icon SVG. + public static let amex = """ + + + AMEX + +""" + + /// Discover icon SVG. + public static let discover = """ + + + + + + + +""" +} diff --git a/apps/mobile-app/ios/VaultUI/Components/ItemLogoView.swift b/apps/mobile-app/ios/VaultUI/Components/ItemLogoView.swift index 9c2315129..f72b9371c 100644 --- a/apps/mobile-app/ios/VaultUI/Components/ItemLogoView.swift +++ b/apps/mobile-app/ios/VaultUI/Components/ItemLogoView.swift @@ -1,34 +1,56 @@ import SwiftUI import Macaw +import VaultModels /// Item logo view - displays logos or type-based icons for items public struct ItemLogoView: View { - private let placeholderImageBase64 = "UklGRjoEAABXRUJQVlA4IC4EAAAwFwCdASqAAIAAPpFCm0olo6Ihp5IraLASCWUA0eb/0s56RrLtCnYfLPiBshdXWMx8j1Ez65f169iA4xUDBTEV6ylMQeCIj2b7RngGi7gKZ9WjKdSoy9R8JcgOmjCMlDmLG20KhNo/i/Dc/Ah5GAvGfm8kfniV3AkR6fxN6eKwjDc6xrDgSfS48G5uGV6WzQt24YAVlLSK9BMwndzfHnePK1KFchFrL7O3ulB8cGNCeomu4o+l0SrS/JKblJ4WTzj0DAD++lCUEouSfgRKdiV2TiYCD+H+l3tANKSPQFPQuzi7rbvxqGeRmXB9kDwURaoSTTpYjA9REMUi9uA6aV7PWtBNXgUzMLowYMZeos6Xvyhb34GmufswMHA5ZyYpxzjTphOak4ZjNOiz8aScO5ygiTx99SqwX/uL+HSeVOSraHw8IymrMwm+jLxqN8BS8dGcItLlm/ioulqH2j4V8glDgSut+ExkxiD7m8TGPrrjCQNJbRDzpOFsyCyfBZupvp8QjGKW2KGziSZeIWes4aTB9tRmeEBhnUrmTDZQuXcc67Fg82KHrSfaeeOEq6jjuUjQ8wUnzM4Zz3dhrwSyslVz/WvnKqYkr4V/TTXPFF5EjF4rM1bHZ8bK63EfTnK41+n3n4gEFoYP4mXkNH0hntnYcdTqiE7Gn+q0BpRRxnkpBSZlA6Wa70jpW0FGqkw5e591A5/H+OV+60WAo+4Mi+NlsKrvLZ9EiVaPnoEFZlJQx1fA777AJ2MjXJ4KSsrWDWJi1lE8yPs8V6XvcC0chDTYt8456sKXAagCZyY+fzQriFMaddXyKQdG8qBqcdYjAsiIcjzaRFBBoOK9sU+sFY7N6B6+xtrlu3c37rQKkI3O2EoiJOris54EjJ5OFuumA0M6riNUuBf/MEPFBVx1JRcUEs+upEBsCnwYski7FT3TTqHrx7v5AjgFN97xhPTkmVpu6sxRnWBi1fxIRp8eWZeFM6mUcGgVk1WeVb1yhdV9hoMo2TsNEPE0tHo/wvuSJSzbZo7wibeXM9v/rRfKcx7X93rfiXVnyQ9f/5CaAQ4lxedPp/6uzLtOS4FyL0bCNeZ6L5w+AiuyWCTDFIYaUzhwfG+/YTQpWyeZCdQIKzhV+3GeXI2cxoP0ER/DlOKymf1gm+zRU3sqf1lBVQ0y+mK/Awl9bS3uaaQmI0FUyUwHUKP7PKuXnO+LcwDv4OfPT6hph8smc1EtMe5ib/apar/qZ9dyaEaElALJ1KKxnHziuvVl8atk1fINSQh7OtXDyqbPw9o/nGIpTnv5iFmwmWJLis2oyEgPkJqyx0vYI8rjkVEzKc8eQavAJBYSpjMwM193Swt+yJyjvaGYWPnqExxKiNarpB2WSO7soCAZXhS1uEYHryrK47BH6W1dRiruqT0xpLih3MXiwU3VDwAAAA==" // swiftlint:disable:this line_length + /// Credit card brand type for local detection + private enum CardBrand { + case visa + case mastercard + case amex + case discover + case generic + + /// Detect credit card brand from card number using BIN prefixes + static func detect(from cardNumber: String?) -> CardBrand { + guard let cardNumber = cardNumber else { return .generic } + + let cleaned = cardNumber.replacingOccurrences(of: "[\\s-]", with: "", options: .regularExpression) + guard cleaned.range(of: "^\\d{4,}", options: .regularExpression) != nil else { return .generic } + + if cleaned.hasPrefix("4") { return .visa } + if cleaned.range(of: "^5[1-5]", options: .regularExpression) != nil || + cleaned.range(of: "^2[2-7]", options: .regularExpression) != nil { return .mastercard } + if cleaned.range(of: "^3[47]", options: .regularExpression) != nil { return .amex } + if cleaned.range(of: "^6(?:011|22|4[4-9]|5)", options: .regularExpression) != nil { return .discover } + + return .generic + } + + /// Get the SVG icon for this card brand from centralized definitions + var icon: String { + switch self { + case .visa: return ItemTypeIcons.visa + case .mastercard: return ItemTypeIcons.mastercard + case .amex: return ItemTypeIcons.amex + case .discover: return ItemTypeIcons.discover + case .generic: return ItemTypeIcons.creditCard + } + } + } let logoData: Data? let itemType: String? let cardNumber: String? - @Environment(\.colorScheme) private var colorScheme - public init(logoData: Data?, itemType: String? = nil, cardNumber: String? = nil) { self.logoData = logoData self.itemType = itemType self.cardNumber = cardNumber } - private var colors: ColorConstants.Colors.Type { - ColorConstants.colors(for: colorScheme) - } - - private var placeholderImage: UIImage? { - if let data = Data(base64Encoded: placeholderImageBase64) { - return UIImage(data: data) - } - return nil - } - private func detectMimeType(_ data: Data) -> String { // Check for SVG if let str = String(data: data.prefix(5), encoding: .utf8)?.lowercased(), @@ -92,20 +114,19 @@ public struct ItemLogoView: View { private func renderTypeBasedIcon(itemType: String) -> some View { Group { // For Note type, always show note icon - if itemType == ItemTypeIcon.ItemType.note.rawValue { - renderSVGIcon(svg: ItemTypeIcon.noteIcon) + if itemType == ItemType.note { + renderSVGIcon(svg: ItemTypeIcons.note) } // For CreditCard type, detect brand and show appropriate icon - else if itemType == ItemTypeIcon.ItemType.creditCard.rawValue { - let brand = ItemTypeIcon.CardBrand.detect(from: cardNumber) - let cardIcon = ItemTypeIcon.getCardIcon(for: brand) - renderSVGIcon(svg: cardIcon) + else if itemType == ItemType.creditCard { + let brand = CardBrand.detect(from: cardNumber) + renderSVGIcon(svg: brand.icon) } // For Login/Alias types, use Logo if available, otherwise placeholder else if let logoData = logoData, !logoData.isEmpty { renderLogo(logoData: logoData) } else { - renderSVGIcon(svg: ItemTypeIcon.placeholderIcon) + renderSVGIcon(svg: ItemTypeIcons.placeholder) } } } @@ -113,13 +134,15 @@ public struct ItemLogoView: View { /// Render an SVG icon from string private func renderSVGIcon(svg: String) -> some View { Group { - if let svgData = svg.data(using: .utf8), - let svgNode = try? SVGParser.parse(text: svg) { + if let svgNode = try? SVGParser.parse(text: svg) { SVGImageView(node: svgNode) .frame(width: 32, height: 32) .clipShape(RoundedRectangle(cornerRadius: 4)) } else { - renderPlaceholder() + // Fallback if SVG can't be parsed - simple colored rectangle + RoundedRectangle(cornerRadius: 4) + .fill(Color.gray.opacity(0.3)) + .frame(width: 32, height: 32) } } } @@ -139,39 +162,16 @@ public struct ItemLogoView: View { .aspectRatio(contentMode: .fit) .frame(width: 32, height: 32) .clipShape(RoundedRectangle(cornerRadius: 4)) - } else if let placeholder = placeholderImage { - Image(uiImage: placeholder) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 32, height: 32) - .clipShape(RoundedRectangle(cornerRadius: 4)) } else { + // Logo data couldn't be decoded, use centralized placeholder renderPlaceholder() } } } - /// Render fallback placeholder + /// Render fallback placeholder using centralized SVG icon private func renderPlaceholder() -> some View { - Group { - if let placeholder = placeholderImage { - Image(uiImage: placeholder) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 32, height: 32) - .clipShape(RoundedRectangle(cornerRadius: 4)) - } else { - // Ultimate fallback if placeholder fails to load - Circle() - .fill(colors.accentBackground) - .frame(width: 32, height: 32) - .overlay( - Circle() - .stroke(colors.accentBorder, lineWidth: 1) - ) - .clipShape(RoundedRectangle(cornerRadius: 4)) - } - } + renderSVGIcon(svg: ItemTypeIcons.placeholder) } } diff --git a/apps/mobile-app/ios/VaultUI/Components/ItemTypeIcon.swift b/apps/mobile-app/ios/VaultUI/Components/ItemTypeIcon.swift deleted file mode 100644 index 6e6bb5ea5..000000000 --- a/apps/mobile-app/ios/VaultUI/Components/ItemTypeIcon.swift +++ /dev/null @@ -1,159 +0,0 @@ -// swiftlint:disable line_length -import SwiftUI - -/// Item type icon helper - provides SVG-based icons for different item types -public struct ItemTypeIcon { - - /// Item type enumeration matching the database model - public enum ItemType: String { - case login = "Login" - case alias = "Alias" - case creditCard = "CreditCard" - case note = "Note" - } - - /// Credit card brand type - public enum CardBrand { - case visa - case mastercard - case amex - case discover - case generic - - /// Detect credit card brand from card number using industry-standard prefixes - public static func detect(from cardNumber: String?) -> CardBrand { - guard let cardNumber = cardNumber else { - return .generic - } - - // Remove spaces and dashes - let cleaned = cardNumber.replacingOccurrences(of: "[\\s-]", with: "", options: .regularExpression) - - // Must be mostly numeric - guard cleaned.range(of: "^\\d{4,}", options: .regularExpression) != nil else { - return .generic - } - - // Visa: starts with 4 - if cleaned.hasPrefix("4") { - return .visa - } - - // Mastercard: starts with 51-55 or 2221-2720 - if cleaned.range(of: "^5[1-5]", options: .regularExpression) != nil || - cleaned.range(of: "^2[2-7]", options: .regularExpression) != nil { - return .mastercard - } - - // Amex: starts with 34 or 37 - if cleaned.range(of: "^3[47]", options: .regularExpression) != nil { - return .amex - } - - // Discover: starts with 6011, 622, 644-649, 65 - if cleaned.range(of: "^6(?:011|22|4[4-9]|5)", options: .regularExpression) != nil { - return .discover - } - - return .generic - } - } - - /// Generic credit card icon SVG - public static let creditCardIcon = """ - - - - - - - """ - - /// Visa card icon SVG - public static let visaIcon = """ - - - - - """ - - /// Mastercard icon SVG - public static let mastercardIcon = """ - - - - - - - """ - - /// Amex card icon SVG - public static let amexIcon = """ - - - AMEX - - """ - - /// Discover card icon SVG - public static let discoverIcon = """ - - - - - - - - """ - - /// Note/document icon SVG - public static let noteIcon = """ - - - - - - - - """ - - /// Placeholder key icon SVG for Login/Alias without logo - public static let placeholderIcon = """ - - - - - - - - """ - - /// Get the appropriate SVG icon for a credit card brand - public static func getCardIcon(for brand: CardBrand) -> String { - switch brand { - case .visa: - return visaIcon - case .mastercard: - return mastercardIcon - case .amex: - return amexIcon - case .discover: - return discoverIcon - case .generic: - return creditCardIcon - } - } - - /// Get the appropriate SVG icon for an item type - public static func getIcon(for itemType: ItemType, cardNumber: String? = nil) -> String { - switch itemType { - case .note: - return noteIcon - case .creditCard: - let brand = CardBrand.detect(from: cardNumber) - return getCardIcon(for: brand) - case .login, .alias: - return placeholderIcon - } - } -} diff --git a/apps/mobile-app/utils/dist/core/models/icons/index.d.ts b/apps/mobile-app/utils/dist/core/models/icons/index.d.ts new file mode 100644 index 000000000..ce141ca8a --- /dev/null +++ b/apps/mobile-app/utils/dist/core/models/icons/index.d.ts @@ -0,0 +1,64 @@ +/** + * Centralized icon definitions for item types. + * This is the single source of truth for all item type icons across platforms. + * + * Generated platform-specific files: + * - C# (Blazor): apps/server/Databases/AliasClientDb/Models/ItemTypeIcons.cs + * - Swift (iOS): apps/mobile-app/ios/VaultModels/ItemTypeIcons.swift + * - Kotlin (Android): apps/mobile-app/android/.../vaultstore/models/ItemTypeIcons.kt + * - TypeScript: distributed via build.sh to browser-extension and mobile-app + * + * Color scheme used in icons: + * - Primary orange: #f49541 + * - Dark orange: #d68338 + * - Light yellow: #ffe096 + * - Lighter yellow: #fbcb74 + */ +/** + * SVG icon definitions for each item type and card brand. + * All icons use a 32x32 viewBox for consistency. + */ +declare const ItemTypeIconSvgs: { + /** + * Placeholder key icon for Login/Alias items without a logo. + * Traditional key design with outline style. + */ + readonly Placeholder: "\n \n \n \n \n \n"; + /** + * Note/document icon with folded corner. + * Used for Note item type. + */ + readonly Note: "\n \n \n \n \n \n"; + /** + * Generic credit card icon. + * Used when card brand cannot be detected. + */ + readonly CreditCard: "\n \n \n \n \n"; + /** + * Visa card icon with brand styling. + */ + readonly Visa: "\n \n \n"; + /** + * Mastercard icon with overlapping circles. + */ + readonly Mastercard: "\n \n \n \n \n"; + /** + * American Express card icon. + */ + readonly Amex: "\n \n AMEX\n"; + /** + * Discover card icon with orange circle logo. + */ + readonly Discover: "\n \n \n \n \n \n"; +}; +type ItemTypeIconKey = keyof typeof ItemTypeIconSvgs; +/** + * Get SVG string for an item type icon. + */ +declare function getItemTypeIconSvg(key: ItemTypeIconKey): string; +/** + * Get all available icon keys. + */ +declare function getAllIconKeys(): ItemTypeIconKey[]; + +export { type ItemTypeIconKey, ItemTypeIconSvgs, getAllIconKeys, getItemTypeIconSvg }; diff --git a/apps/mobile-app/utils/dist/core/models/icons/index.js b/apps/mobile-app/utils/dist/core/models/icons/index.js new file mode 100644 index 000000000..5d1390408 --- /dev/null +++ b/apps/mobile-app/utils/dist/core/models/icons/index.js @@ -0,0 +1,82 @@ +// +// This file was automatically generated. Do not edit manually. + + +// src/icons/ItemTypeIcons.ts +var ItemTypeIconSvgs = { + /** + * Placeholder key icon for Login/Alias items without a logo. + * Traditional key design with outline style. + */ + Placeholder: ` + + + + + +`, + /** + * Note/document icon with folded corner. + * Used for Note item type. + */ + Note: ` + + + + + +`, + /** + * Generic credit card icon. + * Used when card brand cannot be detected. + */ + CreditCard: ` + + + + +`, + /** + * Visa card icon with brand styling. + */ + Visa: ` + + +`, + /** + * Mastercard icon with overlapping circles. + */ + Mastercard: ` + + + + +`, + /** + * American Express card icon. + */ + Amex: ` + + AMEX +`, + /** + * Discover card icon with orange circle logo. + */ + Discover: ` + + + + + +` +}; +function getItemTypeIconSvg(key) { + return ItemTypeIconSvgs[key]; +} +function getAllIconKeys() { + return Object.keys(ItemTypeIconSvgs); +} + +export { ItemTypeIconSvgs, getAllIconKeys, getItemTypeIconSvg }; +//# sourceMappingURL=index.js.map +//# sourceMappingURL=index.js.map \ No newline at end of file