diff --git a/Andromida/AndromidaApp.swift b/Andromida/AndromidaApp.swift index 539a9b5..cfb9e89 100644 --- a/Andromida/AndromidaApp.swift +++ b/Andromida/AndromidaApp.swift @@ -72,7 +72,17 @@ struct AndromidaApp: App { let settings = SettingsStore() _settingsStore = State(initialValue: settings) _categoryStore = State(initialValue: CategoryStore()) - _store = State(initialValue: RitualStore(modelContext: container.mainContext, seedService: RitualSeedService(), settingsStore: settings)) + + let ritualStore = RitualStore(modelContext: container.mainContext, seedService: RitualSeedService(), settingsStore: settings) + if isUITesting, environment["UITEST_SEED_THREE_PRESETS"] == "1" { + ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[0]) // morning + ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[1]) // midday + ritualStore.createRitualFromPreset(RitualPresetLibrary.healthPresets[3]) // evening + } + if isUITesting, environment["UITEST_PRELOAD_DEMO_DATA"] == "1" { + ritualStore.preloadDemoData() + } + _store = State(initialValue: ritualStore) } var body: some Scene { @@ -82,12 +92,13 @@ struct AndromidaApp: App { .ignoresSafeArea() if hasCompletedSetupWizard { + let uiTestInitialTab = uiTestRequestedInitialTab() // Main app - start on Rituals tab if just completed wizard RootView( store: store, settingsStore: settingsStore, categoryStore: categoryStore, - initialTab: justCompletedWizard ? .rituals : .today + initialTab: uiTestInitialTab ?? (justCompletedWizard ? .rituals : .today) ) .transition(.opacity) } else { @@ -111,4 +122,16 @@ struct AndromidaApp: App { .preferredColorScheme(settingsStore.theme.colorScheme) } } + + private func uiTestRequestedInitialTab() -> RootView.RootTab? { + guard ProcessInfo.processInfo.environment["UITEST_MODE"] == "1" else { return nil } + switch ProcessInfo.processInfo.environment["UITEST_INITIAL_TAB"]?.lowercased() { + case "today": return .today + case "rituals": return .rituals + case "insights": return .insights + case "history": return .history + case "settings": return .settings + default: return nil + } + } } diff --git a/Andromida/App/Views/Settings/SettingsView.swift b/Andromida/App/Views/Settings/SettingsView.swift index d687e42..712525c 100644 --- a/Andromida/App/Views/Settings/SettingsView.swift +++ b/Andromida/App/Views/Settings/SettingsView.swift @@ -140,6 +140,7 @@ struct SettingsView: View { ) { ritualStore.preloadDemoData() } + .accessibilityIdentifier("settings.debug.preloadDemoData") SettingsRow( systemImage: "checkmark.circle.badge.xmark", diff --git a/AndromidaUITests/AndromidaUITests.swift b/AndromidaUITests/AndromidaUITests.swift index 2c4912f..3587088 100644 --- a/AndromidaUITests/AndromidaUITests.swift +++ b/AndromidaUITests/AndromidaUITests.swift @@ -8,6 +8,28 @@ import XCTest final class AndromidaUITests: XCTestCase { + private let doneLabels = ["Done", "Terminé", "Listo"] + private let settingsTabLabels = ["Settings", "Réglages", "Paramètres", "Ajustes"] + private let tabLabelMap: [String: [String]] = [ + "Today": ["Today", "Aujourd'hui", "Hoy"], + "Rituals": ["Rituals", "Rituels", "Rituales"], + "Insights": ["Insights", "Aperçus", "Ideas"], + "History": ["History", "Historique", "Historial"], + "Settings": ["Settings", "Réglages", "Paramètres", "Ajustes"] + ] + private let tabSymbolMap: [String: String] = [ + "Today": "sun.max.fill", + "Rituals": "sparkles", + "Insights": "chart.bar.fill", + "History": "calendar", + "Settings": "gearshape.fill" + ] + private let preloadLabels = [ + "Preload 6 Months Demo Data", + "Précharge 6 mois Données de démonstration", + "Precarga 6 Meses Datos de demostración" + ] + private let preloadPrefixLabels = ["Preload 6", "Précharge 6", "Precarga 6"] override func setUpWithError() throws { continueAfterFailure = false @@ -155,14 +177,14 @@ final class AndromidaUITests: XCTestCase { @MainActor func testAppStorePortraitScreenshots() throws { let app = makeApp(resetDefaults: true, hasCompletedSetupWizard: true) + app.launchEnvironment["UITEST_INITIAL_TAB"] = "settings" app.launch() XCUIDevice.shared.orientation = .portrait - // Add three preset rituals across the day, then seed representative history from Debug settings. - addThreePresetRitualsAcrossDay(app: app) + // Ensure rituals exist before seeding demo history. + assertRitualsPresentBeforePreload(app: app) preloadSixMonthsDemoDataFromDebug(app: app) - ensureDataRichStateForScreenshots(app: app) openTab(app: app, label: "Today", index: 0) XCTAssertFalse(app.staticTexts["No Active Rituals"].exists, "Today should show active rituals for App Store screenshots.") @@ -188,6 +210,8 @@ final class AndromidaUITests: XCTestCase { private func makeApp(resetDefaults: Bool, hasCompletedSetupWizard: Bool) -> XCUIApplication { let app = XCUIApplication() app.launchEnvironment["UITEST_MODE"] = "1" + app.launchEnvironment["UITEST_SEED_THREE_PRESETS"] = "1" + app.launchEnvironment["UITEST_PRELOAD_DEMO_DATA"] = "1" if resetDefaults { app.launchEnvironment["UITEST_RESET_USER_DEFAULTS"] = "1" } @@ -195,54 +219,20 @@ final class AndromidaUITests: XCTestCase { return app } - private func addThreePresetRitualsAcrossDay(app: XCUIApplication) { - openTab(app: app, label: "Rituals", index: 1) - - let addMenu = app.buttons["rituals.addMenu"] - guard addMenu.waitForExistence(timeout: 8) else { return } - addMenu.tap() - - let browsePresets = app.buttons["rituals.browsePresets"] - guard browsePresets.waitForExistence(timeout: 8) else { return } - browsePresets.tap() - - let presetTitles = ["Morning Hydration", "Midday Movement", "Evening Nutrition"] - for title in presetTitles { - if let preset = findElementWithVerticalSearch( - app: app, - label: title, - timeoutPerAttempt: 1.0, - swipeCount: 6 - ) { - if preset.isHittable { - preset.tap() - } else { - preset.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() - } - - let addButton = app.buttons["Add to My Rituals"] - if addButton.waitForExistence(timeout: 8) { - addButton.tap() - } - tapDoneInNavigationBar(app: app, title: title) - RunLoop.current.run(until: Date().addingTimeInterval(0.3)) - } + private func preloadSixMonthsDemoDataFromDebug(app: XCUIApplication) { + // iPad tab/sidebars are highly variable in UI tests on iOS 26; + // demo data is already guaranteed via launch environment. + if app.windows.firstMatch.frame.width >= 1000 { + return } - tapDoneInNavigationBar(app: app, title: "Preset Library") - } - - private func preloadSixMonthsDemoDataFromDebug(app: XCUIApplication) { openTab(app: app, label: "Settings", index: 4) - // Move into the lower Debug section before tapping preload. - _ = findElementWithVerticalSearch(app: app, label: "Debug", timeoutPerAttempt: 0.5, swipeCount: 8) - if let preload = findElementWithVerticalSearch( app: app, - label: "Preload 6 Months Demo Data", - timeoutPerAttempt: 0.5, - swipeCount: 10 + label: "settings.debug.preloadDemoData", + timeoutPerAttempt: 0.3, + swipeCount: 12 ) { if preload.isHittable { preload.tap() @@ -250,21 +240,64 @@ final class AndromidaUITests: XCTestCase { preload.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() } RunLoop.current.run(until: Date().addingTimeInterval(1.0)) - waitForHistoryDataSeed(app: app) + return } + + if tapPreloadByPrefixSearch(app: app) { + RunLoop.current.run(until: Date().addingTimeInterval(1.0)) + return + } + + let preload = findAnyElementWithVerticalSearch( + app: app, + labels: preloadLabels, + timeoutPerAttempt: 0.5, + swipeCount: 10 + ) + + if let preload { + if preload.isHittable { + preload.tap() + } else { + preload.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() + } + RunLoop.current.run(until: Date().addingTimeInterval(1.0)) + return + } + } - private func waitForHistoryDataSeed(app: XCUIApplication) { - for _ in 0..<6 { - openTab(app: app, label: "History", index: 3) - let nonZeroDay = app.buttons.matching( - NSPredicate(format: "label CONTAINS[c] %@ AND NOT (label CONTAINS[c] %@)", "percent complete", "0 percent complete") - ).firstMatch - if nonZeroDay.waitForExistence(timeout: 1.5) { - return + private func tapPreloadByPrefixSearch(app: XCUIApplication) -> Bool { + func tapMatchingElement() -> Bool { + let elements = app.descendants(matching: .any).allElementsBoundByIndex + for element in elements where element.exists { + let label = element.label + if preloadPrefixLabels.contains(where: { label.contains($0) }) { + if element.isHittable { + element.tap() + } else { + element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() + } + return true + } } - RunLoop.current.run(until: Date().addingTimeInterval(0.5)) + return false } + + if tapMatchingElement() { return true } + for _ in 0..<12 { + app.swipeUp() + if tapMatchingElement() { return true } + } + return false + } + + private func assertRitualsPresentBeforePreload(app: XCUIApplication) { + openTab(app: app, label: "Rituals", index: 1) + XCTAssertFalse( + app.staticTexts["No Active Rituals"].exists, + "Expected seeded rituals before preload." + ) } @@ -356,35 +389,128 @@ final class AndromidaUITests: XCTestCase { return nil } - private func tapDoneInNavigationBar(app: XCUIApplication, title: String) { - let navDone = app.navigationBars[title].buttons["Done"].firstMatch - if navDone.waitForExistence(timeout: 6) { - navDone.tap() - return + private func findAnyElementWithVerticalSearch( + app: XCUIApplication, + labels: [String], + timeoutPerAttempt: TimeInterval, + swipeCount: Int + ) -> XCUIElement? { + for label in labels { + if let element = firstMatchIfExists(app: app, label: label, timeout: timeoutPerAttempt) { + return element + } } - let anyDone = app.buttons["Done"].firstMatch - if anyDone.waitForExistence(timeout: 4) { + for _ in 0.. XCUIElement? { + firstExistingButton(app: app, labels: doneLabels, timeout: timeout) + } + + private func firstExistingButton(app: XCUIApplication, labels: [String], timeout: TimeInterval) -> XCUIElement? { + let deadline = Date().addingTimeInterval(timeout) + while Date() < deadline { + for label in labels { + let button = app.buttons[label].firstMatch + if button.exists { + return button + } + } + RunLoop.current.run(until: Date().addingTimeInterval(0.1)) } + return nil + } + + private func openTab(app: XCUIApplication, label: String, index: Int) { + let localizedLabels = tabLabelMap[label] ?? [label] let tabButtons = app.tabBars.buttons if tabButtons.count > index { - tabButtons.element(boundBy: index).tap() - return + let indexed = tabButtons.element(boundBy: index) + if indexed.exists { + indexed.tap() + return + } } - let fallback = app.buttons[label].firstMatch - if fallback.exists { - fallback.tap() + for localizedLabel in localizedLabels { + let primary = app.tabBars.buttons[localizedLabel].firstMatch + if primary.waitForExistence(timeout: 2) { + primary.tap() + return + } + } + + for localizedLabel in localizedLabels { + let sidebarButton = app.buttons[localizedLabel].firstMatch + if sidebarButton.waitForExistence(timeout: 2) { + sidebarButton.tap() + return + } + let staticText = app.staticTexts[localizedLabel].firstMatch + if staticText.waitForExistence(timeout: 1) { + staticText.tap() + return + } + } + + if let symbol = tabSymbolMap[label] { + let symbolButton = app.buttons[symbol].firstMatch + if symbolButton.waitForExistence(timeout: 2) { + symbolButton.tap() + return + } + } + + for localizedLabel in localizedLabels { + if let found = findElementWithVerticalSearch( + app: app, + label: localizedLabel, + timeoutPerAttempt: 0.4, + swipeCount: 8 + ) { + if found.isHittable { + found.tap() + } else { + found.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() + } + return + } } } @@ -398,20 +524,19 @@ final class AndromidaUITests: XCTestCase { private func openHistoryDayDetailWithData(app: XCUIApplication) { openTab(app: app, label: "History", index: 3) - let nonZeroDay = app.buttons.matching( - NSPredicate(format: "label CONTAINS[c] %@ AND NOT (label CONTAINS[c] %@)", "percent complete", "0 percent complete") - ).firstMatch - - if nonZeroDay.waitForExistence(timeout: 8) { - nonZeroDay.tap() + // Locale-agnostic: prefer a day-like button with digits in its label. + let dayPredicate = NSPredicate(format: "label MATCHES %@", ".*[0-9].*") + let dayButton = app.buttons.matching(dayPredicate).firstMatch + if dayButton.waitForExistence(timeout: 4) { + dayButton.tap() } else { - let anyDay = app.buttons.matching(NSPredicate(format: "label CONTAINS[c] %@", "percent complete")).firstMatch - if anyDay.waitForExistence(timeout: 8) { - anyDay.tap() + let buttons = app.buttons.allElementsBoundByIndex + if let fallback = buttons.first(where: { $0.exists && $0.isHittable }) { + fallback.tap() } } - _ = app.buttons["Done"].waitForExistence(timeout: 8) + _ = firstExistingDoneButton(app: app, timeout: 2) } private func tapFirstAvailableElementIfPresent( diff --git a/Screenshots/es-MX/iPad-13/01-today-focus-portrait.png b/Screenshots/es-MX/iPad-13/01-today-focus-portrait.png new file mode 100644 index 0000000..356f8c2 Binary files /dev/null and b/Screenshots/es-MX/iPad-13/01-today-focus-portrait.png differ diff --git a/Screenshots/es-MX/iPad-13/02-ritual-arcs-portrait.png b/Screenshots/es-MX/iPad-13/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..d061c33 Binary files /dev/null and b/Screenshots/es-MX/iPad-13/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/es-MX/iPad-13/03-insights-trends-portrait.png b/Screenshots/es-MX/iPad-13/03-insights-trends-portrait.png new file mode 100644 index 0000000..b628e9c Binary files /dev/null and b/Screenshots/es-MX/iPad-13/03-insights-trends-portrait.png differ diff --git a/Screenshots/es-MX/iPad-13/04-history-calendar-portrait.png b/Screenshots/es-MX/iPad-13/04-history-calendar-portrait.png new file mode 100644 index 0000000..dcee4ac Binary files /dev/null and b/Screenshots/es-MX/iPad-13/04-history-calendar-portrait.png differ diff --git a/Screenshots/es-MX/iPad-13/05-history-day-detail-portrait.png b/Screenshots/es-MX/iPad-13/05-history-day-detail-portrait.png new file mode 100644 index 0000000..f4f4159 Binary files /dev/null and b/Screenshots/es-MX/iPad-13/05-history-day-detail-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.3/01-today-focus-portrait.png b/Screenshots/es-MX/iPhone-6.3/01-today-focus-portrait.png new file mode 100644 index 0000000..a55ba13 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.3/01-today-focus-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.3/02-ritual-arcs-portrait.png b/Screenshots/es-MX/iPhone-6.3/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..0abc779 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.3/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.3/03-insights-trends-portrait.png b/Screenshots/es-MX/iPhone-6.3/03-insights-trends-portrait.png new file mode 100644 index 0000000..01a7de3 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.3/03-insights-trends-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.3/04-history-calendar-portrait.png b/Screenshots/es-MX/iPhone-6.3/04-history-calendar-portrait.png new file mode 100644 index 0000000..89d9903 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.3/04-history-calendar-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.3/05-history-day-detail-portrait.png b/Screenshots/es-MX/iPhone-6.3/05-history-day-detail-portrait.png new file mode 100644 index 0000000..acb8783 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.3/05-history-day-detail-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.5-fallback/01-today-focus-portrait.png b/Screenshots/es-MX/iPhone-6.5-fallback/01-today-focus-portrait.png new file mode 100644 index 0000000..b3317bb Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.5-fallback/01-today-focus-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.5-fallback/02-ritual-arcs-portrait.png b/Screenshots/es-MX/iPhone-6.5-fallback/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..5a56c9b Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.5-fallback/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.5-fallback/03-insights-trends-portrait.png b/Screenshots/es-MX/iPhone-6.5-fallback/03-insights-trends-portrait.png new file mode 100644 index 0000000..b65769d Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.5-fallback/03-insights-trends-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.5-fallback/04-history-calendar-portrait.png b/Screenshots/es-MX/iPhone-6.5-fallback/04-history-calendar-portrait.png new file mode 100644 index 0000000..d232d25 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.5-fallback/04-history-calendar-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.5-fallback/05-history-day-detail-portrait.png b/Screenshots/es-MX/iPhone-6.5-fallback/05-history-day-detail-portrait.png new file mode 100644 index 0000000..2e60b8a Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.5-fallback/05-history-day-detail-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.9/01-today-focus-portrait.png b/Screenshots/es-MX/iPhone-6.9/01-today-focus-portrait.png new file mode 100644 index 0000000..c73984d Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.9/01-today-focus-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.9/02-ritual-arcs-portrait.png b/Screenshots/es-MX/iPhone-6.9/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..f8a9025 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.9/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.9/03-insights-trends-portrait.png b/Screenshots/es-MX/iPhone-6.9/03-insights-trends-portrait.png new file mode 100644 index 0000000..ad5c2e9 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.9/03-insights-trends-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.9/04-history-calendar-portrait.png b/Screenshots/es-MX/iPhone-6.9/04-history-calendar-portrait.png new file mode 100644 index 0000000..8e7d9e8 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.9/04-history-calendar-portrait.png differ diff --git a/Screenshots/es-MX/iPhone-6.9/05-history-day-detail-portrait.png b/Screenshots/es-MX/iPhone-6.9/05-history-day-detail-portrait.png new file mode 100644 index 0000000..8eaa4a6 Binary files /dev/null and b/Screenshots/es-MX/iPhone-6.9/05-history-day-detail-portrait.png differ diff --git a/Screenshots/fr-CA/iPad-13/01-today-focus-portrait.png b/Screenshots/fr-CA/iPad-13/01-today-focus-portrait.png new file mode 100644 index 0000000..28490e3 Binary files /dev/null and b/Screenshots/fr-CA/iPad-13/01-today-focus-portrait.png differ diff --git a/Screenshots/fr-CA/iPad-13/02-ritual-arcs-portrait.png b/Screenshots/fr-CA/iPad-13/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..2f3aabb Binary files /dev/null and b/Screenshots/fr-CA/iPad-13/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/fr-CA/iPad-13/03-insights-trends-portrait.png b/Screenshots/fr-CA/iPad-13/03-insights-trends-portrait.png new file mode 100644 index 0000000..2f3aabb Binary files /dev/null and b/Screenshots/fr-CA/iPad-13/03-insights-trends-portrait.png differ diff --git a/Screenshots/fr-CA/iPad-13/04-history-calendar-portrait.png b/Screenshots/fr-CA/iPad-13/04-history-calendar-portrait.png new file mode 100644 index 0000000..2f3aabb Binary files /dev/null and b/Screenshots/fr-CA/iPad-13/04-history-calendar-portrait.png differ diff --git a/Screenshots/fr-CA/iPad-13/05-history-day-detail-portrait.png b/Screenshots/fr-CA/iPad-13/05-history-day-detail-portrait.png new file mode 100644 index 0000000..a980a09 Binary files /dev/null and b/Screenshots/fr-CA/iPad-13/05-history-day-detail-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.3/01-today-focus-portrait.png b/Screenshots/fr-CA/iPhone-6.3/01-today-focus-portrait.png new file mode 100644 index 0000000..da7cda1 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.3/01-today-focus-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.3/02-ritual-arcs-portrait.png b/Screenshots/fr-CA/iPhone-6.3/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..db6d8e5 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.3/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.3/03-insights-trends-portrait.png b/Screenshots/fr-CA/iPhone-6.3/03-insights-trends-portrait.png new file mode 100644 index 0000000..8425d7e Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.3/03-insights-trends-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.3/04-history-calendar-portrait.png b/Screenshots/fr-CA/iPhone-6.3/04-history-calendar-portrait.png new file mode 100644 index 0000000..8f7fcc0 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.3/04-history-calendar-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.3/05-history-day-detail-portrait.png b/Screenshots/fr-CA/iPhone-6.3/05-history-day-detail-portrait.png new file mode 100644 index 0000000..b44eb18 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.3/05-history-day-detail-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.5-fallback/01-today-focus-portrait.png b/Screenshots/fr-CA/iPhone-6.5-fallback/01-today-focus-portrait.png new file mode 100644 index 0000000..c59494f Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.5-fallback/01-today-focus-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.5-fallback/02-ritual-arcs-portrait.png b/Screenshots/fr-CA/iPhone-6.5-fallback/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..7511784 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.5-fallback/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.5-fallback/03-insights-trends-portrait.png b/Screenshots/fr-CA/iPhone-6.5-fallback/03-insights-trends-portrait.png new file mode 100644 index 0000000..618e8b5 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.5-fallback/03-insights-trends-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.5-fallback/04-history-calendar-portrait.png b/Screenshots/fr-CA/iPhone-6.5-fallback/04-history-calendar-portrait.png new file mode 100644 index 0000000..4129034 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.5-fallback/04-history-calendar-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.5-fallback/05-history-day-detail-portrait.png b/Screenshots/fr-CA/iPhone-6.5-fallback/05-history-day-detail-portrait.png new file mode 100644 index 0000000..a38f249 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.5-fallback/05-history-day-detail-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.9/01-today-focus-portrait.png b/Screenshots/fr-CA/iPhone-6.9/01-today-focus-portrait.png new file mode 100644 index 0000000..a40156d Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.9/01-today-focus-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.9/02-ritual-arcs-portrait.png b/Screenshots/fr-CA/iPhone-6.9/02-ritual-arcs-portrait.png new file mode 100644 index 0000000..9ac9fae Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.9/02-ritual-arcs-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.9/03-insights-trends-portrait.png b/Screenshots/fr-CA/iPhone-6.9/03-insights-trends-portrait.png new file mode 100644 index 0000000..51278a9 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.9/03-insights-trends-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.9/04-history-calendar-portrait.png b/Screenshots/fr-CA/iPhone-6.9/04-history-calendar-portrait.png new file mode 100644 index 0000000..d965d7b Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.9/04-history-calendar-portrait.png differ diff --git a/Screenshots/fr-CA/iPhone-6.9/05-history-day-detail-portrait.png b/Screenshots/fr-CA/iPhone-6.9/05-history-day-detail-portrait.png new file mode 100644 index 0000000..b0b73d3 Binary files /dev/null and b/Screenshots/fr-CA/iPhone-6.9/05-history-day-detail-portrait.png differ